关于实践周的第一个项目选择了制作Flying Birds小游戏,预备知识包括面向对象的封装,swing和awt包,Math类,事件监听器,多线程。
关于一些具体参数为何设置实际上应该是和所给素材图片的大小有关,其实也可以利用相关get函数读取相关参数输出后,就可以知道。
以此造成的影响包括图片设置的位置x,y的设定以及小鸟初始位置的设定,以及窗口大小设定。
总的来说,关于设计一个完整项目,最重要的是了解类的属性关系以及类的相关方法。
回顾总设计流程如下
1.绘制面板,放入背景图。
2.设计地面、柱子类完成移动的效果(移动方法实现)。
3.设计小鸟,完成飞行轨迹、与柱子是否碰撞的方法等。
4.设计游戏类,完成游戏类界面的绘制。
5.设计游戏开始的方法与流程。
6.增加鼠标监听器完成对小鸟飞行及游戏运行的控制。
具体知识点包括
变量
1.分支语句
2.循环语句
3.面向对象
4.异常处理
5.Random随机数
6.StringBuffer字符串操作
7.IO操作
8.多线程
9.swing组件和awt组件
10.Math类函数调用
相关知识点是在边学习边使用,需要更加理解并灵活运使用

Flying Birds总结回顾要点

动画参数中重要参数循环中的i

1
2
3
4
5
6
7
8
9
10
11
//初始化动画帧参数
images=new Image[8];

for(int i=0;i<8;i++)
{
images[i]=new ImageIcon("source/"+i+".png").getImage();
}
index=0;

}

由于在source的文件里表示小鸟的图片有8张i是从0开始对应图片source0.jpg,所以i的循环中从0到7满足就是对souce里面source0.jpg到source7.jpg的遍历。

此处弧度作用

1
2
3
4
5
6
7
8
9
10
11
public boolean hit(Ground ground)
{
boolean hit =y+size/2>ground.y;
if(hit)
{
y=ground.y-size/2;
alpha=Math.PI/2;
}
return hit;
}

判断条件中判断到撞击地面后, alpha=Math.PI/2实际上将小鸟的弧度重置为Math.PI/2,表现在游戏中gameover的时候小鸟摔了个底朝天。

More info: 小鸟被撞翻啦

repaint()方法

1
2
3
//休眠1000/60毫秒
Thread.sleep(1000/60);
repaint();

repaint()这个方法是一个具有刷新页面效果的方法,如果你要页面进行重画就可以调用.一般都是在AWT的图形绘制当中调用的到
工作原理如下:
repaint()方法
|
|
V
AWT线程--->paint()方法-->图形绘制
   |
   |
   V
update()方法--->paint()方法--图形绘制

主要需要判断出现的两大界面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
int state;//游戏状态
//状态常量
public static final int START=0;//开始
public static final int RUNNING=1;//运行
public static final int GAME_OVER=2;//结束


