当前位置: 首页 > news >正文

柯桥建设局网站首页上海百度提升优化

柯桥建设局网站首页,上海百度提升优化,wordpress模板赚钱,关于做摄影的网站目录 坦克大战【2】 线程-应用到坦克大战 坦克大战0.3 思路分析: 代码实现: 坦克大战0.4 增加功能 特别说明 思路分析: 代码实现: 坦克大战0.5 增加功能 思路分析: 代码实现: 坦克大战【2】 …

目录

坦克大战【2】

线程-应用到坦克大战

坦克大战0.3

思路分析:

代码实现:

坦克大战0.4

增加功能

特别说明

思路分析:

代码实现:

坦克大战0.5

增加功能

思路分析:

代码实现:


坦克大战【2】

线程-应用到坦克大战

坦克大战0.3

在坦克大战游戏(0.2版)基础上添加如下功能:当玩家按一下j键,就发射一颗子弹

思路分析:

  1. 当发射一颗子弹后,就相当于启动的一个线程
  2. Hero有子弹的对象,当按下J时,就启动一个发射行为(线程),让子弹不停的移动,形成一个射击效果
  3. MyPanel需要不断地重绘,才能出现该效果
  4. 当子弹移动到面板的边界时,就应该销毁(把启动的子弹的线程销毁)

代码实现:

package com18.tank_game03;/*** @author 甲柒* @version 1.0* @title Shot* @package com18.tank_game03* @time 2023/3/29 21:11* 射击子弹*/
public class Shot implements Runnable {int x;//子弹x坐标int y;//子弹y坐标int direct = 0;//子弹方向int speed = 5;//子弹速度boolean isLive = true;//子弹是否存活//构造器public Shot(int x, int y, int direct) {this.x = x;this.y = y;this.direct = direct;}@Overridepublic void run() {//射击while (true) {//子弹线程休眠50mstry {Thread.sleep(50);} catch (InterruptedException e) {throw new RuntimeException(e);}//根据方向改变x,y坐标switch (direct) {case 0://上y -= speed;break;case 1://右x += speed;break;case 2://下y += speed;break;case 3://左x -= speed;break;}//测试,输出子弹的坐标System.out.println("子弹 x=" + x + " y=" + y);//当子弹移动到面板的边界时,就应该销毁(把启动的子弹的线程销毁)if (!(x >= 0 && x <= 1000 && y >= 0 && y <= 750)) {isLive = false;break;}}}
}
package com18.tank_game03;/*** @author 甲柒* @version 1.3* @title Tank* @package com18.tank_game03* @time 2023/3/29 22:27*/
public class Tank {private int x;//坦克的横坐标private int y;//坦克的纵坐标private int direct;//坦克方向 0 上 1 右 2 下 3 左private int speed = 1;public int getSpeed() {return speed;}public void setSpeed(int speed) {this.speed = speed;}public Tank(int x, int y) {this.x = x;this.y = y;}//上下移动方法public void moveUp() {y -= speed;}public void moveRight() {x += speed;}public void moveDown() {y += speed;}public void moveLeft() {x -= speed;}public int getDirect() {return direct;}public void setDirect(int direct) {this.direct = direct;}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;}
}
package com18.tank_game03;import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Vector;/*** @author 甲柒* @version 1.3* @title MyPanel* @package com18.tank_game03* @time 2023/3/29 22:30*/
//为了监听 键盘事件,实现KeyListener
//为了让Panel 不停的重绘子弹,需要将MyPanel实现Runnable,当做一个线程使用
public class MyPanel extends JPanel implements KeyListener, Runnable {//定义我的坦克Hero hero = null;//定义敌人的坦克,放到VectorVector<EnemyTank> enemyTanks = new Vector<>();int enemyTankSize = 3;public MyPanel() {hero = new Hero(100, 100);//初始化自己的坦克//初始化敌人的坦克for (int i = 0; i < enemyTankSize; i++) {//创建一个敌人的坦克EnemyTank enemyTank = new EnemyTank((100 * (i + 1)), 0);//设置方向enemyTank.setDirect(2);//加入enemyTanks.add(enemyTank);}hero.setSpeed(10);}@Overridepublic void paint(Graphics g) {super.paint(g);g.fillRect(0, 0, 1000, 750);//填充矩形,默认黑色//画出坦克-封装方法drawTank(hero.getX(), hero.getY(), g, hero.getDirect(), 0);//画出hero射击的子弹if (hero.shot != null && hero.shot.isLive == true) {System.out.println("子弹被绘制~~~~~");g.draw3DRect(hero.shot.x, hero.shot.y, 2, 2, false);}//画出敌人的坦克,遍历Vectorfor (int i = 0; i < enemyTanks.size(); i++) {//取出坦克EnemyTank enemyTank = enemyTanks.get(i);drawTank(enemyTank.getX(), enemyTank.getY(), g, enemyTank.getDirect(), 1);}}//编写方法,画出坦克/*** @param x      坦克的左上角x坐标* @param y      坦克的左上角y坐标* @param g      画笔* @param direct 坦克方向(上下左右)* @param type   坦克类型*/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;}//根据坦克的方向,来绘制对应形状坦克//direct表示方向(0:向上 1:向右 2:向下 3:向左)switch (direct) {case 0://表示向上g.fill3DRect(x, y, 10, 60, false);//画出坦克左边轮子g.fill3DRect(x + 30, y, 10, 60, false);//画出坦克右边轮子g.fill3DRect(x + 10, y + 10, 20, 40, false);//画出坦克的盖子g.fillOval(x + 10, y + 20, 20, 20);//画出圆形盖子g.drawLine(x + 20, y + 30, x + 20, y);//画出炮筒break;case 1://表示向右g.fill3DRect(x, y, 60, 10, false);//画出坦克左边轮子g.fill3DRect(x, y + 30, 60, 10, false);//画出坦克右边轮子g.fill3DRect(x + 10, y + 10, 40, 20, false);//画出坦克的盖子g.fillOval(x + 20, y + 10, 20, 20);//画出圆形盖子g.drawLine(x + 30, y + 20, x + 60, y + 20);//画出炮筒break;case 2://表示向下g.fill3DRect(x, y, 10, 60, false);//画出坦克左边轮子g.fill3DRect(x + 30, y, 10, 60, false);//画出坦克右边轮子g.fill3DRect(x + 10, y + 10, 20, 40, false);//画出坦克的盖子g.fillOval(x + 10, y + 20, 20, 20);//画出圆形盖子g.drawLine(x + 20, y + 30, x + 20, y + 60);//画出炮筒break;case 3://表示向左g.fill3DRect(x, y, 60, 10, false);//画出坦克左边轮子g.fill3DRect(x, y + 30, 60, 10, false);//画出坦克右边轮子g.fill3DRect(x + 10, y + 10, 40, 20, false);//画出坦克的盖子g.fillOval(x + 20, y + 10, 20, 20);//画出圆形盖子g.drawLine(x + 30, y + 20, x, y + 20);//画出炮筒break;default:System.out.println("暂时没有处理");}}@Overridepublic void keyTyped(KeyEvent e) {}//处理ADWS键按下的情况@Overridepublic void keyPressed(KeyEvent e) {if (e.getKeyCode() == KeyEvent.VK_W) {//按下W键//改变坦克的方向hero.setDirect(0);//修改坦克坐标 y+=1hero.moveUp();} else if (e.getKeyCode() == KeyEvent.VK_D) {//D键hero.setDirect(1);hero.moveRight();} else if (e.getKeyCode() == KeyEvent.VK_S) {//S键hero.setDirect(2);hero.moveDown();} else if (e.getKeyCode() == KeyEvent.VK_A) {//A键hero.setDirect(3);hero.moveLeft();}//如果用户按下J,就发射if (e.getKeyCode() == KeyEvent.VK_J) {System.out.println("用户按下了J开始射击~~~~");hero.shotEnemyTank();}//重绘this.repaint();}@Overridepublic void keyReleased(KeyEvent e) {}@Overridepublic void run() {//每隔100ms 重绘区域 刷新绘图区域while (true) {try {Thread.sleep(100);} catch (InterruptedException e) {throw new RuntimeException(e);}this.repaint();}}
}
package com18.tank_game03;/*** @author 甲柒* @version 1.3* @title Hero* @package com18.tank_game03* @time 2023/3/29 22:29*/
public class Hero extends Tank {//定义一个Shot对象,表示一个射击(线程)Shot shot = null;public Hero(int x, int y) {super(x, y);}//射击public void shotEnemyTank() {//创建Shot对象,根据当前Hero对象的位置和方向来创建Shotswitch (getDirect()) {case 0://向上shot = new Shot(getX() + 20, getY(), 0);break;case 1://向右shot = new Shot(getX() + 60, getY() + 20, 1);break;case 2://向下shot = new Shot(getX() + 20, getY() + 60, 2);break;case 3://向左shot = new Shot(getX(), getY() + 20, 3);break;}//启动Shot线程new Thread(shot).start();}
}
package com18.tank_game03;/*** @author 甲柒* @version 1.3* @title EnemyTank* @package com18.tank_game03* @time 2023/3/29 12:06* 敌人的坦克*/
public class EnemyTank extends Tank {public EnemyTank(int x, int y) {super(x, y);}
}
package com18.tank_game03;import javax.swing.*;/*** @author 甲柒* @version 1.3* @title TankGame03* @package com18.tank_game03* @time 2023/3/29 22:33*/
public class TankGame03 extends JFrame {//定义MyPanelMyPanel mp = null;public TankGame03() {mp = new MyPanel();//将mp 放入到Thread,并启动Thread thread = new Thread(mp);thread.start();this.add(mp);//把面板(就是游戏的绘图区域)this.setSize(1000, 750);this.addKeyListener(mp);//让JFrame监听mp的键盘事件this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.setVisible(true);}public static void main(String[] args) {TankGame03 tankGame03 = new TankGame03();}
}

