飞机的java_Java版飞机游戏

先贴游戏图。

20b81a4ecc55b294c6171959e1054504.gif

......................................跳过.........................................

时间加起来也算是用了一天的时间,碰碰撞撞,修修补补终于是把这个游戏给做完了,虽然不完美,也还有bug,不过对自己而言,也算是不错的了。

在之前,自己一直觉得这游戏真的挺麻烦的,所以在动手自己开始做前,还一直在网上找相关视频借鉴借鉴,然而却没有,所以没办法只能自己动手。真正的开始敲下第一行代码时,思路却都已经出现在脑海中,然后一发不可收拾,用一个下午的时间把基本功能都给做完了,然后晚上边玩,边修复一些小的bug,第二天早上把排行榜给做了。

现在回过头来看,不扯这个小游戏,我发现我一直都在小看自己,总是在做某件事前,就给自己打上了有可能不成功的标签,又觉得事情很难。在真正开始做时,好多时候事情真的很简单,只是自己对这一方面的内容不熟悉而已。

自己害怕失败吧...真的,一个年轻人还没开始做事之前就退却了,真是不可理喻啊。慢慢来吧,现在还有时间,趁自己还有可以犯错的资本时,多尝试尝试总是好事。

.......................................分割线......................................

我把所有的图都画在了JLabel上,然后再在面板上显示,看起来很方便,但缺点也是很明显,就是不管是我方飞机,还是敌方飞机,还是子弹,在移动起来,总是一卡一卡的,不流畅,可自己又想不出好的法子了,只能这样做下去。

讲一些重要的代码,不然会显得很繁琐,例如继承了JLabel的MyPlane类,Bullet类就不贴了,一些没必要的注释或者调试的输出就不删了。

GameFrame类实现了KeyListener接口,为的是可以直接操作我方飞机的移动,因为我方飞机的JLabel是直接加载这个上面的。移动键为WSAD,然后对活动范围也加了一些限制,总不能移动到可见界面外去了是吧。

@Override

public void keyTyped(KeyEvent e) {

//获得飞机位置

int x = myplane.getX();

int y = myplane.getY();

//每次移动大小

int speed = 10;

//根据不同指令执行命令

if (e.getKeyChar() == 'W' || e.getKeyChar() == 'w') { // 上移

y -= speed;

} else if (e.getKeyChar() == 'S' || e.getKeyChar() == 's') { // 下移

y += speed;

} else if (e.getKeyChar() == 'A' || e.getKeyChar() == 'a') { // 左移

x -= speed;

} else if (e.getKeyChar() == 'D' || e.getKeyChar() == 'd') { // 右移

x += speed;

}

//设置活动范围

if (x > -5 && x < Constant.WIDTH - 65 && y > 0

&& y < Constant.HEIGHT - 110) {

myplane.setLocation(x, y);

}

// repaint();

}

而对于子弹而言,肯定是伴随着飞机发射的,所以出现的位置肯定是跟飞机位置相关,并且是自动发射,不要用户控制,直接开启个线程,可能因为图片的原因,所以需要对位置稍微进行小的偏移修改。

// 开启子弹线程

private void launch() {

new Thread() {

@Override

public void run() {

//如果为true,则启动线程,否则关闭

while (flagBullet) {

// 给出现时的坐标加上一个值,调整位置

//以飞机坐标为参数,生成一个子弹对象

Bullet bullet = new Bullet(myplane.getX() + 30,

myplane.getY() + 30, GameFrame.this);

// 将子弹加入面板

panel.add(bullet);

// 添加进子弹列表

GameList.bulletList.add(bullet);

// 开始行动

new Thread(bullet).start();

// 每隔300毫秒发射一颗子弹

try {

Thread.sleep(300);

} catch (Exception e) {

e.printStackTrace();

}

}

}

}.start();

}

而对于敌机,则是随机出现的,当然,也不是可以出现在任意位置,而是固定了几个位置,然后随机的。也给限制了数量,面板最多一次可见多少个,然后没隔10秒增加一个,如果达到上限,则不会新出现飞机。

/*

* 启动敌机线程

*/

private void otherPlane() {

new Thread() {

@Override

public void run() {

//获得第一次出现敌机的时间

long firstTime = System.currentTimeMillis();

//一次最多存在number数量的敌机

int number = 5;

while (flagPlane) {

//获得当前时间

long currentTime = System.currentTimeMillis();

//每10秒多增加一架可以在界面上显示的敌机

if(currentTime - firstTime > 10000){

number ++;

//交换数据

firstTime = currentTime;

}

//System.out.println("OtherPlane's number is : "

//+ GameList.planeList.size());

int size = GameList.planeList.size();

//如果list中的敌机数量小于总共可以在界面上显示的,则创建对象

if (size <= number) {

OtherPlane otherPlane = new OtherPlane(GameFrame.this);

//需要把该对象放到面板中去显示

panel.add(otherPlane);

//加入list

GameList.planeList.add(otherPlane);

//启动,可以活动

new Thread(otherPlane).start();

//没500毫秒生成一个

try {

Thread.sleep(500);

} catch (Exception e) {

e.printStackTrace();

}

}

}

}

}.start();

}

