Old Java programmers spent a day writing a plane war, very comfortable!

Old Java programmers spent 1 day making a plane war

introduction:

Two days ago, I found that there are two articles about aircraft wars on CSDN that are extremely popular, and various indicators are very high (reading, likes, comments, collections, etc.), but they are all written in python, it is not my big Java, to be honest As a veteran java player, I feel so lost in my heart. Isn't it possible that I can't play a plane with a big java? Even if the big java is not good for hitting planes, then I will use the hand speed of being single for 30 years, I will definitely do (anyway, my code is the master, just play!), so I decided to stretch out my hand and write a plane war in java. I asked you if I can fly by plane. My wife said yes. How about you? Welcome my dear big Java players to like + comment + favorite! Chong, Chong, Chong for me. . .

Code

Create window

First create a game window class GameFrame, inherited from JFrame, used to display on the screen (the object of the window), each game has a window, set the window title, size, layout, and so on.

/*
 * 游戏窗体类
 */
public class GameFrame extends JFrame {
	
	public GameFrame() {
		setTitle("飞机大战");//设置标题
		setSize(526, 685);//设定尺寸
		setLayout(new BorderLayout());
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//点击关闭按钮是关闭程序
        setLocationRelativeTo(null);   //设置居中
    	setResizable(false); //不允许修改界面大小
	}
}

Create a panel container GamePanel inherited to JPanel

package main;

import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
/*
 * 画布类
 */
public class GamePanel extends JPanel{
	GamePanel gamePanel=this;
	private JFrame mainFrame=null;
	//构造里面初始化相关参数
	public GamePanel(JFrame frame){
		this.setLayout(null);
		mainFrame = frame;
		
		mainFrame.setVisible(true);
	}
	
	@Override
	public void paint(Graphics g) {
		
	}
}

Create a Main class to start this window to start.

package main;
public class Main {
	//主类
	public static void main(String[] args) {
		GameFrame frame = new GameFrame();
		GamePanel panel = new GamePanel(frame);
		frame.add(panel);
		frame.setVisible(true);//设定显示
	}
}

Right-execute the Main class, built out of the window

window

Create menus and menu options

Create menu

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");
}

Implement ActionListener and override method actionPerformed

Insert picture description here


Implementation of the actionPerformed method

@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);
	}
}
Insert picture description here

Create the background

Rewrite the paint method in the GamePanel class and draw the background image

//绘图方法
@Override
public void paint(Graphics g) {
	gameHeight = this.getHeight();
	gameWidth = this.getWidth();
	//绘制背景
	g.drawImage((BufferedImage)imageMap.get("bg"), 0, -150, null);
}
Insert picture description here

Start the main thread

The main thread is used to redraw the page. All redrawing is handed over to the main thread. The main thread calls the repaint method. To generate animation, it depends on this repaint.

//刷新线程,用来重新绘制页面
private class RefreshThread implements Runnable {
	@Override
	public void run() {
		while (startFlag) {
			repaint();
			try {
				Thread.sleep(50);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

Start the main thread in the structure of the GamePanel

Insert picture description here


With this main thread refresh, we will update the position of the aircraft later, and the aircraft will move. There is no need for additional code to call the repaint method (this is my approach and is for reference only).

Create our plane

Create the MyPlane class, with attributes such as coordinates x, y, width and height, picture, whether it is alive, whether it can be moved, etc. The methods mainly include drawing, moving, shooting, etc.

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);
	}
}

Create (Here is just the aircraft object created and needs to be drawn)

//创建自己飞机
private void initMyPlane() {
	myPlane = new MyPlane(200, 530, 132, 86, this);
}

Draw in the paint method

//绘图方法
@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);
	}
}
Insert picture description here

Mouse event monitoring

The purpose of monitoring is to make the aircraft move with the mouse. The rule I set here is that the mouse must move to the aircraft for the first time, and then the aircraft will follow.

The code uses a property canMove to control, the default is false, only when the mouse is moved into the aircraft for the first time, this property is set to true, and then it can move with the mouse.

//鼠标事件的创建
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);
}

Let’s implement the move method of MyPlane. The boundary is processed here to ensure that the aircraft does not go out of the boundary and the mouse is in the middle of the aircraft.

//飞机跟随鼠标移动
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;
	}
}
Insert picture description here

Create bullet class

Attributes are coordinates, width and height, and add movement methods to the bullet

//移动
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();
}

Add a shooting method to the aircraft class, creating a bullet in 200 milliseconds

//射击
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();
}

Don't forget to draw the sub-pop in the paint method

//绘制子弹
Bullet bullet=null;
for (int i = 0; i < bulletList.size(); i++) {
	bullet = (Bullet)bulletList.get(i);
	bullet.draw(g);
}
Insert picture description here

Create an enemy plane

Create abstract class 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();
}

Create an enemy aircraft subclass

There is a special place: Because there are 4 types of enemy aircraft, here are the 4 random numbers 1, 2, 3, and 4 as the attribute index, and then display different aircraft pictures according to this index. Of course, you can also set the enemy aircraft’s different moving speeds through this index. But to be lazy, I move at the same speed, hehe.
Moving is to start the thread to increase the y coordinate. There is nothing to talk about. Adding an aircraft collision here is the question of how to judge the collision when the enemy aircraft and our aircraft collide.

Collision analysis (collision between enemy aircraft and our aircraft)

Insert picture description here


Insert picture description here


