• java.swing 飞机大战小游戏


    上午没事刷到网上最近炒热了一些简单的小游戏和爱心代码,单身8个月了,对爱心代码不是很感冒,所以想蹭个热度,写一个飞机大站来玩玩。

    首先,分析小游戏需要那些技术与怎么设计:

    窗体,因为是java小游戏,那么就需要用到java的swing或者是Fx包里的相关图形化方法。

    多线程,因为不可能是只有我们的飞机在飞,敌方也有飞机,子弹也需要飞行。

    图片读取:需要将图片放入窗体中,所以需要借助画布,但是前提是我们需要将图片解析出来。

    实体设计:越成熟的游戏设计的敌方飞机与我方飞机的功能与属性越多,这都需要基于实体实现。


    那么基于以上几个点,我们首先就是建立一个可视化的窗体出来:

    借助所谓的JFrame窗体类实现(也可继承来实现):

    1. public static void main(String[] args) throws IOException {
    2. JFrame frame = new JFrame();
    3. GamePanel gamePanel = new GamePanel();
    4. frame.add(gamePanel);
    5. frame.setSize(576, 840);
    6. frame.setTitle("战机");
    7. frame.setLocationRelativeTo(null);
    8. frame.setVisible(true);
    9. frame.setDefaultCloseOperation(3);
    10. gamePanel.move();
    11. frame.addMouseListener(gamePanel);
    12. frame.addMouseMotionListener(gamePanel);
    13. }

    因为是一个窗体,所以我们需要借助画布对象来给窗体内部添加一些元素。也需要借助鼠标监听的相关接口对鼠标事件进行业务重写。

    这里我们直接挂出来(相关代码的释疑都在注释里):

    画布类:

    1. package com.hlc.Game;
    2. import javax.imageio.ImageIO;
    3. import javax.swing.*;
    4. import java.awt.*;
    5. import java.awt.event.MouseEvent;
    6. import java.awt.event.MouseListener;
    7. import java.awt.event.MouseMotionListener;
    8. import java.io.File;
    9. import java.io.IOException;
    10. import java.util.LinkedList;
    11. import java.util.List;
    12. import static java.awt.Font.BOLD;
    13. public class GamePanel extends JPanel implements MouseListener, MouseMotionListener {
    14. Image backGround, boss, zu, me,mePlus, ziDan, destroy, startGame;//图片资源
    15. int state;//控制游戏状态开关 变量 0未开始,1开始,2暂停,3退出
    16. int mark = 0, count = 0;//分数与计数器
    17. int mouseX = 180, mouseY = 500, blood = 100;//我方战斗机坐标X,Y与战斗机血量。
    18. boolean boom = false;//爆炸开关 显示爆炸图片的控制开关
    19. int badAirX, badAirY;//存储爆炸敌方飞机坐标便于画出爆炸图片
    20. List badAirs = new LinkedList<>();//存储敌机对象
    21. List ziDans = new LinkedList<>();//存储子弹对象
    22. public GamePanel() throws IOException {
    23. state = 0;
    24. mark = 0;
    25. backGround = ImageIO.read(new File("D:\\java项目\\Game\\Image\\back.png"));
    26. boss = ImageIO.read(new File("D:\\java项目\\Game\\Image\\boss.png"));
    27. startGame = ImageIO.read(new File("D:\\java项目\\Game\\Image\\start.png"));
    28. me = ImageIO.read(new File("D:\\java项目\\Game\\Image\\mePlus.png"));
    29. mePlus = ImageIO.read(new File("D:\\java项目\\Game\\Image\\me.png"));
    30. zu = ImageIO.read(new File("D:\\java项目\\Game\\Image\\zu.png"));
    31. ziDan = ImageIO.read(new File("D:\\java项目\\Game\\Image\\ziDan.png"));
    32. destroy = ImageIO.read(new File("D:\\java项目\\Game\\Image\\destroy.png"));
    33. }
    34. @Override
    35. public void paint(Graphics g) {
    36. super.paint(g);
    37. g.setFont(new Font("仿宋", BOLD, 20));
    38. g.setColor(Color.YELLOW);
    39. /*初始游戏状态*/
    40. if (state == 0) {
    41. g.drawImage(backGround, 0, 0, null);
    42. g.drawString("分数:" + mark + "", 0, 20);
    43. g.drawImage(boss, 204, 0, null);
    44. g.drawImage(startGame, 258, 300, null);
    45. g.drawString("开始游戏", 248, 400);
    46. g.drawImage(mePlus, 237, 500, null);
    47. }
    48. /*开始游戏状态*/
    49. else if (state == 1) {
    50. g.drawImage(backGround, 0, 0, null);
    51. g.drawString("分数:" + mark + "", 0, 20);
    52. if(mark > 50){
    53. g.drawImage(mePlus,mouseX-51,mouseY-63,null);
    54. }
    55. else
    56. g.drawImage(me,mouseX-23,mouseY-28,null);
    57. if (boom) {
    58. g.drawImage(destroy, badAirX, badAirY, null);
    59. boom = false;
    60. }
    61. for (int i = 0; i < ziDans.size(); i++) {
    62. ziDans.get(i).drawZiDan(g);
    63. }
    64. for (int i = 0; i < badAirs.size(); i++) {
    65. badAirs.get(i).drawPanel(g);
    66. }
    67. }
    68. /*暂停游戏状态*/
    69. else if (state == 2) {
    70. g.drawImage(backGround, 0, 0, null);
    71. g.drawString("分数:" + mark + "", 0, 20);
    72. g.drawImage(boss, 156, 0, null);
    73. g.drawImage(startGame, 210, 300, null);
    74. g.drawString("开始游戏", 200, 400);
    75. g.drawImage(me, 189, 500, null);
    76. }
    77. /*退出游戏状态(数据清空,等待重新开始游戏)*/
    78. else {
    79. state = 0;
    80. repaint();
    81. }
    82. }
    83. public void move() {
    84. new Thread() {
    85. @Override
    86. public void run() {
    87. super.run();
    88. while (true) {
    89. if (state == 1) {
    90. count++;//计数器自增开始
    91. if (count % 3 == 0) {
    92. ziDans.add(new ZiDan(mouseX,mouseY,ziDan));//创建新子弹
    93. }
    94. for (int i = 0;i
    95. ziDans.get(i).setY(ziDans.get(i).getY()-10);//发射子弹,超出窗体外则删除子弹对象
    96. if (ziDans.get(i).getY()<0){
    97. ziDans.remove(i);
    98. }
    99. }
    100. if (count%21 == 0){
    101. badAirs.add(new BadAir(zu));//创建敌机
    102. }else if(count % 72 == 0){
    103. badAirs.add(new BadAir(boss));
    104. }
    105. for (int i =0;i
    106. badAirs.get(i).setY(badAirs.get(i).getY()+3);//运动敌机,到达我方阵地则重新准备新局
    107. if (badAirs.get(i).getY()>700){
    108. state = 3;
    109. mark = 0;
    110. blood = 100;
    111. }
    112. }
    113. GameJudgeDead judgeDead = new GameJudgeDead();//初始化判断碰撞对象
    114. for (int i = 0;i
    115. ZiDan ziDan = ziDans.get(i);
    116. for (int j=0;j
    117. BadAir badAir = badAirs.get(j);
    118. if (judgeDead.judgeBoomZiDan(ziDan,badAir)){
    119. mark+=2;
    120. badAirX = badAir.getX();
    121. badAirY = badAir.getY();
    122. boom = true;
    123. ziDans.remove(i);
    124. badAirs.remove(j);
    125. break;
    126. }
    127. }
    128. }
    129. for (int i=0;i
    130. if (judgeDead.judgeBoomAir(badAirs.get(i),mouseX,mouseY)){
    131. badAirX = badAirs.get(i).getX();
    132. badAirY = badAirs.get(i).getY();
    133. boom = true;
    134. blood -= 30;
    135. if (blood <= 0) {
    136. state = 3;
    137. mark = 0;
    138. blood = 100;
    139. }
    140. }
    141. }
    142. }
    143. repaint();
    144. try{
    145. Thread.sleep(20);
    146. }catch (InterruptedException e){
    147. e.printStackTrace();
    148. }
    149. }
    150. }
    151. }.start();
    152. }
    153. @Override
    154. public void mouseClicked(MouseEvent e) {
    155. if (state == 0) {
    156. state = 1;
    157. } else if (state == 1) {
    158. state = 2;
    159. } else if (state == 2) {
    160. state = 1;
    161. } else {
    162. state = 0;
    163. }
    164. }
    165. .........接口方法存根省略..........
    166. @Override
    167. public void mouseMoved(MouseEvent e) {
    168. mouseX = e.getX();
    169. mouseY = e.getY();
    170. }
    171. }

    这里需要注意几个问题,之前用webp格式的图片下载之后强行改后缀为png之后再内部怎么写都不能加载出来图片显示,这是一个问题,因为浏览器对图片进行了压缩解码,所以一定要下载原图!!!

    接下来我们挂出来碰撞判断类:

    1. public class GameJudgeDead {
    2. public boolean judgeBoomZiDan(ZiDan ziDan, BadAir badAir) {
    3. return badAir.getX() < ziDan.getX() && badAir.getY() + badAir.height > ziDan.getY() && badAir.getX() + badAir.width > ziDan.getX();
    4. }
    5. public boolean judgeBoomAir(BadAir badAir, int mouseX, int mouseY) {
    6. mouseX = mouseX - 51;
    7. mouseY = mouseY - 63;
    8. return badAir.getX() < mouseX && badAir.getY() + badAir.height > mouseY && badAir.getX() + badAir.width > mouseY;
    9. }
    10. }

    这里面你需要计算碰撞的条件,以及里面的坐标代表的意思,尤其是你切换图片之后对应的尺寸会变化,所以最好用实体。

    敌机实体:

    1. public class BadAir {
    2. int X;
    3. int Y;
    4. Image badAir;
    5. int height;
    6. int width;
    7. public BadAir( Image badAir) {
    8. X =(int) (Math.random()*480);
    9. Y = -30;
    10. this.badAir = badAir;
    11. height = badAir.getHeight(null);
    12. width = badAir.getWidth(null);
    13. }
    14. void drawPanel(Graphics g){
    15. g.drawImage(badAir,X-27,Y-20,null);
    16. }
    17. public int getX() {
    18. return X;
    19. }
    20. public void setX(int x) {
    21. X = x;
    22. }
    23. public int getY() {
    24. return Y;
    25. }
    26. public void setY(int y) {
    27. Y = y;
    28. }
    29. }

    注意这里将图片的尺寸写入到实体属性中去了,方便后续因为图片的切换来。

    子弹实体类

    1. public class ZiDan {
    2. int x,y;
    3. Image ZiDan;
    4. public ZiDan(int mouseX,int mouseY,Image ZiDan){
    5. this.x = mouseX;
    6. this.y = mouseY;
    7. this.ZiDan = ZiDan;
    8. }
    9. public void drawZiDan(Graphics g){
    10. g.drawImage(ZiDan,x,y,null);
    11. }
    12. public int getX() {
    13. return x;
    14. }
    15. public void setX(int x) {
    16. this.x = x;
    17. }
    18. public int getY() {
    19. return y;
    20. }
    21. public void setY(int y) {
    22. this.y = y;
    23. }
    24. }

    这里没有给敌机添加子弹。

    OK拜拜!!!

     

     

     

  • 相关阅读:
    外卖项目(SpringBoot)--- 菜品模块、套餐模块
    经典Ubuntu20.04版本U盘安装双系统教程
    虚拟试穿VTNFP论文笔记
    好用的企微scrm系统应具备哪些能力
    6.1 Hive学习总结
    【mmdetection代码解读 3.x版本】以Fcos+FasterRcnn为例
    【ES】elasticsearch8.3.3
    博云入选 Gartner 中国 DevOps 代表厂商
    Shell常用的几个正则表达式:[:alnum:], [:alpha:], [:upper:], [:lower:], [:digit:] 认知
    nginx的使用
  • 原文地址:https://blog.csdn.net/m0_59588838/article/details/127926774