前端小废物系列(1)

您所在的位置:网站首页 类似screeps 前端小废物系列(1)

前端小废物系列(1)

2023-09-15 12:52| 来源: 网络整理| 查看: 265

新手教程(1)游戏 UI 和基本脚本

本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。

image.png

基本界面是这样的,第一步是认识教程关的提示按钮,有的时候提示是一大堆英文(如果和我一样不愿意打机翻中文补丁),看的人很烦。这个按钮用来开关提示,对我这样的新手很有用。

界面里我们这块地界称为一个「房间」,实际游戏时每个房间是挨在一起的(看这个地盘四周的出口),但是现在是教学关,暂时没必要放其他房间。(我记得教学关使用的是本地的 CPU,实际游戏使用的是游戏服务器的 CPU,这个游戏可以自己搞个服务器和同事朋友同学师长等等人自己玩,后面会讲到)关于实际游戏的房间排布参照这里:Game world

image.png

屏幕中间的是第一个「Spawn」,大概理解成虫族产卵的单位,这是种群的中心。

image.png

屏幕下面的位置是写代码用的,因为是在浏览器里玩(我截图是在客户端里玩,客户端实际上也是套壳浏览器,还有其他各式各样的客户端,后面会讲到),所以就借用了浏览器调试代码的这种形式。

image.png

脚本,控制台,内存这三个有快捷键,分别是「Alt + 1」「Alt + 2」「Alt + 3」

image.png

在浏览器里面玩的话,可以同时打开浏览器的调试窗口 Ctrl + Shift + J,然后觉得游戏内的这个太简陋还挡视线用 Alt + Enter 关掉。

image.png

「Spawn」 这个单位生产各种 「Creep」 使用的方法叫做 spawnCreep,每一个 「Creep」 都有一个具体的名字和一些特定的身体部件表达不同的行为(面向对象它来了)。

定位生产单位用 Game.spawns['Spawn1']。

这一步我们需要创建一个名为 Harvester1 的 「Creep」 对象,身体部件数组有 [WORK, CARRY, MOVE],命令敲到控制台上。

文档:

Your colony Creeps Game object StructureSpawn.spawnCreep Game.spawns['Spawn1'].spawnCreep( [WORK, CARRY, MOVE], 'Harvester1' );

image.png

生产中。。。

image.png

在右边查看这个 Harvester1 的详细信息(查看其他单位类似,需要鼠标先选中一个单位)

image.png

英文提示中的“View”动作,这里卖个关子,后面教程我记得是有专门区分的。

image.png

现在就可以让 Harvester1 动起来了(它有三个行为:工作,搬运,移动),地图里黄色一闪一闪的方块是能量资源,这些宝贵的资源可以被拥有一个或以上 WORK 部件的 「Creep」 收割,然后被拥有 CARRY 部件的 「Creep」 送回 「Spawn」。

image.png

为了让 「Creep」 一直工作,在控制台一遍一遍的催是不够的,脚本这时候就来了。(有些游戏里只要鼠标点点让采矿车锁定矿区就能自动工作下去,这里是用命令来驱动各种 「Creep」 的行为,没命令它们就原地待命)

image.png

在这里可以编写永久运行的脚本,游戏都是循环运行的(服务器不停你就可以继续榨取价值,这里的”tick“是双关语,前面界面也有,右边一个大大的暂停下面写出了 tick 和现实时间之间的转换比例,之后在真实游戏里详细说明),它允许玩家编写不断工作的程序来控制各种 「Creep」 的行为,即使玩家离线(仅在真实的游戏中,而不是教学关)程序也在服务器上不断运行。

要将脚本提交到游戏中运行,可以点这个对勾,也可以按 Ctrl+Enter。

每个教学关的代码都是在它自己的分支中创建的。玩家可以查看来自这些分支的代码,以便在自己的脚本中进一步使用。

文档:

Scripting basics

image.png

代码终于来了。。。把这段直接照搬过去就行,Harvester1 就能一直工作了

image.png

module.exports.loop = function () { var creep = Game.creeps['Harvester1']; var sources = creep.room.find(FIND_SOURCES); if(creep.harvest(sources[0]) == ERR_NOT_IN_RANGE) { creep.moveTo(sources[0]); } }

收割方法 harvest 需要 「Creep」挨着矿点(黄色资源点),寻址或者定位 「Creep」 用 Game.creeps['Harvester1']。然后在 Room.find 方法里加入常量参数 FIND_SOURCES,就是在房间里找资源点。

文档:

Game.creeps RoomObject.room Room.find Creep.moveTo Creep.harvest

image.png

采矿中。。。

image.png

