[翻译] 使用FXGL创建一个非常基本的游戏

news2024/11/16 9:55:49

游戏要求

首先,让我们为我们的简单游戏定义一些要求:

  1. 一个600x600的窗口。
  2. 屏幕上的玩家,由蓝色矩形表示。
  3. 可以通过按键盘上的W、S、A或D来移动玩家。
  4. UI由一行文本表示。
  5. 当玩家移动时,UI文本会更新以显示玩家在其生命周期内移动了多少像素。

在本教程的最后,你可以获得这样的一个游戏窗口 (可能略有不同):

虽然它可能看起来不像游戏,但它将帮助你了解FXGL的基本功能。完成本教程后,你可以构建各种简单的游戏。

准备工作

既然我们对游戏的期望有一个大致的概念,我们可以回到集成开发环境,为我们的游戏创建一个包。

注意: 目录结构类似于Maven目录结构,但是,如果你不知道这是什么,请不要担心。我们将在稍后阶段介绍结构。此时,将 src作为主源目录就足够了。

我要用tutorial作为包名称。

  1. 在你的IDE中创建包 tutorial .

  2. 在package中,使用BasicGameApp名称创建Java类.

通常,在你的main()所在的类上附加 "App"。这可以让其他开发者轻松识别你的游戏的主要入口在哪里。为了使你接下来的步骤更容易,我建议你打开你的BasicGameApp类并添加这些导入。

import com.almasb.fxgl.app.GameApplication;
import com.almasb.fxgl.app.GameSettings;
import com.almasb.fxgl.dsl.FXGL;
import com.almasb.fxgl.entity.Entity;
import com.almasb.fxgl.input.Input;
import com.almasb.fxgl.input.UserAction;
import javafx.scene.input.KeyCode;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;
import java.util.Map;
复制代码

我们现在可以开始编写我们的代码了

编码阶段

为了使用FXGL,你的App 类需要继承GameApplication 并重写initSettings()方法:

public class BasicGameApp extends GameApplication {

    @Override
    protected void initSettings(GameSettings settings) {}
}
复制代码

一旦继承GameApplication ,大多数IDEs将自动生成重写方法。现在我们希望能够开始游戏。为此,只需添加以下内容:

public static void main(String[] args) {
    launch(args);
}
复制代码

如果你以前使用过JavaFX,那么你会注意到,它与我们用来启动JavaFX应用程序的方法完全相同。简而言之,FXGL是一个具有游戏开发功能的JavaFX应用程序,仅此而已。

需求1 (窗口)

在这一点上,你应该已经能够运行你的游戏,但是首先让我们调整一些设置。

@Override
protected void initSettings(GameSettings settings) {
    settings.setWidth(600);
    settings.setHeight(600);
    settings.setTitle("Basic Game App");
    settings.setVersion("0.1");
}
复制代码

正如你所看到的,所有的设置都是在initSettings()中配置的。一旦设置好了,在运行时就不能改变设置。现在你可以在你的IDE中点击 "run",它应该以600x600的窗口和 "Basic Game App "为标题启动游戏。

我们现在达到了我们的需求1。很简单,对吧?

需求 2 (Player)

下一步是在屏幕上添加一个玩家。我们将在initGame()中完成这一工作。简而言之,这是你设置游戏开始前需要准备的所有东西的地方。

private Entity player;

@Override
protected void initGame() {
    player = FXGL.entityBuilder()
            .at(300, 300)
            .view(new Rectangle(25, 25, Color.BLUE))
            .buildAndAttach();
}
复制代码

(注意:对于保存/加载系统来说,我们不在声明时初始化实例级字段,而是在'initGame()'中进行初始化,这一点很重要。)

如果你不熟悉函数式 API,那么上面的代码是很难一下子接受的。所以我们要慢慢开始。

