写这篇文章的目的是为了在之后会讲到的关于Screeps中如何跨Tick执行代码这篇文章做铺垫。
本章内容也许对目前的你没有任何启发或者是作用,但他的的确确成为了跨Tick执行技术的基础。
状态模拟技术
概念:修改Screeps中的对象属性,让其拥有未来某个或任意Tick的状态或属性。
作用:这使得你可以在本tick中,计算下一个tick或任意一个可能的情况下,某个对象的操作。
这么说可能比较模糊,下面我们来到Screeps来实际运用一下状态模拟技术。
准备工作
- 1只Creep
- 1个SOURCE对象
请看下面的代码
(抽象代码,请勿直接使用)
RoomSources = Game.rooms[roomName].find(FIND_SOURCES)[0];
console.log(RoomSources.pos)
这段代码我们获得了一个Sources对象,并输出了它的pos位置对象。结果如下
{
roomName:"E10N10",
x:16
y:25
}
这表明这个Sources对象位于房间E10N10中16,25坐标上。
接下来我们来看看Creep
console.log(mycreep.pos)
得到输出
{
roomName:"E10N10",
x:22
y:16
}
同理也可见这个creep所在的房间和位置,很明显这个Creep和目标的Sources还有一段距离。
那么现在我们让这个Creep在当前位置尝试Harvest,下面是我们得到的结果
//某个tick内
RoomSources = Game.rooms[roomName].find(FIND_SOURCES)[0];
console.log(mycreep.harvest(RoomSources));
//返回
"ERR_NOT_IN_RANGE"
可见此时我们的creep尝试采集操作是提示距离不够的。
重点来了,如果我们尝试修改这个Creep的pos对象让他就在目标sources旁边呢?
//某个tick内
RoomSources = Game.rooms[roomName].find(FIND_SOURCES)[0];
mycreep.pos.x = 16;
mycreep.pos.y = 26;
console.log(mycreep.harvest(RoomSources));
//返回
"OK"
可见,即使我们的creep在当前tick并不在16,26这个坐标上,但通过我们强行修改,这个坐标不仅生效了,还成功让harvest方法返回了OK。
这就是状态模拟技术。
我们可以模拟这个creep的任意属性,再配合api,我们可以在第一个tick内计算第二个,第三个tick甚至第N个tick时,这个creep的预期行为。
了解了状态模拟概念,也许你应该零星明白了跨tick技术的基本原理。我们可以通过原型拓展(详见hoho大佬的文章,这里不详诉)以及链表技术,缓存creep未来几个tick的操作和行为。即使某个tick不对creep进行任何api操作,这个creep也能执行预期的任务。并且跨tick技术同时实现了运算和调用的完全分离,同时也让cpu的运行更加高效。
同理,状态模拟技术可以用于任何Screeps对象,下一篇文章我会细谈如何给这些对象进行高效的原型拓展以便于跨tick技术的应用。
不久将会更新关于跨tick技术的详解文章,敬请关注。