2022/3/13
这周都在忙着做游戏,真是一波三折啊,总体感觉就是各种子类继承父类,继承方法,各种方法各种调,稍一疏忽关系就乱了。所以我就稍微整理下整个游戏的思路,先看下游戏截图。
感人的极简艺术风又彰显着些许粗糙呆呆的游戏界面,还有这堪比“3A”大作的超高画质(我承认我撒谎了)
只需按1/2键就可以轻松实现模式切换,简单而又纯粹,拥有着超强的人机交互体验。。。
游戏开始界面来啊,驾驶着小时候的坦克,让我们在这风起云涌的战场上尽情驰骋,“哒哒哒。。。”。虽然队友已经阵亡,但我还是要继续战斗,fire!
游戏战斗界面按一下p键实现游戏暂停,拒绝繁琐,摆脱“ESC”的传统制约束缚,我的游戏我做主(因为ESC按键暂停进入菜单,然后退出,流程过于麻烦,取消了这种机制(实际上是自己技术有限。。。。))
刚才中弹身亡,又重开了一局,我的战友回来了。确实一个人控制两个坦克操作有点累。
游戏思路
1 创建窗口(需要继承Jframe类,这样才能创建窗口,实现监听鼠标键盘事件)
创建GanmePanel类继承JFrame类,创建launch方法初始化窗口信息
2 为背景上色
创建paint方法(它继承于JFrame类,可以添加图片,文字)
3 为窗口启动页添加文字
4 为窗口添加键盘事件 (此事件的前提是需要继承JFrame类或者含有JFrame类才能获得点击事件)
5 键盘控制指针图片移动选择游戏模式
1 定义指针图片select
2 定义y为指针初始坐标
3 paint方法里绘制指针
4 添加游戏模式变量state 1为单人,2为双人
5 在paint方法里添加if语句判断state=0时打印启动页文字,state=1/2时打印相应模式
6 在键盘监视器中添加键盘事件,新建变量a ,将a的值赋值给state,实现1/2选择模式,enter进入相应模式
6 定义双缓存图片(定义空图片,然后把所有组件绘制道空图片上,再一次性绘制到主窗口中)
1 定义双缓存图片offScreenImage为null
2 在paint方法中绘制和游戏窗口大小一样的图片,获取gImage图片的画笔,把之前的画笔g全部改为gImage图片,实现所有元素绘制到图片上
3 将缓冲区绘制好哦的图片整个绘制到容器的画布中
7 创建游戏父类GameObject
1 添加变量:图片,坐标,界面gamePanel
2 构造父类函数,转换参数图片的类型
3 添加paintSelf方法,可以把自身绘制出来,参数是画布
4 添加获取矩形的方法,来判断游戏元素是否相交(如为了检测坦克和子弹有无碰撞)
8 创建游戏子类Tank继承游戏父类
1 添加变量:尺寸,速度,方向,坦克四个方向的图片
2 构造子类函数,继承父类元素
3 继承父类的paintSelf方法和获取元素矩形getRec方法
9 添加坦克玩家1类继承坦克类
1 添加构造函数以及继承方法
2 绘制玩家一,1把玩家一四个方向图片添加到image文件夹里,2在游戏主类中定义玩家一,3在paint方法里游戏开始状态下绘制出玩家一:PlayOne.paintSelf(gImage);
10 键盘控制坦克移动(需要改变变量坐标和方向)
1 在坦克类中添加向四个方向移动的方法(leftward(),),添加setImage()方法
2 在playerOne()类中添加键盘按下方法和键盘松开方法,实现按下哪个方向键,方向赋值为true,来实现坦克移动。松开按键,赋值为false,停止移动
3 在gamePanel类中调用以上两个方法,在键盘监视器中default中添加playOne键盘事件
11 编写子弹类Bullet继承游戏父类
1 定义变量尺寸,速度,方向
2 构造函数,继承父类paintSelf和getRec方法
3 编写子弹四个方向移动的方法(leftWard())
4 编写go方法,用switch判断direction的值来调用相应的方法
5 把go方法放入paintSelf方法中,这样在绘制子弹的过程中就可以调用这个方法移动子弹
12 发射并绘制子弹
1在坦克类中添加发射方法attack
2在坦克类中添加获取坦克头部的坐标getHeadPoint()
3在attack方法中初始化子弹
4 绘制子弹 在游戏主类中添加元素列表中添加一个子弹列表
在坦克类中的attack方法中把初始化的新子弹添加到子弹列表中
在游戏主类中的paint方法中循环子弹列表,绘制每一个子弹列表中的元素
5 添加键盘事件
在playOne类中keyPress中添加空格键盘事件,就会调用射击方法
13 设置子弹发射间隔时间(新建一个线程计算射击冷却时间)
在坦克类中新建变量攻击冷却状态attackCoolDown和攻击冷却时间毫秒间隔时间
添加线程,创建内部类,继承Thread类。在类中添加run方法(先将攻击状态设置为冷却false,再让线程休眠一秒,然后解除冷却为true,再终止线程)
把线程添加到attack方法进行启动
14 绘制敌方坦克并批量添加
1 新建敌方坦克类 Bot继承坦克类
2 和玩家一一样继承构造函数和继承方法
3 把敌方坦克图片添加到image文件夹
4 再游戏主类中定义敌方坦克变量
5 在paint方法中绘制变量
6批量生成敌方坦克
1在主类中添加敌方坦克Bot列表
2 在while循环里批量添加
3 为了控制添加敌方坦克的速度,定义count来表示画布重绘次数
4在游戏开始时,也就是state=1/2时,每重绘一次画布count+1。在while语句中判断count条件(画布每重绘100次,就生成一个坦克)
5 为了控制敌人数量,新建变量enemyCount来计算已生成敌方坦克数量,每生成一个enemyCount++,在while语句中加入判断条件enemyCount大于10就不再生成
6 为了随机位置生成敌方坦克,定义random变量
7 在paint方法中用for循环遍历坦克列表,把里面的元素都绘制一边
15 敌方坦克随机移动
1 在敌方坦克类建造一个随机获取方向的方法getRandomDirection(),根据随机数值判断返回的方向
2 定时改变方向 在敌方坦克Bot类中新建变量movetime记录坦克移动次数,在go方法中用switch判断如果次数超过20,就用随机数改变坦克方向。未超过20,moveTime+1
16 敌方坦克随机射击
1 新建一个敌方子弹ennmyBullet类继承子弹类,写出构造函数和继承方法
2 在继承方法paintSelf中调用go方法
3 在敌方坦克类中添加attack方法,先获取坦克头部纵坐标,然后用random随机一个0-100之间的数,如果小于4就发射子弹
4 发射子弹,新建一个敌方子弹变量,并添加到子弹列表中
5 在image文件夹中添加黄色子弹图片作为敌方子弹
6 在敌方坦克类中把attack方法添加到go方法中
17 子弹与坦克碰撞检测(碰撞检测顾名思义,就是检测两个物体是否碰撞
检测方法我们用到的是。把两个物体当作矩形。
在他们移动过程中调用intersects方法判断两个矩形是否相交,如果是证明被碰撞到了
检测完成后,还要考虑后续。比如碰撞后运动状态怎么改变,碰撞后是否还存在。
如果碰撞后消逝,就把他从paint遍历中去掉,他就不能重绘了 )
1新建remove子弹列表,先将要删除的子弹添加到该列表
2 在子弹类中创建hitBot()子弹撞击敌方坦克检测方法
3 把方法添加到paintSelf()方法中
4 敌方子弹撞击我方坦克检测方法
1 添加玩家坦克列表
2 在主类中键盘检测中的按enter时添加玩家一
3 在paint方法中绘制坦克玩家
4 在敌方子弹类中添加敌方子弹撞击我方坦克检测方法hitPlayer(),然后把这个方法添加到paintSelf()中
18 添加围墙类继承游戏父类
1 添加构造函数和构造方法,变量尺寸
2 在主类中添加围墙列表,在paint方法中添加绘制围墙列表中的函数
3 在launch方法中添加围墙,把围墙图片添加到image文件夹
19 添加子弹击中围墙检测
1 在子弹类中添加hitWall()方法
2 把hitWall()添加到go()方法
20 添加坦克与围墙碰撞检测(先检测坦克下一步将要移动的坐标与墙体的坐标,再移动坦克)
1 在坦克类中添加坦克与墙体碰撞检测方法
2 在向四个方向移动的方法中,给坦克添加移动条件
21 添加坦克与围墙边缘碰撞检测
1 在坦克类中创建moveToBorder()方法,如果坦克边缘坐标越界则返回false,否则为true
2 再给坦克移动方法添加条件
22 添加子弹越界删除方法
1 再子弹类中创建moveToBorder():判断子弹坐标是否越界,是则删除子弹
23 添加基地,并添加子弹与基地碰撞检测功能
1 创建基地类Base继承游戏父类 ,构造函数, 继承方法 ,
2 再主类中添加基地列表,再paint()方法中绘制基地元素
3 添加基地,初始化基地对象 ,导入基地图片
4 再launch()中添加基地
5 再子弹类中添加hitBase()方法,然后把该方法添加到go()
24 游戏规则
1 游戏胜利(当游戏开始state=0,敌方坦克生成10个后,state改为5,游戏胜利)
再主类while(true)中添加判定游戏胜利条件,并添加绘制游戏胜利的条件
2 游戏失败(我方坦克列表为0或者基地被摧毁,state改为4,游戏失败)
在while(true)中添加游戏失败判定条件,并绘制游戏失败
25 绘制爆炸特效
1 导入爆炸特效图片
2 创建爆炸类Blast 游戏父类,构造函数,继承方法
3 添加变量,先添加爆炸图集
4 通过遍历的方法在爆炸数组里面添加爆炸图片,然后再paintSelf()绘制爆炸
5 在游戏界面GamePanel类中绘制出来爆炸
1 首先添加爆炸元素列表
2 在paint()中绘制爆炸列表中的元素
3 分别在玩家子弹撞击敌方坦克检测中和敌方坦克子弹撞击玩家坦克检测中添加爆炸位置
26 1 修改游戏界面开始的文字 2添加记录敌方剩余坦克数量的功能(敌方剩余坦克数量为坦克列表的长度)
if(state == 0)
//添加文字
gImage.drawString("选择游戏模式", 220, 100);
gImage.drawString("单人模式",220,200);
gImage.drawString("双人模式",
220,
300);
//绘制指针
gImage.drawImage(select,
160,
y ,
null);
//state ==
0/1,
游戏开始
eLse if(state == 1 ll
state == 2) {
首先删除以下代码,然后重新设置字体,添加剩余坦克数量的文字
gImage.drawString("游戏开始",220,
, 100);
if(state ==
1)
{
gImage.drawString("单人模式",
220,
200);
}
eLse
☑
YT
gImage.drawString("双人模式",220,200);
27 添加游戏玩家2
1 首先创建玩家2类,玩家1和2的方法都是一样的,然后把玩家1类中所有内容复制到2 2 然后只需要修改键盘事件,把wasd改成上下左右,攻击键由空格改为k键
3 然后在游戏主类中添加游戏玩家2 4 然后把玩家2图片移动到文件夹里,然后修改玩家2坐标 5在双人模式中把坦克2添加到坦克列表里,添加游戏玩家2 6
6 添加玩家2键盘事件
28 为玩家2添加生命(27的时候玩家二被击中,坦克虽然消逝,但仍可以发射子弹。因为只是把坦克2从坦克列表中删除,但键盘事件中的按键仍然可以使用)
1 在坦克类新建布尔变量用来判断玩家二是否存活 2 在射击attack方法中添加射击条件 3 主类中将的双人模式条件下,将坦克1/2改为变量alive改为true。在敌方子弹类子弹碰撞检测中将alive设置为false