前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Screeps Arena 游戏基础教程

Screeps Arena 游戏基础教程

作者头像
害恶细君
发布2024-04-03 08:15:37
1130
发布2024-04-03 08:15:37
举报
Screeps Arena 是一款纯编程的RTS游戏(即时战略游戏),通过编写JavaScript(或其他语言)代码,控制从采集资源、生产单位、建造、移动、攻击的各种操作和应变逻辑,来让自己的战略运行起来,和其他的代码成果进行对局。

一. 游戏内教程汉化

1. 循环和导入(Loop and Import)

欢迎来到本教程,您将学习如何通过编码发挥爬虫竞技场 (Screeps Arena) 的基础知识。

你通过在本地文件夹中编写代码来玩游戏,游戏内的编辑器不好使,所有我们推荐你们使用一些其他的代码编辑器,例如vscode来编写代码。

循环: 当您点击PLAY按钮时,这些文件被提交给服务器。如果你的代码中没有语法错误,游戏就会开始,你就可以观看了。你不能在游戏期间更改提交的代码,比赛几秒钟后就结束了之后,你可以用任何速度观看。

每一个回合(或者我们称之为tick),游戏都会运行你的主函数 loop() 。该函数在main.mjs中被定义:

代码语言:javascript
复制
export function loop() {
    // Your code goes here
}

这个函数中的所有内容都将被反复执行,直到游戏结束。

导入: 有一个特殊的函数getTicks(),您可以调用它来确定当前的刻度是多少。为了调用它,你必须将它从/game/utils模块导入到你的代码中:

代码语言:javascript
复制
import { getTicks } from 'game/utils';

export function loop() {
    console.log('Current tick:', getTicks());
}

有许多方法和对象可以通过这种方式导入。请参阅文档了解。console.log()输出游戏控制台面板中的任何值,以便您可以调试和检查正在运行的代码。你不需要导入这个函数,它是全局可用的。

让我们开始: 在教程的第一步,我们没有任何游戏对象,游戏地图完全是空的。完成这一步所要的就是打印循环的一些信息。只需要将上面的代码复制粘贴到你的main.mjs文件中,然后点击PLAY按钮运行。

在这里插入图片描述
在这里插入图片描述

2. 简单移动(Simple move)

每个爬虫可以做各种动作,显然它可以移动。

代码语言:javascript
复制
creep.moveTo(target);

这个命令会让你的爬虫向目标移动一步,如果你在每次循环迭代中都执行它,你的爬虫就会一直移动到目的地。(在调用此函数时立即执行,但只能在循环函数完成之后执行移动。)

从代码访问你的爬虫,有一个特殊的函数叫做getObjectsByPrototype( ) ,它返回一个数组,其中包含所有具有给定原型或类的游戏对象。你可以像下面这样选择游戏中的所有爬虫:

代码语言:javascript
复制
import { getObjectsByPrototype } from 'game/utils';
import { Creep } from 'game/prototypes';

export function loop() {
    let creeps = getObjectsByPrototype(Creep);
}

在本教程的步骤中,我们有一个Flag对象,它也有它的原型名称。

最终目标:使用移动的方法让你的爬虫踩到旗子上。

代码如下:

代码语言:javascript
复制
import { getObjectsByPrototype } from 'game/utils';
import { Creep, Flag } from 'game/prototypes';

export function loop() {
    let creeps = getObjectsByPrototype(Creep);
    let flags = getObjectsByPrototype(Flag);
    creeps[0].moveTo(flags[0]);
}

3. 首次攻击(First Attack)

Screeps Arena是一款多人PvP游戏,你的爬虫将会和对手的爬虫战斗,所有让我们来简单学习一下攻击。

如何判断哪些是你的爬虫,使用JavaScript标准的Array.filter( )Array.find( )方法返回给定条件的元素数组。

filter( ) 方法返回提供的数组中满足所提供测试函数的所有元素的数组。

代码语言:javascript
复制
const words = ['spray', 'elite', 'exuberant', 'destruction', 'present'];
const result = words.filter((word) => word.length > 6);
console.log(result);
// Expected output: Array ["exuberant", "destruction", "present"]