接下来讲解一下上述代码:

  • 有一个名为player的实例级字段,其类型为Entity

  • 一个实体基本上就是一个游戏对象。这就是你现在需要知道的一切。

  • FXGL.entityBuilder()是构建实体的首选方式。

  • 通过调用.at(),我们将实体定位到我们想要的位置。在这个例子中,它是x = 300,y = 300。

(注意: 实体在FXGL中的位置是其左上角,就像在JavaFX中一样。)

然后我们告诉构建器,通过使用我们传入的UI节点作为参数来创建实体的视图。这里是一个标准的JavaFX Rectanglewidth=25height =25,颜色为蓝色。

(注意:你可以使用任何基于JavaFX节点的对象,这非常酷。 😄)

最后,我们调用.buildAndAttach()方法。通过调用build,我们可以获得我们正在构建的实体的引用。至于 "attach "部分,它可以方便地将构建的实体直接连接到游戏世界中。如果你运行游戏,你现在应该在屏幕中心附近看到一个蓝色的矩形。

太好了,我们刚刚完成了2号需求!

需求3 (输入)

现在,我们将继续执行与用户输入相关的要求。我们将输入处理代码放入initInput()中。下面的代码显示了用于添加输入操作的所有API。考虑之后,我们将看到如何使用更简单的API。

We will now proceed with the requirement related to user input. We put the input handling code in initInput(). The below code shows the "full" API for adding an input action. After considering it, we will see how to use simpler API.pixels

@Override
protected void initInput() {
    Input input = FXGL.getInput();

    input.addAction(new UserAction("右移") {
        @Override
        protected void onAction() {
            player.translateX(5); // 向右移动5个像素
        }
    }, KeyCode.D);
}
复制代码

让我们逐行浏览这个片段。

首先得到输入对象。正如你所注意到的,要使用大部分的FXGL功能,你需要做的就是调用FXGL.***,你的IDE会显示你可以调用的所有功能。

接下来,我们添加一个动作,然后是一个按键代码。同样,如果你以前使用过JavaFX,那么你就会知道,这些键码与事件处理程序中使用的键码完全相同。我们在说:当'D'被按下时,做我们所创建的动作。现在让我们来看看动作本身。

当我们创建一个动作时,我们也给它一个名字--"右移"。这很重要,因为这个名字会直接反馈给控件和菜单系统,用户可以随时改变它们。所以这个名字必须对用户有意义,而且是唯一的。一旦我们创建了这个动作,我们就覆盖它的一个方法(这次是onAction()),并提供一些代码。该代码将在动作发生时被调用,即当 "D "被按下时。

回顾一下需求,我们想要移动玩家。所以当'D'被按下时,我们想把Player向右移动。我们调用player.translateX(5),将其X坐标平移5像素。

(注意: translate是计算机图形学中使用的术语,意思是移动。)

现在让我们缩短它:

@Override
protected void initInput() {
    FXGL.onKey(KeyCode.D, () -> {
        player.translateX(5); // 向右移动5个像素
    });
}
复制代码

这也导致玩家实体向右移动5个像素,并且 (几乎) 等同于我们之前编写的代码。但是,我认为你会同意此API (称为DSL) 更加简洁。如果导入com.almasb.fxgl.dsl.FXGL.*,这可以进一步缩短,即:

import static com.almasb.fxgl.dsl.FXGL.*;
复制代码

然而,为了避免引入太多的新概念,我们现在还不会这么做。你可能会猜测其余的输入代码会是什么样子,但以防万一,以下是所有的代码

@Override
protected void initInput() {
    FXGL.onKey(KeyCode.D, () -> {
        player.translateX(5); // move right 5 pixels
    });

    FXGL.onKey(KeyCode.A, () -> {
        player.translateX(-5); // move left 5 pixels
    });

    FXGL.onKey(KeyCode.W, () -> {
        player.translateY(-5); // move up 5 pixels
    });

    FXGL.onKey(KeyCode.S, () -> {
        player.translateY(5); // move down 5 pixels
    });
}
复制代码

