共计 4964 个字符,预计需要花费 13 分钟才能阅读完成。
本章目标
- 增加多个机器坦克
- 让机器坦克动起来
- 让坦克智能起来
一、增加多个机器坦克
目前我的坏营垒的坦克只有一个,是咱们手动创立进去的
然而咱们当初想要玩的过瘾,杀的畅快就要创立多个坦克,也须要应用一个容器治理起来
public class TankClient extends Frame {
// 治理多个坏坦克容器
List<Tank> tanklist = new ArrayList<Tank>();
@Override
public void paint(Graphics g) {
// 省略其余关键性代码....
// 画出容器里的坦克
for (int i = 0; i < tanklist.size();i++){Tank tank = tanklist.get(i);
tank.draw(g);
}
// 画出 好的 坦克
mytank.draw(g);
}
// 定义窗口办法
public void lauchFrame() {
// 省略其余关键性代码....
// 游戏窗口界面创立多个坦克
// 画出容器里的爆炸成果
for (int i = 0; i < 10;i++){tanklist.add(new Tank(50 + 40 * (i+1),50,this,false));
}
}
// 省略其余关键性代码....
}
这时咱们就有十个敌方营垒的坦克了
然而咱们还是要思考一个问题: 咱们发射的子弹怎么打中这些容器里的坦克呢?
class Missle{public boolean hitTank(List<Tank> tankList){for(Tank tank:tankList){if(hitTank(tank)){return true;}
}
return false;
}
// 省略其余关键性代码....
}
咱们在子弹的类里增加对装放坦克汇合类的解决,那么咱们调用也要进行优化
public class TankClient extends Frame {
// 治理多个坏坦克容器
List<Tank> tanklist = new ArrayList<Tank>();
@Override
public void paint(Graphics g) {
// 画出容器里的子弹
for (int i = 0; i < missles.size();i++){Missle m = missles.get(i);
// 由原先敌方坦克的解决
// 批改为对装放一堆坦克的容器解决
m.hitTank(tanklist);
m.draw(g);
}
// 省略其余关键性代码....
}
// 省略其余关键性代码....
}
这时咱们就能够对十个敌方坦克一顿乱杀了,实现苦楚的体验
当咱们击毙敌方坦克时,是不是同样也要与子弹、爆炸成果一样,须要移出容器里?
class Tank{
// 省略其余关键性代码....
// 增加办法实现坦克的绘画
public void draw(Graphics g) {
// 死掉的坦克不必绘制
if(!live){
// 如果是坏营垒的坦克则移出容器里
if(!camp){tc.tanklist.remove(this);}
return;
}
// 省略其余关键性代码....
}
}
步骤总结
- ✧用容器来装敌人的 Tank
- ✧向容器中装入多辆敌人 Tank
- ✧游戏窗口将容器里的坦克画进去
- ✧增加 hitTanks 办法解决打掉容器里的一系列 Tank
- ✧TankClient 外面每发子弹都对坦克容器进行解决
二、让机器坦克动起来
咱们发现这个敌方坦克尽管是进去了,然而他并没有动起来,只是被咱们打而已
那么咱们先考虑一下: 怎么让这些敌方坦克动起来呢?
咱们晓得坦克是不是都有方向?
如果咱们初始时不给予 STOP 方向,而给定其余方向,它能动起来吗?
class Tank{
// 省略其余关键性代码....
// 增加初始坦克时方向的给予
public Tank(int x, int y, TankClient tc, boolean camp, Direction dir) {
this.x = x;
this.y = y;
this.tc = tc;
this.camp = camp;
this.dir = dir;
}
}
咱们在 TankClint 中给予不同的初始方向看看,是否能动起来
public class TankClient extends Frame {
// 营垒:好的坦克初始方向不动
Tank mytank = new Tank(50,50,this,true,Tank.Direction.STOP);
// 定义窗口办法
public void lauchFrame() {
// 营垒坏的坦克初始方向为:下
for (int i = 0; i < 10;i++){tanklist.add(new Tank(50 + 40 * (i+1),50,this,false,Tank.Direction.D));
}
// 省略其余关键性代码....
}
// 省略其余关键性代码....
}
动起来了,然而咱们发现敌方坦克的初始方向为:下后,则始终都是往下
那么咱们能不能让他随机产生一些方向并进行挪动呢?答案: 随机数
class Tank{
// 随机数
private static Random random = new Random();
void move() {
// 针对于坏的坦克咱们进行随机方向挪动
if(!camp){
// 将方向枚举转为数组
Direction[] dirarr = Direction.values();
// 依据八个方向产生一个随机方向进去
int rn = random.nextInt(dirarr.length);
dir = dirarr[rn];
}
// 省略其余关键性代码....
}
// 省略其余关键性代码....
}
这时咱们运行起游戏窗口就能够发现,敌方坦克曾经能够依据随机方向动起来了
步骤总结
- ✧让敌军坦克动起来:构造函数中能够指定方向
- ✧游戏窗口 new 敌军坦克的时候指定敌军坦克的方向
- ✧让敌军坦克向随机方向挪动
- ✧(Tank) 类增加动态的随机数产生器 java.util.Random
- ✧将方向枚举转为数组 Direction. values()
- ✧在 move 实现后如果是敌军坦克的,随机产生一个数来设定坦克下一个方向
坦克是曾经动起来了,然而咱们须要思考一下: 怎么让它动的更加智能?
三、让坦克智能起来
咱们目前的坦克尽管动起来了,然而挪动的范畴比拟小,像个蚂蚁转来转去
那么咱们能够让它先朝一个方向挪动一段距离再批改方向会不会好点呢?
class Tank{
// 定义变量随便挪动的步数
// 最小值挪动三步,最大值挪动 14 步
private int randowStep = random.nextInt(12) + 3;
void move() {
// 针对于坏的坦克咱们进行随机方向挪动
if(!camp){
// 将方向枚举转为数组
Direction[] dirarr = Direction.values();
// 当挪动间隔完后从新调整方向继续移动
if (randowStep == 0){randowStep = random.nextInt(12) + 3;
// 依据八个方向产生一个随机方向进去
int rn = random.nextInt(dirarr.length);
dir = dirarr[rn];
}
// 一直的挪动间隔
randowStep --;
}
// 省略其余关键性代码....
}
// 省略其余关键性代码....
}
这时咱们在运行起来就发现,敌方坦克挪动的范畴更加的大了
当初敌方坦克是会动了,然而还不会发射炮弹,那么咱们怎么让他发射炮弹呢?
这时可能有小伙伴就会说,那我间接 fire 停火不就行了吗?实际一起看看
class Tank{void move() {
// 针对于坏的坦克咱们进行随机方向挪动
if(!camp){
// 省略其余关键性代码....
// 实现停火
this.fire();}
// 省略其余关键性代码....
}
// 省略其余关键性代码....
}
运气来咱们就会发现,这时敌方坦克发射炮弹就碰撞到本人造成灭亡了
所以咱们须要对子弹也要做一个营垒的辨别
class Missle{
// 辨别子弹的营垒
private boolean camp = true;
// 坦克发射子弹的时候增加营垒身份
public Missle(int x, int y, Tank.Direction dir, TankClient tc, boolean camp) {
this.x = x;
this.y = y;
this.dir = dir;
this.tc = tc;
this.camp = camp;
}
}
当坦克发射子弹时携带营垒标识,并且碰撞的解决为对异营垒进行解决
class Tank{
// 坦克发射子弹.....
public Missle fire(){
// 省略其余关键性代码....
// 坦克发射炮弹的时候,携带本人的营垒标识
Missle missle =new Missle(x,y,ptdir,tc,camp);
tc.missles.add(missle);
return missle;
}
// 省略其余关键性代码....
}
class Missle{public boolean hitTank(Tank t){if(t.isLive() && this.getRect().intersects(t.getRect()) && this.camp != t.isCamp()){t.setLive(false);
this.live = false;
// 爆炸成果产生在与子弹产生碰撞的中央
Explode e = new Explode(x,y,tc);
tc.explods.add(e);
return true;
}
return false;
}
// 省略其余关键性代码....
}
这时咱们运行游戏窗口,就不会对同营垒造成挫伤了
然而这时咱们的敌方营垒的子弹太猛了,咱们有没有什么办法缩小一点? 答案是: 随机数
class Tank{
// 坦克发射子弹.....
void move() {
// 针对于坏的坦克咱们进行随机方向挪动
if(!camp){
// 省略其余关键性代码....
// 如果生成的随机大于 38 才发射子弹
if(random.nextInt(40) > 38 ){
// 实现停火
this.fire();}
}
}
// 省略其余关键性代码....
}
这时敌方坦克的子弹就没有这么剧烈了,然而有个问题: 咱们怎么是无敌状态?
咱们怎么让敌方营垒打到咱们,而后打中后怎么也跟着沦亡呢?
public class TankClient extends Frame {
@Override
public void paint(Graphics g) {g.drawString("missiles count:" + missles.size()+"",10,50);
// 画出容器里的子弹
for (int i = 0; i < missles.size();i++){Missle m = missles.get(i);
// 将营垒坏的坦克放进来进行碰撞
m.hitTank(tanklist);
// 将咱们本人的坦克也放进来进行碰撞
m.hitTank(mytank);
m.draw(g);
}
// 省略其余关键性代码....
}
// 省略其余关键性代码....
}
这时当敌方坦克击中咱们的时候,咱们也跟着进行沦亡了
同时当咱们的坦克沦亡后,就不用进行发生爆炸成果与发射子弹了
class Tank{
// 坦克发射子弹.....
public Missle fire(){
// 如果坦克沦亡了不用发射子弹
if(!live){return null;}
// 省略其余关键性代码....
}
// 省略其余关键性代码....
}
class Missle{public boolean hitTank(Tank t){
// 要求:指标坦克是活的、不同营垒的、子弹与坦克碰撞一块
if(t.isLive() && t.isLive() && this.getRect().intersects(t.getRect()) && this.camp != t.isCamp()){t.setLive(false);
this.live = false;
// 爆炸成果产生在与子弹产生碰撞的中央
Explode e = new Explode(x,y,tc);
tc.explods.add(e);
return true;
}
return false;
}
// 省略其余关键性代码....
}
步骤总结
让敌军坦克发射炮弹:
- ✧本军炮弹不打本军
- ✧炮弹增加好坏 bGood, 依据好坏画不同色彩
- ✧批改炮弹的构造方法
- ✧批改 Tank 的 fire 办法
- ✧批改 hitTank 办法,好不能打好,坏不能打坏
- ✧敌军炮火不能太剧烈
参考资料
尚学堂:坦克大战(马士兵老师)