从前看马士兵老师的教程,学过一个坦克大战,不过当时一头雾水,一直想着模仿着写一个飞机大战,放假了终于动手写了,虽然AWT似乎已经不推荐用了,但是懒得研究swing啊,作为javase的练习还是可以的。
有点成型,尚未完成。
构想:
飞机从一开始就一直发射子弹(和微信那个差不多),敌方飞机从“天上”往下降落,但是不会发射子弹。
普通敌方飞机一炸就死。
BOSS敌方飞机则需要较长时间的攻击。
我方飞机一炸就死。
我方飞机可以吃技能,分别是
- 无敌技能
- 三射技能
- 变弱技能
这三个技能不能共存,使用状态模式控制。
首先,实现游戏窗口:继承Frame类
public class GameClient extends Frame
// 启动窗口
private void launchFrame() {
// 位置,大小,添加按键监听
this.setLocation(GameConstant.FrameData.WIN_X,
GameConstant.FrameData.WIN_Y);
this.setSize(GameConstant.FrameData.WIN_WIDTH,
GameConstant.FrameData.WIN_HEIGHT);
this.setResizable(false);
this.setTitle(GameConstant.GameStr.GAME_NAME);
this.setBackground(GameConstant.ColorHelper.GAMEBKCOLOR);
this.addWindowListener(new MyWindowAdapter());
this.addKeyListener(new KeyMonitor());
setVisible(true);
new Thread(paintThread).start();
new Thread(attack).start();
new Thread(fire).start();
new Thread(bossAttackThread).start();
}
四个线程是分别控制游戏的线程,暂时不理。
GameConstant这个类是用来放一些静态变量的,可以自己控制调试,游戏速度,角色大小等。
import java.awt.Color;
public class GameConstant {
// 游戏窗口的静态变量
public static class FrameData {
public static final int WIN_WIDTH = 400;
public static final int WIN_HEIGHT = 600;
public static final int WIN_X = 350;
public static final int WIN_Y = 50;
}
// 颜色
public static class ColorHelper {
public static final Color MAIN_PALNE_COLOR = Color.BLUE;
public static final Color PCNORMALCOLOR = Color.RED;
public static final Color BOSSCOLOR = Color.YELLOW;
public static final Color MISSLECOLOR = Color.BLACK;
public static final Color GAMEBKCOLOR = Color.WHITE;
}
// 游戏相关的静态变量
public static class GameStr {
public static final String GAME_NAME = "beatPlane";
}
// 子弹静态变量
public static class BulletData {
public static final int RADIUS = 10;
public static final int SPEED = 3;
public static final int ATTACKVALUE = 1;
}
// 我方飞机静态变量
public static class MainPlaneData {
public static final int RADIUS = 20;
public static final int FIRST_X = 175;
public static final int FIRST_Y = 550;
public static final int SPEED = 5;
}
// 普通敌方飞机的静态变量
public static class NormalPcPlaneData {
public static final int RADIUS = 20;
public static final int INIT_SPEED = 1;
public static final int BLOOD = 1;
}
// 敌方飞机BOSS的静态变量
public static class BossPcPlaneData {
public static final int RADIUS = 40;
public static final int INIT_SPEED = 1;
public static final int BLOOD = 10;
}
}
这里的 MyWindowAdapter很简单,为了控制右上角点击xx时候的动作,默认当然是退出游戏。
public class MyWindowAdapter extends WindowAdapter{
public void windowClosing(WindowEvent arg0) {
System.exit(0);
}
}
// 按键监听
private class KeyMonitor extends KeyAdapter {
public void keyPressed(KeyEvent keyEvent) {
mainPlane.onkeyPressed(keyEvent);
}
}
在launchFrame方法执行之后,启动了四个线程:
new Thread(paintThread).start();
new Thread(attack).start();
new Thread(fire).start();
new Thread(bossAttackThread).start();
new Thread(fire).start();
new Thread(bossAttackThread).start();
先看paintThread:
// 不断刷新画面的线程
private class PaintThread implements Runnable {
public void run() {
while (true) {
// 每隔15ms,调用父类的repaint()方法
repaint();
try {
Thread.sleep(15);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
为什么调用父类的repaint方法呢?
就要看这个update方法了:
// 重写update方法,在父类repaint()方法调用的时候会调用这个方法
public void update(Graphics g) {
if (offScreanImage == null) {
offScreanImage = this.createImage(GameConstant.FrameData.WIN_WIDTH,
GameConstant.FrameData.WIN_HEIGHT);
}
Graphics gOffScrean = offScreanImage.getGraphics();
Color preColor = gOffScrean.getColor();
gOffScrean.setColor(GameConstant.ColorHelper.GAMEBKCOLOR);
gOffScrean.fillRect(0, 0, GameConstant.FrameData.WIN_WIDTH,
GameConstant.FrameData.WIN_HEIGHT);
gOffScrean.setColor(preColor);
paint(gOffScrean);
g.drawImage(offScreanImage, 0, 0, null);
}
If this component is not a lightweight component, the AWT calls the update
method in response to a call to repaint
. You can assume that the background is not cleared.
简单理解,这个update就是用来刷新界面的,我其实也不是特别理解。
先到这里吧。