Rot.js 随机地牢,迷宫地图生成

2023-11-06

js 插件随机地牢,迷宫地图生成

插件git https://github.com/ondras/rot.js/tree/master/dist

使用:
1.我们的游戏是在网页内进行的;一个基本的 HTML 文件就足够了

<!doctype html>
<html>
    <head>
        <title>Ananas aus Caracas: rot.js tutorial game</title>
        <script src="https://cdn.jsdelivr.net/npm/rot-js@2/dist/rot.js"></script>
        <script src="/path/to/the/game.js"></script>
    </head>
    <body onload="Game.init()">
        <h1>Ananas aus Caracas</h1>
    </body>
</html>

2.cocoscreator,Laya引擎使用去上面git下载,然后把里面的rot.js 或者 rot.min.js 文件放到项目里面即可
3.下面是一些使用的方法

地图数据生成

我们将使用 rot.js 的内置地图生成器之一来创建游戏关卡。Rot的设计范式之一.是人们不应该被迫使用一些预定义的数据结构;这就是生成器基于回调的原因。我们将自定义函数传递给生成器;在此过程中,它将被反复调用。
这可能是查看rot.js手册的好时机,其中包含有用的代码示例和使用概述。
我们应该如何存储生成的地图数据?我们将使用一种非常基本的存储方法:一个普通的JS对象(“hashmap”),由字符串索引(格式为“x,y”),值表示地砖。我们不会存储墙壁/固体细胞。
注意:我们正在通过,而不仅仅是挖掘机。这对于确保在正确的上下文(ECMA 术语中的激活对象)中调用我们的回调是必要的

	var digger = new ROT.Map.Digger();
	var digCallback = function(x, y, value) {
        if (value) { return; } /* do not store walls */

        var key = x+","+y;
        this.map[key] = ".";
        
        for (var key in this.map) {
        var parts = key.split(",");
        var x = parseInt(parts[0]);
        var y = parseInt(parts[1]);
        this.display.draw(x, y, this.map[key]);
    	}
    }
digger.create(digCallback.bind(this));

随机生成的框

最后,让我们创建一些盒子 - 潜在的阿纳纳斯存储。我们将在本教程的后面部分中将 ananas 隐藏在其中一个中。要放置 10 个随机框,我们将利用 rot.js 的随机数生成器。
ROT.RNG可以做很多事情,但我们需要一些简单的东西:一个介于零(包括)和一(不包括)之间的随机、均匀分布的数字,就像它一样。执行此操作的正确方法是调用 。Math.randomROT.RNG.getUniform()
我们将空单元格存储在一个数组中;对于放置的每个框,我们将选择一个随机的空单元格,将其从列表中删除,并在存储结构中将该位置标记为框(星号)。

_generateMap = function() {
    var digger = new ROT.Map.Digger();
    var freeCells = [];
    var digCallback = function(x, y, value) {
        if (value) { return; } /* do not store walls */

        var key = x+","+y;
        freeCells.push(key);
        this.map[key] = ".";
    }
    digger.create(digCallback.bind(this));

    this._generateBoxes(freeCells);

    this._drawWholeMap();
}

_generateBoxes = function(freeCells) {
    for (var i=0;i<10;i++) {
        var index = Math.floor(ROT.RNG.getUniform() * freeCells.length);
        var key = freeCells.splice(index, 1)[0];
        this.map[key] = "*";
    }
}

上面其实只是地图的生成,Rot.js其实还有很多功能,他其实是一个游戏插件

玩家角色

是时候制作一些有趣的互动闪亮了!首先,玩家需要一个体面的代表。使用普通 JS 对象来表示玩家就足够了,但通常通过其构造函数定义播放器并将其实例化会更健壮。

此时,您可能已经习惯了某些变量名称以下划线开头的事实。这是一种相对常见的将它们标记为私有的技术。JavaScript 不提供真正的私有变量,所以这种基于下划线的命名法只是我们将东西标记为“内部”的有用方法。

我们想将玩家放在一些备用地砖上:让我们使用与本教程第 1 部分完全相同的技术来放置盒子:只需从列表中选择一个空闲位置即可。

