资料来源:https://www.bilibili.com/video/BV1Aq4y1W79E?p=2

1、战斗机:HeroPlane

  1. package cn.tx.ltzj;
  2. import javax.swing.*;
  3. import java.awt.*;
  4. // 飞机在不断的监控按下的键盘,所以继承Thread,单独使用一个线程
  5. public class HeroPlane extends Thread{
  6. // 英雄机在画板上的位置
  7. int x = 230, y = 600;
  8. // 飞机大小
  9. int width = 80, heigth = 80;
  10. // 飞机移动的速度
  11. int speed = 8;
  12. // 飞机图像
  13. Image image = new ImageIcon("img/10011.png").getImage();
  14. // 定义键盘上方向键的标志
  15. boolean up, down, left, right;
  16. public HeroPlane(int x, int y, int width, int heigth) {
  17. this.x = x;
  18. this.y = y;
  19. this.width = width;
  20. this.heigth = heigth;
  21. }
  22. public HeroPlane() {
  23. }
  24. @Override
  25. public void run() {
  26. while (true){
  27. if(up){
  28. // y轴向上
  29. y -= speed;
  30. }
  31. if(down){
  32. // y轴向下
  33. y += speed;
  34. }
  35. if(left){
  36. x -= speed;
  37. }
  38. if(right){
  39. x += speed;
  40. }
  41. try {
  42. Thread.sleep(10);
  43. } catch (InterruptedException e) {
  44. e.printStackTrace();
  45. }
  46. }
  47. }
  48. }

2、敌机:EnemyPlane

  1. package cn.tx.ltzj;
  2. import javax.swing.*;
  3. import java.awt.*;
  4. // 敌机
  5. public class EnemyPlane extends Thread{
  6. public GameFrame gf;
  7. // 敌机在画板上的位置
  8. public int x, y;
  9. // 飞机大小
  10. public int width = 40, heigth = 40;
  11. // 飞机移动的速度
  12. public int speed = 1;
  13. // 飞机图像
  14. public Image image = new ImageIcon("img/10025.png").getImage();
  15. public EnemyPlane(int x, int y, GameFrame gf) {
  16. super();
  17. this.gf = gf;
  18. this.x = x;
  19. this.y = y;
  20. }
  21. public EnemyPlane(int x, int y, int width, int heigth, GameFrame gf) {
  22. super();
  23. this.gf = gf;
  24. this.x = x;
  25. this.y = y;
  26. this.width = width;
  27. this.heigth = heigth;
  28. }
  29. // 飞翔的额逻辑,移动的逻辑都在这里
  30. public void run(){
  31. while (true){
  32. // 向左走
  33. // 碰撞到了
  34. if(hit()){
  35. System.out.println("hit........");
  36. this.speed = 0;
  37. // 敌机爆炸了
  38. this.image = new ImageIcon("img/300350.png").getImage();
  39. try {
  40. Thread.sleep(500);
  41. } catch (InterruptedException e) {
  42. e.printStackTrace();
  43. }
  44. // 从屏幕中移除被击毁的敌机
  45. gf.enemyPlanes.remove(this);
  46. break; // 飞机被子弹击毁的中断。中断当前敌机的线程
  47. }
  48. // 飞机没有被击毁,但已过边界
  49. if(this.y >= 760){
  50. break;
  51. }
  52. try {
  53. Thread.sleep(10);
  54. } catch (InterruptedException e) {
  55. e.printStackTrace();
  56. }
  57. }
  58. }
  59. // 检测碰撞
  60. public boolean hit(){
  61. // Swing技术中,已经提供
  62. // 声明敌机的矩形
  63. Rectangle myrect = new Rectangle(this.x, this.y, this.width, this.heigth);
  64. // 声明子弹的矩形
  65. Rectangle rect = null;
  66. // 遍历所有的矩形
  67. for (int i = 0; i < gf.bullets.size(); i++) {
  68. Bullet bullet = gf.bullets.get(i);
  69. System.out.println("test hit");
  70. rect = new Rectangle(bullet.x, bullet.y - 1, bullet.width, bullet.heigth);
  71. // 碰撞检测:子弹与敌机的碰撞
  72. if(myrect.intersects(rect)){
  73. return true;
  74. }
  75. }
  76. return false;
  77. }
  78. @Override
  79. public String toString() {
  80. return "EnemyPlane{" +
  81. "x=" + x +
  82. ", y=" + y +
  83. ", width=" + width +
  84. ", heigth=" + heigth +
  85. '}';
  86. }
  87. }