find() 方法返回提供的数组中满足所提供测试函数的第一个元素。

代码语言:javascript
复制
const array1 = [5, 12, 8, 130, 44];
const found = array1.find((element) => element > 10);
console.log(found);
// Expected output: 12

在下面的例子中,可以基于爬虫的属性来查找指定爬虫。

代码语言:javascript
复制
import { getObjectsByPrototype } from 'game/utils';
import { Creep } from 'game/prototypes';

export function loop() {
    var myCreep = getObjectsByPrototype(Creep).find(creep => creep.my);
    var enemyCreep = getObjectsByPrototype(Creep).find(creep => !creep.my);
}

现在我们可以使用attack方法攻击敌人了,当它无法到达目标时,他将返回ERR_NOT_IN_RANGE的错误信息,所以你需要先使用moveTo:

代码语言:javascript
复制
if(myCreep.attack(enemyCreep) == ERR_NOT_IN_RANGE) {
    myCreep.moveTo(enemyCreep);
}

本节最终目标:消灭敌方爬虫。

代码语言:javascript
复制
import { getObjectsByPrototype } from 'game/utils';
import { Creep } from 'game/prototypes';
import { ERR_NOT_IN_RANGE } from 'game/constants';

export function loop() {
    let myCreep = getObjectsByPrototype(Creep).find(creep => creep.my);
    let enemyCreep = getObjectsByPrototype(Creep).find(creep => !creep.my);
    if(myCreep.attack(enemyCreep) === ERR_NOT_IN_RANGE) {
        myCreep.moveTo(enemyCreep);
    }
}

4. 爬虫的身体部分(Creeps Bodies)

你可以调用爬虫的很多函数来完成某个行为,但是并非所有函数都可以用于某个爬虫。爬虫可以调用什么函数取决于它的身体部位。你可以检查他的body属性,它是一个数组,其中数组每个元素代表某种类型的一个主体部分:

MOVE:使爬虫移动。 ATTACK:允许它近战范围内攻击。 RANGED_ATTACK:允许它攻击3格外的目标。 HEAL:允许治疗它自己或另一个爬虫。 WORK:可以建造建筑或收集能量。 CARRY:增加爬虫携带资源的能力,身上可以携带更多的资源。 TOUGH :没有任何效果。

代码语言:javascript
复制
if(creep.body.some(bodyPart => bodyPart.type == ATTACK)) {
    // this creep has ATTACK body parts
}

Array..some() 是 JavaScript 中用于数组的方法之一,它用于检查数组中是否至少有一个元素满足指定的条件。这个方法会遍历数组的每个元素,直到找到一个满足条件的元素,然后立即返回 true。如果没有找到满足条件的元素,则返回 false。

代码语言:javascript
复制
array.some(callback(element[, index[, array]])[, thisArg])

参数说明: callback:一个用于测试每个元素的函数,它可以接受三个参数: element:当前正在处理的数组元素。 index(可选):当前正在处理的元素的索引。 array(可选):调用 some 方法的数组本身。 thisArg(可选):可选参数,函数执行时的 this 值。

每一个身体部位都会使爬虫的攻击力提高100点。当爬虫受到伤害时,他的身体部分也会受到伤害,如果该部分的数值被攻击清零了,它就会失去该部分的功能。同一类型的身体部位越多,这种类型的效果就越强。

现在,本教程步骤中我们有3种不同的部位:ATTACKRANGED_ATTACKHEAL的爬虫。只有协调好对手的行动,你才能打败他们。

为了做到这一点,使用与前一个教程步骤相同的方法,但根据他们的身体部位区分他们的行动,伤害发送者应该使用不同的方法(attackrangedAttack)进行伤害,治疗者应该使用heal方法治疗你受伤的爬虫。

代码语言:javascript
复制
import { getObjectsByPrototype } from 'game/utils';
import { Creep } from 'game/prototypes';
import { ERR_NOT_IN_RANGE, ATTACK, RANGED_ATTACK, HEAL } from 'game/constants';

