资料来源:https://www.bilibili.com/video/BV1Aq4y1W79E?p=2
1、战斗机:HeroPlane
package cn.tx.ltzj;import javax.swing.*;import java.awt.*;// 飞机在不断的监控按下的键盘,所以继承Thread,单独使用一个线程public class HeroPlane extends Thread{// 英雄机在画板上的位置int x = 230, y = 600;// 飞机大小int width = 80, heigth = 80;// 飞机移动的速度int speed = 8;// 飞机图像Image image = new ImageIcon("img/10011.png").getImage();// 定义键盘上方向键的标志boolean up, down, left, right;public HeroPlane(int x, int y, int width, int heigth) {this.x = x;this.y = y;this.width = width;this.heigth = heigth;}public HeroPlane() {}@Overridepublic void run() {while (true){if(up){// y轴向上y -= speed;}if(down){// y轴向下y += speed;}if(left){x -= speed;}if(right){x += speed;}try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}}}}
2、敌机:EnemyPlane
package cn.tx.ltzj;import javax.swing.*;import java.awt.*;// 敌机public class EnemyPlane extends Thread{public GameFrame gf;// 敌机在画板上的位置public int x, y;// 飞机大小public int width = 40, heigth = 40;// 飞机移动的速度public int speed = 1;// 飞机图像public Image image = new ImageIcon("img/10025.png").getImage();public EnemyPlane(int x, int y, GameFrame gf) {super();this.gf = gf;this.x = x;this.y = y;}public EnemyPlane(int x, int y, int width, int heigth, GameFrame gf) {super();this.gf = gf;this.x = x;this.y = y;this.width = width;this.heigth = heigth;}// 飞翔的额逻辑,移动的逻辑都在这里public void run(){while (true){// 向左走// 碰撞到了if(hit()){System.out.println("hit........");this.speed = 0;// 敌机爆炸了this.image = new ImageIcon("img/300350.png").getImage();try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}// 从屏幕中移除被击毁的敌机gf.enemyPlanes.remove(this);break; // 飞机被子弹击毁的中断。中断当前敌机的线程}// 飞机没有被击毁,但已过边界if(this.y >= 760){break;}try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}}}// 检测碰撞public boolean hit(){// Swing技术中,已经提供// 声明敌机的矩形Rectangle myrect = new Rectangle(this.x, this.y, this.width, this.heigth);// 声明子弹的矩形Rectangle rect = null;// 遍历所有的矩形for (int i = 0; i < gf.bullets.size(); i++) {Bullet bullet = gf.bullets.get(i);System.out.println("test hit");rect = new Rectangle(bullet.x, bullet.y - 1, bullet.width, bullet.heigth);// 碰撞检测:子弹与敌机的碰撞if(myrect.intersects(rect)){return true;}}return false;}@Overridepublic String toString() {return "EnemyPlane{" +"x=" + x +", y=" + y +", width=" + width +", heigth=" + heigth +'}';}}
3、玩家:Player
package cn.tx.ltzj;import java.awt.event.KeyAdapter;import java.awt.event.KeyEvent;/*** 定义一个玩家,继承键盘适配器*/public class Player extends KeyAdapter {GameFrame gameFrame;public Player(GameFrame gameFrame) {this.gameFrame = gameFrame;}/*** 按住键盘* @param e*/@Overridepublic void keyPressed(KeyEvent e) {// 获取敲击键盘时,具体键对应的数值int keyCode = e.getKeyCode();// 键盘上的上下左右键对应的值分别为:38、40、37、39switch(keyCode){case 38:gameFrame.heroPlane.up = true;break;case 40:gameFrame.heroPlane.down = true;break;case 37:gameFrame.heroPlane.left = true;break;case 39:gameFrame.heroPlane.right = true;break;case 66: // 装子弹addBullut();break;}System.out.println(keyCode);}/*** 松开键盘* @param e*/@Overridepublic void keyReleased(KeyEvent e) {// 松开键盘时,具体键对应的数值int keyCode = e.getKeyCode();switch(keyCode){case 38:gameFrame.heroPlane.up = false;break;case 40:gameFrame.heroPlane.down = false;break;case 37:gameFrame.heroPlane.left = false;break;case 39:gameFrame.heroPlane.right = false;break;}}/*** 装弹*/public void addBullut(){gameFrame.bullets.add(new Bullet(gameFrame.heroPlane.x + 5, gameFrame.heroPlane.y - 20));}}
4、子弹:Bullet
package cn.tx.ltzj;import javax.swing.*;import java.awt.*;// 子弹public class Bullet{// 子弹在画板上的位置int x, y;// 飞机大小int width = 50, heigth = 50;// 子弹移动的速度int speed = 10;// 子弹图像Image image = new ImageIcon("img/30025.png").getImage();public Bullet(int x, int y, int width, int heigth) {this.x = x;this.y = y;this.width = width;this.heigth = heigth;}public Bullet(int x, int y) {this.x = x;this.y = y;}public Bullet() {}}
5、主类:GameFrame
package cn.tx.ltzj;import javax.swing.*;import java.awt.*;import java.awt.image.BufferedImage;import java.util.Random;import java.util.Vector;// Java做成图形界面,需要借助JFrampublic class GameFrame extends JFrame {HeroPlane heroPlane;// 定义子弹的集合。Vector线程安全,需要销毁子弹Vector<Bullet> bullets = new Vector<>();// 敌机集合Vector<EnemyPlane> enemyPlanes = new Vector<>();GameFrame frame;public GameFrame(){frame = this;// 创建英雄机heroPlane = new HeroPlane();heroPlane.start(); // 启动飞机单独的线程// 设置窗体的宽高this.setSize(500, 760);// 标题this.setTitle("雷霆战机");this.setResizable(false);this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);this.setLocationRelativeTo(null);// 窗口可见this.setVisible(true);// 单独启动一个线程,供画笔使用,画笔会一直执行new Thread(new Runnable() {@Overridepublic void run() {while (true){repaint(); // 不间断调用paint方法try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}}}}).start();// 产生敌机的线程,不断产生new Thread(new Runnable() {Random random = new Random();@Overridepublic void run() {while (true){// 不断产生敌机,让X轴随机EnemyPlane enemyPlane = new EnemyPlane(random.nextInt(500), 0, frame);// 启动敌机:必须在生产敌机的时候就要启动敌机,而不是绘制敌机的时候启动,// 否则报错Exception in thread "AWT-EventQueue-0" java.lang.IllegalThreadStateExceptionenemyPlane.start();enemyPlanes.add(enemyPlane);try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}}}).start();}/*** 在窗口上画,内容,paint这个画笔的方法在窗口初始化的时候会默认的执行* @param graphics 画笔*/public void paint(Graphics graphics){// System.out.println("绘制画板");// 画背景BufferedImage image = (BufferedImage) this.createImage(this.getSize().width, this.getSize().height);// 高效缓存的画笔Graphics bi = image.getGraphics();// 绘制背景图,在当前窗口的0, 0位置上bi.drawImage(new ImageIcon("img/skypay_bg.png").getImage(),0,0,null);// 绘制飞机bi.drawImage(heroPlane.image, heroPlane.x, heroPlane.y, heroPlane.width, heroPlane.heigth,null);// 绘制子弹for (int i = 0; i < bullets.size(); i++) {// System.out.println(bullets);Bullet bullet = bullets.get(i);if(bullet.y > 0){bi.drawImage(bullet.image, bullet.x, bullet.y -= bullet.speed, bullet.width, bullet.heigth, null);}else {// 子弹到屏幕外了,删除子弹bullets.remove(bullet);}}// 绘制敌机for (int i = 0; i < enemyPlanes.size(); i++) {// System.out.println(enemyPlanes);EnemyPlane ep = enemyPlanes.get(i);if(ep.y < 760){bi.drawImage(ep.image, ep.x, ep.y += ep.speed, ep.width, ep.heigth, null);}else {// 敌机到屏幕外了,删除敌机bullets.remove(ep);}}// 生效graphics.drawImage(image,0,0,null);}public static void main(String[] args) {GameFrame frame = new GameFrame();Player player = new Player(frame);// 在启动GameFrame后,启用playerframe.addKeyListener(player);}}