需求3--完成了,尘埃落定。我们已经完成了一半以上,做得很好!

需求 4 (UI)

我们现在进入下一个位--UI,你或许已经猜到了,initUI()

@Override
protected void initUI() {
    Text textPixels = new Text();
    textPixels.setTranslateX(50); // x = 50
    textPixels.setTranslateY(100); // y = 100

    FXGL.getGameScene().addUINode(textPixels); // add to the scene graph
}
复制代码

对于大多数UI对象,我们只是使用JavaFX对象,因为没有必要重新发明轮子。你应该注意到,当我们在世界中添加一个实体时,游戏场景接收到了该实体有一个与之相关的视图这一事实。因此,游戏场景神奇地将该实体添加到场景图中。对于UI对象,我们要负责将其添加到场景图中,我们可以通过调用getGameScene().addUINode()方法来实现。

这就是需求4。继续!

需求5 (Gameplay)

为了完成最后一个要求,我们将使用游戏变量。在FXGL中,可以从游戏的任何部分访问和修改游戏变量。从某种意义上说,它是一个全局变量,其范围与FXGL游戏实例相关联。此外,这些变量可以绑定(类似于JavaFX属性)。我们从创建这样一个变量开始:

@Override
protected void initGameVars(Map<String, Object> vars) {
    vars.put("pixelsMoved", 0);
}
复制代码

然后我们需要在玩家移动时更新变量。我们可以在输入处理部分执行此操作。

FXGL.onKey(KeyCode.D, () -> {
    player.translateX(5); // move right 5 pixels
    FXGL.inc("pixelsMoved", +5);
});
复制代码

我会让你对剩下的动作做同样的事情 (左、上、下)。最后一步 (对于需求和教程) 是将我们的UI文本对象绑定到变量pixelsMoved。在initUI()一旦我们创建了textPixels 对象,我们可以执行以下操作:

textPixels.textProperty().bind(FXGL.getWorldProperties().intProperty("pixelsMoved").asString());
复制代码

之后,UI文本将显示播放器自动移动了多少像素。

你现在有了一个基本的FXGL游戏。希望你玩得开心。下面是本教程的全部源代码,所有FXGL.*调用都是静态导入的。

package tutorial;

import com.almasb.fxgl.app.GameApplication;
import com.almasb.fxgl.app.GameSettings;
import com.almasb.fxgl.dsl.FXGL;
import com.almasb.fxgl.entity.Entity;
import javafx.scene.input.KeyCode;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;
import java.util.Map;

import static com.almasb.fxgl.dsl.FXGL.*;

public class BasicGameApp extends GameApplication {
    @Override
    protected void initSettings(GameSettings settings) {
        settings.setWidth(600);
        settings.setHeight(600);
        settings.setTitle("Basic Game App");
        settings.setVersion("0.1");
    }

    @Override
    protected void initInput() {
        onKey(KeyCode.D, () -> {
            player.translateX(5); // move right 5 pixels
            inc("pixelsMoved", +5);
        });

        onKey(KeyCode.A, () -> {
            player.translateX(-5); // move left 5 pixels
            inc("pixelsMoved", -5);
        });

        onKey(KeyCode.W, () -> {
            player.translateY(-5); // move up 5 pixels
            inc("pixelsMoved", +5);
        });

        onKey(KeyCode.S, () -> {
            player.translateY(5); // move down 5 pixels
            inc("pixelsMoved", +5);
        });
    }

    @Override
    protected void initGameVars(Map<String, Object> vars) {
        vars.put("pixelsMoved", 0);
    }

    private Entity player;

    @Override
    protected void initGame() {
        player = entityBuilder()
                .at(300, 300)
                .view(new Rectangle(25, 25, Color.BLUE))
                .buildAndAttach();
    }