public void mousePressed(MouseEvent e)
{
try {
switch(state) {
case START:
//在开始前按下鼠标转为运行状态
state=RUNNING;
break;
case RUNNING:
//在运行状态,按下鼠标小鸟向上飞行
bird.flappy();
break;
case GAME_OVER:
//在结束状态,按下鼠标重置数据变为开始
column1=new Column(1);
column2=new Column(2);
bird=new Bird();
score=0;
state=START;
break;
}
}
//绘制开始和结束界面
switch(state)
{
case START:
g.drawImage(startImage, 0, 0, null);
break;
case GAME_OVER:
g.drawImage(overImage, 0, 0, null);
break
}

通过Bird类里面的碰撞判断再来判断Birdgame类里面的state//状态常量,通过状态常量在switch语句里面的条件判断情况后,绘制
不同情况下所应该显示的对应图片。

JFrame的使用到的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
 
public static void main(String[] args) throws Exception
{

JFrame frame=new JFrame();
BirdGame game=new BirdGame();
frame.add(game);
frame.setSize(440,670);
frame.setLocationRelativeTo(null);//设置窗口相对于指定组件的位置。如果组件当前未显示或者 为 null,则此窗口将置于屏幕的中央
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//如果在代码里没加这个方法,那么在点击框架的”叉叉“退出框架后,程序仍然没有退出,只是JFrame被关闭了。
frame.setVisible(true);
game.action();
}

JFrame是最底层,JPanel是置于其面上,同一个界面只有一个JFrame,一个JFrame可以放多个JPanel。
JFrame 用来设计类似于 Windows 系统中窗口形式的界面。JFrame 是 Swing 组件的顶层容器,该类继承了 AWT 的 Frame 类,支持 Swing 体系结构的高级 GUI 属性。
JPanel 是一种中间层容器,它能容纳组件并将组件组合在一起,但它本身必须添加到其他容器中使用。

JFrame常见使用方法

1
2
3
4
5
6
7
JFrame jf = new JFrame("我是标题鸭!!!");//创建一个JFrame对象
jf.setTitle("我是标题鸭!!!");//标题的设置
jf.setSize(20,10)//设置了一个长为20,高为10的框图。
jf.setBounds(1,2,20,10)//设置一个左上角顶点在(1,2),长为20,宽为10的窗体。
jf.setLocation(1,2)//设置一个左上角顶点在(1,2)的窗体。
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置同步开关
jf.setVisible(true);//设置窗体可见

JPanel常见使用方法

1
2
3
4
5
6
7
8
9
//构造方法
JPanel():使用默认的布局管理器创建新面板,默认的布局管理器为 FlowLayout。
JPanel(LayoutManagerLayout layout):创建指定布局管理器的 JPanel 对象。
//常见函数
Component add(Component comp) 将指定的组件追加到此容器的尾部
void remove(Component comp) 从容器中移除指定的组件
void setFont(Font f) 设置容器的字体
void setLayout(LayoutManager mgr) 设置容器的布局管理器
void setBackground(Color c) 设置组件的背景色

More info: JPanel和JFrame的使用方法

Welcome back AM1ng!

2021年07月17日
阅读更多...

关于实践周的第一个项目选择了制作Flying Birds小游戏。接下来是地面类和柱子类详细参数的设置。

地面类初始化

1
2
3
4
5
6
7
8
public Ground() throws Exception
{
image =new ImageIcon("source/ground.png").getImage();//原图片
width=image.getWidth(null);//使用 img.getWidth(null); 图片加载到内存中,可获图片真实宽度
height=image.getHeight(null);//使用 img.getHeight(null); 图片加载到内存中,可获图片真实高度
x=0;
y=500;
}

设计Gound类里默认读取图片资源中的ground的图片利用image.getWidth(null) image.getHeight(null)读取图片的高宽。
x y来控制图片放置的位置。

Ground类左移

1
2
3
4
5
6
7
8
9
//左移
public void step()
{
x-=4;
if(x<=-109)
{
x=0;
}
}

同样名为step类意味小鸟移动其实是用地面的图像左移的动画来实现的。

柱子类初始化

1
2
3
4
5
6
7
8
9
10
public Column(int n) throws Exception
{
image=new ImageIcon("source/column.png").getImage();
width=image.getWidth(null);
height=image.getHeight(null);
gap=144;
distance=245;
x=550+(n-1)*distance;
y=random.nextInt(218)+132;
}

同理可以默认读取图片资源中的clolumn的图片利用image.getWidth(null) image.getHeight(null)读取图片的高宽。
利用random类使游戏过程中柱子不断刷新后的纵坐标不同,所以柱子出现的高矮就会不同甚至没有上柱子。
gap是柱子之间缝隙(上下),由于贴图原因实际上gap应该为定制,如果缩小gap可能在间隙也会发生碰撞,如果扩大gap虽然确实可以增加通过的间隙,但是部分
间隙和柱子重叠,显示的是鸟经过了柱子但是没有发生碰撞。
由于柱子类出现X可以有distance控制,所以改变distance实际上是可以改变柱子出现的间隔距离(左右)。可以通过此处来改变游戏难度。

柱子类移动

1
2
3
4
5
6
7
8
9
public void step()
{
x-=4;
if(x<= -width/2)
{
x=distance*2-width/2;
y=random.nextInt(218);
}
}

柱子随地面按step函数移动。

Welcome back AM1ng!

2021年07月17日
阅读更多...

Bird类思路要点

关于实践周的第一个项目选择了制作Flying Birds小游戏,此小游戏的易上手之处其实还在于通过几帧的小鸟图片来代表小鸟的运动形态。
飞行动作(变化一帧)依靠以图片类型构成的数组内重复调用小鸟状态的图片来显示。
移动一步需要依靠计算上跑位移、计算鸟的坐标、计算下次移动速度、计算倾角(反正切函数),向上飞行时按照惯性需要重置速度。
其中设计小鸟的另外两个关键函数在于判断小鸟是否碰撞到地面或者检测小鸟是否撞到柱子,此为游戏规则。

Bird动画原理

1
2
3
4
5
6
7
8
9
10
11
12
13
Image[] images;//一组图片记录小鸟动画帧(images类数组的一组照片,Source里面的小鸟的不同照片完成小鸟的动作动画)
int index;//帧数下标
...
...
//初始化动画帧参数
images=new Image[8];

for(int i=0;i<8;i++)
{
images[i]=new ImageIcon("source/"+i+".png").getImage();
}
index=0;//利用source后面i++来访问souce里面的Bird照片,所以照片存储摆放会有影响

首先有一个Souce文件里面需要收集小鸟多个状态的图片,在此次项目中放置在Source的文件包里面,关于小鸟的每一帧形态的图片为该包内的0-7个文件。
此处文件顺序对动作会有影响,上述代码附带解释。

Bird中step:移动一步

1
2
3
4
5
6
7
8
9
10
11
12
13
public void step()
{
double v0=speed;
//计算上跑位移
s=v0*t+g*t*t/2;
//计算鸟的坐标
y=y-(int)s;
//计算下次移动速度
double v=v0-g*t;
speed =v;
//计算倾角(反正切函数)
alpha=Math.atan(s/8);
}

移动中根据间隔时间需要计算鸟出现的坐标以及倾斜角展示鸟下落或者上飞的一个过程。

Bird类碰撞判断(游戏不碰撞的规则)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

//检测小鸟是否碰撞到地面
public boolean hit(Ground ground)
{
boolean hit =y+size/2>ground.y;
if(hit)
{
y=ground.y-size/2;
alpha=Math.PI/2;
}
return hit;
}

//检测小鸟是否撞到柱子
public boolean hit(Column column)
{
//检测是否在柱子范围内
if(x>column.x-column.width/2-size/2&&x<column.x+column.width/2+size/2)
{
if(y>column.y-column.gap/2+size/2&&y<column.y+column.gap/2-size/2) return false;
return true;
}
return false;
}
}