export function loop() {
    let myCreeps = getObjectsByPrototype(Creep).filter(creep => creep.my);
    let enemyCreep = getObjectsByPrototype(Creep).find(creep => !creep.my);

    for(let creep of myCreeps) {
        if(creep.body.some(bodyPart => bodyPart.type == ATTACK)) {
            if(creep.attack(enemyCreep) == ERR_NOT_IN_RANGE) {
                creep.moveTo(enemyCreep);
            }
        }
        if(creep.body.some(bodyPart => bodyPart.type == RANGED_ATTACK)) {
            if(creep.rangedAttack(enemyCreep) == ERR_NOT_IN_RANGE) {
                creep.moveTo(enemyCreep);
            }
        }
        if(creep.body.some(bodyPart => bodyPart.type == HEAL)) {
            let myDamagedCreeps = myCreeps.filter(i => i.hits < i.hitsMax);
            if(myDamagedCreeps.length > 0) {
                if(creep.heal(myDamagedCreeps[0]) == ERR_NOT_IN_RANGE) {
                    creep.moveTo(myDamagedCreeps[0]);
                }
            }
        }
    }
}

for...of 语句执行一个循环,该循环处理来自可迭代对象的值序列。可迭代对象包括内置对象的实例,例如 Array、String、TypedArray、Map、Set、NodeList(以及其他 DOM 集合),还包括 arguments 对象、由生成器函数生成的生成器,以及用户定义的可迭代对象。

代码语言:javascript
复制
const array1 = ['a', 'b', 'c'];
for (const element of array1) {
  console.log(element);
}
// Expected output: "a"
// Expected output: "b"
// Expected output: "c"

5. 存储和转移 (Store and Transfer)

在不同的区域,有不同的可用资源。但是有一种常见的资源类型RESOURCE_ENERGY,用来建造建筑、生产爬虫等各种活动。

塔(Tower)可以造成50点的范围攻击伤害,尽管它的效率随着距离的增加而降低。在本教程的步骤中,我们将使用能量来给塔充能,以击败敌人。

代码语言:javascript
复制
tower.attack(target);

塔每次射击消耗10个能量单位。为了给它装载能量,你需要使用一个将能量传递给它的爬虫。

代码语言:javascript
复制
creep.transfer(tower, RESOURCE_ENERGY);

从哪里获得能量?附近有一个容器(Container),它的store有一些能量。你可以移动爬虫去容器中回收能量:

代码语言:javascript
复制
creep.withdraw(container, RESOURCE_ENERGY);

当塔内有足够能量时,他会攻击并摧毁目标。

如果你使用我们的示例代码,请注意我们现在是如何以不同的方式导入内容的(不是特别定义他们,而是从/game模块导入整个命名空间。)用哪种导入的写法,根据自己的喜好来:

代码语言:javascript
复制
import { prototypes, utils, constants } from 'game';

export function loop() {
    const tower = utils.getObjectsByPrototype(prototypes.StructureTower)[0];
    if(tower.store[constants.RESOURCE_ENERGY] < 10) {
        let myCreep = utils.getObjectsByPrototype(prototypes.Creep).find(creep => creep.my);
        if(myCreep.store[constants.RESOURCE_ENERGY] == 0) {
            let container = utils.getObjectsByPrototype(prototypes.StructureContainer)[0];
            myCreep.withdraw(container, constants.RESOURCE_ENERGY);
        } else {
            myCreep.transfer(tower, constants.RESOURCE_ENERGY);
        }
    } else {
        let target = utils.getObjectsByPrototype(prototypes.Creep).find(creep => !creep.my);
        tower.attack(target);
    }
}

6. 地形 (Terrain)

游戏中5种地形:平原地形、天然的坚不可摧的墙壁、建造的可摧毁的墙、沼泽、道路。

沼泽和道路上移动与爬虫的重量相关联。每个爬虫的身体部位,除了MOVE,都会增加了他的重量。(一个空的CARRY 身体部位不会增加重量),但如果爬虫体内有资源将会增加它的身体重量。每个MOVE部位能增加爬虫的移动速度。如果的MOVE身体部位和所有其他身体部位数量数量相同时,你的爬虫将勉勉强强能够在平原地形上移动。否则小于的话,他会感到疲劳,动弹不得。

