目录
1.系统功能分析
2.设计模式应用
2.1 单例模式
应用场景:创建英雄机,为了保证英雄机类仅有一个实例,并提供访问该实例的全局访问点,需要用到单例模式来设计英雄机类。
UML结构图:
2.2 工厂模式
应用场景:飞机大战游戏中道具中不同种类道具的生成以及敌机中不同种类敌机的生成需要使用到工厂模式。原来的代码中,敌机以及道具都是需要使用时则新建一个对象,对象的创建和使用不分离。
道具类工厂模式的UML类图:
敌机类工厂模式的UML类图:
2.3 策略模式
应用场景:飞机大战游戏中子弹弹道的实现需要用到此模式。目前子弹的弹道只有单射模式,为了新增不同的子弹弹道并使得不同飞机可以按照不同的弹道模式发射子弹,则需使用策略模式封装不同的弹道模式,使不同的弹道模式可以相互替换,独立于调用弹道模式的飞机而变化。
UML结构图:
2.4 数据访问对象模式
应用场景:飞机大战游戏中玩家的得分排行等信息的获取需要用到数据访问对象模式。使用该模式新增了DAO层,不会影响到服务或者实体对象与数据库交互,发生错误会在该层进行异常抛出,使得程序中的其他部分可以通过DAO来访问数据而 不必与特定的读取和写入数据库的实现方式进行绑定。
UML:
2.5 观察者模式
应用场景:飞机大战游戏中炸弹道具的实现需要用到观察者模式。将炸弹道具生效时要清除的对象放进订阅者列表中,炸弹道具生效时通过notify方法通知所有订阅者,使订阅者调用vanish方法,实现清除效果。使用该模式可以简单高效的对多个对象执行相同的操作。
UML结构图:
2.6 模板模式
应用场景: 飞机大战游戏中设计三种不同难度的游戏需要用到模板模式。在飞机大战游戏中,easyGame、normalGame、hardGame继承Game,在Game基础上重写特定步骤,实现三种难度的具体细化。
UML结构图:
3.项目结构以及部分代码
项目结构:
主程序:
飞机类:
飞机工厂:
子弹类:
道具类:
道具工厂:
弹道策略:
部分类代码
Main:
public class Main {
public static final int WINDOW_WIDTH = 512;
public static final int WINDOW_HEIGHT = 768;
public static final Object lock = new Object();
public static void main(String[] args) {
System.out.println("Hello Aircraft War");
// 获得屏幕的分辨率,初始化 Frame
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
JFrame frame = new JFrame("Aircraft War");
frame.setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
frame.setResizable(false);
//设置窗口的大小和位置,居中放置
frame.setBounds(((int) screenSize.getWidth() - WINDOW_WIDTH) / 2, 0,
WINDOW_WIDTH, WINDOW_HEIGHT);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
degreeselect select=new degreeselect();
JPanel newMainPanel = select.getMainPanel();
frame.setContentPane(newMainPanel);
frame.setVisible(true);
synchronized (lock){
while(newMainPanel.isVisible()){
try {
lock.wait();
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
frame.remove(newMainPanel);
Game game = select.gamestart();
game.setDegree(select);
game.setmusicoff(select);
game.setUsername(select);
frame.setContentPane(game);
frame.setVisible(true);
game.action();
synchronized (lock){
while(game.isVisible()){
try{
lock.wait();
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
UserDaoImpl userDao = new UserDaoImpl();
UserTable usertable=new UserTable(userDao);
JPanel userPanel=usertable.getmainPanel();
frame.setContentPane(userPanel);
frame.setVisible(true);
}
}
AbstractAircraft
public abstract class AbstractAircraft extends AbstractFlyingObject {
/**
* 生命值
*/
protected int maxHp;
protected int hp;
/**
* 子弹射击方向 (向上发射:-1,向下发射:1)
*/
protected int direction;
/**
* 子弹伤害
*/
protected int power;
/**
* 子弹一次发射数量
*/
protected int shootNum;
public AbstractAircraft(int locationX, int locationY, int speedX, int speedY, int hp) {
super(locationX, locationY, speedX, speedY);
this.hp = hp;
this.maxHp = hp;
this.direction=-1;
this.power=30;
this.shootNum=1;
}
public void decreaseHp(int decrease){
hp -= decrease;
if(hp <= 0){
hp=0;
vanish();
}
}
/**
* 设置射击模式
* @param strategy
*/
protected Strategy shootMode;
public void setShootMode(Strategy strategy){
this.shootMode = strategy;
}
public int getHp() {
return hp;
}
public int getDirection() {return direction;}
public int getPower(){return power;}
public int getShootNum(){return shootNum;}
/**
* 改变水平移动速度
* @param
*/
public void xmove(int x){
if(x<0) {
speedX = -speedX;
}
}
/**
* 飞机射击方法,可射击对象必须实现
* @return
* 可射击对象需实现,返回子弹
* 非可射击对象空实现,返回null
*/
public abstract List<AbstractBullet> shoot();
public void setPower(int power){this.power=power;}
}
AbstractItem
public class AbstractItem extends AbstractFlyingObject {
public AbstractItem (int locationX, int locationY, int speedX, int speedY) {
super(locationX, locationY, speedX, speedY);
}
@Override
public void forward() {
super.forward();
// 判定 y 轴向下飞行出界
if (locationY >= Main.WINDOW_HEIGHT ) {
vanish();
}
}
public void effect(HeroAircraft heroAircraft){
}
}
AbstractBullet
public class AbstractBullet extends AbstractFlyingObject {
private int power = 10;
public AbstractBullet(int locationX, int locationY, int speedX, int speedY, int power) {
super(locationX, locationY, speedX, speedY);
this.power = power;
}
@Override
public void forward() {
super.forward();
// 判定 x 轴出界
if (locationX <= 0 || locationX >= Main.WINDOW_WIDTH) {
vanish();
}
// 判定 y 轴出界
if (speedY > 0 && locationY >= Main.WINDOW_HEIGHT ) {
// 向下飞行出界
vanish();
}else if (locationY <= 0){
// 向上飞行出界
vanish();
}
}
public int getPower() {
return power;
}
}
4. 视频演示
JAVA飞机大战演示视频