Java桌面程序实现飞机大战,FlyBird游戏,JavaFx

                                           JAVA飞机大战游戏

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

游戏规则设计

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

    先看效果图

Java桌面程序实现飞机大战,FlyBird游戏,JavaFx

Java桌面程序实现飞机大战,FlyBird游戏,JavaFx

Java桌面程序实现飞机大战,FlyBird游戏,JavaFx

Java桌面程序实现飞机大战,FlyBird游戏,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;
        }
    }
}

最后


其他类的代码太多,就不一一贴出了,需要源码的私聊我!