Java经典飞机大战游戏

news/2024/10/17 18:17:37/

《飞机大战》这款小游戏相信许多朋友早就已经玩过,但是作为小白,学习过程中就是要拿各种经典项目来练手,飞机大战就是老师拿来让我们练手的一个小项目。老师给我们提供了素材包,让我们自由发挥,刚开始真的是没什么头绪,不过这几天的确学习到一些东西,随着慢慢尝试,终于背景动了起来,飞机动了起来,子弹动了起来,可以消灭敌机了,到这也算实现了最底层的功能,这里把代码和我理解的注释写下来,算是对学习过程的记录,也希望可以帮到其他朋友。

一、建立模板类,创建敌机和子弹的模板

敌机模板类Dj.java代码:

package model;import java.awt.Graphics;
import java.awt.Image;import javax.swing.ImageIcon;public class Dj {int x,y;String icon;public Dj(String icon) { //参数为敌机图片路径this.icon=icon;x=(int)(Math.random()*360)+10; //随机生成x坐标y=-30;}//画敌机public void drawPlane(Graphics g) {Image plane=new ImageIcon(icon).getImage();g.drawImage(plane, x-15, y-15, null);}//x,y的get和set方法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;}}

子弹模板类Zd.java代码:

package model;import java.awt.Graphics;
import java.awt.Image;import javax.swing.ImageIcon;public class Zd {int x, y;//构造方法public Zd(int a, int b) { //参数为英雄机坐标this.x=a;this.y=b;}//画子弹public void drawZd(Graphics g) {Image zd=new ImageIcon("src/images/bullet_7.png").getImage();g.drawImage(zd, x-19, y-80, null);}//x,y的get和set方法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;}}

二、创建碰撞判断类Crash

碰撞判断类Crash.java代码:

package model;public class Crash {// 判断子弹和敌机碰撞public boolean Boom(Zd z, Dj d) {int zx, zy, dx, dy;boolean crash = false;//子弹坐标zx = z.getX();zy = z.getY();//敌机坐标dx = d.getX();dy = d.getY();if (dx < zx && zy - dy < 30 && dx + 30 > zx) {crash = true; //如果相撞返回真值}return crash;}//飞机相撞public boolean Boom2(Dj d, int x, int y) {int dx, dy;boolean crash = false;//敌机坐标dx = d.getX();dy = d.getY();//英雄机坐标x = x - 50;y = y - 80;//相撞条件if (dx > x+20 && y - dy < 20 && dx < x + 60) {crash = true; //如果相撞返回真值}return crash;}}

三、创建画布类GamePanel

在画布类中创建敌机和子弹模板对象,并在画布上画出来,在新线程循环中改变坐标重画使其移动,获取鼠标坐标画出英雄机,循环遍历子弹和敌机集合,调用Crash类中的方法判断是否相撞
画布类GamePanel.java代码:

package panel;import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import java.util.List;import javax.swing.ImageIcon;
import javax.swing.JPanel;import model.Crash;
import model.Dj;
import model.Zd;public class GamePanel extends JPanel implements MouseMotionListener, MouseListener {/*** */private static final long serialVersionUID = 1682690307762671162L;int bx, by, x, y, dx, dy, score = 0,count=0,state; //背景坐标bx,by,英雄机坐标x,y,敌机坐标dx,dy,分数score,计数器count,运行状态stateImage bg; //背景图boolean db = false; //敌机爆炸图片绘图开关List<Zd> zd = new ArrayList<Zd>(); //存储子弹对象List<Dj> dj = new ArrayList<Dj>(); //存储敌机对象//运行状态常量public static final int START=1;public static final int RUNNING=2;public static final int PAUSE=3;public static final int OVER=4;//构造方法public GamePanel() {state=START;bx = 0;by = -5350;bg = new ImageIcon("src/images/background_1.png").getImage();}//重写paint方法@Overridepublic void paint(Graphics g) {super.paint(g);if(state==RUNNING){String sc = "分数:" + String.valueOf(score);g.drawImage(bg, bx, by, null); //画出背景g.drawRoundRect(0, 0, 120, 30, 5, 5); //分数框g.setFont(new Font("TimesRoman", Font.BOLD, 24));g.setColor(Color.RED);g.drawString(sc, 2, 20); //画出分数Image hero = new ImageIcon("src/images/plane_2.png").getImage(); g.drawImage(hero, x - 50, y - 80, null);  //画出英雄机if (db) { //在敌机爆炸时画出爆炸图片Image boom = new ImageIcon("src/images/boom1.png").getImage();g.drawImage(boom, dx, dy, null);db = false;}for (int i = 0; i < zd.size(); i++) {zd.get(i).drawZd(g);  //画出所有子弹}for (int j = 0; j < dj.size(); j++) {dj.get(j).drawPlane(g); //画出所有敌机}}else if(state==START){ //开始界面Image start=new ImageIcon("src/images/start.png").getImage();g.drawImage(start, 0, 0, 400, 650, null);}else if(state==OVER){ //结束界面Image over=new ImageIcon("src/images/over.png").getImage();g.drawImage(over, 0, 0, 400, 650, null);}else if(state==PAUSE){ //暂停界面Image pause=new ImageIcon("src/images/pause.png").getImage();g.drawImage(pause, 0, 0, 400, 650, null);}}// 移动类public void Move() {new Thread() {@Overridepublic void run() {super.run();while (true) {if(state==RUNNING){// 背景移动count++;by += 2;if (by > 0) {by = -5350;bg = new ImageIcon("src/images/background_2.png").getImage();}// 创建子弹if (count % 3 == 0) {zd.add(new Zd(x, y));} for (int a = 0; a < zd.size(); a++) {zd.get(a).setY(zd.get(a).getY() - 30); //改变子弹坐标,使子弹移动if (zd.get(a).getY() < 0) { //判断子弹越界zd.remove(a);}}// 创建敌机if (count % 21 == 0) {dj.add(new Dj("src/images/e4.png"));}else if (count % 31 == 0) {dj.add(new Dj("src/images/e5.png"));}else if (count % 41 == 0) {dj.add(new Dj("src/images/e6.png"));}for (int b = 0; b < dj.size(); b++) {dj.get(b).setY(dj.get(b).getY() + 3); //改变敌机坐标,使敌机移动if (dj.get(b).getY() > 650) { //判断敌机越界state=OVER; //游戏结束}}// 子弹和敌机碰撞Crash crash = new Crash();for (int j = 0; j < zd.size(); j++) {Zd z = zd.get(j);for (int i = 0; i < dj.size(); i++) {Dj d = dj.get(i);if (crash.Boom(z, d)) { //调用Crash对象的Boom方法判断是否相撞score += 2; //分数加2dx = dj.get(i).getX(); //敌机坐标dy = dj.get(i).getY();db = true; //敌机爆炸dj.remove(i); //从集合中删除敌机zd.remove(j); //从集合中删除子弹break;}}}//判断飞机相撞for (int i = 0; i < dj.size(); i++) {Dj d = dj.get(i);if (crash.Boom2(d, x, y)) {dx = dj.get(i).getX();dy = dj.get(i).getY();db = true;state=OVER; //游戏结束}}}repaint(); //重画try {Thread.sleep(20); //线程休眠} catch (InterruptedException e) {e.printStackTrace();}}}}.start();}//鼠标点击事件@Overridepublic void mouseClicked(MouseEvent e) {if(state==START||state==PAUSE){state=RUNNING;}else if (state==RUNNING){state=PAUSE;;}else if(state==OVER){//重新开始后初始化参数值state=RUNNING;score=0;count=0;bx = 0;bg = new ImageIcon("src/images/background_1.png").getImage();by = -5350;zd = new ArrayList<Zd>();dj = new ArrayList<Dj>();}}@Overridepublic void mousePressed(MouseEvent e) {// TODO 自动生成的方法存根}@Overridepublic void mouseReleased(MouseEvent e) {// TODO 自动生成的方法存根}@Overridepublic void mouseEntered(MouseEvent e) {// TODO 自动生成的方法存根}@Overridepublic void mouseExited(MouseEvent e) {// TODO 自动生成的方法存根}@Overridepublic void mouseDragged(MouseEvent e) {// TODO 自动生成的方法存根}@Overridepublic void mouseMoved(MouseEvent e) {x = e.getX(); //动态获取鼠标的坐标值y = e.getY();}}

四、 创建游戏主线程和游戏窗口

窗口类Game.java代码:

package frame;import javax.swing.JFrame;import panel.GamePanel;public class Game {public static void main(String[] args) {JFrame j = new JFrame(); //创建窗口GamePanel g = new GamePanel(); //创建画布j.add(g); //添加画布j.setSize(400, 650);j.setTitle("PlaneWar"); //设置标题j.setLocationRelativeTo(null); //设置居中j.setDefaultCloseOperation(3); //默认关闭j.setVisible(true); //窗口可见性g.Move(); //调用Move方法j.addMouseListener(g); //添加监听器j.addMouseMotionListener(g);}}

到这里,一个太监版的飞机大战小游戏就完成了。你有你的王者荣耀,我有我的飞机大战,不是很炫,但是很六。


http://www.ppmy.cn/news/598235.html

相关文章

Docker-compose 安装 Nacos2.x并配置mysql数据库存储

1.安装Nacos 1.1 创建数据库nacos并导入sql 在mysql数据库中创建nacos并导入nacos-db.sql。这个sql在安装包中有提供。 1.2 创建docker-compose version: 3services:nacos:image: nacos/nacos-server:[版本号]container_name: nacosports:- 8848:8848- 9848:9848- 9849:984…

电机飞车现象

什么是飞车现象&#xff1f; 直流电动机转速失去控制&#xff0c;大电流大转矩加速运行。因转速太高而导致直流电动机和机械损坏。 在运转时&#xff0c;&#xff08;直流&#xff09;电机突然的失磁&#xff0c;导致电枢过电流而产生很大的加速变化&#xff0c;放炮或跳闸。…

机车风暴3制作揭密译文

译自 DIGITAL FOUNTRY 网站对 机车风暴3制作团队的采访全文&#xff0c;图片及文字全部翻译完毕&#xff0c;欢迎各位同学讨论、批评、指正。原贴地址&#xff1a; http://www.eurogamer.net/article ... m-apocalypse?page1 译文全文如下&#xff1a; 机车风暴3的制作过程揭…

什么是断路器?谈谈服务雪崩效应?服务雪崩效应产生的原因?

短路器&#xff1a; 熔断机制&#xff08;短路器&#xff09;是应对雪崩效应的一种微服务链路保护机制。 当链路的某个微服务出错不可用或者响应时间太长时&#xff0c;会进行服务的降级&#xff0c;进而熔断该节点微服务的调用&#xff0c;快速返回错误的响应信息。当检测到…

CPP使用const的情况

文章目录 使用示例const常量引用和普通引用常量引用和普通引用区别示例报错原因 使用示例 在 C 中&#xff0c;我们使用 const 关键字来表示一个常量&#xff0c;即其值在编译时就已经被设定并且在运行时不能被改变。 例如131.分割回文串&#xff0c;最开始传入的字符串strin…

JMeter在高分辨率电脑上,页面显示字体特别小

最近使用JMeter的过程中&#xff0c;发现一个问题&#xff0c;在高分辨率的电脑上&#xff0c;JMeter启动后&#xff0c;页面显示的字体特别小&#xff0c;上图 我电脑的分辨率是2880*1800&#xff0c;缩放200% 上图里显示的字体真心看不清楚 我以为是JMeter的bug&#xff0c…

2023-06-27 LeetCode每日一题(删除一次得到子数组最大和)

2023-06-27每日一题 一、题目编号 1186. 删除一次得到子数组最大和二、题目链接 点击跳转到题目位置 三、题目描述 给你一个整数数组&#xff0c;返回它的某个 非空 子数组&#xff08;连续元素&#xff09;在执行一次可选的删除操作后&#xff0c;所能得到的最大元素总和…

SpringBoot 生产中 16 条最佳实践

1、使用自定义 BOM 来维护第三方依赖 2、使用自动配置 3、使用 Spring Initializr 来开始一个新的 Spring Boot 项目 4、考虑为常见的组织问题创建自己的自动配置 5、正确设计代码目录结构 6、保持 Controller 的简洁和专注 7、围绕业务功能构建 Service 8、使数据库独立于核心…