JAVA飞机大战游戏

简介:本人在本学期,通过JAVA实训,做了一款Java桌面程序游戏(飞机大战),设计思想和自己之前的C语言一样。还是通过多线程技术为核心。因为是学校实训内容,主要目的是巩固JAVA的学习,利用到了Java中面向对象的思想(继承,封装,多态),文件的读取,数组,集合(List), 线程同步,JAVAFx图形界面,鼠标事件监听等。

游戏规则设计

    主要是英雄机和敌机对战,英雄机和敌机都可以发射子弹,并且英雄机可以和敌机对掉子弹。英雄机打爆某一特殊敌机时,有奖励作用,分为加一条命,或者加火力值。

    先看效果图

飞机大战 java 代码 javafx飞机大战_Java 游戏 源代码

飞机大战 java 代码 javafx飞机大战_Java 游戏 源代码_02

飞机大战 java 代码 javafx飞机大战_Java_03

飞机大战 java 代码 javafx飞机大战_Java 游戏 源代码_04

核心技术分析

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;
         }
     }
 }