从上面的代码中可以都可以看到一个GameList类,这个类我是为了操作方便而写的,其实肯定是不符合规范的。在里面实现了一些方法,例如子弹打到了敌机,或者敌机与我方飞机碰到了等等。

下面这个方法就是子弹打到了敌机,然后子弹和敌机都消失,但当时在写这个的时候,出现了很多问题,其中最严重的是当子弹和敌机都消失后,我方飞机还是会被本该消失的飞机碰到,调试了好久才发现,虽然敌机从面板上和list中都移除了,但他的线程仍然存在,也就是说我们只是看不到他了,但还是活着的,所以需要把对应的线程结束掉才行。

//停止相碰的子弹和敌机的线程

op.setFlag(false);

bullet.setFlag(false);

// 判断子弹是否与敌机有接触

public static void intersectsBullet(Bullet bullet, GameFrame gameFrame) {

// 创建子弹的矩形

Rectangle bulletRect = new Rectangle(bullet.getX(), bullet.getY(),

bullet.getWidth(), bullet.getHeight());

for (int i = 0; i < planeList.size(); i++) {

// 创建每一个敌机的矩形,逐一进行判断

OtherPlane op = planeList.get(i);

Rectangle planeRect = new Rectangle(op.getX(), op.getY(),

op.getWidth(), op.getHeight());

// 如果两个矩形相交

if (bulletRect.intersects(planeRect)) {

//分数+1

Score.score ++;

//停止相碰的子弹和敌机的线程

op.setFlag(false);

bullet.setFlag(false);

// 从面板中移除掉敌机和子弹

gameFrame.remove(op);

gameFrame.remove(bullet);

// 从list中移除两个对象

bulletList.remove(bullet);

planeList.remove(op);

// 刷新界面

gameFrame.repaint();

}

}

}

从上面的代码可以看出,我判断是否产生接触用的是Rectangle类中的intersects方法,这个方法的意思是判断两个矩形是否相交,所以需要把需要判断的两个对象提取相应的位置,宽,高出来。但问题是,他们的宽和高都是根据图片设置的,所以在碰撞这个问题是,会有点小bug。

结束游戏有两种方式,一种是地方飞机与我方飞机发生了碰撞

//判断敌机和我方飞机是否相撞

public static void intersectsPlane(OtherPlane op, GameFrame gameFrame) {

//创建我方飞机矩形

MyPlane myplane = gameFrame.getMyPlane();

Rectangle myRect = new Rectangle(myplane.getX(), myplane.getY(),

myplane.getWidth(), myplane.getHeight());

//敌方飞机矩形

Rectangle opRect = new Rectangle(op.getX(), op.getY(), op.getWidth(),

op.getHeight());

//如果矩形相交,则发生碰撞,游戏结束

if (opRect.intersects(myRect)) {

gameFrame.remove(op);

gameFrame.remove(myplane);

op.setFlag(false);

//游戏结束

gameOver(gameFrame);

}

}

例外一种是时间到了,在另外一个类中,就是判断倒计时是否归0了。他们都需要共同的代码,需要提取出来,封装成一个方法了。

结束掉所有的线程,并且清除所有的数据,注意的是,也要把我方飞机的数据置null才行。

public static void gameOver(GameFrame gameFrame){

//清除我方飞机数据

gameFrame.setMyPlane(null);

// 终止生成子弹和生成敌机的循环

gameFrame.setFlagBullet(false);

gameFrame.setFlagPlane(false);

//停止时间分数线程

Score.flag = false;

// 清空list

bulletList.clear();

planeList.clear();

//对话框要出现在清理数据之后

String name = JOptionPane.showInputDialog("游戏结束,请输入你的大名:");

Recorder recorder = new Recorder();

recorder.write(name, Score.score);

// 关闭界面

gameFrame.dispose();

// 打开主界面

new MainFrame();

}

因为也同时写了排行榜,所以在游戏结束时,会弹出一个对话框,提示游戏结束,并且输入自己的姓名。而数据会写入到xml文件中,xml文件解析用的是dom方法,很惭愧的是,才学了没多久,竟然就忘了差不多了,还需要翻看笔记才能想起。

写起来没逻辑,整个程序放在了附件,有需要的朋友可以下载,如果有什么好的建议或不足,谢谢在评论中提出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值