但是有相同身体部位的爬虫在沼泽上,它会变得更加疲劳,并且每5 tick才只能移动一次。为了让你每次tick都能移动,你的爬虫将需要5倍以上的MOVE部件。

相反,道路减少了你的爬虫对MOVE部件的需求。例如,如果你的爬虫有10个负重的身体部位,你在道路上移动就只需要5个MOVE身体部件就可以使这个爬虫每次循环移动。

注意,当你需要使用寻路算法从一个数组中找到一个位置最近的对象时,可以使用findClosestByPath 函数。

代码语言:javascript
复制
let flags = getObjectsByPrototype(Flag);
let closestFlag = creep.findClosestByPath(flags);

在本节教程中,你只需要将每个爬虫移动到相应的旗子。代码如下:

代码语言:javascript
复制
import { getObjectsByPrototype } from 'game/utils';
import { Creep, Flag } from 'game/prototypes';

export function loop() {
    let creeps = getObjectsByPrototype(Creep).filter(i => i.my);
    let flags = getObjectsByPrototype(Flag);
    for(let creep of creeps) {
        let flag = creep.findClosestByPath(flags);
        creep.moveTo(flag);
    }
}

7. 生产爬虫(Spawn Creeps)

当你在一个有Spawn结构的竞技场上玩游戏时,你可以使用spawnCreep方法创建新的爬虫。您需要将新爬虫的主体定义为包含其主体部分的数组。

你想要刷出的爬虫越大,它消耗的能量就越多,具体数值如下: MOVE:50能量 ATTACK:80能量 RANGED_ATTACK:150能量 HEAL:250能量 WORK:100能量 CARRY:50能量 TOUGH :10能量

spawnCreep方法返回一个稍后使用的Creep实例。

代码语言:javascript
复制
let creep = mySpawn.spawnCreep([MOVE, ATTACK]).object;

你甚至可以在loop函数之外定义变量,以便在tick之间使用它们:

代码语言:javascript
复制
let creep;
export function loop() {
    if(!creep) {
        creep = mySpawn.spawnCreep([MOVE, ATTACK]).object;
    }
}

请注意,您可以为这个爬虫对象分配任何属性,如果你想要给爬虫分布一些目标、角色或其他数据,这可能会很有用:

代码语言:javascript
复制
creep.target = flag;

在本教程步骤中,你有一个刷出和两个旗帜。目标:刷出两个爬虫,并将每个爬虫移动到每个旗帜上。

代码语言:javascript
复制
import { getObjectsByPrototype } from 'game/utils';
import { Creep, Flag, StructureSpawn } from 'game/prototypes';
import { MOVE } from 'game/constants';

let creep1, creep2;

export function loop() {
    let mySpawn = getObjectsByPrototype(StructureSpawn)[0];
    let flags = getObjectsByPrototype(Flag);

    if(!creep1) {
        creep1 = mySpawn.spawnCreep([MOVE]).object;
    } else {
        creep1.moveTo(flags[0]);

        if(!creep2) {
            creep2 = mySpawn.spawnCreep([MOVE]).object;
        } else {
            creep2.moveTo(flags[1]);
        }
    }
}

8. 收割能源(Harvest Energy)

能源可以以不同的形式获得,它可以存储在容器中,但是也可以从Sources中收获,如果你的爬虫有work身体部位,那么它就可以使用使用harvest方法从Source提取一些能量。

代码语言:javascript
复制
creep.harvest(source);

你的爬虫必须靠近能源才能执行这个动作。它拥有的WORK身体部位越多,每一次从能源处提取的能量就越多。能源中的能量储备是无限的,一段时间后会重新刷满。

本节目标:收割和转移1000能量到Spawn

代码语言:javascript
复制
import { prototypes, utils, constants } from 'game';