坦克大战0.4

增加功能

  1. 让敌人的坦克也能发射子弹(可以有多颗子弹)
  2. 当我方坦克击中敌人时,敌人的坦克就消失,如果能做出爆炸效果更好
  3. 让敌人的坦克也可以自由随机的上下左右移动
  4. 控制我方坦克和敌方坦克在规定的范围移动

特别说明

  1. 只要能实现就行
  2. 完成上面的任务

思路分析:

让敌人的坦克也能发射子弹(可以有多颗子弹)

  1. 在敌人的坦克类,使用Vector保存多个Shot
  2. 当每创建一个敌人坦克对象,给该敌人坦克对象初始化一个Shot对象,同时启动Shot
  3. 在绘制敌人坦克时,需要遍历敌人坦克对象Vector,绘制所有的子弹,当子弹isLive == false时,就从Vector移除

让敌人的坦克也可以自由随机的上下左右移动

  1. 需要将敌人坦克当成线程使用
  2. 需要EnemyTank implements Runnable
  3. 在run方法中写上相应的业务代码
  4. 在创建敌人坦克对象时,启动线程

代码实现:

package com18.tank_game04;/*** @author 甲柒* @version 1.4* @title Tank* @package com18.tank_game04* @time 2023/3/29 22:27*/
public class Tank {private int x;//坦克的横坐标private int y;//坦克的纵坐标private int direct;//坦克方向 0 上 1 右 2 下 3 左private int speed = 1;public int getSpeed() {return speed;}public void setSpeed(int speed) {this.speed = speed;}public Tank(int x, int y) {this.x = x;this.y = y;}//上下移动方法public void moveUp() {y -= speed;}public void moveRight() {x += speed;}public void moveDown() {y += speed;}public void moveLeft() {x -= speed;}public int getDirect() {return direct;}public void setDirect(int direct) {this.direct = direct;}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;}
}
package com18.tank_game04;import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Vector;/*** @author 甲柒* @version 1.4* @title MyPanel* @package com18.tank_game04* @time 2023/3/29 22:30*/
//为了监听 键盘事件,实现KeyListener
//为了让Panel 不停的重绘子弹,需要将MyPanel实现Runnable,当做一个线程使用
public class MyPanel extends JPanel implements KeyListener, Runnable {//定义我的坦克Hero hero = null;//定义敌人的坦克,放到VectorVector<EnemyTank> enemyTanks = new Vector<>();//定义一个Vector 用于存放炸弹//说明 当子弹击中坦克时,加入一个Bomb对象到bombsVector<Bomb> bombs = new Vector<>();int enemyTankSize = 3;//定义三张炸弹图片,用于显示爆炸效果Image image1 = null;Image image2 = null;Image image3 = null;public MyPanel() {hero = new Hero(100, 100);//初始化自己的坦克//初始化敌人的坦克for (int i = 0; i < enemyTankSize; i++) {//创建一个敌人的坦克EnemyTank enemyTank = new EnemyTank((100 * (i + 1)), 0);//设置方向enemyTank.setDirect(2);//启动敌人坦克进程new Thread(enemyTank).start();//给该enemyTank 加入一颗子弹Shot shot = new Shot(enemyTank.getX() + 20, enemyTank.getY() + 60, enemyTank.getDirect());//加入enemyTank的Vector成员enemyTank.shots.add(shot);//启动shot对象new Thread(shot).start();//加入enemyTanks.add(enemyTank);}//初始化图片对象image1 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_1.gif"));image2 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_2.gif"));image3 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_3.gif"));//设置我方坦克速度hero.setSpeed(10);}//编写方法,判断我方的子弹是否击中敌方的坦克public void hiTank(Shot s, EnemyTank enemyTank) {//判断s击中坦克switch (enemyTank.getDirect()) {case 0://坦克向上case 2://坦克向下if (s.x > enemyTank.getX() && s.x < enemyTank.getX() + 40&& s.y > enemyTank.getY() && s.y < enemyTank.getY() + 60) {s.isLive = false;enemyTank.isLive = false;//当我的子弹击中敌人坦克后,将enemyTank 从 Vector 拿掉enemyTanks.remove(enemyTank);//创建Bomb对象,加入到bombs集合Bomb bomb = new Bomb(enemyTank.getX(), enemyTank.getY());bombs.add(bomb);}break;case 1://坦克向右case 3://坦克向左if (s.x > enemyTank.getX() && s.x < enemyTank.getX() + 60&& s.y > enemyTank.getY() && s.y < enemyTank.getY() + 40) {s.isLive = false;enemyTank.isLive = false;//创建Bomb对象,加入到bombs集合Bomb bomb = new Bomb(enemyTank.getX(), enemyTank.getY());bombs.add(bomb);}break;}}//编写方法,画出坦克@Overridepublic void paint(Graphics g) {super.paint(g);g.fillRect(0, 0, 1000, 750);//填充矩形,默认黑色//画出坦克-封装方法drawTank(hero.getX(), hero.getY(), g, hero.getDirect(), 0);//画出hero射击的子弹if (hero.shot != null && hero.shot.isLive == true) {System.out.println("子弹被绘制~~~~~");g.draw3DRect(hero.shot.x, hero.shot.y, 2, 2, false);}//如果bombs 集合中有对象,就画出for (int i = 0; i < bombs.size(); i++) {//取出炸弹Bomb bomb = bombs.get(i);//根据当前这个bomb对象的life值去画出对应的的图片if (bomb.life > 6) {g.drawImage(image1, bomb.x, bomb.y, 60, 60, this);} else if (bomb.life > 3) {g.drawImage(image2, bomb.x, bomb.y, 60, 60, this);} else {g.drawImage(image3, bomb.x, bomb.y, 60, 60, this);}//让这个炸弹的生命值减少bomb.lifeDown();//如果bomb life 为0,就从bombs的集合中删除if (bomb.life == 0) {bombs.remove(bomb);}}//画出敌人的坦克,遍历Vectorfor (int i = 0; i < enemyTanks.size(); i++) {//从 Vector 取出坦克EnemyTank enemyTank = enemyTanks.get(i);if (enemyTank.isLive) {//当敌人坦克是存活的,才画出该坦克drawTank(enemyTank.getX(), enemyTank.getY(), g, enemyTank.getDirect(), 1);//画出 enemyTank 所有子弹for (int j = 0; j < enemyTank.shots.size(); j++) {//取出子弹Shot shot = enemyTank.shots.get(j);//绘制if (shot.isLive) {//isLive == trueg.draw3DRect(shot.x, shot.y, 1, 1, false);} else {//从Vector中移除enemyTank.shots.remove(shot);}}}}}/*** @param x      坦克的左上角x坐标* @param y      坦克的左上角y坐标* @param g      画笔* @param direct 坦克方向(上下左右)* @param type   坦克类型*/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;}//根据坦克的方向,来绘制对应形状坦克//direct表示方向(0:向上 1:向右 2:向下 3:向左)switch (direct) {case 0://表示向上g.fill3DRect(x, y, 10, 60, false);//画出坦克左边轮子g.fill3DRect(x + 30, y, 10, 60, false);//画出坦克右边轮子g.fill3DRect(x + 10, y + 10, 20, 40, false);//画出坦克的盖子g.fillOval(x + 10, y + 20, 20, 20);//画出圆形盖子g.drawLine(x + 20, y + 30, x + 20, y);//画出炮筒break;case 1://表示向右g.fill3DRect(x, y, 60, 10, false);//画出坦克左边轮子g.fill3DRect(x, y + 30, 60, 10, false);//画出坦克右边轮子g.fill3DRect(x + 10, y + 10, 40, 20, false);//画出坦克的盖子g.fillOval(x + 20, y + 10, 20, 20);//画出圆形盖子g.drawLine(x + 30, y + 20, x + 60, y + 20);//画出炮筒break;case 2://表示向下g.fill3DRect(x, y, 10, 60, false);//画出坦克左边轮子g.fill3DRect(x + 30, y, 10, 60, false);//画出坦克右边轮子g.fill3DRect(x + 10, y + 10, 20, 40, false);//画出坦克的盖子g.fillOval(x + 10, y + 20, 20, 20);//画出圆形盖子g.drawLine(x + 20, y + 30, x + 20, y + 60);//画出炮筒break;case 3://表示向左g.fill3DRect(x, y, 60, 10, false);//画出坦克左边轮子g.fill3DRect(x, y + 30, 60, 10, false);//画出坦克右边轮子g.fill3DRect(x + 10, y + 10, 40, 20, false);//画出坦克的盖子g.fillOval(x + 20, y + 10, 20, 20);//画出圆形盖子g.drawLine(x + 30, y + 20, x, y + 20);//画出炮筒break;default:System.out.println("暂时没有处理");}}@Overridepublic void keyTyped(KeyEvent e) {}//处理ADWS键按下的情况@Overridepublic void keyPressed(KeyEvent e) {if (e.getKeyCode() == KeyEvent.VK_W) {//按下W键//改变坦克的方向hero.setDirect(0);//修改坦克坐标 y+=1if (hero.getY() > 0) {hero.moveUp();}} else if (e.getKeyCode() == KeyEvent.VK_D) {//D键hero.setDirect(1);if (hero.getX() + 60 < 1000) {hero.moveRight();}} else if (e.getKeyCode() == KeyEvent.VK_S) {//S键hero.setDirect(2);if (hero.getY() + 60 < 750) {hero.moveDown();}} else if (e.getKeyCode() == KeyEvent.VK_A) {//A键hero.setDirect(3);if (hero.getX() > 0) {hero.moveLeft();}}//如果用户按下J,就发射if (e.getKeyCode() == KeyEvent.VK_J) {System.out.println("用户按下了J开始射击~~~~");hero.shotEnemyTank();}//重绘this.repaint();}@Overridepublic void keyReleased(KeyEvent e) {}@Overridepublic void run() {//每隔100ms 重绘区域 刷新绘图区域while (true) {try {Thread.sleep(100);} catch (InterruptedException e) {throw new RuntimeException(e);}//判断是否击中了敌人的坦克if (hero.shot != null && hero.shot.isLive) {//当我的子弹还存活//遍历敌人的所有坦克for (int i = 0; i < enemyTanks.size(); i++) {EnemyTank enemyTank = enemyTanks.get(i);hiTank(hero.shot, enemyTank);}}this.repaint();}}
}
package com18.tank_game04;/*** @author 甲柒* @version 1.4* @title Hero* @package com18.tank_game04* @time 2023/3/29 22:29*/
public class Hero extends Tank {//定义一个Shot对象,表示一个射击(线程)Shot shot = null;public Hero(int x, int y) {super(x, y);}//射击public void shotEnemyTank() {//创建Shot对象,根据当前Hero对象的位置和方向来创建Shotswitch (getDirect()) {case 0://向上shot = new Shot(getX() + 20, getY(), 0);break;case 1://向右shot = new Shot(getX() + 60, getY() + 20, 1);break;case 2://向下shot = new Shot(getX() + 20, getY() + 60, 2);break;case 3://向左shot = new Shot(getX(), getY() + 20, 3);break;}//启动Shot线程new Thread(shot).start();}
}
package com18.tank_game04;/*** @author 甲柒* @version 1.4* @title Shot* @package com18.tank_game04* @time 2023/3/29 21:11* 射击子弹*/
public class Shot implements Runnable {int x;//子弹x坐标int y;//子弹y坐标int direct = 0;//子弹方向int speed = 5;//子弹速度boolean isLive = true;//子弹是否存活//构造器public Shot(int x, int y, int direct) {this.x = x;this.y = y;this.direct = direct;}@Overridepublic void run() {//射击while (true) {//子弹线程休眠50mstry {Thread.sleep(50);} catch (InterruptedException e) {throw new RuntimeException(e);}//根据方向改变x,y坐标switch (direct) {case 0://上y -= speed;break;case 1://右x += speed;break;case 2://下y += speed;break;case 3://左x -= speed;break;}//测试,输出子弹的坐标System.out.println("子弹 x=" + x + " y=" + y);//当子弹移动到面板的边界时,就应该销毁(把启动的子弹的线程销毁)//当子弹碰到敌人坦克时,也应该结束线程if (!(x >= 0 && x <= 1000 && y >= 0 && y <= 750 && isLive)) {isLive = false;break;}}}
}
package com18.tank_game04;import java.util.Vector;/*** @author 甲柒* @version 1.4* @title EnemyTank* @package com18.tank_game04* @time 2023/3/29 12:06* 敌人的坦克*/
public class EnemyTank extends Tank implements Runnable {//在敌人的坦克类,使用Vector保存多个ShotVector<Shot> shots = new Vector<>();boolean isLive = true;public EnemyTank(int x, int y) {super(x, y);}@Overridepublic void run() {while (true) {//根据坦克的方向来继续移动switch (getDirect()) {case 0://向上for (int i = 0; i < 100; i++) {if (getY() > 0) {moveUp();}//让坦克保持一个方向 走30步try {Thread.sleep(50);} catch (InterruptedException e) {throw new RuntimeException(e);}}break;case 1://向右for (int i = 0; i < 100; i++) {if (getX() + 60 < 1000) {moveRight();}//让坦克保持一个方向 走30步try {Thread.sleep(50);} catch (InterruptedException e) {throw new RuntimeException(e);}}break;case 2://向下for (int i = 0; i < 100; i++) {if (getY() + 60 < 750) {moveDown();}//让坦克保持一个方向 走30步try {Thread.sleep(50);} catch (InterruptedException e) {throw new RuntimeException(e);}}break;case 3://向左for (int i = 0; i < 100; i++) {if (getX() > 0) {moveLeft();}//让坦克保持一个方向 走30步try {Thread.sleep(50);} catch (InterruptedException e) {throw new RuntimeException(e);}}break;}//休眠50mstry {Thread.sleep(50);} catch (InterruptedException e) {throw new RuntimeException(e);}//然后随机地改变坦克方向 0-3setDirect((int) (Math.random() * 4));//注意 写并发程序 一定要考虑清楚 该线程什么时候结束if (!isLive) {break;//退出程序}}}
}
package com18.tank_game04;/*** @author 甲柒* @version 1.0* @title Bomb* @package com18.tank_game04* @time 2023/3/29 22:47* 炸弹*/
public class Bomb {int x, y;//炸弹的坐标int life = 9;//炸弹的生命周期boolean isLive = true;//是否存活public Bomb(int x, int y) {this.x = x;this.y = y;}//减少生命值public void lifeDown() {//配合图片爆炸的效果if (life > 0) {life--;} else {isLive = false;}}
}
package com18.tank_game04;import javax.swing.*;/*** @author 甲柒* @version 1.4* @title TankGame04* @package com18.tank_game04* @time 2023/3/29 22:33*/
public class TankGame04 extends JFrame {//定义MyPanelMyPanel mp = null;public TankGame04() {mp = new MyPanel();//将mp 放入到Thread,并启动Thread thread = new Thread(mp);thread.start();this.add(mp);//把面板(就是游戏的绘图区域)this.setSize(1000, 750);this.addKeyListener(mp);//让JFrame监听mp的键盘事件this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.setVisible(true);}public static void main(String[] args) {TankGame04 tankGame04 = new TankGame04();}
}

