文章目录
前言
本人Java开发小白一枚,从0开始学开发。
本文将从头记录如何开发出自己的飞机大战,也供日后复习参考。
本文仅供参考,可能存在不少漏洞,望请指教。
提示:以下是本篇文章正文内容,下面案例可供参考
一、飞机大战一共需要哪几个类?
1. 界面类 2. 游戏监听器 3. 游戏主线程 4. 飞机对象类 5. 自动化线程二、各类详细讲解
1.界面类
顾名思义,GameUI 是用于创建游戏界面,包括设置界面属性,添加游戏中涉及到的监听器。一般需要在最开始就写出来。
代码如下(示例):
package feijidazhan.java0302;
import java.awt.Graphics;
import javax.swing.JFrame;
public class GameUI extends JFrame{
public static void main(String[] args) {
GameUI gameui= new GameUI();
gameui.initUI();
}
public void initUI() {
setTitle("飞机大战");
setSize(700,700);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
Graphics g = getGraphics(); //获取画笔
GameListener gl= new GameListener(g);
addMouseListener(gl);//添加鼠标监听器
addKeyListener(gl);//添加键盘监听器
addMouseMotionListener(gl); //添加鼠标拖拽监听器
}
}
2.游戏监听器
在这个类中需要把飞机大战中涉及到的监听器方法重写。
可以想一下,飞机大战需要哪些监听器呢?
首先,我们可以尝试添加一个鼠标监听器,当我们按下鼠标的时候就可以产生一个飞机。
代码如下(示例):
public void mousePressed(MouseEvent e){
Plane plane = new Plane(e.getX(), e.getY(), 100, 0, 1, 1, 1);//获取飞机的坐标
gl.planes[index++]= plane;//将飞机依次存入planes 队列
这里重写了鼠标监听器的方法,plane对象需要在Plane飞机类里写。
除此之外,我们还需要键盘监听器,我们可以通过键盘来控制飞机运动,从而实现友机和敌机的区分。
在最后,还引入了一个MouseMotionListener,这个监听器可以实现通过拖拽鼠标控制飞机。
在引入这些监听器之后,我们不着急先去写监听器中的方法,我们先去想一下如何写游戏主线程。
3.游戏主线程
可以想一下,这个主线程中,我们需要做些什么事?
1.画飞机 2.让飞机移动。
该如何画飞机呢?
在游戏中,应该是会有无数个敌机从上方飞下来,所以我们首先需要定义一个队列,把产生的飞机存到这个队列里面。然后从这个队列里面一个一个的取出来我们的飞机并画出来然后让飞机自己移动。
Plane[] planes= new Plane[1000];//创建队列 监听器获取飞机坐标后存入队列
while (true) {
g2d.drawImage(background, 0, 0, 700, 700,null); //在缓冲画布上绘制背景
for (int i =0; i<planes.length; i++) {
if (planes[i]!=null) {
//飞机绘制 移动 碰撞
Plane plane= planes[i];//依次读取队列中飞机
plane.drawplane(g2d);
plane.moveplane();
// plane.crashplane(planes);
}
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
此时,我们已经把敌机取出来并且可以画出来了,为了让敌机的飞行更流畅,我们选择先将飞机画在缓存画布上,然后在将缓存画布完整画出来,同时我们也将提前选好的飞机大战背景图片先画在缓存画布上面。
完整代码如下:
package feijidazhan.java0302;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
//绘制游戏主线程
public class GameThread implements Runnable{
Plane[] planes= new Plane[1000];//创建队列 监听器获取飞机坐标后存入队列
Graphics gui;
Plane goodplane;//声明变量 goodplane
@Override
public void run() {
// TODO Auto-generated method stub
BufferedImage buffimg=new BufferedImage(700, 700,BufferedImage.TYPE_INT_ARGB); //缓存画布
Graphics g= buffimg.getGraphics();
// g 绘制的内容显示在 buffimg上 -- 过程: 内存中 先绘制一个实心矩形 在绘制飞机
// gui 绘制 buffimg 负责将每张buffimg都绘制出来
Graphics2D g2d = (Graphics2D)g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Image background = new ImageIcon("飞机大战/background.jpeg").getImage();//声明背景并获取背景图片
while (true) {
// g2d.setColor(Color.white);
// g2d.fillRect(0, 0, 700, 700);
g2d.drawImage(background, 0, 0, 700, 700,null); //在缓冲画布上绘制背景
goodplane.drawplane(g2d);//画好飞机
for (int i =0; i<planes.length; i++) {
if (planes[i]!=null) {
// System.out.println(planes[i]);
//飞机绘制 移动 碰撞
Plane plane= planes[i];//依次读取队列中飞机
plane.drawplane(g2d);
plane.moveplane();
// plane.crashplane(planes);
}
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
gui.drawImage(buffimg, 0, 0, null);
}
}
}
4.飞机对象类
我们将在飞机对象类里面定义飞机如何画出、如何飞行、如何碰撞(在此还没完成如何碰撞)
package feijidazhan.java0302;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.ImageIcon;
public class Plane {
int x,y,size;
double speedx,speedy;
int identity,status;
Image goodplane = new ImageIcon("飞机大战/goodplane.png").getImage();//获取好飞机图像
Image badplane = new ImageIcon("飞机大战/badplane.png").getImage();//获取敌机图像
//飞机构造方法
public Plane(int x, int y, int size, double speedx, double speedy, int identity, int status) {
this.x = x;
this.y = y;
this.size = size;
this.speedx = speedx;
this.speedy = speedy;
this.identity = identity;
this.status = status;
}
public void crashplane(Plane[] planes) {
// TODO Auto-generated method stub
}
public void moveplane() {
// TODO Auto-generated method stub
y+=speedy;
}
public void drawplane(Graphics g) {
// TODO Auto-generated method stub
//判断飞机身份
if(identity == 1) {
g.drawImage(goodplane, x, y, size, size, null); //绘制敌机
}
else{
g.drawImage(badplane, x, y, size, size, null);//绘制好飞机
}
}
}
5.自动化线程
由于之前写到的飞机队列,我们将飞机依次从队列中取出,但是在游戏中,我们需要让敌机自动产生,而非我们手动点击产生,并且敌机的位置是随机的。
所以我们需要添加一个自动化线程类,通过该线程,我们可以调用plane方法,并且随机给飞机定义一个位置,并存入飞机队列中。
package feijidazhan.java0302;
import java.util.Random;
public class AutoThread implements Runnable {
Random random = new Random();
Plane planes[];
int index=0;
public void run() {
while(true) {
Plane plane = new Plane(random.nextInt(700), random.nextInt(100),50, 0, 3, 1, 1);//获取飞机的坐标
planes[index++]= plane;//将飞机依次存入planes 队列
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
6.完整代码
GameUI:
package feijidazhan.java0302;
import java.awt.Graphics;
import javax.swing.JFrame;
public class GameUI extends JFrame{
public static void main(String[] args) {
GameUI gameui= new GameUI();
gameui.initUI();
}
public void initUI() {
setTitle("飞机大战");
setSize(700,700);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
Graphics g = getGraphics(); //获取画笔
GameListener gl= new GameListener(g);
addMouseListener(gl);//添加鼠标监听器
addKeyListener(gl);//添加键盘监听器
addMouseMotionListener(gl); //添加鼠标拖拽监听器
}
}
GameListener:
package feijidazhan.java0302;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
public class GameListener implements MouseListener,KeyListener,MouseMotionListener{
Graphics g;
GameThread gt = new GameThread();//创建游戏主线程的对象
AutoThread at= new AutoThread();//创建自动出现敌机的线程对象
int index=0;//定义数组中飞机存放位置
Plane goodplane= new Plane(350, 350, 100, 0, 0, 0, 0); //x,y,size,speedx,speedy,identity,status,蓝色飞机
public GameListener (Graphics g) {
this.g =g;
gt.gui=g;
gt.goodplane= goodplane;
Thread thread = new Thread(gt);
at.planes= gt.planes;//让自动线程的planes 队列 得到 planes 队列中的飞机 ,从而自动产生飞机
Thread autothread = new Thread(at);
thread.start();
autothread.start();
}
public void mouseClicked(MouseEvent e) {}
public void mousePressed(MouseEvent e){
// Plane plane = new Plane(e.getX(), e.getY(), 100, 0, 1, 1, 1);//获取飞机的坐标
// gl.planes[index++]= plane;//将飞机依次存入planes 队列
}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e) {}
public void keyTyped(KeyEvent e) {}
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_UP) {
goodplane.y-=5;
}
if(e.getKeyCode()==KeyEvent.VK_DOWN) {
goodplane.y+=5;
}
if(e.getKeyCode()==KeyEvent.VK_LEFT) {
goodplane.x-=5;
}
if(e.getKeyCode()==KeyEvent.VK_RIGHT) {
goodplane.x+=5;
}
}
public void keyReleased(KeyEvent e) {}
public void mouseDragged(MouseEvent e) {
//鼠标拖动飞机移动-按下
goodplane.x=e.getX();
goodplane.y=e.getY();
}
public void mouseMoved(MouseEvent e) {}
}
GameThread:
package feijidazhan.java0302;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
//绘制游戏主线程
public class GameThread implements Runnable{
Plane[] planes= new Plane[1000];//创建队列 监听器获取飞机坐标后存入队列
Graphics gui;
Plane goodplane;//声明变量 goodplane
@Override
public void run() {
// TODO Auto-generated method stub
BufferedImage buffimg=new BufferedImage(700, 700,BufferedImage.TYPE_INT_ARGB); //缓存画布
Graphics g= buffimg.getGraphics();
// g 绘制的内容显示在 buffimg上 -- 过程: 内存中 先绘制一个实心矩形 在绘制飞机
// gui 绘制 buffimg 负责将每张buffimg都绘制出来
Graphics2D g2d = (Graphics2D)g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Image background = new ImageIcon("飞机大战/background.jpeg").getImage();//声明背景并获取背景图片
while (true) {
// g2d.setColor(Color.white);
// g2d.fillRect(0, 0, 700, 700);
g2d.drawImage(background, 0, 0, 700, 700,null); //在缓冲画布上绘制背景
goodplane.drawplane(g2d);//画友机
for (int i =0; i<planes.length; i++) {
if (planes[i]!=null) {
// System.out.println(planes[i]);
//飞机绘制 移动 碰撞
Plane plane= planes[i];//依次读取队列中飞机
plane.drawplane(g2d);
plane.moveplane();
// plane.crashplane(planes);
}
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
gui.drawImage(buffimg, 0, 0, null);
}
}
}
Plane:
package feijidazhan.java0302;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.ImageIcon;
public class Plane {
int x,y,size;
double speedx,speedy;
int identity,status;
Image goodplane = new ImageIcon("飞机大战/goodplane.png").getImage();//获取好飞机图像
Image badplane = new ImageIcon("飞机大战/badplane.png").getImage();//获取敌机图像
//飞机构造方法
public Plane(int x, int y, int size, double speedx, double speedy, int identity, int status) {
this.x = x;
this.y = y;
this.size = size;
this.speedx = speedx;
this.speedy = speedy;
this.identity = identity;
this.status = status;
}
public void crashplane(Plane[] planes) {
// TODO Auto-generated method stub
}
public void moveplane() {
// TODO Auto-generated method stub
y+=speedy;
}
public void drawplane(Graphics g) {
// TODO Auto-generated method stub
//判断飞机身份
if(identity == 1) {
g.drawImage(goodplane, x, y, size, size, null); //绘制敌机
}
else{
g.drawImage(badplane, x, y, size, size, null);//绘制好飞机
}
}
}
AutoThread:
package feijidazhan.java0302;
import java.util.Random;
public class AutoThread implements Runnable {
Random random = new Random();
Plane planes[];
int index=0;
public void run() {
while(true) {
Plane plane = new Plane(random.nextInt(700), random.nextInt(100),50, 0, 3, 1, 1);//获取飞机的坐标
planes[index++]= plane;//将飞机依次存入planes 队列
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
总结
以上就是如何通过线程制作一个简单的飞机大战游戏,总共涉及了5个类,各类之间的关系也并不复杂。但目前还未完成飞机碰撞以及发射子弹部分,后续会继续更新。
如有问题,欢迎批评指出。