上午没事刷到网上最近炒热了一些简单的小游戏和爱心代码,单身8个月了,对爱心代码不是很感冒,所以想蹭个热度,写一个飞机大站来玩玩。
首先,分析小游戏需要那些技术与怎么设计:
窗体,因为是java小游戏,那么就需要用到java的swing或者是Fx包里的相关图形化方法。
多线程,因为不可能是只有我们的飞机在飞,敌方也有飞机,子弹也需要飞行。
图片读取:需要将图片放入窗体中,所以需要借助画布,但是前提是我们需要将图片解析出来。
实体设计:越成熟的游戏设计的敌方飞机与我方飞机的功能与属性越多,这都需要基于实体实现。
那么基于以上几个点,我们首先就是建立一个可视化的窗体出来:
借助所谓的JFrame窗体类实现(也可继承来实现):
- public static void main(String[] args) throws IOException {
- JFrame frame = new JFrame();
- GamePanel gamePanel = new GamePanel();
- frame.add(gamePanel);
- frame.setSize(576, 840);
- frame.setTitle("战机");
- frame.setLocationRelativeTo(null);
- frame.setVisible(true);
- frame.setDefaultCloseOperation(3);
- gamePanel.move();
- frame.addMouseListener(gamePanel);
- frame.addMouseMotionListener(gamePanel);
- }
因为是一个窗体,所以我们需要借助画布对象来给窗体内部添加一些元素。也需要借助鼠标监听的相关接口对鼠标事件进行业务重写。
这里我们直接挂出来(相关代码的释疑都在注释里):
画布类:
- package com.hlc.Game;
-
- import javax.imageio.ImageIO;
- import javax.swing.*;
- import java.awt.*;
- import java.awt.event.MouseEvent;
- import java.awt.event.MouseListener;
- import java.awt.event.MouseMotionListener;
- import java.io.File;
- import java.io.IOException;
- import java.util.LinkedList;
- import java.util.List;
-
- import static java.awt.Font.BOLD;
-
-
- public class GamePanel extends JPanel implements MouseListener, MouseMotionListener {
-
- Image backGround, boss, zu, me,mePlus, ziDan, destroy, startGame;//图片资源
- int state;//控制游戏状态开关 变量 0未开始,1开始,2暂停,3退出
- int mark = 0, count = 0;//分数与计数器
- int mouseX = 180, mouseY = 500, blood = 100;//我方战斗机坐标X,Y与战斗机血量。
-
- boolean boom = false;//爆炸开关 显示爆炸图片的控制开关
- int badAirX, badAirY;//存储爆炸敌方飞机坐标便于画出爆炸图片
- List
badAirs = new LinkedList<>();//存储敌机对象 - List
ziDans = new LinkedList<>();//存储子弹对象 -
-
- public GamePanel() throws IOException {
- state = 0;
- mark = 0;
- backGround = ImageIO.read(new File("D:\\java项目\\Game\\Image\\back.png"));
- boss = ImageIO.read(new File("D:\\java项目\\Game\\Image\\boss.png"));
- startGame = ImageIO.read(new File("D:\\java项目\\Game\\Image\\start.png"));
- me = ImageIO.read(new File("D:\\java项目\\Game\\Image\\mePlus.png"));
- mePlus = ImageIO.read(new File("D:\\java项目\\Game\\Image\\me.png"));
- zu = ImageIO.read(new File("D:\\java项目\\Game\\Image\\zu.png"));
- ziDan = ImageIO.read(new File("D:\\java项目\\Game\\Image\\ziDan.png"));
- destroy = ImageIO.read(new File("D:\\java项目\\Game\\Image\\destroy.png"));
- }
-
- @Override
- public void paint(Graphics g) {
- super.paint(g);
- g.setFont(new Font("仿宋", BOLD, 20));
- g.setColor(Color.YELLOW);
- /*初始游戏状态*/
- if (state == 0) {
- g.drawImage(backGround, 0, 0, null);
- g.drawString("分数:" + mark + "", 0, 20);
- g.drawImage(boss, 204, 0, null);
- g.drawImage(startGame, 258, 300, null);
- g.drawString("开始游戏", 248, 400);
- g.drawImage(mePlus, 237, 500, null);
- }
- /*开始游戏状态*/
- else if (state == 1) {
- g.drawImage(backGround, 0, 0, null);
- g.drawString("分数:" + mark + "", 0, 20);
- if(mark > 50){
- g.drawImage(mePlus,mouseX-51,mouseY-63,null);
- }
- else
- g.drawImage(me,mouseX-23,mouseY-28,null);
-
- if (boom) {
- g.drawImage(destroy, badAirX, badAirY, null);
- boom = false;
- }
-
- for (int i = 0; i < ziDans.size(); i++) {
- ziDans.get(i).drawZiDan(g);
- }
-
- for (int i = 0; i < badAirs.size(); i++) {
- badAirs.get(i).drawPanel(g);
- }
- }
- /*暂停游戏状态*/
- else if (state == 2) {
- g.drawImage(backGround, 0, 0, null);
- g.drawString("分数:" + mark + "", 0, 20);
- g.drawImage(boss, 156, 0, null);
- g.drawImage(startGame, 210, 300, null);
- g.drawString("开始游戏", 200, 400);
- g.drawImage(me, 189, 500, null);
- }
- /*退出游戏状态(数据清空,等待重新开始游戏)*/
- else {
- state = 0;
- repaint();
- }
-
- }
-
- public void move() {
- new Thread() {
- @Override
- public void run() {
- super.run();
- while (true) {
- if (state == 1) {
- count++;//计数器自增开始
-
- if (count % 3 == 0) {
- ziDans.add(new ZiDan(mouseX,mouseY,ziDan));//创建新子弹
- }
- for (int i = 0;i
- ziDans.get(i).setY(ziDans.get(i).getY()-10);//发射子弹,超出窗体外则删除子弹对象
- if (ziDans.get(i).getY()<0){
- ziDans.remove(i);
- }
- }
-
- if (count%21 == 0){
- badAirs.add(new BadAir(zu));//创建敌机
- }else if(count % 72 == 0){
- badAirs.add(new BadAir(boss));
- }
-
- for (int i =0;i
- badAirs.get(i).setY(badAirs.get(i).getY()+3);//运动敌机,到达我方阵地则重新准备新局
- if (badAirs.get(i).getY()>700){
- state = 3;
- mark = 0;
- blood = 100;
- }
- }
-
- GameJudgeDead judgeDead = new GameJudgeDead();//初始化判断碰撞对象
-
- for (int i = 0;i
- ZiDan ziDan = ziDans.get(i);
- for (int j=0;j
- BadAir badAir = badAirs.get(j);
- if (judgeDead.judgeBoomZiDan(ziDan,badAir)){
- mark+=2;
- badAirX = badAir.getX();
- badAirY = badAir.getY();
- boom = true;
- ziDans.remove(i);
- badAirs.remove(j);
- break;
- }
- }
- }
-
- for (int i=0;i
- if (judgeDead.judgeBoomAir(badAirs.get(i),mouseX,mouseY)){
- badAirX = badAirs.get(i).getX();
- badAirY = badAirs.get(i).getY();
- boom = true;
- blood -= 30;
- if (blood <= 0) {
- state = 3;
- mark = 0;
- blood = 100;
- }
- }
- }
- }
- repaint();
- try{
- Thread.sleep(20);
- }catch (InterruptedException e){
- e.printStackTrace();
- }
- }
- }
- }.start();
- }
-
- @Override
- public void mouseClicked(MouseEvent e) {
- if (state == 0) {
- state = 1;
- } else if (state == 1) {
- state = 2;
- } else if (state == 2) {
- state = 1;
- } else {
- state = 0;
- }
- }
- .........接口方法存根省略..........
- @Override
- public void mouseMoved(MouseEvent e) {
- mouseX = e.getX();
- mouseY = e.getY();
- }
- }
这里需要注意几个问题,之前用webp格式的图片下载之后强行改后缀为png之后再内部怎么写都不能加载出来图片显示,这是一个问题,因为浏览器对图片进行了压缩解码,所以一定要下载原图!!!
接下来我们挂出来碰撞判断类:
- public class GameJudgeDead {
-
- public boolean judgeBoomZiDan(ZiDan ziDan, BadAir badAir) {
- return badAir.getX() < ziDan.getX() && badAir.getY() + badAir.height > ziDan.getY() && badAir.getX() + badAir.width > ziDan.getX();
- }
-
- public boolean judgeBoomAir(BadAir badAir, int mouseX, int mouseY) {
- mouseX = mouseX - 51;
- mouseY = mouseY - 63;
- return badAir.getX() < mouseX && badAir.getY() + badAir.height > mouseY && badAir.getX() + badAir.width > mouseY;
- }
- }
这里面你需要计算碰撞的条件,以及里面的坐标代表的意思,尤其是你切换图片之后对应的尺寸会变化,所以最好用实体。
敌机实体:
- public class BadAir {
- int X;
- int Y;
- Image badAir;
- int height;
- int width;
-
- public BadAir( Image badAir) {
- X =(int) (Math.random()*480);
- Y = -30;
- this.badAir = badAir;
- height = badAir.getHeight(null);
- width = badAir.getWidth(null);
- }
-
- void drawPanel(Graphics g){
- g.drawImage(badAir,X-27,Y-20,null);
- }
-
-
- public int getX() {
- return X;
- }
-
- public void setX(int x) {
- X = x;
- }
-
- public int getY() {
- return Y;
- }
-
- public void setY(int y) {
- Y = y;
- }
-
- }
注意这里将图片的尺寸写入到实体属性中去了,方便后续因为图片的切换来。
子弹实体类
- public class ZiDan {
- int x,y;
- Image ZiDan;
- public ZiDan(int mouseX,int mouseY,Image ZiDan){
- this.x = mouseX;
- this.y = mouseY;
- this.ZiDan = ZiDan;
- }
- public void drawZiDan(Graphics g){
- g.drawImage(ZiDan,x,y,null);
- }
-
- 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;
- }
- }
这里没有给敌机添加子弹。
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