把矿送回去又需要脚本了,对应前面所说的”没命令就原地待命“。「Creep」 把能量送回 「Spawn」 的方法是 Creep.transfer,方法同样在 「Creep」 和目标 「Spawn」紧挨时才能完成,所以采完矿的 「Creep」 还得走回去。

如果在代码里加入了 .store.getFreeCapacity() > 0 这句检查 「Creep」 的剩余容量,那自动采矿车就完成了。

文档:

Creep.transfer Creep.store module.exports.loop = function () { var creep = Game.creeps['Harvester1']; if(creep.store.getFreeCapacity() > 0) { var sources = creep.room.find(FIND_SOURCES); if(creep.harvest(sources[0]) == ERR_NOT_IN_RANGE) { creep.moveTo(sources[0]); } } else { if( creep.transfer(Game.spawns['Spawn1'], RESOURCE_ENERGY) == ERR_NOT_IN_RANGE ) { creep.moveTo(Game.spawns['Spawn1']); } } }

这是目前全部的脚本,只需要加上前面缺少的判断和送回相关语句。

image.png

正在往回送货。。。

image.png

这个 「Creep」 之后就以收割者(这么翻译总让人觉得它还有攻击性,但其实攻击相关的行为和方法在后面的教学关里,提前说一下不要搞混)的身份工作到狗带。几乎所有 「Creep」 的生命周期都是 1500 game ticks,之后它们就老掉了(教学关里狗带被关掉了)。

现在来再创建一个“工作细胞”(这么说是不是很形象)来帮助之前的 Harvester1。创建需要 200 点能量,所以需要等 Harvester1 收集足够的能量给 「Spawn」,这期间调用 spawnCreep 方法会返回错误代码 ERR_NOT_ENOUGH_ENERGY(-6) 直到有足够能量生产”工作细胞“。

如果命令只执行一次就用控制台。(脚本里的代码会反复执行,一直生产一个名字的对象后面也会报错)

生产第二个 「Creep」,称作 Harvester2,和 Harvester1 只有名字上的差别。

文档:

StructureSpawn.spawnCreep Game.spawns['Spawn1'].spawnCreep( [WORK, CARRY, MOVE], 'Harvester2' );

现在有两个收割者了,第二个因为没收到命令所以原地待命,现在要把它写到脚本里去,让它一直工作。

因为只有两个收割者,直接复制一份代码改对象名就行。更好的方法是用 for 循环包括所有的 「Creep」(目前所有的 「Creep」 都是收割者,所以不要紧,以后肯定还会有更多的收割者,还会有其他类型的 「Creep」,之后肯定还要改这里的代码)

文档:

for...in loops

image.png

module.exports.loop = function () { for(var name in Game.creeps) { var creep = Game.creeps[name]; if(creep.store.getFreeCapacity() > 0) { var sources = creep.room.find(FIND_SOURCES); if(creep.harvest(sources[0]) == ERR_NOT_IN_RANGE) { creep.moveTo(sources[0]); } } else { if(creep.transfer(Game.spawns['Spawn1'], RESOURCE_ENERGY) == ERR_NOT_IN_RANGE) { creep.moveTo(Game.spawns['Spawn1']); } } } }

image.png

代码就是要不断优化,这些“工蚁”(形象的比喻)的行为可以分离到一个 module 里。

创建一个名叫 role.harvester 的模块,在 module.exports 对象里定义一个函数 run 来包含 「Creep」 的行为

文档:

Organizing scripts using modules var roleHarvester = { /** @param {Creep} creep **/ run: function(creep) { if(creep.store.getFreeCapacity() > 0) { var sources = creep.room.find(FIND_SOURCES); if(creep.harvest(sources[0]) == ERR_NOT_IN_RANGE) { creep.moveTo(sources[0]); } } else { if(creep.transfer(Game.spawns['Spawn1'], RESOURCE_ENERGY) == ERR_NOT_IN_RANGE) { creep.moveTo(Game.spawns['Spawn1']); } } } }; module.exports = roleHarvester;

创建模块在左下角直接输入名字

image.png

有了模块以后代码结构就更清晰了,把主模块里多余的代码删掉,只留循环,用 require('role.harvester') 调用刚才新创建的模块。

image.png

var roleHarvester = require('role.harvester'); module.exports.loop = function () { for(var name in Game.creeps) { var creep = Game.creeps[name]; roleHarvester.run(creep); } }

image.png

这样教学关第一关就完成了,最后提醒的是让我们给代码分层,善用 role 和 module 来掌控各种各样的 「Creep」,下一关我们会开发新的 「Creep」 角色。

参考网页

screeps.com/

github.com/screeps/scr…

docs.screeps.com/

screeps-cn.github.io/

screeps.com/a/#!/sim/tu…



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3