var Player = function(x, y) {
    this._x = x;
    this._y = y;
    this._draw();
}
Player.prototype._draw = function() {
    Game.display.draw(this._x, this._y, "@", "#ff0");
}
Game.player = null;
Game._generateMap = function() {
    /* ...previous stuff... */
    this._createPlayer(freeCells);
};
Game._createPlayer = function(freeCells) {
    var index = Math.floor(ROT.RNG.getUniform() * freeCells.length);
    var key = freeCells.splice(index, 1)[0];
    var parts = key.split(",");
    var x = parseInt(parts[0]);
    var y = parseInt(parts[1]);
    this.player = new Player(x, y);
};

准备游戏回合引擎

在我们的游戏中将有两个实体轮流:玩家角色和佩德罗(敌人)。为了简单起见,让我们均匀地交替轮次。但即使在这种简单的情况下,我们也可以利用时间框架来发挥我们的优势。ROT.Engine

这是如何工作的?首先,将提供所有可用的参与者 - 该组件将负责公平回合调度。然后,将使用此调度程序在循环中自动调用相关参与者。(注意:我们作为第二个参数传递给 - 这意味着我们的 actor 不是一个一次性事件,而是一个重复的项目。ROT.Scheduler.SimpleROT.Enginetruescheduler.add

接受客户端 JavaScript 世界中一切都是异步的事实非常重要:基本上没有阻塞调用。这消除了将简单的 while 循环作为我们的主要计时/调度工具的可能性。幸运的是,为此做好了充分的准备。ROT.Engine

创建调度程序和引擎只需在我们的代码中添加几行:

Game.engine = null;

Game.init = function() {
    var scheduler = new ROT.Scheduler.Simple();
    scheduler.add(this.player, true);
    this.engine = new ROT.Engine(scheduler);
    this.engine.start();
}

演员和引擎之间的交互

引擎与其参与者之间存在紧密的共生关系。运行时,引擎会反复选择适当的参与者(使用调度程序)并调用参与者的方法。允许参与者通过调用并恢复此循环来中断此循环(例如,异步等待时)。act()ROT.Engine::lockROT.Engine::unlock
可以有多个锁级别(锁是递归的);这允许异步调用的复杂链接。幸运的是,这在我们的简单游戏中是不需要的。
那么,什么是演员呢?任何带有 act 方法的 JS 对象。

Player.prototype.act = function() {
    Game.engine.lock();
    /* wait for user input; do stuff when user hits a key */
    window.addEventListener("keydown", this);
}

Player.prototype.handleEvent = function(e) {
    /* process user input */
}

我们使用一些不常见(但非常有用!)的技术来分配事件处理程序:我们将一个JS对象作为第二个参数传递给调用。这样的对象(在本例中)必须具有方法,一旦事件发生(“keydown”)就会调用该方法。addEventListenerthishandleEvent

查看盒子内部

游戏生成了几个盒子,但到目前为止,它们都没有包含珍贵的阿那纳斯。让我们将 ananaas 存储在生成的第一个框中:

Game.ananas = null;

Game._generateBoxes = function(freeCells) {
    for (var i=0;i<10;i++) {
        /* ...previous stuff... */
        if (!i) { this.ananas = key; } /* first box contains an ananas */
    }
}

玩家还必须执行一项交互:查看盒子。我们将允许输入执行此操作:
打开一个盒子来验证其内容就像将玩家的当前位置与我们的盒子列表和存储的 ananas 位置进行比较一样简单:

Player.prototype._checkBox = function() {
    var key = this._x + "," + this._y;
    if (Game.map[key] != "*") {
        alert("There is no box here!");
    } else if (key == Game.ananas) {
        alert("Hooray! You found an ananas and won this game.");
        Game.engine.lock();
        window.removeEventListener("keydown", this);
    } else {
        alert("This box is empty :-(");
    }
}

基于寻路的人工智能

到目前为止,佩德罗缺少它的方法。我们将使用 rot.js 的寻路函数之一来实现 Pedro 的行为:(A* 算法)。一些基本的脚手架是必要的:act()ROT.Path.AStar

玩家必须有公共方法来读取其位置,
我们需要一个 passableCallback 函数,它告诉路径查找器哪些区域是可通过的,
我们需要一个pathCallback函数,它将从路径查找器中调用(以通知我们找到的最短路径)。
此外,为了使佩德罗比玩家弱一些,我们将仅在 4 拓扑中使用探路者。

Player.prototype.getX = function() { return this._x; }

Player.prototype.getY = function() { return this._y; }

Pedro.prototype.act = function() {
    var x = Game.player.getX();
    var y = Game.player.getY();
    var passableCallback = function(x, y) {
        return (x+","+y in Game.map);
    }
    var astar = new ROT.Path.AStar(x, y, passableCallback, {topology:4});

    var path = [];
    var pathCallback = function(x, y) {
        path.push([x, y]);
    }
    astar.compute(this._x, this._y, pathCallback);
}

我们现在有佩德罗和球员之间的最短路径,存储在变量中。请注意,佩德罗目前的位置也是路径的一部分;这就是为什么我们首先放弃我们路径的第一项。如果生成的路径只有一个单元格长,则佩德罗站在玩家附近,游戏结束(玩家丢失)。否则,我们将应用与本教程第 2 部分中用于玩家的相同移动逻辑。path

Pedro.prototype.act = function() {
    /* ...previous stuff... */

    path.shift(); /* remove Pedro's position */
    if (path.length == 1) {
        Game.engine.lock();
        alert("Game over - you were captured by Pedro!");
    } else {
        x = path[0][0];
        y = path[0][1];
        Game.display.draw(this._x, this._y, Game.map[this._x+","+this._y]);
        this._x = x;
        this._y = y;
        this._draw();
    }

}

心得:确定这个插件刚开始接触,只是能使用,但是确实封装的可以,有很多学习的地方。有什么使用上的心得想要交流的可以加我qq 2053163664。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Rot.js 随机地牢,迷宫地图生成 的相关文章

随机推荐

  • 疯壳-鸿蒙OS-总线驱动开发及实现之SPI

    总线驱动及实现之SPI 疯壳 出品 SPI接口说明 鸿蒙OS中关于spi接口的定义在源码目录 drivers hdf frameworks include platform drivers hdf frameworks support pl
  • Python3-类型标注支持

    typing为Python的一个标注库 此默认支持PEP 484和PEP 526指定的类型提示 最基本的支持由Any Union Tuple Callable TypeVar和Generic类型组成 有关完整的规范 请参阅PEP 484 有
  • 本人亲自整理的极客时间设计模式之美的硬核笔记

    由于笔记内容过多 我把它放到语雀上了 点击我 以下内容是为了让搜索引擎 检测到这篇文章 要阅读体验 请点击上面的连接 点击我 去我的语雀看 对了 我看到语雀那里有投诉的功能 请读者不要去点 程序员不要为难程序员 你去点了 就再也无法看到我的
  • 分布式存储Ceph介绍及搭建

    一 存储的类型 1 单机存储设备 DAS 直接附加存储 是直接接到计算机的主板总线上去的存储 IDE SATA SCSI SAS USB 接口的磁盘 所谓接口就是一种存储设备驱动下的磁盘设备 提供块级别的存储 NAS 网络附加存储 是通过网
  • Scratch2.0在线注册用户并使用帮助

    教学目标 1 在Scratch2 0中注册一个账号 2 登录后 进行再线学习 3 利用帮助进行自主学习 了解Scratch作品的创作过程 教学过程 一 注册用户 第一步 https scratch mit edu 打开官网 点 加入Scra
  • cuda编程学习2——add

    cudaMalloc 分配的指针有使用限制 设备指针的使用限制总结如下 1 可以将其传递给在设备上执行的函数 2 可以在设备代码中使用其进行内存的读写操作 3 可以将其传递给在主机上执行的函数 4 不能在主机代码中使用其进行内存的读写操作
  • Rust Diesel SQLite Windows

    问题描述 windos下想用Rocket使用SQLite3 自带案例 example todo 提示链接不到sqlite3 lib 原因分析 找到两个相关的issues https github com SergioBenitez Rock
  • 配置JAVA_HOME环境变量

    打开到环境变量 1 右击此电脑选择属性 2 选择高级系统设置 3 选择环境变量 配置JAVA HOME环境变量 1 新建系统变量 1 在系统变量中找到Path 如果没有就新建一个 然后新建两个变量
  • 第一章:VUE3学习(一)---Nodejs安装以及环境变量配置

    Nodejs安装以及环境变量配置 1 下载Nodejs 1 1最新版下载 1 2历史版本下载 2 安装 3 验证 4 环境变量配置 5 npm下载设置 6 测试 6 设置国内镜像提高下载速度 1 下载Nodejs 1 1最新版下载 直接官网
  • 用QT写一个类似的安装向导界面

    本文目录 功能描述 功能实现 框架 功能1 点击同意协议 才能进行下一步 功能2 选中指定路径的文件夹 并遍历该文件夹下所有的文件 功能3 设置进度条 功能4 两种激活方式 完整代码 功能描述 1 点击同意协议 才能进行下一步 2 选择一个
  • 2020软件测试学习自学路线分享,附完整资料,绝对有用哟

    2020软件测试学习路线图 内附自学路线 视频 工具经验 面试篇 划重点 资源链接 黑马程序员社区 想毕业后做测试相关的工作的 找学习资源找的头大 还好终于找到这么优质的可以系统地学习测试知识的途径 想学测试的小伙伴看看 真的可以跟着一步步
  • 误差向量幅度(EVM)

    转自 http blog sina com cn s blog 6c46cb860100otm3 html 误差向量幅度 EVM 误差向量 包括幅度和相位的矢量 是在一个给定时刻理想无误差基准信号与实际发射信号的向量差 Error Vect
  • 微信小程序添加插件腾讯位置服务路线规划,找不着的solution

    第一个 找到网页点击添加插件 提示类别不一样pass 第二个 在后台管理添加插件 提示找不着 pass 这两方法都不行 解决方法是 开发者后台登陆后 右上角服务 进入微信服务市场 选择开发者资源 然后选择插件 搜索腾讯位置服务路线规划 亲测
  • 3045 Lcm与Gcd构造

    已知 gcd a b n lcm a b m 求min a b 是多少 通过gcd的了解我们可以知道 两个数a k1 n以及b k2 n并且gcd k1 k2 1 ab n m m a b n ab k1 k2 n n 于是可以得到 m k
  • Yii Framework 开发教程(44) Zii组件-Resizable示例

    CJuiResizable可以使包含在其中的UI组件支持缩放功能 它封装了 JUI Resizable插件 CJuiResizable基本使用方法如下 php view plain copy print
  • Anaconda Prompt的用法

    Windows 开始菜单 打开Anaconda Prompt 这个窗口和cmd窗口一样的 用命令 conda list 查看已安装的包 从这些库中我们可以发现NumPy Matplotlib Pandas 说明已经安装成功了 下一步可以测试
  • ACM入门攻略(紫书入门,不间断更新)

    声明 本文仅供参考 并且假定读者已经可以熟练运用C语言及其相关知识 大神请走开 谢谢配合 目录 一 ACM入门的相关准备 书籍 OJ 编程语言 常用网站或工具 二 入门阶段的学习路线及其策略 全文以紫书为例 1 紫书第五章语言篇写题策略 2
  • JS之对象-对象声明及静态方法

    声明对象 1 原型实例化 声明对象的方式1 原型实例化 let obj1 new Object obj1 name obj1 张三 obj1 getName function return this name console log obj
  • 八十七.查找与排序习题总结(二)

    查找与排序习题总结 一 查找与排序习题总结 三 题一 调整数组顺序 奇数在左 偶数在右 调整数组的顺序使奇数位于偶数前面 输入一个整数数组 调整数组中数字的顺序使得所有奇数位于数组的前半部分 所有偶数位于数组的后半部分 要求时间复杂度为O
  • Rot.js 随机地牢,迷宫地图生成

    js 插件随机地牢 迷宫地图生成 插件git https github com ondras rot js tree master dist 使用 1 我们的游戏是在网页内进行的 一个基本的 HTML 文件就足够了