坦克大战0.5

增加功能

  1. 我方坦克在发射的子弹消亡后,才能发射新的子弹 =》拓展(发射多颗子弹,控制5颗子弹)
  2. 让敌方坦克发射的子弹消亡后,可以再次发射子弹
  3. 当敌方坦克击中我方坦克时,我方坦克消失,并出现爆炸效果

思路分析:

我方坦克在发射的子弹消亡后,才能发射新的子弹 =》拓展(发射多颗子弹,控制5颗子弹)

  1. 在按下J键,判断当前hero对象的子弹,是否已经销毁
  2. 如果没有销毁,就不去触发shotEnemyTank
  3. 如果已经销毁,才去触发shotEnemyTank
  4. 如果要发射多颗子弹,就使用Vector保存
  5. 在绘制我方子弹时,需要遍历该Vector集合

当敌方坦克击中我方坦克时,我方坦克消失,并出现爆炸效果

  1. 编写方法,判断敌方坦克是否击中我方坦克

代码实现:

package com18.tank_game04;/*** @author 甲柒* @version 1.4* @title Tank* @package com18.tank_game04* @time 2023/3/29 22:27*/
public class Tank {boolean isLive = true;private int x;//坦克的横坐标private int y;//坦克的纵坐标private int direct;//坦克方向 0 上 1 右 2 下 3 左private int speed = 1;public Tank(int x, int y) {this.x = x;this.y = y;}public int getSpeed() {return speed;}public void setSpeed(int speed) {this.speed = speed;}//上下移动方法public void moveUp() {y -= speed;}public void moveRight() {x += speed;}public void moveDown() {y += speed;}public void moveLeft() {x -= speed;}public int getDirect() {return direct;}public void setDirect(int direct) {this.direct = direct;}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;}
}
package com18.tank_game04;/*** @author 甲柒* @version 1.4* @title Hero* @package com18.tank_game04* @time 2023/3/29 22:29*/
public class Hero extends Tank {//定义一个Shot对象,表示一个射击(线程)Shot shot = null;//可以发射多颗子弹
//    Vector<Shot> shots = new Vector<>();public Hero(int x, int y) {super(x, y);}//射击public void shotEnemyTank() {//控制只有5颗子弹
//        if (shots.size() == 5) {
//            return;
//        }//创建Shot对象,根据当前Hero对象的位置和方向来创建Shotswitch (getDirect()) {case 0://向上shot = new Shot(getX() + 20, getY(), 0);break;case 1://向右shot = new Shot(getX() + 60, getY() + 20, 1);break;case 2://向下shot = new Shot(getX() + 20, getY() + 60, 2);break;case 3://向左shot = new Shot(getX(), getY() + 20, 3);break;}//把新创建的shot加入到集合shots中
//        shots.add(shot);//启动Shot线程new Thread(shot).start();}
}
package com18.tank_game04;import java.util.Vector;/*** @author 甲柒* @version 1.4* @title EnemyTank* @package com18.tank_game04* @time 2023/3/29 12:06* 敌人的坦克*/
@SuppressWarnings({"all"})
public class EnemyTank extends Tank implements Runnable {//在敌人的坦克类,使用Vector保存多个ShotVector<Shot> shots = new Vector<>();boolean isLive = true;public EnemyTank(int x, int y) {super(x, y);}@Overridepublic void run() {while (true) {//这里判断如果shots size() == 0//创建一颗子弹 放入到shots 集合 并启动if (isLive && shots.size() < 1) {Shot s = null;//判断坦克的方向,创建对应的子弹switch (getDirect()) {case 0://上s = new Shot(getX() + 20, getY(), 0);break;case 1://右s = new Shot(getX() + 60, getY() + 20, 1);break;case 2://下s = new Shot(getX() + 20, getY() + 60, 2);break;case 3://左s = new Shot(getX(), getY() + 20, 3);break;}shots.add(s);//启动new Thread(s).start();}//根据坦克的方向来继续移动switch (getDirect()) {case 0://向上for (int i = 0; i < 50; i++) {if (getY() > 0) {moveUp();}//让坦克保持一个方向 走50步try {Thread.sleep(50);} catch (InterruptedException e) {throw new RuntimeException(e);}}break;case 1://向右for (int i = 0; i < 50; i++) {if (getX() + 60 < 1000) {moveRight();}//让坦克保持一个方向 走30步try {Thread.sleep(50);} catch (InterruptedException e) {throw new RuntimeException(e);}}break;case 2://向下for (int i = 0; i < 50; i++) {if (getY() + 60 < 750) {moveDown();}//让坦克保持一个方向 走30步try {Thread.sleep(50);} catch (InterruptedException e) {throw new RuntimeException(e);}}break;case 3://向左for (int i = 0; i < 50; i++) {if (getX() > 0) {moveLeft();}//让坦克保持一个方向 走30步try {Thread.sleep(50);} catch (InterruptedException e) {throw new RuntimeException(e);}}break;}//休眠50mstry {Thread.sleep(50);} catch (InterruptedException e) {throw new RuntimeException(e);}//然后随机地改变坦克方向 0-3setDirect((int) (Math.random() * 4));//注意 写并发程序 一定要考虑清楚 该线程什么时候结束if (!isLive) {break;//退出程序}}}
}
package com18.tank_game04;/*** @author 甲柒* @version 1.4* @title Shot* @package com18.tank_game04* @time 2023/3/29 21:11* 射击子弹*/
public class Shot implements Runnable {int x;//子弹x坐标int y;//子弹y坐标int direct = 0;//子弹方向int speed = 5;//子弹速度boolean isLive = true;//子弹是否存活//构造器public Shot(int x, int y, int direct) {this.x = x;this.y = y;this.direct = direct;}@Overridepublic void run() {//射击while (true) {//子弹线程休眠50mstry {Thread.sleep(50);} catch (InterruptedException e) {throw new RuntimeException(e);}//根据方向改变x,y坐标switch (direct) {case 0://上y -= speed;break;case 1://右x += speed;break;case 2://下y += speed;break;case 3://左x -= speed;break;}//测试,输出子弹的坐标System.out.println("子弹 x=" + x + " y=" + y);//当子弹移动到面板的边界时,就应该销毁(把启动的子弹的线程销毁)//当子弹碰到敌人坦克时,也应该结束线程if (!(x >= 0 && x <= 1000 && y >= 0 && y <= 750 && isLive)) {isLive = false;break;}}}
}
package com18.tank_game04;/*** @author 甲柒* @version 1.0* @title Bomb* @package com18.tank_game04* @time 2023/3/29 22:47* 炸弹*/
public class Bomb {int x, y;//炸弹的坐标int life = 9;//炸弹的生命周期boolean isLive = true;//是否存活public Bomb(int x, int y) {this.x = x;this.y = y;}//减少生命值public void lifeDown() {//配合图片爆炸的效果if (life > 0) {life--;} else {isLive = false;}}
}
package com18.tank_game04;import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Vector;/*** @author 甲柒* @version 1.4* @title MyPanel* @package com18.tank_game04* @time 2023/3/29 22:30*/
//为了监听 键盘事件,实现KeyListener
//为了让Panel 不停的重绘子弹,需要将MyPanel实现Runnable,当做一个线程使用
public class MyPanel extends JPanel implements KeyListener, Runnable {//定义我的坦克Hero hero = null;//定义敌人的坦克,放到VectorVector<EnemyTank> enemyTanks = new Vector<>();//定义一个Vector 用于存放炸弹//说明 当子弹击中坦克时,加入一个Bomb对象到bombsVector<Bomb> bombs = new Vector<>();int enemyTankSize = 3;//定义三张炸弹图片,用于显示爆炸效果Image image1 = null;Image image2 = null;Image image3 = null;public MyPanel() {hero = new Hero(600, 100);//初始化自己的坦克//初始化敌人的坦克for (int i = 0; i < enemyTankSize; i++) {//创建一个敌人的坦克EnemyTank enemyTank = new EnemyTank((100 * (i + 1)), 0);//设置方向enemyTank.setDirect(2);//启动敌人坦克进程new Thread(enemyTank).start();//给该enemyTank 加入一颗子弹Shot shot = new Shot(enemyTank.getX() + 20, enemyTank.getY() + 60, enemyTank.getDirect());//加入enemyTank的Vector成员enemyTank.shots.add(shot);//启动shot对象new Thread(shot).start();//加入enemyTanks.add(enemyTank);}//初始化图片对象image1 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_1.gif"));image2 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_2.gif"));image3 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_3.gif"));//设置我方坦克速度hero.setSpeed(10);}//如果我方坦克可以发射多个子弹//在判断我方子弹是否击中敌方坦克时,就需要把我们的子弹集合中//所有的子弹,都取出和敌人的所有坦克,进行判断public void hitEnemyTank() {
//        //遍历我们的子弹
//        for (int j = 0; j < hero.shots.size(); j++) {
//            Shot shot = hero.shots.get(j);
//            //判断我方子弹是否击中了敌人的坦克
//            if (shot != null && shot.isLive) {//当我的子弹还存活
//
//                //遍历敌人的所有坦克
//                for (int i = 0; i < enemyTanks.size(); i++) {
//                    EnemyTank enemyTank = enemyTanks.get(i);
//                    hiTank(shot, enemyTank);
//                }
//            }
//        }//单颗子弹if (hero.shot != null && hero.shot.isLive) {//当我的子弹还存活//遍历敌人的所有坦克for (int i = 0; i < enemyTanks.size(); i++) {EnemyTank enemyTank = enemyTanks.get(i);hiTank(hero.shot, enemyTank);}}}//编写方法,判断敌方坦克是否击中我方坦克public void hitHero() {//遍历所有敌方坦克for (int i = 0; i < enemyTanks.size(); i++) {//取出敌方坦克EnemyTank enemyTank = enemyTanks.get(i);//遍历enemyTank对象的所有子弹for (int j = 0; j < enemyTank.shots.size(); j++) {//取出子弹Shot shot = enemyTank.shots.get(j);//判断shot是否击中我方坦克if (hero.isLive && shot.isLive) {hiTank(shot, hero);}}}}//编写方法,判断我方的子弹是否击中敌方的坦克public void hiTank(Shot s, Tank enemyTank) {//判断s击中坦克switch (enemyTank.getDirect()) {case 0://坦克向上case 2://坦克向下if (s.x > enemyTank.getX() && s.x < enemyTank.getX() + 40&& s.y > enemyTank.getY() && s.y < enemyTank.getY() + 60) {s.isLive = false;enemyTank.isLive = false;//当我的子弹击中敌人坦克后,将enemyTank 从 Vector 拿掉enemyTanks.remove(enemyTank);//创建Bomb对象,加入到bombs集合Bomb bomb = new Bomb(enemyTank.getX(), enemyTank.getY());bombs.add(bomb);}break;case 1://坦克向右case 3://坦克向左if (s.x > enemyTank.getX() && s.x < enemyTank.getX() + 60&& s.y > enemyTank.getY() && s.y < enemyTank.getY() + 40) {s.isLive = false;enemyTank.isLive = false;//创建Bomb对象,加入到bombs集合Bomb bomb = new Bomb(enemyTank.getX(), enemyTank.getY());bombs.add(bomb);}break;}}//编写方法,画出坦克@Overridepublic void paint(Graphics g) {super.paint(g);g.fillRect(0, 0, 1000, 750);//填充矩形,默认黑色if (hero != null && hero.isLive) {//画出坦克-封装方法drawTank(hero.getX(), hero.getY(), g, hero.getDirect(), 0);}//画出hero射击的子弹,单颗子弹if (hero.shot != null && hero.shot.isLive == true) {System.out.println("子弹被绘制~~~~~");g.draw3DRect(hero.shot.x, hero.shot.y, 2, 2, false);}//多颗子弹//将hero的子弹集合shots,遍历取出绘制
//        for (int i = 0; i < hero.shots.size(); i++) {
//            Shot shot = hero.shots.get(i);
//            if (shot != null && shot.isLive) {
//                System.out.println("子弹被绘制~~~~~");
//                g.draw3DRect(shot.x, shot.y, 2, 2, false);
//            } else {//如果该shot对象已经无效,就从shots集合中拿掉
//                hero.shots.remove(shot);
//            }
//        }//如果bombs 集合中有对象,就画出for (int i = 0; i < bombs.size(); i++) {//取出炸弹Bomb bomb = bombs.get(i);//根据当前这个bomb对象的life值去画出对应的的图片if (bomb.life > 6) {g.drawImage(image1, bomb.x, bomb.y, 60, 60, this);} else if (bomb.life > 3) {g.drawImage(image2, bomb.x, bomb.y, 60, 60, this);} else {g.drawImage(image3, bomb.x, bomb.y, 60, 60, this);}//让这个炸弹的生命值减少bomb.lifeDown();//如果bomb life 为0,就从bombs的集合中删除if (bomb.life == 0) {bombs.remove(bomb);}}//画出敌人的坦克,遍历Vectorfor (int i = 0; i < enemyTanks.size(); i++) {//从 Vector 取出坦克EnemyTank enemyTank = enemyTanks.get(i);if (enemyTank.isLive) {//当敌人坦克是存活的,才画出该坦克drawTank(enemyTank.getX(), enemyTank.getY(), g, enemyTank.getDirect(), 1);//画出 enemyTank 所有子弹for (int j = 0; j < enemyTank.shots.size(); j++) {//取出子弹Shot shot = enemyTank.shots.get(j);//绘制if (shot.isLive) {//isLive == trueg.draw3DRect(shot.x, shot.y, 1, 1, false);} else {//从Vector中移除enemyTank.shots.remove(shot);}}}}}/*** @param x      坦克的左上角x坐标* @param y      坦克的左上角y坐标* @param g      画笔* @param direct 坦克方向(上下左右)* @param type   坦克类型*/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;}//根据坦克的方向,来绘制对应形状坦克//direct表示方向(0:向上 1:向右 2:向下 3:向左)switch (direct) {case 0://表示向上g.fill3DRect(x, y, 10, 60, false);//画出坦克左边轮子g.fill3DRect(x + 30, y, 10, 60, false);//画出坦克右边轮子g.fill3DRect(x + 10, y + 10, 20, 40, false);//画出坦克的盖子g.fillOval(x + 10, y + 20, 20, 20);//画出圆形盖子g.drawLine(x + 20, y + 30, x + 20, y);//画出炮筒break;case 1://表示向右g.fill3DRect(x, y, 60, 10, false);//画出坦克左边轮子g.fill3DRect(x, y + 30, 60, 10, false);//画出坦克右边轮子g.fill3DRect(x + 10, y + 10, 40, 20, false);//画出坦克的盖子g.fillOval(x + 20, y + 10, 20, 20);//画出圆形盖子g.drawLine(x + 30, y + 20, x + 60, y + 20);//画出炮筒break;case 2://表示向下g.fill3DRect(x, y, 10, 60, false);//画出坦克左边轮子g.fill3DRect(x + 30, y, 10, 60, false);//画出坦克右边轮子g.fill3DRect(x + 10, y + 10, 20, 40, false);//画出坦克的盖子g.fillOval(x + 10, y + 20, 20, 20);//画出圆形盖子g.drawLine(x + 20, y + 30, x + 20, y + 60);//画出炮筒break;case 3://表示向左g.fill3DRect(x, y, 60, 10, false);//画出坦克左边轮子g.fill3DRect(x, y + 30, 60, 10, false);//画出坦克右边轮子g.fill3DRect(x + 10, y + 10, 40, 20, false);//画出坦克的盖子g.fillOval(x + 20, y + 10, 20, 20);//画出圆形盖子g.drawLine(x + 30, y + 20, x, y + 20);//画出炮筒break;default:System.out.println("暂时没有处理");}}@Overridepublic void keyTyped(KeyEvent e) {}//处理ADWS键按下的情况@Overridepublic void keyPressed(KeyEvent e) {if (e.getKeyCode() == KeyEvent.VK_W) {//按下W键//改变坦克的方向hero.setDirect(0);//修改坦克坐标 y+=1if (hero.getY() > 0) {hero.moveUp();}} else if (e.getKeyCode() == KeyEvent.VK_D) {//D键hero.setDirect(1);if (hero.getX() + 60 < 1000) {hero.moveRight();}} else if (e.getKeyCode() == KeyEvent.VK_S) {//S键hero.setDirect(2);if (hero.getY() + 60 < 750) {hero.moveDown();}} else if (e.getKeyCode() == KeyEvent.VK_A) {//A键hero.setDirect(3);if (hero.getX() > 0) {hero.moveLeft();}}//如果用户按下J,就发射if (e.getKeyCode() == KeyEvent.VK_J) {System.out.println("用户按下了J开始射击~~~~");//判断hero的子弹是否销毁,发射一颗子弹if (hero.shot == null || !hero.shot.isLive) {hero.shotEnemyTank();}//发射多颗子弹
//            hero.shotEnemyTank();}//重绘this.repaint();}@Overridepublic void keyReleased(KeyEvent e) {}@Overridepublic void run() {//每隔100ms 重绘区域 刷新绘图区域while (true) {try {Thread.sleep(100);} catch (InterruptedException e) {throw new RuntimeException(e);}//判断敌我方坦克是否击中敌方坦克hitEnemyTank();//判断敌方坦克是否击中了我方坦克hitHero();this.repaint();}}
}
package com18.tank_game04;import javax.swing.*;/*** @author 甲柒* @version 1.4* @title TankGame04* @package com18.tank_game04* @time 2023/3/29 22:33*/
public class TankGame04 extends JFrame {//定义MyPanelMyPanel mp = null;public TankGame04() {mp = new MyPanel();//将mp 放入到Thread,并启动Thread thread = new Thread(mp);thread.start();this.add(mp);//把面板(就是游戏的绘图区域)this.setSize(1200, 950);this.addKeyListener(mp);//让JFrame监听mp的键盘事件this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.setVisible(true);}public static void main(String[] args) {TankGame04 tankGame04 = new TankGame04();}
}