hit类用boolean类型定义返回值可以选用0或1方便之后的判断是否碰撞(即0或1)
考虑碰撞的两个需要同时满足的因素:一是小鸟是否会从侧面撞到柱子所以调用到column.width 二是在满足一的条件下小鸟坐标是否位于间隙(gap)坐标内

Bird起飞

1
2
3
4
5
6
//向上飞行
public void flappy()
{
//重置速度
speed=v0;
}

对鼠标左键进行监听,当点击鼠标左键时,小鸟会获得一个向上的速度,当松开鼠标左键的时候,小鸟就会坠落。

Welcome back AM1ng!

2021年07月16日
阅读更多...

Birdgame类

关于实践周的第一个项目选择了制作Flying Birds小游戏,首先会考虑到最直观的界面设计。
其中主要运用swing和awt包:图形界面工具,绘制出游戏场景。
主要设计对象包括游戏开始界面,游戏分数统计,游戏结束界面。

整个Birdgame类继承JPanel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class BirdGame extends JPanel {
...
...
}
JPanel中常用方法
void add(Component):添加组件。
void add(Component,int):添加组件至索引指定位置。
void add(Component,Object):按照指定布局限制添加组件。
void add(Component,Object,int):按照指定布局管理器限制添加组件到指定位置。
void remove(Component):移除组件。
void remove(int):移除指定位置的组件。
void removeAll():移除所有组件。
void paintComponent(Graphics):绘制组件。``
void repaint():重新绘制。
void setPreferredSize(Dimension):设置组件尺寸。
Dimension getPreferredSize():获取最佳尺寸。

组件是构成应用程序界面的基本元素,按钮、文本框、进度条等,都是组件。可视化组件又可以分为容器组件和非容器组件,可以在JPanel中放置按钮、文本框等非容器组件,甚至可以在JPanel中再放置若干个JPanel组件,顶层容器也是容器组件,每一个窗口应用程序中有且只能有一个顶层容器组件。
经常使用JPanel先创建一个面板,在向这个面板添加组件,然后把这个面板添加到其他容器中。
JPanel面板的默认布局是FlowLayout布局**
More info: JFrame,JPanel,JLabel详解

Graphics2D类基本使用

1
2
3
4
//绘制小鸟
Graphics2D g2=(Graphics2D) g;
g2.rotate(-bird.alpha,bird.x,bird.y);//rotate(double arc,double x, double y):图形以点(x,y)为轴点,旋转arc弧度。
g2.rotate(bird.alpha,bird.x,bird.y);//rotate(double arc,double x, double y):图形以点(x,y)为轴点,旋转arc弧度。

Java语言在Graphics类提供绘制各种基本的几何图形的基础上,扩展Graphics类提供一个Graphics2D类,它拥用更强大的二维图形处理能力,提供、坐标转换、颜色管理以及文字布局等更精确的控制。
Graphics2D定义了几种方法,用于添加或改变图形的状态属性。可以通过设定和修改状态属性,指定画笔宽度和画笔的连接方式;设定平移、旋转、缩放或修剪变换图形;以及设定填充图形的颜色和图案等。图形状态属性用特定的对象存储。
More info: Graphics2D类基本使用

