Java最新老Java程序员花一天时间写了个飞机大战,很舒服!,Java岗面试

最后

金三银四到了,送上一个小福利!

image.png

image.png

专题+大厂.jpg

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

右键执行这个Main类,窗口建出来了

​​窗口

创建菜单及菜单选项


创建菜单

private void initMenu(){

// 创建菜单及菜单选项

jmb = new JMenuBar();

JMenu jm1 = new JMenu(“游戏”);

jm1.setFont(new Font(“微软雅黑”, Font.BOLD, 15));// 设置菜单显示的字体

JMenu jm2 = new JMenu(“帮助”);

jm2.setFont(new Font(“微软雅黑”, Font.BOLD, 15));// 设置菜单显示的字体

JMenuItem jmi1 = new JMenuItem(“开始新游戏”);

JMenuItem jmi2 = new JMenuItem(“退出”);

jmi1.setFont(new Font(“微软雅黑”, Font.BOLD, 15));

jmi2.setFont(new Font(“微软雅黑”, Font.BOLD, 15));

JMenuItem jmi3 = new JMenuItem(“操作说明”);

jmi3.setFont(new Font(“微软雅黑”, Font.BOLD, 15));

JMenuItem jmi4 = new JMenuItem(“胜利条件”);

jmi4.setFont(new Font(“微软雅黑”, Font.BOLD, 15));

jm1.add(jmi1);

jm1.add(jmi2);

jm2.add(jmi3);

jm2.add(jmi4);

jmb.add(jm1);

jmb.add(jm2);

mainFrame.setJMenuBar(jmb);// 菜单Bar放到JFrame上

jmi1.addActionListener(this);

jmi1.setActionCommand(“Restart”);

jmi2.addActionListener(this);

jmi2.setActionCommand(“Exit”);

jmi3.addActionListener(this);

jmi3.setActionCommand(“help”);

jmi4.addActionListener(this);

jmi4.setActionCommand(“win”);

}

实现ActionListener并重写方法actionPerformed

在这里插入图片描述

actionPerformed方法的实现

@Override

public void actionPerformed(ActionEvent e) {

String command = e.getActionCommand();

UIManager.put(“OptionPane.buttonFont”, new FontUIResource(new Font(“宋体”, Font.ITALIC, 18)));

UIManager.put(“OptionPane.messageFont”, new FontUIResource(new Font(“宋体”, Font.ITALIC, 18)));

if (“Exit”.equals(command)) {

Object[] options = { “确定”, “取消” };

int response = JOptionPane.showOptionDialog(this, “您确认要退出吗”, “”,

JOptionPane.YES_OPTION, JOptionPane.QUESTION_MESSAGE, null,

options, options[0]);

if (response == 0) {

System.exit(0);

}

}else if(“Restart”.equals(command)){

if(startFlag){

Object[] options = { “确定”, “取消” };

int response = JOptionPane.showOptionDialog(this, “游戏中,您确认要重新开始吗”, “”,

JOptionPane.YES_OPTION, JOptionPane.QUESTION_MESSAGE, null,

options, options[0]);

if (response == 0) {

//需要先结束游戏

realGameEnd(1);

restart();

}

}else{

restart();

}

}else if(“help”.equals(command)){

JOptionPane.showMessageDialog(null, “游戏开始后,要先动鼠标到飞机处,触发移动效果,然后飞机就会跟随鼠标移动!”,

“提示!”, JOptionPane.INFORMATION_MESSAGE);

}else if(“win”.equals(command)){

JOptionPane.showMessageDialog(null, “得分1000,获得胜利!”,

“提示!”, JOptionPane.INFORMATION_MESSAGE);

}

}

在这里插入图片描述

创建背景


在GamePanel类中重写paint方法,绘制背景图即可

//绘图方法

@Override

public void paint(Graphics g) {

gameHeight = this.getHeight();

gameWidth = this.getWidth();

//绘制背景

g.drawImage((BufferedImage)imageMap.get(“bg”), 0, -150, null);

}

在这里插入图片描述

开启主线程