3、玩家:Player

  1. package cn.tx.ltzj;
  2. import java.awt.event.KeyAdapter;
  3. import java.awt.event.KeyEvent;
  4. /**
  5. * 定义一个玩家,继承键盘适配器
  6. */
  7. public class Player extends KeyAdapter {
  8. GameFrame gameFrame;
  9. public Player(GameFrame gameFrame) {
  10. this.gameFrame = gameFrame;
  11. }
  12. /**
  13. * 按住键盘
  14. * @param e
  15. */
  16. @Override
  17. public void keyPressed(KeyEvent e) {
  18. // 获取敲击键盘时,具体键对应的数值
  19. int keyCode = e.getKeyCode();
  20. // 键盘上的上下左右键对应的值分别为:38、40、37、39
  21. switch(keyCode){
  22. case 38:
  23. gameFrame.heroPlane.up = true;
  24. break;
  25. case 40:
  26. gameFrame.heroPlane.down = true;
  27. break;
  28. case 37:
  29. gameFrame.heroPlane.left = true;
  30. break;
  31. case 39:
  32. gameFrame.heroPlane.right = true;
  33. break;
  34. case 66: // 装子弹
  35. addBullut();
  36. break;
  37. }
  38. System.out.println(keyCode);
  39. }
  40. /**
  41. * 松开键盘
  42. * @param e
  43. */
  44. @Override
  45. public void keyReleased(KeyEvent e) {
  46. // 松开键盘时,具体键对应的数值
  47. int keyCode = e.getKeyCode();
  48. switch(keyCode){
  49. case 38:
  50. gameFrame.heroPlane.up = false;
  51. break;
  52. case 40:
  53. gameFrame.heroPlane.down = false;
  54. break;
  55. case 37:
  56. gameFrame.heroPlane.left = false;
  57. break;
  58. case 39:
  59. gameFrame.heroPlane.right = false;
  60. break;
  61. }
  62. }
  63. /**
  64. * 装弹
  65. */
  66. public void addBullut(){
  67. gameFrame.bullets.add(new Bullet(gameFrame.heroPlane.x + 5, gameFrame.heroPlane.y - 20));
  68. }
  69. }

4、子弹:Bullet

  1. package cn.tx.ltzj;
  2. import javax.swing.*;
  3. import java.awt.*;
  4. // 子弹
  5. public class Bullet{
  6. // 子弹在画板上的位置
  7. int x, y;
  8. // 飞机大小
  9. int width = 50, heigth = 50;
  10. // 子弹移动的速度
  11. int speed = 10;
  12. // 子弹图像
  13. Image image = new ImageIcon("img/30025.png").getImage();
  14. public Bullet(int x, int y, int width, int heigth) {
  15. this.x = x;
  16. this.y = y;
  17. this.width = width;
  18. this.heigth = heigth;
  19. }
  20. public Bullet(int x, int y) {
  21. this.x = x;
  22. this.y = y;
  23. }
  24. public Bullet() {
  25. }
  26. }