与鼠标互动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
不断重复和绘制
MouseListener l=new MouseAdapter()
{
public void mousePressed(MouseEvent e)
{
try {
switch(state) {
case START:
//在开始前按下鼠标转为运行状态
state=RUNNING;
break;
case RUNNING:
//在运行状态,按下鼠标小鸟向上飞行
bird.flappy();
break;
case GAME_OVER:
//在结束状态,按下鼠标重置数据变为开始
column1=new Column(1);
column2=new Column(2);
bird=new Bird();
score=0;
state=START;
break;
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}

};
addMouseListener(l);

java中 addMouseListener()方法用于接收组件上“感兴趣”的鼠标事件(按下、释放、单击、进入或离开)的侦听器接口。(要跟踪鼠标移动和鼠标拖动,请使用 MouseMotionListener。)
MouseListener与MouseAdapter的区别在于一个是类,一个是接口。
适配器已经实现了相应的接口,例如MouseAdapter类实现了MouseListener接口,因此可以使用MouseAdapter的子类创建的对象做监视器,只需重写需要的接口方法即可。

启动方法

1
2
3
4
5
6
7
8
9
10
11
12
13

public static void main(String[] args) throws Exception
{

JFrame frame=new JFrame();
BirdGame game=new BirdGame();
frame.add(game);
frame.setSize(440,670);
frame.setLocationRelativeTo(null);//设置窗口相对于指定组件的位置。如果组件当前未显示或者 为 null,则此窗口将置于屏幕的中央
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//如果在代码里没加这个方法,那么在点击框架的”叉叉“退出框架后,程序仍然没有退出,只是JFrame被关闭了。
frame.setVisible(true);
game.action();
}

关于Java的setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) 这个方法是JFrame类的一个方法,EXIT_ON_CLOSE是JFrame的一个静态常量。
该方法的翻译大概是“设置默认的关闭操作,参数”在关闭动作时退出“。

Welcome back AM1ng!

2021年07月13日
阅读更多...
404 Oh>..< 我找不到回家的路了
2021年07月12日
阅读更多...

关于实践周的第一个项目选择了制作Flying Birds小游戏,预备知识包括面向对象的封装,swing和awt包,Math类,事件监听器,多线程。

新的需要了解的包

AWT

1
import java.awt.*;

AWT(Abstract Window Toolkit),中文译为抽象窗口工具包,是Java提供的用来建立和设置Java的 图形用户界面 的基本工具。
AWT由Java中的java.awt包提供,里面包含了许多可用来建立与平台无关的图形用户界面(GUI)的类,这些类又被称为组件( component s)。

More info: AWT

Swing

1
import javax.swing.*;

Swing 包含了构建图形界面(GUI)的各种组件,如: 窗口、标签、按钮、文本框等。
Swing 提供了许多比 AWT 更好的屏幕显示元素,使用纯 Java 实现,能够更好的兼容跨平台运行。
为了和AWT组件区别,Swing组件在javax.swing.包下,类名均以 J 开头,例如: JFrame、JLabel、JButton等.

More info: Swing

imageIO

1
import javax.imageio.ImageIO;

Java使用imageio 读写图像,比较常见。读取如Bird的状态,Ground,Column类的图像(这里用已有素材,自己就PS了)

源码分类

1
2
3
4
Birdgame.java //绘制面板,放入背景图 增加鼠标监听器完成对小鸟飞行及游戏运行的控制,设计游戏开始的方法与流程。
Bird.java //设计小鸟,完成飞行轨迹、与柱子是否碰撞的方法等。
Ground.java //设计地面类完成移动的效果(移动方法实现)。
Column.java //设计柱子类完成移动的效果(移动方法实现)。

综上:
面向对象的封装:设计包装出小鸟、地面、柱子、游戏四个类。
swing和awt包:图形界面工具,绘制出游戏场景。
Math类:运用atan等方法辅助完成小鸟旋转角度转换。
事件监听器:运用鼠标监听器完成游戏状态转换及小鸟移动。
多线程:该项目就用到了一个sleep休眠。

Welcome back AM1ng!

2021年07月12日
阅读更多...

Welcome to Hexo! 这是am第一个个人博客.主题自Stun和Sakura系列失败后选择了Dearmsdan,有中文注释并且也相对方便理解。基于Hexo Git Node.js 的搭建
效率方面和文件夹分类管理习惯息息相关。搭建费了不少时间,关于之前项目的Blog之后会连续更新。以下是几Hexo提示到的基本操作。

AM1ng’s Blog!

Create a new post

1
$ hexo new "My New Post"

More info: Writing

Run server

1
$ hexo server

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment

第一篇的Blog内容局限于此,主要遇到的问题在有关blog配置文件的config与选择主题之后主题config里语法使用。
初学建议从找中文标签的主题开始,其实安装git node 和环境变量配置问题按照步骤很简单。

See U next time!

2021年07月09日
阅读更多...