Java之详解坦克大战游戏(四)
来源:互联网 发布:php计算九九加法表 编辑:程序博客网 时间:2024/06/06 04:07
目前我们的坦克能发子弹,但是只能发一颗,而且打到敌人坦克敌人还不会消失,本篇我们就来解决这个问题…子弹要想做到连发,就得初始化多个子弹,这个时候我们仍然还是跟定义敌人的坦克组一样用Vector集合..
class Hero extends Tank{ //子弹 Vector<Shot> ss = new Vector<Shot>(); //Vector集合 Shot s = null; //... //开火 public void shotEnemy() { switch (this.direct) //子弹的方向 {//s只是代号而已,指向谁就谁,不要理解它是同一颗子弹 case 0: //创建一颗子弹(下同) s=new Shot(x+10, y,0); //把子弹加入向量(下同) ss.add(s); break; case 1: s=new Shot(x+30,y+10,1); ss.add(s); break; case 2: s=new Shot(x+10,y+30,2); ss.add(s); break; case 3: s=new Shot(x,y+10,3); ss.add(s); break; } //启动子弹线程 Thread t = new Thread(s); t.start(); }
在到MyPanel类修改和添加代码
public void paint(Graphics g) { super.paint(g); g.fillRect(0, 0, 1200, 900); //填充使背景变为黑色 //从ss中取出每颗子弹,并画出 for(int i=0;i<hero.ss.size();i++) { Shot myShot = hero.ss.get(i); //画出一颗子弹 if(myShot!=null && myShot.isLive == true) { g.setColor(Color.yellow); g.draw3DRect(myShot.x, myShot.y, 1, 1, false); } if(myShot.isLive==false) //子弹死亡(下面将用到) { //从ss中删除该子弹 hero.ss.remove(myShot); } }
随着代码越写越多,可能我们会觉得很乱,这时看Eclipse编写代码页面右边有个Outline
点一下就跳到我们要的类或方法了,比较容易看..
这时,子弹已经可以连发了..不过,打得还真是没有限制哦,无限连发,游戏都没难度了。所以,我们还是来设置一下连发限制吧..
public void keyPressed(KeyEvent e) { //....... //判断玩家是否按下j键 if(e.getKeyCode() == KeyEvent.VK_J) { if(this.hero.ss.size()<=4)//最多连发5颗子弹 {//为什么是<=4?因为进入shotEnemy后才由集合里面个数才由0变为1 //开火 this.hero.shotEnemy(); } }}
这样最多能发五颗了,什么叫连发呢?上面paint方法有个子弹死亡的处理,也就是子弹打出后飞出界了或打到敌人坦克就算死亡,那么,接下来就要让敌人坦克碰到我们的子弹就消失吧..
这里我们写一个函数专门判断子弹是否会击中敌人坦克,先到Members.java文件中EnemyTank类添加一个变量isLive用于判断坦克的死活
boolean isLive=true;
//写一个函数专门判断子弹是否会击中敌人坦克 public void hitTank(Shot s,EnemyTank et) { //判断该坦克的方向 switch (et.direct) { //如果敌人坦克方向是上或是下 case 0: case 2: //根据子弹坐标和敌人坦克坐标确定是否子弹到敌人坦克范围(可以测试看看) if(s.x<et.x && s.x<et.x+20 && s.y>et.y && s.y<et.y+30) { //击中 //子弹死亡 s.isLive=false; //敌人坦克死亡 et.isLive=false; } break; //向左或向右 case 1: case 3: if(s.x>et.x && s.x<et.x+30 && s.y>et.y && s.y<et.y+20) { //击中 //子弹死亡 s.isLive=false; //敌人坦克死亡 et.isLive=false; } break; } }
接下来我们到TankGame3.java文件的run方法里面调用
public void run() { //每隔100毫秒来重绘 while(true) { try { Thread.sleep(100); } catch (Exception e) { // TODO: handle exception } //判断是否击中 for(int i=0;i<hero.ss.size();i++) { //取出子弹 Shot myShot=hero.ss.get(i); //判断子弹是否有效 if(myShot.isLive) { //取出每个坦克,与它判断 for(int j=0;j<ets.size();j++) { //取出坦克 EnemyTank et = ets.get(j); if(et.isLive) { this.hitTank(myShot, et); } } } } //重绘 this.repaint(); } }
这个时候就可以让敌人坦克消失了,效果如图:
下篇讲如何让敌人坦克自由移动和打子弹,最后,附上此篇源代码
TankGame3.java
package com.TankGame3;import javax.swing.*;import java.awt.*;import java.awt.event.KeyEvent;import java.awt.event.KeyListener;import java.util.Vector;/* * * */public class TankGame3 extends JFrame{ MyPanel mp =null; public static void main(String[] args) { TankGame3 tankgame3 = new TankGame3(); } public TankGame3() { mp=new MyPanel(); Thread t = new Thread(mp); t.start(); this.addKeyListener(mp);//注册监听 this.setVisible(true); this.setSize(400, 300); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.add(mp); }}//我的面板class MyPanel extends Panel implements KeyListener,Runnable{//子弹要看到,要不停的重绘,paint函数每隔段时间久更新,重绘是在paint函数发生的,所以MyPanel要实现Runnable接口 //定义一个我的坦克 Hero hero =null; //敌人的坦克组 Vector<EnemyTank> ets = new Vector<EnemyTank>(); int enSize=3; //敌人坦克初始数量 public MyPanel() { hero =new Hero(100,100); //坦克的初始位置(10,10) //初始化敌人的坦克 for(int i=0;i<enSize;i++) { //创建一辆敌人的坦克对象 EnemyTank et =new EnemyTank((i+1)*50,0); et.setColor(0); et.setDirect(2); //加入 ets.add(et); } } //重新paint public void paint(Graphics g) { super.paint(g); g.fillRect(0, 0, 1200, 900); //填充使背景变为黑色 //从ss中取出每颗子弹,并画出 for(int i=0;i<hero.ss.size();i++) { Shot myShot = hero.ss.get(i); //画出一颗子弹 if(myShot!=null && myShot.isLive == true) { g.setColor(Color.yellow); g.draw3DRect(myShot.x, myShot.y, 1, 1, false); } if(myShot.isLive==false) { //从ss中删除该子弹 hero.ss.remove(myShot); } } //画出自己的坦克 this.drawTank(hero.getX(), hero.getY(), g, this.hero.direct, 1); //画出敌人的坦克 for(int i=0;i<ets.size();i++) { EnemyTank et =ets.get(i); if(et.isLive) { this.drawTank(et.getX(), et.getY(), g, et.getDirect(), 0); } } } //写一个函数专门判断子弹是否会击中敌人坦克 public void hitTank(Shot s,EnemyTank et) { //判断该坦克的方向 switch (et.direct) { //如果敌人坦克方向是上或是下 case 0: case 2: if(s.x>et.x && s.x<et.x+20 && s.y>et.y && s.y<et.y+30) { //击中 //子弹死亡 s.isLive=false; //敌人坦克死亡 et.isLive=false; } case 1: case 3: if(s.x>et.x && s.x<et.x+30 && s.y>et.y && s.y<et.y+20) { //击中 //子弹死亡 s.isLive=false; //敌人坦克死亡 et.isLive=false; } } } //画出坦克的函数 public void drawTank(int x,int y,Graphics g,int direct,int type) { switch(type)//判断是什么类型的坦克 { case 0: g.setColor(Color.cyan); break; case 1: g.setColor(Color.yellow); break; } //判断方向 switch(direct) { //向上 case 0: //画出我的坦克(到时再封装成一个函数) //1.画出左边的矩形 g.fill3DRect(x, y, 5, 30,false); //2.画出右边矩形 g.fill3DRect(x+15, y, 5, 30,false); //3.画出中间矩形 g.fill3DRect(x+5, y+5, 10, 20,false); //4.画出圆形 g.fillOval(x+5, y+10, 10, 10); //5.画直线 g.drawLine(x+10, y+15, x+10, y); break; case 1://炮筒向右 //画出上面矩形 g.fill3DRect(x, y, 30, 5,false); //2.画出右边矩形 g.fill3DRect(x, y+15, 30, 5,false); //3.画出中间矩形 g.fill3DRect(x+5, y+5, 20, 10,false); //4.画出圆形 g.fillOval(x+10, y+5, 10, 10); //5.画直线 g.drawLine(x+15, y+10, x+30, y+10); break; case 2://炮筒向下 //画出上面矩形 g.fill3DRect(x, y, 5, 30,false); //2.画出右边矩形 g.fill3DRect(x+15, y, 5, 30,false); //3.画出中间矩形 g.fill3DRect(x+5, y+5, 10, 20,false); //4.画出圆形 g.fillOval(x+5, y+10, 10, 10); //5.画直线 g.drawLine(x+10, y+15, x+10, y+30); break; case 3://炮筒向左 //画出上面矩形 g.fill3DRect(x, y, 30, 5,false); //2.画出右边矩形 g.fill3DRect(x, y+15, 30, 5,false); //3.画出中间矩形 g.fill3DRect(x+5, y+5, 20, 10,false); //4.画出圆形 g.fillOval(x+10, y+5, 10, 10); //5.画直线 g.drawLine(x+15, y+10, x, y+10); break; } }/*实现KeyListener接口的方法*/ //键入某个键时调用此方法。 public void keyTyped(KeyEvent e) { } //释放某个键时调用此方法 public void keyReleased(KeyEvent e) { } //按下某个键时调用此方法: a代表向左,w代表向上,d代表向右,s代表向下 public void keyPressed(KeyEvent e) { if(e.getKeyCode() == KeyEvent.VK_W)//向上 { this.hero.setDirect(0); this.hero.moveUp(); } else if(e.getKeyCode() == KeyEvent.VK_D)//向右 { this.hero.setDirect(1); this.hero.moveRight(); } else if(e.getKeyCode() == KeyEvent.VK_S)//向下 { this.hero.setDirect(2); this.hero.moveDown(); } else if(e.getKeyCode() == KeyEvent.VK_A)//向左 { this.hero.setDirect(3); this.hero.moveLeft(); } //判断玩家是否按下j键 if(e.getKeyCode() == KeyEvent.VK_J) { //开火 if(this.hero.ss.size()<=4) //子弹最多连发5颗 { this.hero.shotEnemy(); } } this.repaint();//调用repaint()函数,来重绘页面 } public void run() { //每隔100毫秒来重绘 while(true) { try { Thread.sleep(100); } catch (Exception e) { // TODO: handle exception } //判断是否击中 for(int i=0;i<hero.ss.size();i++) { //取出子弹 Shot myShot=hero.ss.get(i); //判断子弹是否有效 if(myShot.isLive) { //取出每个坦克,与它判断 for(int j=0;j<ets.size();j++) { //取出坦克 EnemyTank et = ets.get(j); if(et.isLive) { this.hitTank(myShot, et); } } } } //重绘 this.repaint(); } }}
Members.java
package com.TankGame3;import java.util.Vector;//坦克类class Tank{ //表示坦克的横坐标 int x=0; //表示坦克的纵坐标 int y=0; //坦克方向 //0表示上,1表示右,2表示下,3表示左 int direct=0; int color;//坦克的颜色 public int getColor() { return color; } public void setColor(int color) { this.color = color; } public int getDirect() { return direct; } public void setDirect(int derect) { this.direct = derect; } //坦克速度 int speed=1; public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } public Tank(int x,int y) { this.x=x; this.y=y; }}//敌人的坦克class EnemyTank extends Tank{ boolean isLive=true; public EnemyTank(int x, int y) { super(x, y); }}//我的坦克class Hero extends Tank{ //子弹 //Shot s = null; Vector<Shot> ss = new Vector<Shot>(); Shot s=null; public Hero(int x,int y) { super(x,y); } //开火 public void shotEnemy() { switch (this.direct) //子弹的方向 {//s只是代号而已,指向谁就谁,不要理解它是同一个子弹 case 0: //创建一颗子弹 s=new Shot(x+10, y,0); //把子弹加入向量 ss.add(s); break; case 1: s=new Shot(x+30,y+10,1); ss.add(s); break; case 2: s=new Shot(x+10,y+30,2); ss.add(s); break; case 3: s=new Shot(x,y+10,3); ss.add(s); break; } //启动子弹线程 Thread t = new Thread(s); t.start(); } //坦克向上移动 public void moveUp() { y-=speed; } //坦克向右移动 public void moveRight() { x+=speed; } //坦克向下移动 public void moveDown() { y+=speed; } //坦克向左移动 public void moveLeft() { x-=speed; }}//子弹类class Shot implements Runnable{ int x; int y; int direct;//子弹的方向 int speed=1; //子弹速度 boolean isLive=true;//子弹是否活着 public Shot(int x,int y,int direct) { this.x=x; this.y=y; this.direct=direct; } public void run() { while(true) { try { Thread.sleep(50); } catch (Exception e) { // TODO: handle exception } switch(direct) { case 0://向上打出 y-=speed; break; case 1: x+=speed; break; case 2: y+=speed; break; case 3: x-=speed; break; } //判断子弹是否碰到边缘 if( x<0 || x>400 || y<0 || y>300) { this.isLive=false; break; } } }}
0 0
- Java之详解坦克大战游戏(四)
- Java之详解坦克大战游戏(一)
- Java之详解坦克大战游戏(二)
- Java之详解坦克大战游戏(六)
- Java之详解坦克大战游戏(三)
- Java之详解坦克大战游戏(五)
- HTML5之坦克大战游戏
- HTML5之坦克大战游戏
- 【Java_项目篇<1>】--JAVA实现坦克大战游戏--子弹连发+爆炸效果(四)
- java之坦克大战(一)
- Java开发的游戏之三 坦克大战 完整源代码
- Java坦克大战 (四) 之子弹的产生
- 【Java_项目篇<1>】--JAVA实现坦克大战游戏--坦克移动+添加敌方坦克(二)
- Android坦克大战游戏设计解析四
- JAVA练手项目(三):坦克大战游戏源代码
- Java坦克大战游戏(人机对战)
- 坦克大战之声音处理类(四)
- 基于JAVA的简易坦克大战(四)
- 从零开始学java(小游戏 石头剪刀布)
- 随机分享几个软件。。。
- JSP Servlet SQL 三者之间数据传递
- Mysql 学习笔记
- itext poi 学习之旅 (1)创建pdf
- Java之详解坦克大战游戏(四)
- itext poi 学习之旅 (2)创建excel
- itext poi 学习之旅 (3)读取数据库信息并由excel展现出来
- Leetcode解题笔记(Array)
- sip协议呼叫流程详解
- 为什么KMP算法的预处理时间是Θ(m)?
- C++中的友元函数、static函数、常函数小结(理论篇)
- 移动支付时代的手机和app安全设置
- Swift - 访问控制(private,internal,public)