5、主类:GameFrame

  1. package cn.tx.ltzj;
  2. import javax.swing.*;
  3. import java.awt.*;
  4. import java.awt.image.BufferedImage;
  5. import java.util.Random;
  6. import java.util.Vector;
  7. // Java做成图形界面,需要借助JFram
  8. public class GameFrame extends JFrame {
  9. HeroPlane heroPlane;
  10. // 定义子弹的集合。Vector线程安全,需要销毁子弹
  11. Vector<Bullet> bullets = new Vector<>();
  12. // 敌机集合
  13. Vector<EnemyPlane> enemyPlanes = new Vector<>();
  14. GameFrame frame;
  15. public GameFrame(){
  16. frame = this;
  17. // 创建英雄机
  18. heroPlane = new HeroPlane();
  19. heroPlane.start(); // 启动飞机单独的线程
  20. // 设置窗体的宽高
  21. this.setSize(500, 760);
  22. // 标题
  23. this.setTitle("雷霆战机");
  24. this.setResizable(false);
  25. this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
  26. this.setLocationRelativeTo(null);
  27. // 窗口可见
  28. this.setVisible(true);
  29. // 单独启动一个线程,供画笔使用,画笔会一直执行
  30. new Thread(new Runnable() {
  31. @Override
  32. public void run() {
  33. while (true){
  34. repaint(); // 不间断调用paint方法
  35. try {
  36. Thread.sleep(10);
  37. } catch (InterruptedException e) {
  38. e.printStackTrace();
  39. }
  40. }
  41. }
  42. }).start();
  43. // 产生敌机的线程,不断产生
  44. new Thread(new Runnable() {
  45. Random random = new Random();
  46. @Override
  47. public void run() {
  48. while (true){
  49. // 不断产生敌机,让X轴随机
  50. EnemyPlane enemyPlane = new EnemyPlane(random.nextInt(500), 0, frame);
  51. // 启动敌机:必须在生产敌机的时候就要启动敌机,而不是绘制敌机的时候启动,
  52. // 否则报错Exception in thread "AWT-EventQueue-0" java.lang.IllegalThreadStateException
  53. enemyPlane.start();
  54. enemyPlanes.add(enemyPlane);
  55. try {
  56. Thread.sleep(500);
  57. } catch (InterruptedException e) {
  58. e.printStackTrace();
  59. }
  60. }
  61. }
  62. }).start();
  63. }
  64. /**
  65. * 在窗口上画,内容,paint这个画笔的方法在窗口初始化的时候会默认的执行
  66. * @param graphics 画笔
  67. */
  68. public void paint(Graphics graphics){
  69. // System.out.println("绘制画板");
  70. // 画背景
  71. BufferedImage image = (BufferedImage) this.createImage(this.getSize().width, this.getSize().height);
  72. // 高效缓存的画笔
  73. Graphics bi = image.getGraphics();
  74. // 绘制背景图,在当前窗口的0, 0位置上
  75. bi.drawImage(new ImageIcon("img/skypay_bg.png").getImage(),0,0,null);
  76. // 绘制飞机
  77. bi.drawImage(heroPlane.image, heroPlane.x, heroPlane.y, heroPlane.width, heroPlane.heigth,null);
  78. // 绘制子弹
  79. for (int i = 0; i < bullets.size(); i++) {
  80. // System.out.println(bullets);
  81. Bullet bullet = bullets.get(i);
  82. if(bullet.y > 0){
  83. bi.drawImage(bullet.image, bullet.x, bullet.y -= bullet.speed, bullet.width, bullet.heigth, null);
  84. }else {
  85. // 子弹到屏幕外了,删除子弹
  86. bullets.remove(bullet);
  87. }
  88. }
  89. // 绘制敌机
  90. for (int i = 0; i < enemyPlanes.size(); i++) {
  91. // System.out.println(enemyPlanes);
  92. EnemyPlane ep = enemyPlanes.get(i);
  93. if(ep.y < 760){
  94. bi.drawImage(ep.image, ep.x, ep.y += ep.speed, ep.width, ep.heigth, null);
  95. }else {
  96. // 敌机到屏幕外了,删除敌机
  97. bullets.remove(ep);
  98. }
  99. }
  100. // 生效
  101. graphics.drawImage(image,0,0,null);
  102. }
  103. public static void main(String[] args) {
  104. GameFrame frame = new GameFrame();
  105. Player player = new Player(frame);
  106. // 在启动GameFrame后,启用player
  107. frame.addKeyListener(player);
  108. }
  109. }