在整个代码实现中,以GUI绘制界面,使用线程来控制敌方飞机和大boss的创建,采用键盘监听来实现控制小飞机的飞行方向和发射子弹。话不多说,先上最后效果图。
资源源码在这里
程序入口,界面主类:
public class GameWindow extends Frame {
//窗口宽度
public static int WINDOW_WIDTH = 1366;
//窗口高度,单位像素
public static int WINDOW_HEIGHT = 720;
private static Image bgimg = null;
public GameWindow(String title) {
super(title);
init();
//播放背景音乐
GameComponent.getBackgroundMusic().play();
//启动线程重复画面板
new Thread(new PrintPlane(this)).start();
//启动线程创建UFO
new Thread(new CreateUfo(this)).start();
}
/**
* 初始化方法
*/
private void init() {
setBounds(GameUtil.getMidXY(WINDOW_WIDTH, POSITION.X),GameUtil.getMidXY(WINDOW_HEIGHT,POSITION.Y),WINDOW_WIDTH,WINDOW_HEIGHT);
//设置窗口界面
setVisible(true);
//添加监听方法
addListener();
}
public void addListener() {
//窗口关闭的监听
this.addWindowListener(new GameAdapter(this));
// 键盘按键监听
this.addKeyListener(new GameAdapter(this));
}
/**
* 重写update方法,reprint被调用则就是调用的update方法
* @param g
*/
@Override
public void update(Graphics g) {
if (bgimg == null) bgimg = createImage(WINDOW_WIDTH,WINDOW_HEIGHT);
//得到这个底片的画笔
Graphics bg = bgimg.getGraphics();
bg.setColor(Color.white);
bg.fillRect(0,0,WINDOW_WIDTH,WINDOW_HEIGHT);
print(bg);
g.drawImage(bgimg,0,0,this);
}
/**
* 窗口每变更一次,此方法则被调用一次
* @param g
*/
@Override
public void paint(Graphics g) {
//画背景图
GameComponent.getBackground(this).showMe(g);
//显示飞机
GameComponent.getPlane(GameWindow.this).showMe(g);
//画飞机的血条
GameComponent.getPlaneBloodBar(this).showMe(g);
//显示我方飞机的子弹
List<Bullet> bulletList = GameComponent.getBulletList();
for (int i = 0;i<bulletList.size();i++) {
Bullet bullet = bulletList.get(i);
bullet.showMe(g);
}
//画飞碟小怪
List<Ufo> ufoList = GameComponent.getUfoList();
for (int i = 0;i<ufoList.size();i++) {
Ufo ufo = ufoList.get(i);
ufo.showMe(g);
}
//画飞碟子弹
List<UfoBullet> ufoBulletList = GameComponent.getUfoBulletList();
for (int i = 0;i<ufoBulletList.size();i++) {
UfoBullet ufoBullet = ufoBulletList.get(i);
ufoBullet.showMe(g);
}
//画Boss
List<Boss> bossList = GameComponent.getBossList();
for (int i = 0;i<bossList.size();i++) {
Boss boss = bossList.get(i);
boss.showMe(g);
}
//画Boss子弹
List<BossBullet> bossBulletList = GameComponent.getBossBulletList();
for (int i = 0;i<bossBulletList.size();i++) {
BossBullet bossBullet = bossBulletList.get(i);
bossBullet.showMe(g);
}
//画爆炸效果
List<Bomb> bombList = GameComponent.getBombList();
for (int i = 0;i<bombList.size();i++) {
Bomb bomb = bombList.get(i);
bomb.showMe(g);
}
//画消灭小怪的数目
g.setColor(Color.black);
g.drawString("消灭小怪数量:" + GlobalVariable.deadUfoCount,20,50);
}
public void addBullet(Bullet bullet) {
GameComponent.addBullet(bullet);
}
public static void main(String[] args) {
GameComponent.init();
new GameWindow("飞机大战");
}
//内部类线程控制画窗口
private class PrintPlane implements Runnable {
private GameWindow gameWindow;
public PrintPlane(GameWindow gameWindow) {
this.gameWindow = gameWindow;
}
@Override
public void run() {
//死循环一直画窗口的内容,实现动画效果。
while (true) {
gameWindow.repaint();
}
}
}
}
游戏中组件的父类
public abstract class GameRole {
//组件在窗口的位置
protected int x;
protected int y;
//大小
protected int width = 5;
protected int height = 5;
//是否活着,即确认窗口是否画该组件
protected boolean isAlive;
//显示组件的窗口
protected GameWindow gameWindow;
//组件在窗口显示自己的方法
public abstract void showMe(Graphics g);
public GameRole() {
}
public GameRole(int x, int y, int width, int height, boolean isAlive, GameWindow gameWindow) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.isAlive = isAlive;
this.gameWindow = gameWindow;
}
//组件移动的方法
public abstract void move();
//得到组件的外切矩形
public Rectangle getRectangle(){
return new Rectangle(x,y,width,height);
}
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;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public boolean isAlive() {
return isAlive;
}
public void setAlive(boolean alive) {
isAlive = alive;
}
public GameWindow getGameWindow() {
return gameWindow;
}
public void setGameWindow(GameWindow gameWindow) {
this.gameWindow = gameWindow;
}
}
主角飞机类
package com.hyy.pojo;
import com.hyy.enums.DIRECTION;
import com.hyy.main.GameWindow;
import com.hyy.utils.GameComponent;
import java.awt.*;
import java.awt.event.KeyEvent;
public class Plane extends GameRole{
//飞机速度
private int speed = 1;
//飞机方向
private boolean up,down,left,right;
private DIRECTION dir = DIRECTION.STOP;
//飞机上下飞动画索引
private int index = 4;
//血条
private int hp = 355;
public Plane() {}
public Plane(int x, int y, int width, int height, boolean isAlive, GameWindow gameWindow) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.isAlive = isAlive;
this.gameWindow = gameWindow;
}
public Plane(int x, int y, boolean isAlive,int width, int height, int speed, GameWindow gameWindow) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.isAlive = isAlive;
this.speed = speed;
this.gameWindow = gameWindow;
}
/**
* 在窗口显示飞机
*/
public void showMe(Graphics g) {
if (hp <= 0) isAlive = false;
if (gameWindow != null && isAlive) {
g.drawImage(GameComponent.getPlaneImage()[index],x,y,width,height,gameWindow);
move();
}
}
/**
* 键盘按下的监听
* @param e
*/
public void isPressed(KeyEvent e) {
switch(e.getKeyCode()) {
case KeyEvent.VK_W:
up = true;
break;
case KeyEvent.VK_S:
down = true;
break;
case KeyEvent.VK_A:
left = true;
break;
case KeyEvent.VK_D:
right = true;
break;
case KeyEvent.VK_J:
if (isAlive) fire();
break;
}
}
/**
* 发射子弹
*/
public void fire() {
Bullet bullet = new Bullet(x + width, y + (height/2), true,10,10, gameWindow);
gameWindow.addBullet(bullet);
GameComponent.getPlaneShootMusic().play();
}
/**
* 受伤
*/
public void injure(int injuryValue) {
hp -= injuryValue;
GameComponent.getPlaneBloodBar(gameWindow).setAllowance(hp);
}
/**
* 键盘松开的监听
* @param e
*/
public void isReleased(KeyEvent e) {
switch(e.getKeyCode()) {
case KeyEvent.VK_W:
up = false;
break;
case KeyEvent.VK_S:
down = false;
break;
case KeyEvent.VK_A:
left = false;
break;
case KeyEvent.VK_D:
right = false;
break;
}
}
/**
* 设置飞机方向
*/
public void setDirection() {
if (up && !down && !left && !right) dir = DIRECTION.UP;
if (!up && down && !left && !right) dir = DIRECTION.DOWN;
if (!up && !down && left && !right) dir = DIRECTION.LEFT;
if (!up && !down && !left && right) dir = DIRECTION.RIGHT;
if (up && !down && left && !right) dir = DIRECTION.LEFT_UP;
if (!up && down && left && !right) dir = DIRECTION.LEFT_DOWN;
if (up && !down && !left && right) dir = DIRECTION.RIGHT_UP;
if (!up && down && !left && right) dir = DIRECTION.RIGHT_DOWN;
if (!up && !down && !left && !right) dir = DIRECTION.STOP;
}
/**
* 控制飞机移动
*/
public void move() {
//其中的if语句限制了飞机的移动位置,防止飞机移动到屏幕范围外
setDirection();
switch (dir) {
case UP:
if (index > 0) index--;
if (y > 30)
y -= speed;
break;
case DOWN:
if (index < 8) index++;
if (y < (GameWindow.WINDOW_HEIGHT - 144))
y += speed;
break;
case LEFT:
if (x > 0)
x -= speed;
break;
case RIGHT:
if (x < (GameWindow.WINDOW_WIDTH - width))
x += speed;
break;
case LEFT_UP:
if (index > 0) index--;
if (x > 0)
x -= speed;
if (y > 30)
y -= speed;
break;
case LEFT_DOWN:
if (index < 8) index++;
if (x > 0)
x -= speed;
if (y < (GameWindow.WINDOW_HEIGHT - 144))
y += speed;
break;
case RIGHT_UP:
if (x < (GameWindow.WINDOW_WIDTH - width))
x += speed;
if (y > 30)
y -= speed;
break;
case RIGHT_DOWN:
if (x < (GameWindow.WINDOW_WIDTH - width))
x += speed;
if (y < (GameWindow.WINDOW_HEIGHT - 144))
y += speed;
break;
}
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
public int getHp() {
return hp;
}
public void setHp(int hp) {
this.hp = hp;
}
}
boss和小怪的实体类与主角飞机类似,不在一一贴代码了。