    @Override
    protected void initUI() {
        Text textPixels = new Text();
        textPixels.setTranslateX(50); // x = 50
        textPixels.setTranslateY(100); // y = 100

        textPixels.textProperty().bind(getWorldProperties().intProperty("pixelsMoved").asString());

        getGameScene().addUINode(textPixels); // add to the scene graph
    }

    public static void main(String[] args) {
        launch(args);
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/12219.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

今天给在家介绍一篇基于jsp的旅游网站设计与实现

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

zookeeper报错length is greater than jute.maxbuffer=1048575

1、场景 最近在给上云项目部署系统&#xff0c;通过压测都已经正式上生产后发现kafka存在异常错误&#xff0c;经排查发现zookeeper也存在错误&#xff0c;怀疑kafka的问题可能是由于zk异常到的&#xff0c;报错如下 2022-11-17 06:26:43,052 [myid:] - WARN [NIOWorkerThr…

HTML学生个人网站作业设计:游戏网站设计——原神首页 1页 带轮播图

⛵ 源码获取 文末联系 ✈ Web前端开发技术 描述 网页设计题材&#xff0c;DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业 | 游戏官网 | 游戏网站 | 电竞游戏 | 游戏介绍 | 等网站的设计与制作 | HTML期末大学生网页设计作业&#xff0c;Web大学生网页 HTML&#xff1a;结构 …

Burpsuite简介及MIME上传绕过实例

目录预备知识1.了解burpsuite2.了解服务端MIME类型检测实验目的实验环境实验步骤一使用Burpsuite的代理功能Target模块实验步骤二使用burpsuite上传绕过服务端MIME类型检测预备知识 1.了解burpsuite Burp Suite是用于攻击web应用程序的集成平台。包含了许多工具&#xff0c;并…

[附源码]Python计算机毕业设计 学生宿舍管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

我们与元宇宙的距离

元宇宙的发展是一个循序渐进的过程&#xff0c;需要经过初始阶段、规划阶段、系统阶段和优化阶段。当前&#xff0c;虽然已经有许多元宇宙完成了搭建&#xff0c;但都是针对单一特定场景的模拟仿真&#xff0c;并且没有实现全面的推广应用&#xff0c;因此我们仍处于元宇宙的初…

浅析多通道接收单元噪声系数的测试

之前一个朋友要测试低噪声放大器(LNA)的噪声系数&#xff0c;但是声称遇到一些麻烦。LNA噪声系数的测试采用Y因子法非常简便&#xff0c;校准完成后直接连接待测件即可测试&#xff0c;可操作性非常强。麻烦在哪里呢&#xff1f; 原来待测件是一个含有四个通道的接收模块&…

2023年三大网络安全威胁不容忽视

2022年已进入尾声&#xff0c;降低数字化风险、增强安全防御能力依然是众多企业组织数字化发展中的重要需求和目标。随着技术的不断进步&#xff0c;网络攻击者的攻击成本不断降低&#xff0c;同时攻击方式更加先进&#xff0c;美国《福布斯》网站在近日的报道中列出了2023年值…

Zoho 如何使用低代码 #1 - 赋予人力资源以技术实力

Zoho 为客户提供了一套跨功能产品&#xff0c;从运行简单的调查到简化复杂的企业组织职能&#xff0c;Zoho 几乎提供了企业的业务运行所需的一切。 组织在新的规范和挑战中不断进行扩展&#xff0c;这就不断需要构建可定制的解决方案。这就是为什么除了现成的应用程序之外&…

第1关:ZooKeeper初体验

ZooKeeper安装方法 由于本实验环境已经安装ZooKeeper并配置&#xff0c;下面主要讲述一般环境的安装方法。 可以从ZooKeeper的官方网站上下载稳定版&#xff0c;下载地址如下&#xff1a;Apache ZooKeeper 下载后&#xff0c;利用tar命令将压缩包解压到/opt/zookeeper-3.4.1…

实验31:温湿度传感器实验

本实验也比较简单 用LCD1602显示温湿度传感器返回的温湿度值 本专栏就要结尾了 希望对大家有一定的帮助 学习就是一点一滴的 01 硬件电路设计 整体电路图 重点还是接口: 因为最后相放一个学生做的大创为结尾彩蛋,所以这里就不再添加报警灯什么的额外操作了 每一个实验…

OVS 和 OVS-DPDK 对比

OVS 目前有两种比较突出的架构&#xff0c;一种是原生的 OVS 架构&#xff08;使用 kernel 作为 datapath&#xff09;&#xff0c;一种是基于 DPDK 的架构&#xff08;使用用户空间作为 datapath&#xff09;。 原生 OVS 原生 OVS 架构如下所示&#xff0c;主要包含两个组件…

冷启动问题分析与解决办法

1、什么是冷启动问题&#xff1f; 在缺乏有价值数据的时候&#xff0c;如何有效地满足业务需求的问题&#xff0c;就是“冷启动问题”。为了沟通方便&#xff0c;下面统一从推荐系统的角度来讲“冷启动问题”&#xff0c;其他业务场景同理。 冷启动问题是机器学习系统中十分常…

完成Zookeeper集群部署

目录一、实验介绍1.1实验内容1.2实验知识点1.3实验环境1.4实验资源1.5实验步骤清单二、实验架构三、实验环境准备四、实验步骤4.1部署Zookeeper集群4.1.1配置hosts文件4.1.2安装Zookeeper软件(master)4.1.3修改zookeeper配置文件4.1.4配置Zookeeper集群4.2验证Zookeeper集群4.2…

python419社区疫情综合管理系统django

目 录 摘 要 I 目 录 I 第1章 绪论 1 1.1课题背景 1 1.2目的和意义 1 1.3研究现状 2 1.4研究内容 3 第2章 关键技术研究 4 开发语言&#xff1a;Python 框架&#xff1a;django Python版本&#xff1a;python3.7.7 数据库&#xff1a;mysql 数…

js的闭包例题

1、垃圾回收 &#xff08;1&#xff09;全局变量不会被回收 &#xff08;2&#xff09;局部变量会被回收&#xff0c;函数执行结束&#xff0c;函数内部东西会被销毁 &#xff08;3&#xff09;某作用域中的某个变量还在被另一个作用域引用就不会被回收 var a[]; for(var i 0…

docker安装部署实战详细手册

文章目录一、docker介绍1.什么是docker2.为什么使用docker二、docker架构三、docker安装1.安装2.卸载结尾一、docker介绍 1.什么是docker Docker 是一个开源的容器引擎&#xff0c;它有助于更快地交付应用。Docker 可将应用程序和基础设施层隔离&#xff0c; 并且能将基础设施…

docker 部署运行springboot-web.jar

Docker Hub官方公用仓库:https://hub.docker.com 一、docker安装jdk 1.先查看自己需要的版本 2.从仓库中下载 3.查看下载的镜像 4.创建并启动容器 其中(--namejdk1.8 这个jdk1.8是镜像majiajue/jdk1.8别名) docker run -di --namejdk1.8 majiajue/jdk1.8 5.查看是否启动容器…

用PyTorch简单实现线性回归

参考视频&#xff1a;05.用PyTorch实现线性回归_哔哩哔哩_bilibili 还是以y3x2y3x2y3x2为例&#xff08;事先不知道&#xff09; 学习率设为0.01&#xff0c;训练1000次 要注意视频中定义损失函数的部分所用的参数size_averageFalse已经过时&#xff0c;需要改成reduction‘…

深度学习系列1——Pytorch 图像分类(LeNet)

1. 概述 本文主要是参照 B 站 UP 主 霹雳吧啦Wz 的视频学习笔记&#xff0c;参考的相关资料在文末参照栏给出&#xff0c;包括实现代码和文中用的一些图片。 整个工程已经上传个人的 github https://github.com/lovewinds13/QYQXDeepLearning &#xff0c;下载即可直接测试&a…