http://www.hengruixuexiao.com/news/52135.html

相关文章:

  • wordpress手机显示缩windows优化大师卸载
  • 重庆营销型网站建设价格宁德市安全教育平台
  • 铜川免费做网站公司深圳最好的外贸seo培训
  • 合肥百度团购网站建设网站关键词免费优化
  • 小程序的推广方法宁宁网seo
  • 微信公众号链接的网站怎么做的搜索引擎优化特点
  • 怎样在别人网站做加强链接网站多久被百度收录
  • 外国网站做vr网站排名优化价格
  • 成都网站建设招标seo外链友情链接
  • 做网站属于什么学科福州短视频seo获客
  • 网站建设维护与推广百度公司简介介绍
  • 自己建网站做网店高端定制网站建设公司
  • 什么网站上做推广下载谷歌浏览器并安装
  • 做响应式网站价格网站搜索引擎优化技术
  • 丽水微信网站建设公司接广告的平台推荐
  • wordpress鼠标烟花绽放的效果北京seo相关
  • 杭州萧山做网站公司如何创建网页链接
  • 公司网站建设全包优化大师手机版下载安装app
  • 网站注销备案表下载百度软件应用中心
  • 自己怎样做网站广州公关公司
  • html引导页源码seo优化官网
  • 什么人做网站谷歌浏览器手机版官网下载
  • 网站制作员推广吧
  • PS做网站页面尺寸sem代运营公司
  • 无极网站设计自己网站怎么推广
  • 卖做游戏点卡网站创业产品推广营销
  • 深圳龙岗是不是很落后seo优化报价公司
  • 怎么下学做衣服网站网上做广告推广
  • css创意网站模板电商平台运营
  • 义乌电子商务有限公司东莞seo培训