export function loop() {
    let creep = utils.getObjectsByPrototype(prototypes.Creep).find(i => i.my);
    let source = utils.getObjectsByPrototype(prototypes.Source)[0];
    let spawn = utils.getObjectsByPrototype(prototypes.StructureSpawn).find(i => i.my);

    if(creep.store.getFreeCapacity(constants.RESOURCE_ENERGY)) {
        if(creep.harvest(source) == constants.ERR_NOT_IN_RANGE) {
            creep.moveTo(source);
        }
    } else {
        if(creep.transfer(spawn, constants.RESOURCE_ENERGY) == constants.ERR_NOT_IN_RANGE) {
            creep.moveTo(spawn);
        }
    }
}

9. 建设(Construction)

你不仅可以生成爬虫,还可以建造建筑!只需要一点能量和一个工人就能完成工作。

首先,使用createConstructionSite函数放置一个名为StructureTower在某个地方,你需要指定建筑的坐标和原型。

代码语言:javascript
复制
import { createConstructionSite } from 'game/utils';
import { StructureTower } from 'game/prototypes';

export function loop() {
    let constructionSite = createConstructionSite({x: 50, y: 55}, StructureTower).object;
}

你带着能量的爬虫必须接近建筑工地建造他:

代码语言:javascript
复制
creep.build(constructionSite);

每一次成功的建造行动都会消耗你的爬虫体内存储的一些能量,所以你的爬虫需要在你的能量供应处和建筑工地之间来回穿梭。

本节目标:建造一座塔。

代码语言:javascript
复制
import { prototypes, utils } from 'game';
import { RESOURCE_ENERGY, ERR_NOT_IN_RANGE } from 'game/constants';

export function loop() {
    const creep = utils.getObjectsByPrototype(prototypes.Creep).find(i => i.my);
    if(!creep.store[RESOURCE_ENERGY]) {
        const container = utils.findClosestByPath(creep, utils.getObjectsByPrototype(prototypes.StructureContainer));
        if(creep.withdraw(container, RESOURCE_ENERGY) == ERR_NOT_IN_RANGE) {
            creep.moveTo(container);
        }
    } else {
        const constructionSite = utils.getObjectsByPrototype(prototypes.ConstructionSite).find(i => i.my);
        if(!constructionSite) {
            utils.createConstructionSite(50,55, prototypes.StructureTower);
        } else {
            if(creep.build(constructionSite) == ERR_NOT_IN_RANGE) {
                creep.moveTo(constructionSite);
            }
        }
    }
}

10. 最终测试(Final Test)

现在你已经学会了如何控制爬虫,攻击敌人,使用能量,产生新的爬虫,建造新的结构。看起来你已经为最终测试做好了准备!

在本教程步骤中,你有一个Spawn和一个Source。有一群敌人的爬虫,你要产生更多的爬虫,并击败他们。这次我们甚至不会给你提供示例代码! 当你完成本教程,你可以移动到真正的PvP竞技场,并开始在多人模式下与其他人战斗。祝你好运!

目标:在攻击中幸存下来,杀死所有的敌人并完成教程。

本节就不写示例代码了,每个人都有每个人自己的写法,正好做一个小小测试。

游戏官方已经提供了比较全面的vscode代码补全功能了,你只要用vscode打开对应模式的文件夹(注意不要单打开文件,而应该打开文件夹!)就能使用代码补全来编写代码了。然后在第一行加上// @ts-nocheck就不会报错啦。

以后打算再汉化一下官方的API文档,敬请期待,希望能帮到大家!

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2024-04-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Screeps Arena 是一款纯编程的RTS游戏(即时战略游戏),通过编写JavaScript(或其他语言)代码,控制从采集资源、生产单位、建造、移动、攻击的各种操作和应变逻辑,来让自己的战略运行起来,和其他的代码成果进行对局。
  • 一. 游戏内教程汉化
    • 1. 循环和导入(Loop and Import)
      • 2. 简单移动(Simple move)
        • 3. 首次攻击(First Attack)
          • 4. 爬虫的身体部分(Creeps Bodies)
            • 5. 存储和转移 (Store and Transfer)
              • 6. 地形 (Terrain)
                • 7. 生产爬虫(Spawn Creeps)
                  • 8. 收割能源(Harvest Energy)
                    • 9. 建设(Construction)
                      • 10. 最终测试(Final Test)
                      相关产品与服务
                      容器服务
                      腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档