Insert picture description here


What can be seen from the above pictures? Because the picture is square, at least one of their 4 vertices must be within the range of each other. Take another look at the image hit from the left:

Insert picture description here


Insert picture description here


Insert picture description here


It can be seen from the above picture. The same is true for the other two directions. To stabilize, I also added a situation:

1. Determine whether the 4 points of the enemy aircraft are within the range of the aircraft. If there are, it means a collision.
2. If 1 is not true, then conversely, judge whether the 4 points of our aircraft are within the range of the enemy aircraft, if it is a collision.

//判断飞机与子弹是否碰撞
private boolean isPoint(MyPlane plane) {
	/*
	 * 
	 * 两种情况
	 * 1.需要判断敌机的4个点是否在飞机范围内,如果有则表示碰撞了
	 * 2.如果步骤1不成立,则反过来,判断我机的4个点是否在敌机的范围内,如果是标志碰撞了
	*/
	
	//方式1
	
	//左上角
	int x1 = x;
	int y1 = y;
	//右上角
	int x2 = x+width;
	int y2 = y;
	//右下角
	int x3 = x+width;
	int y3 = y+height;
	//左下角
	int x4 = x;
	int y4 = y+height;
	//只要有一个点在范围内,则判断为碰撞
	if(comparePointMyPlane(x1,y1,plane)|| comparePointMyPlane(x2,y2,plane)||comparePointMyPlane(x3,y3,plane)||comparePointMyPlane(x4,y4,plane) ){
		return true;
	}
	
	//方式1没成立则用方式2判断
	
	//方式2
	x1 = plane.getX();
	y1 = plane.getY();
	//右上角
	x2 = plane.getX()+plane.getWidth();
	y2 = plane.getY();
	//右下角
	x3 = plane.getX()+plane.getWidth();
	y3 =plane.getY()+plane.getHeight();
	//左下角
	x4 = plane.getX();
	y4 = plane.getY()+plane.getHeight();
	if(comparePoint(x1,y1)|| comparePoint(x2,y2)||comparePoint(x3,y3)||comparePoint(x4,y4) ){
		return true;
	}
	return false;
}
//用敌机的坐标来判断
private boolean comparePointMyPlane(int x,int y,MyPlane plane){
	//大于左上角,小于右下角的坐标则肯定在范围内
	if(x>plane.getX() && y >plane.getY()
		&& x<plane.getX()+plane.getWidth() && y <plane.getY()+plane.getHeight()	){
		return  true;
	}
	return false;
}
//用我机的坐标来判断
private boolean comparePoint(int x,int y){
	//大于左上角,小于右下角的坐标则肯定在范围内
	if(x>this.x && y >this.y
		&& x<this.x+this.width && y <this.y+this.height){
		return  true;
	}
	return false;
}

Test the effect

Insert picture description here

Forgot to say that it hit the enemy plane (the principle is the same as before, the code is put directly)

//判断击中敌机
protected void hitEnemy() {
	EnemyPlane enemyPlane=null;
	List enemys = panel.enemyList;
	for (int i = 0; i < enemys.size(); i++) {
		try {
			enemyPlane = (EnemyPlane)enemys.get(i);
		} catch (Exception e) {
		}
		if(enemyPlane==null) continue;
		if(this.isPoint(enemyPlane)){
			
			panel.curCount+=enemyPlane.getCount();
			//删除当前子弹
			clear();
			
			//飞机爆炸
			enemyPlane.boom();
			
			if(panel.curCount>=panel.totalCount){
				panel.myPlane.setCanMove(false);
				panel.gameWin();
			}
		}
	}
}

//判断飞机与子弹是否碰撞
private boolean isPoint(EnemyPlane plane) {
	//因为子弹比飞机小,所以只需要判断子弹的4个点是否在飞机范围内,如果有则表示碰撞了
	//左上角
	int x1 = x;
	int y1 = y;
	//右上角
	int x2 = x+width;
	int y2 = y;
	//右下角
	int x3 = x+width;
	int y3 = y+height;
	//左下角
	int x4 = x;
	int y4 = y+height;
	//只要有一个点在范围内,则判断为碰撞
	if(comparePoint(x1,y1,plane)|| comparePoint(x2,y2,plane)||comparePoint(x3,y3,plane)||comparePoint(x4,y4,plane) ){
		return true;
	}
	return false;
}

private boolean comparePoint(int x,int y,EnemyPlane plane){
	//大于左上角,小于右下角的坐标则肯定在范围内
	if(x>plane.getX() && y >plane.getY()
		&& x<plane.getX()+plane.getWidth() && y <plane.getY()+plane.getHeight()	){
		return  true;
	}
	return false;
}

Finally, add scoring, victory, defeat and other hints and you're done!

Seeing the big guys here, move the little hands of making a fortune like + Reply + Favorites,can【 attention] One wave is better.
Need source codeleave a message or Private letters,I send it to you!

In order to help more Xiaobai advanced Java engineers from zero, I got a set from the CSDN official side "Java Engineers Learning and Growth Knowledge Graph",size 870mm x 560mmAfter unfolding, it has the size of a desk, or it can be folded into the size of a book. Interested friends can find out about it.

Insert picture description here

★ More exciting

♥ Java Plants vs. Zombies♥

♥ Java tank battle, memories of childhood! ♥

♥ Java minesweeper games, I used to play in school ♥

♥Java Student Dormitory Management System♥