JAVA飞机大战游戏
简介:本人在本学期,通过JAVA实训,做了一款Java桌面程序游戏(飞机大战),设计思想和自己之前的C语言一样。还是通过多线程技术为核心。因为是学校实训内容,主要目的是巩固JAVA的学习,利用到了Java中面向对象的思想(继承,封装,多态),文件的读取,数组,集合(List), 线程同步,JAVAFx图形界面,鼠标事件监听等。
游戏规则设计
主要是英雄机和敌机对战,英雄机和敌机都可以发射子弹,并且英雄机可以和敌机对掉子弹。英雄机打爆某一特殊敌机时,有奖励作用,分为加一条命,或者加火力值。
先看效果图
核心技术分析
Canvas canvas = new Canvas(ShootGame.WIDTH, ShootGame.HEIGHT);
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.drawImage(image, 110, 375);
通过JAVAFx的二维画笔,画出资源路径下的图片文件。
再通过Timer 定时器,通过不断的去绘制图片,达到动态效果,再监听鼠标事件,坐标监听,来完成游戏规则。
部分代码截图
主界面代码及布局文件
public class Main extends Application {
private static final int WIDTH = 400;
private static final int HEIGHT = 654;
private static Image background = Tool.readImg("main2.jpg"); @Override
public void start(Stage primaryStage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("shoot/plane.fxml"));
primaryStage.setTitle("小游戏");
Pane pane = (Pane) root;
pane.setBackground(new Background(new BackgroundImage(background, BackgroundRepeat.NO_REPEAT, BackgroundRepeat.NO_REPEAT, BackgroundPosition.DEFAULT, BackgroundSize.DEFAULT)));
ObservableList<Node> children = ((Pane) root).getChildren();
Button plane = (Button) children.get(1);
plane.setOnAction(event -> {
Stage plane_Main = new Stage();
ShootGame game = new ShootGame();
game.start();
game.setCursor(Cursor.HAND);
Scene scene = new Scene(game, WIDTH, HEIGHT);
plane_Main.setScene(scene);
plane_Main.setTitle("飞机大战");
plane_Main.getIcons().add(Tool.readImg("own1.png"));
plane_Main.setWidth(WIDTH);
plane_Main.setHeight(HEIGHT);
plane_Main.setResizable(false);
plane_Main.setAlwaysOnTop(true);
plane_Main.show();
primaryStage.hide();
plane_Main.setOnCloseRequest(event1 -> {
game.close();
primaryStage.show();
});
});
Button bird = (Button) children.get(2);
bird.setOnAction(event -> {
Stage plane_Main = new Stage();
FlyBird game = new FlyBird();
game.start();
game.setCursor(Cursor.HAND);
Scene scene = new Scene(game, WIDTH, HEIGHT);
plane_Main.setScene(scene);
plane_Main.setTitle("FlyBird");
plane_Main.getIcons().add(Tool.readImg("0.png"));
plane_Main.setAlwaysOnTop(true);
plane_Main.setWidth(WIDTH);
plane_Main.setHeight(HEIGHT);
plane_Main.setResizable(false);
plane_Main.show();
primaryStage.hide();
plane_Main.setOnCloseRequest(event1 -> {
game.close();
primaryStage.show();
});
});
primaryStage.setScene(new Scene(root, WIDTH, HEIGHT));
primaryStage.getIcons().add(Tool.readImg("game.png"));
primaryStage.setWidth(WIDTH);
primaryStage.setHeight(HEIGHT);
primaryStage.setResizable(false);
primaryStage.show();
} public static void main(String[] args) {
launch(args);
}
}
fxml 布局文件
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.effect.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?><BorderPane xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1">
<top>
<Label style="-fx-font-family: '等线 Light';" text="经典小游戏" textAlignment="CENTER" textFill="#0800e3" BorderPane.alignment="CENTER">
<BorderPane.margin>
<Insets top="100.0" />
</BorderPane.margin>
<font>
<Font size="49.0" />
</font>
<opaqueInsets>
<Insets />
</opaqueInsets>
<effect>
<Glow />
</effect>
</Label>
</top>
<center>
<Button fx:id="plane" defaultButton="true" graphicTextGap="0.0" mnemonicParsing="false" text="飞机大战" textAlignment="CENTER" textFill="#1a10d7" BorderPane.alignment="TOP_CENTER">
<BorderPane.margin>
<Insets top="150.0" />
</BorderPane.margin>
<font>
<Font name="System Bold" size="33.0" />
</font>
<cursor>
<Cursor fx:constant="HAND" />
</cursor> </Button>
</center>
<bottom>
<Button defaultButton="true" graphicTextGap="0.0" mnemonicParsing="false" text="FlyBird" textAlignment="CENTER" textFill="#1a10d7" BorderPane.alignment="TOP_CENTER">
<BorderPane.margin>
<Insets bottom="150" />
</BorderPane.margin>
<font>
<Font name="System Bold" size="35.0" />
</font>
<cursor>
<Cursor fx:constant="HAND" />
</cursor> </Button>
</bottom>
</BorderPane>
利用面向对象的思想,来封装具体的实体,因为所有的实体都具有通用的属性和行为,则抽为基类定义。
/**
* 飞行物基类
*/
public abstract class FlyingObject {
public static final int ALIVE = 0;//活着
public static final int DEAD = 1;//死亡
public static final int DELETABLE = 2;//可删除
public int state = ALIVE;//状态
public Image image;
public int x;
public int y; //英雄机或子弹构造
public FlyingObject(Image image, int x, int y) {
this.image = image;
this.x = x;
this.y = y;
} //敌机构造
public FlyingObject(Image image) {
this.image = image;
int w1 = ShootGame.WIDTH;//屏幕宽
int w2 = (int) this.image.getWidth();
int h2 = (int) this.image.getHeight();
Random random = new Random();
this.x = random.nextInt(w1 - w2);
this.y = h2 / 2;
} public int getState() {
return state;
} public void setState(int state) {
this.state = state;
} public Image getImage() {
return image;
} public void setImage(Image image) {
this.image = image;
} 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;
} int index = 1;
public void setImage(Image[] images) {
if (state == ALIVE) {
image = images[0];
} else if (state == DEAD) {
image = images[index];
index++;
if (index == images.length) {
state = DELETABLE;
}
} else {
image = null;
}
} public abstract void setImage();
}
再通过继承方式,再定义自己独特的行为及属性
/**
* 英雄机
*/
public class HeroPlane extends FlyingObject {
private static Image[] images;//图片数组
private int life = 3;
private int bulletCount;//子弹数
private int fire = 2;//火力(默认为2) static {
images = new Image[2];
images[0] = Tool.readImg("own1.png");
images[1] = Tool.readImg("ownbz.png");
} public HeroPlane() {
super(images[0], ShootGame.WIDTH / 2, ShootGame.HEIGHT / 4 * 3);
} //加命
public void addLife() {
life++;
} //减命
public void subLife() {
life--;
} //获取命
public int getLife() {
return life;
} //加火力
public void addFire() {
fire++;
} //清空火力
public void ClearFire() {
fire = 0;
} //发射子弹
public HeroBullet[] shootBullet() {
if (fire >= 3) {
bulletCount = 3;
} else if (fire == 2) {
bulletCount = 2;
} else {
bulletCount = 1;
}
//根据英雄机的位置确定子弹
HeroBullet[] hbs = new HeroBullet[bulletCount];
int yStep = (int) (this.image.getHeight() / 2);
int xStep = (int) (this.image.getWidth() / (bulletCount + 1));
for (int i = 0; i < hbs.length; i++) {
hbs[i] = new HeroBullet(this.x - ((int) this.image.getWidth() / 2) + (i + 1) * xStep, this.y - yStep);
}
return hbs;
} //移动
public void move(int x, int y) {
this.x = x;
this.y = y;
} //设置图片
public void setImage() {
setImage(images);
} int index = 0;
public void changeImage() {
setImage(images[1]);
} @Override
public void setImage(Image[] images) {
if (state == ALIVE) {
image = images[0];
} else if (state == DEAD) {
image = images[index];
index++;
if (index == images.length) {
state = DELETABLE;
}
} else {
image = null;
}
}
}