主线程,用来重绘页面,重绘全部交给主线程,主线程调用 repaint方法就行,要产生动画就要靠这个repaint。

//刷新线程,用来重新绘制页面

private class RefreshThread implements Runnable {

@Override

public void run() {

while (startFlag) {

repaint();

try {

Thread.sleep(50);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

在GamePanel的构造里面启动这个主线程

在这里插入图片描述

有了这个主线程刷新,待会我们更新飞机的位置,飞机就会移动,不需要另外的代码去调用repaint方法了(这是我的做法,仅供参考)。

创建我方飞机


创建MyPlane类,属性有坐标x、y,宽高、图片、是否存活、是否可以移动等;方法主要有绘制、移动、射击等。

public class MyPlane {

private int x = 0;

private int y = 0;

private int width = 0;

private int height = 0;

private BufferedImage image = null;

private GamePanel panel=null;

private HashMap imageMap=null;

private boolean alive=true;

private boolean canMove=false;

private int key=1;

private HashMap boomImageMap=null;

private boolean hitFlag=false;//正在碰撞

public MyPlane(int x,int y,int width,int height,GamePanel panel) {

this.x=x;

this.y=y;

this.width=width;

this.height=height;

this.panel=panel;

this.imageMap=panel.imageMap;

this.image=(BufferedImage)imageMap.get(“myplane1”);

this.boomImageMap=panel.mypalneBoomImageMap;

}

//绘制

public void draw(Graphics g) {

g.drawImage(image, x, y, width,height, null);

}

}

创建(这里只是创建好了飞机对象,需要绘制)

//创建自己飞机

private void initMyPlane() {

myPlane = new MyPlane(200, 530, 132, 86, this);

}

在paint方法中绘制

//绘图方法

@Override

public void paint(Graphics g) {

gameHeight = this.getHeight();

gameWidth = this.getWidth();

//绘制背景

g.drawImage((BufferedImage)imageMap.get(“bg”), 0, -150, null);

//绘制飞机

if(myPlane!=null){

myPlane.draw(g);

}

}

在这里插入图片描述

鼠标事件监听


加入监听是为了让飞机跟随鼠标移动,我这里定的规则是第一次鼠标必须移动到飞机上,然后飞机才会跟随。

代码里面用一个属性canMove来控制,默认是false,只有鼠标第一次移入到飞机上时,这个属性设置为true,然后就可以跟随鼠标移动了。

//鼠标事件的创建

private void createMouseListener() {

MouseAdapter mouseAdapter = new MouseAdapter() {

@Override

public void mouseMoved(MouseEvent e) {

int x = e.getX();

int y = e.getY();

if(myPlane==null) return ;

//飞机第一次是不允许移动的,只有飞机的canMove为true才去跟随

if(myPlane.isCanMove()){

myPlane.move(x,y);

return;

}

//判断鼠标的移入,如果移动到飞机上则canMove设置为true

if(myPlane.isPoint(x,y)){

myPlane.setCanMove(true);

}

}

};

addMouseMotionListener(mouseAdapter);

addMouseListener(mouseAdapter);

}

来实现一下MyPlane的move方法,这里处理了边界,保证飞机不出界,同时保证鼠标在飞机的中间位置

//飞机跟随鼠标移动

public void move(int x,int y) {

//判断范围,当横向移动在窗口范围内

if(x-width/2>=0 && x<=panel.getWidth()-width/2){

this.x=x-width/2;

}

//判断范围,当纵向移动在窗口范围内

if(y-height/2>=0 && y<=panel.getHeight()-height/2){

this.y=y-height/2;

}

}

在这里插入图片描述

创建子弹类


属性也就是坐标、宽高这些,给子弹加入移动方法

//移动

void move(){

new Thread(new Runnable() {

@Override

public void run() {

while(alive){

y-=speed;

if(y<=0){

clear();

}

try {

Thread.sleep(50);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}).start();

}

飞机类加入射击方法,200毫秒创建一发子弹

//射击

void shoot() {

new Thread(new Runnable() {

@Override

public void run() {

while(alive){

//创建子弹

createBullet();

try {

Thread.sleep(200);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

private void createBullet() {

Bullet bullet = new Bullet(x+width/2-10, y, 20, 30, panel);

panel.bulletList.add(bullet);

new MusicPlayer(“/music/shoot.wav”).play();

}

}).start();

}

别忘记在paint方法里面绘制子弹出来

//绘制子弹

Bullet bullet=null;

for (int i = 0; i < bulletList.size(); i++) {

bullet = (Bullet)bulletList.get(i);

bullet.draw(g);

}

在这里插入图片描述

创建敌机


创建抽象类Plane

package main;

import java.awt.Graphics;

public abstract class Plane {

public abstract void move();

public abstract void draw(Graphics g);

public abstract void boom();

public abstract void clear();

abstract int getX();

abstract int getY();

abstract int getWidth();

abstract int getHeight();

}

创建敌机子类

有个特殊一点的地方: 因为有4种敌机,这里随机1、2、3、4这4个数字作为属性index,然后根据这个index来展现不同的飞机图片,当然也可以通过这个index来设置敌机不同的移动速度,但是我为了偷懒,就全部一样的移动速度,嘿嘿。

移动就是开启线程让y坐标增加,没什么好讲的,这里加一个飞机碰撞,就是当敌机跟我方飞机如何判断碰撞的问题。

撞机分析(敌机与我机的撞机)

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

从上面几个图可看出什么?因为图片是方形的,他们的4个顶点一定至少有一个在对方的范围内。再看一下从左边撞击的图:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

从上图看到也是这样,其他两个方向的也是一样的道理,为了稳点我还加了一种情况:

1.判断敌机的4个点是否在飞机范围内,如果有则表示碰撞了。

2.如果1不成立,则反过来,判断我机的4个点是否在敌机的范围内,如果是表示碰撞了。

//判断飞机与子弹是否碰撞

private boolean isPoint(MyPlane plane) {

/*

  • 两种情况

  • 1.需要判断敌机的4个点是否在飞机范围内,如果有则表示碰撞了

  • 2.如果步骤1不成立,则反过来,判断我机的4个点是否在敌机的范围内,如果是标志碰撞了

*/

写在最后

学习技术是一条慢长而艰苦的道路,不能靠一时激情,也不是熬几天几夜就能学好的,必须养成平时努力学习的习惯。所以:贵在坚持!

最后再分享的一些BATJ等大厂20、21年的面试题,把这些技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,上面只是以图片的形式给大家展示一部分。

蚂蚁金服三面直击面试官的Redis三连,Redis面试复习大纲在手,不慌

Mybatis面试专题

蚂蚁金服三面直击面试官的Redis三连,Redis面试复习大纲在手,不慌

MySQL面试专题

蚂蚁金服三面直击面试官的Redis三连,Redis面试复习大纲在手,不慌

并发编程面试专题

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

,如果有则表示碰撞了。

2.如果1不成立,则反过来,判断我机的4个点是否在敌机的范围内,如果是表示碰撞了。

//判断飞机与子弹是否碰撞

private boolean isPoint(MyPlane plane) {

/*

  • 两种情况

  • 1.需要判断敌机的4个点是否在飞机范围内,如果有则表示碰撞了

  • 2.如果步骤1不成立,则反过来,判断我机的4个点是否在敌机的范围内,如果是标志碰撞了

*/

写在最后

学习技术是一条慢长而艰苦的道路,不能靠一时激情,也不是熬几天几夜就能学好的,必须养成平时努力学习的习惯。所以:贵在坚持!

最后再分享的一些BATJ等大厂20、21年的面试题,把这些技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,上面只是以图片的形式给大家展示一部分。

[外链图片转存中…(img-pBBRb9Fi-1715442217239)]

Mybatis面试专题

[外链图片转存中…(img-Gtja0COR-1715442217239)]

MySQL面试专题

[外链图片转存中…(img-u9JZqjjU-1715442217240)]

并发编程面试专题

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

  • 30
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值