前言
某天在高铁站刷某乎时刷到一个话题,有没有一种游戏对外提供Api接口供玩家编程玩(大概就是这个意思)
下面有个回答就提到了这个游戏,Screeps
本人马上就去Steam关注了这款游戏,没过多久就直接全款入了(没过几天就半价了😅😅😅),本文简单记录了本人玩儿款游戏的入门过程以及心路历程还有本人现在运行的脚本的设计思路,供大家参考
本文并非完全是入门教程,仅有少部分教学内容,如果有更好的方法或建议,可以在评论区提出
一、工程搭建
在游戏初期,我采用的时官方教程中的那种编写方式,就是几个js文件,整个项目没有采用工程化的形式,又不熟悉Api,在逐渐增加功能时,越来越难维护,不能模块化的管理导致代码的混乱,于是我花了一段时间,将项目工程化。
从此开启狂肝之路。
工程化的教程参考HoPGoldy大佬的简书教程
二、设计构思
-
doc:JSDoc生成的文档(本项目没有使用TS,而是使用JS+JSDoc的形式)
-
src:存放所有源码的文件夹
-
modules:根目录
-
action:存放行为逻辑
-
creep:存放creep的行为逻辑,文件以角色命名
- public:存放creep公共的行为逻辑
-
structure:存放建筑的行为逻辑,文件以建筑命名
- public:存放建筑公共的行为逻辑
-
-
config:存放了生成creep的配置(考虑到要控制多个房间,每个房间生成的creep的配置也不同,通过一个方法来读取配置从而生成creep)
javascriptimport {BUILDER, HARVERSTER, REPAIRER, UPGRADER} from "../constant/roleConstant.js"; const creepNumConfig = { "E18S35": { "harvester": { role: HARVERSTER, bodys: [WORK, WORK, CARRY, CARRY, CARRY, CARRY, CARRY, CARRY, MOVE, MOVE], number: 4 }, "upgrader": { role: UPGRADER, bodys: [WORK, WORK, WORK, WORK, CARRY, CARRY, CARRY, CARRY, MOVE, MOVE], number: 7 }, "builder": { role: BUILDER, bodys: [WORK, WORK, CARRY, CARRY, MOVE, MOVE], number: 2 }, "repairer": { role: REPAIRER, bodys: [WORK, CARRY, MOVE], number: 1 } } }
-
constant:存放了一些角色、工作状态的常量
-
controller:分管各个模块的控制器(main中只调用控制器)
-
mount:原型扩展(暂时未用到)
此时,大体的工程以及相关对象的行为逻辑就已经构建完成,直到我的控制器升到4级。
三、优化改进
优化是逐步的,不要一开始就开始优化
资源利用率
上面提到的代码中creep的行为逻辑大概是,出生=>去挖矿(未工作状态)=>自检自身的能量是否存满=>存满了就更改为工作状态=>进行自己角色对应的工作=>能量耗尽=>去挖矿(未工作状态),所有的creep都遵循这一套逻辑,只是具体的工作不同,有的是升级控制器,有些是建造建筑。
这样的逻辑很简单粗暴,但是会造成以下的几个问题:
- 一个source的点位最多就只能容纳3个creep(视自己的房间情况定,有些source的开采点位有很多),也就是说,如果有4个creep的目标是同一个source,那么就会有一个creep会一直闲置在source旁,必须等到其中一个creep挖完了才行。
- 所有的creep从矿点到工作点还是有一段距离,挖完矿后可能会有疲劳问题,导致速度下降,这样就会把大量的时间浪费在路上
- 不连续的挖矿导致一个source周期(大约300tick)内不能把能量挖完,这样会产生极大的浪费
优化建议
针对以上的3个问题,本人仅发表自己的看法,如有更好的方法,可以在评论区提出。
**挖运分离:**在可用的矿点(creep能开采的那格)建造container(会自动收集同一格掉落的source),这样就可以实现挖运分离,一个角色复杂挖矿,另一个角色负责运输,一个3000点的资源,两个带有3个WORK组件的creep,在300tick内就能开采完,负责挖的creep只需要有WORK组件和MOVE组件,MOVE组件主要是要消除creep走到source那一段的疲劳值。
**善用link:**和container不同,link需要creep去运送能量,这样可以让creep去挖source然后运给link,link再传递给指定的link,我的升级者(升级controller的creep)只需要蹲在link旁拿能量就行,能量有百分之3的损耗,基本上不用考虑。
link传以此能量是有冷却时间的,冷却时间是随传输距离定的,两个link隔的越远,冷却越长。
优化后配置(生成creep的数量减少了,个体的强度也减少了,但是对source的开采率变高了,既开源又节流):
javascript
const creepNumConfig = {
"E18S35": {
"harvester": {
role: HARVERSTER,
bodys: [WORK, WORK, WORK, MOVE, MOVE, MOVE],
number: 2,
weight: 4
},
"upgrader": {
role: UPGRADER,
bodys: [WORK, WORK, WORK, WORK, WORK, WORK, WORK, CARRY, MOVE, MOVE],
number: 2,
weight: 2
},
"builder": {
role: BUILDER,
bodys: [WORK, WORK, WORK, WORK, CARRY, CARRY, MOVE, MOVE, MOVE],
number: 3,
weight: 5
},
"repairer": {
role: REPAIRER,
bodys: [WORK, CARRY, MOVE],
number: 1,
weight: 6
},
"transporter": {
role: TRANSPORTER,
bodys: [CARRY, CARRY, CARRY,CARRY,CARRY,CARRY, MOVE, MOVE, MOVE],
number: 2,
weight: 1
},
"linkTransporter": {
role: LINKTRANSPORTER,
bodys: [WORK, WORK, WORK, CARRY, CARRY, MOVE, MOVE],
number: 2,
weight: 3
}
}
}
新加的weight字段主要用来决定,生成的creep的顺序问题,在本游戏中,挖取资源的角色应该是最高优先级,所以要保证它的生成顺序是在第一顺位。
creep对房间的兼容性
有朋友可能会想一个问题,当控制多个房间的时候,房间的控制器等级是不一样的,这样就会导致有些房间可能没有container和link这些建筑,那creep就不能遵循优化的那个逻辑了。
优化建议
在执行工作的逻辑的基础上添加一个,如果房间不存在某某建筑,那就去挖矿,用最简单粗暴的那种方式发育,等控制器等级上去了再来优化
这是一段我的升级者的实例代码
javascript
import {getAppointFreeStructure, getStorageSources, workSwitch} from "./public/CreepPublicAction.js";
import {UPGRADING} from "../../constant/workStateConstant.js";
/**
* 升级者工作逻辑
* @param {Creep} creep
*/
export const upgraderRun = (creep) => {
//工作逻辑转换
workSwitch(creep, UPGRADING, '🔄 harvest', '⚡ upgrade')
//creep.memory[UPGRADING]是一个boolen值,能量满时为true
if (creep.memory[UPGRADING]) {
workCore(creep)
} else {
getSources(creep)
}
};
const workCore = (creep) => {
if (creep.upgradeController(creep.room.controller) === ERR_NOT_IN_RANGE) {
creep.moveTo(creep.room.controller, {visualizePathStyle: {stroke: '#aeef06'}});
}
}
const getSources = (creep) => {
//getAppointFreeStructure是我自己封装的方法,主要是用来筛选指定的有存储能力的建筑。
const link = getAppointFreeStructure(creep, STRUCTURE_LINK)
//检测link是否存在
if (link.length > 0) {
if (creep.withdraw(link[1], RESOURCE_ENERGY) === ERR_NOT_IN_RANGE) {
creep.moveTo(link[1])
}
} else {
//此方法也是自己封装的方法,没有link时就去Storage获取能量,没有Storage就去挖矿。
getStorageSources(creep, 1)
}
}
总结
以上就是本人几天玩儿下来的小感悟,2024年4月8号买的这个游戏,截至今天发稿,已经玩儿了将近110个小时了,这个游戏真的很对我胃口😂😂😂