这是苔原塔竞技场的进阶强化篇。如果说前一篇讲的是"玩法规则",那么本篇就是你的编程工具箱——把竞技场里能用到的所有方法和属性按类整理出来,方便你随时查阅。
本篇按四大类组织:Hero 类(你的英雄,掌控全局)、Tower 类(防御塔对象)、Guard 类(古代守卫对象)、Vector 类(向量数学工具)。每一个 API 都同时给出 Python 和 C++ 两种语言的示例代码,点击代码块上方的标签即可切换。
x 坐标的属性和方法,当你以蓝队身份对战时都会被系统自动镜像。你只需按红队视角编写一套代码即可,无需为蓝队做任何特殊处理。
x 与纵坐标 y。蓝队时坐标自动镜像。# 读取基地坐标与状态 baseX = hero.x baseY = hero.y elapsed = hero.time # 基地血量低于一半时,做出反应 if hero.health < hero.maxHealth / 2: if hero.isReady("burst"): hero.special("burst", hero.x + 10, hero.y)
// 读取基地坐标与状态 auto baseX = hero.x; auto baseY = hero.y; auto elapsed = hero.time; // 基地血量低于一半时,做出反应 if (hero.health < hero.maxHealth / 2) { if (hero.isReady("burst")) { hero.special("burst", hero.x + 10, hero.y); } }
towerTypes 返回可召唤的塔类型列表;monsterTypes 返回怪物波次中会遇到的怪物类型列表。list# 攒够 25 法力才建塔 if hero.mana >= 25: hero.build("archer", "A") # 读取所有可用塔类型和怪物类型 towers = hero.towerTypes monsters = hero.monsterTypes
// 攒够 25 法力才建塔 if (hero.mana >= 25) { hero.build("archer", "A"); } // 读取所有可用塔类型和怪物类型 auto towers = hero.towerTypes; auto monsters = hero.monsterTypes;
"A" 到 "I")建造一座塔。只能建在本队颜色或紫色(公共)格子上。建造消耗法力——若法力不足,代码会被阻塞直到攒够为止。若格子被对手的塔占据则无法建造;若被你自己的塔占据,则升级该塔到下一级,并在类型不符时切换为 towerType 类型。{x, y} 的格子中心建造一座塔,规则同上。返回 tower 对象hero.availableTowerTypes 属性查阅所有可用塔类型。
# 方式一:用点位名建造 hero.build("archer", "A") # 方式二:用坐标建造,并接收返回的塔对象 tower = hero.build("mage", 15, 40) level = tower.level # 在同一点位再建一次 = 升级 hero.build("archer", "A") # 升级 A 点的弓箭塔
// 方式一:用点位名建造 hero.build("archer", "A"); // 方式二:用坐标建造,并接收返回的塔对象 auto tower = hero.build("mage", 15, 40); auto level = tower.level; // 在同一点位再建一次 = 升级 hero.build("archer", "A"); // 升级 A 点的弓箭塔
{x, y} 的格子是否可以建造(可升级也返回 true)。boolean# 先确认能建,再建,避免法力被阻塞浪费 if hero.canBuildAt(30, 50): hero.build("cannon", 30, 50)
// 先确认能建,再建,避免法力被阻塞浪费 if (hero.canBuildAt(30, 50)) { hero.build("cannon", 30, 50); }
{x, y} 释放一个引力技能。特殊技能不消耗法力,但需要时间冷却。可用的 specialType 有:"pull"(引力井,吸聚怪物)、"push"(推开怪物)、"burst"(短促强力的推)、"teleport"(把怪物传送到对手基地方向)。# 拉力就绪时,把怪物吸聚到加农炮射程内 if hero.isReady("pull"): hero.special("pull", 40, 40) # 怪物逼近基地,用爆发救场 if hero.isReady("burst"): hero.special("burst", hero.x + 10, hero.y)
// 拉力就绪时,把怪物吸聚到加农炮射程内 if (hero.isReady("pull")) { hero.special("pull", 40, 40); } // 怪物逼近基地,用爆发救场 if (hero.isReady("burst")) { hero.special("burst", hero.x + 10, hero.y); }
# 遍历我方所有塔,统计类型与等级 myTowers = hero.findMyTowers() for t in myTowers: type = t.type level = t.level # 比较双方基地血量 enemy = hero.getEnemyHero() if hero.health > enemy.health: hero.build("archer", "A")
// 遍历我方所有塔,统计类型与等级 auto myTowers = hero.findMyTowers(); for (auto& t : myTowers) { auto type = t.type; auto level = t.level; } // 比较双方基地血量 auto enemy = hero.getEnemyHero(); if (hero.health > enemy.health) { hero.build("archer", "A"); }
type、level、attackDamage、attackRange、attackCooldown、cost。type、attackDamage、attackRange、maxSpeed、mana、flying(是否飞行)。# 查询 3 级法师塔的参数 params = hero.getTowerParameters("mage", 3) range = params.attackRange # 判断怪物是否会飞,决定是否需要法师塔 mp = hero.getMonsterParameters("rider") if mp.flying: hero.build("mage", "B")
// 查询 3 级法师塔的参数 auto params = hero.getTowerParameters("mage", 3); auto range = params.attackRange; // 判断怪物是否会飞,决定是否需要法师塔 auto mp = hero.getMonsterParameters("rider"); if (mp.flying) { hero.build("mage", "B"); }
# getWaves() 返回结构示例: # [ # ['munchkin'], # 第1波只有 munchkin # ['munchkin', 'ogre'], # 一个 munchkin 再一个 ogre,循环 # ['ogre', 'thrower', 'munchkin'], # 三种怪物按此顺序 # ] waves = hero.getWaves() total = len(waves)
// getWaves() 返回结构示例: // [ // ["munchkin"], // 第1波只有 munchkin // ["munchkin", "ogre"], // 一个 munchkin 再一个 ogre,循环 // ["ogre", "thrower", "munchkin"], // 三种怪物按此顺序 // ] auto waves = hero.getWaves(); auto total = waves.size();
getWave(n) 返回第 n 波的怪物类型数组(第一波编号为 0);getWaveNumber() 返回当前波次编号(整数,首波为 0)。# 提前侦察下一波,若有飞行怪就补法师塔 nextWave = hero.getNextWave() if "bird" in nextWave or "rider" in nextWave: hero.build("mage", "B") current = hero.getWaveNumber()
// 提前侦察下一波,若有飞行怪就补法师塔 auto nextWave = hero.getNextWave(); if (nextWave.contains("bird") || nextWave.contains("rider")) { hero.build("mage", "B"); } auto current = hero.getWaveNumber();
targetingType 可为:'close'(默认,最近的怪)、'left'(按 X 坐标离基地最近)、'right'(按 X 坐标离基地最远)、'weak'(血量最低)、'strong'(血量最高)。| 策略 | 含义 | 适用场景 |
|---|---|---|
'close' | 最近的怪物(默认) | 通用,保护塔自身周边 |
'left' | 按 X 离基地最近 | 优先打最逼近基地的怪 |
'right' | 按 X 离基地最远 | 提前点掉刚进场的怪 |
'weak' | 血量最低 | 快速收割、刷法力 |
'strong' | 血量最高 | 集火精英厚血怪 |
# 让 A 点的塔优先攻击最逼近基地的怪 tower = hero.build("archer", "A") hero.setTargeting(tower, "left") # 让所有加农炮集火血量最高的精英怪 for t in hero.findMyTowers(): if t.type == "cannon": hero.setTargeting(t, "strong")
// 让 A 点的塔优先攻击最逼近基地的怪 auto tower = hero.build("archer", "A"); hero.setTargeting(tower, "left"); // 让所有加农炮集火血量最高的精英怪 for (auto& t : hero.findMyTowers()) { if (t.type == "cannon") { hero.setTargeting(t, "strong"); } }
force(强度,正数=拉、负数=推)、x、y、endX/endY(传送出口坐标)、name(产生它的技能名)、duration(剩余持续时间)。t 秒,什么也不做。# 守卫生成回调:自动攻击最近怪物 def guardAct(data): guard = data.guard while True: monster = guard.findNearestMonster() if monster: guard.attack(monster) hero.on("spawn-guard", guardAct) # 查看活跃技能并等待 anomalies = hero.findActiveAnomalies() if len(anomalies) == 0: hero.wait(1)
// 守卫生成回调:自动攻击最近怪物 void guardAct(auto data) { auto guard = data.guard; while (true) { auto monster = guard.findNearestMonster(); if (monster) { guard.attack(monster); } } } hero.on("spawn-guard", guardAct); // 查看活跃技能并等待 auto anomalies = hero.findActiveAnomalies(); if (anomalies.size() == 0) { hero.wait(1); }
spawn-guard 的回调函数里调用会阻塞的英雄方法(如 hero.build、hero.special),否则会卡住主线程。回调里只使用守卫自己的方法。
targets 数组中返回离英雄最近的目标;数组为空时返回 null。# 找到最近的怪物,并对它所在位置释放拉力 monsters = hero.findMonsters() nearest = hero.findNearest(monsters) if nearest and hero.isReady("pull"): d = hero.distanceTo(nearest) if d < 40: hero.special("pull", nearest.x, nearest.y)
// 找到最近的怪物,并对它所在位置释放拉力 auto monsters = hero.findMonsters(); auto nearest = hero.findNearest(monsters); if (nearest && hero.isReady("pull")) { auto d = hero.distanceTo(nearest); if (d < 40) { hero.special("pull", nearest.x, nearest.y); } }
由 hero.build(...) 或 hero.findMyTowers() 等方法得到的塔对象拥有以下只读属性:
| 属性 | 说明 |
|---|---|
tower.x / tower.y | 塔中心的横 / 纵坐标(蓝队时自动镜像) |
tower.attackDamage | 塔每次攻击的伤害 |
tower.attackCooldown | 塔两次攻击之间的间隔时间 |
tower.attackRange | 塔攻击的最大射程 |
tower.level | 塔的等级 |
tower.type | 塔的类型字符串 |
# 找出等级最低的塔,优先升级它 towers = hero.findMyTowers() if len(towers) > 0: weakest = towers[0] for t in towers: if t.level < weakest.level: weakest = t hero.build(weakest.type, weakest.x, weakest.y)
// 找出等级最低的塔,优先升级它 auto towers = hero.findMyTowers(); if (towers.size() > 0) { auto weakest = towers[0]; for (auto& t : towers) { if (t.level < weakest.level) { weakest = t; } } hero.build(weakest.type, weakest.x, weakest.y); }
在 spawn-guard 回调函数中拿到的 guard 对象拥有以下方法。它们用来移动、攻击、释放守卫专属技能。
{x, y}。该方法阻塞守卫代码,直到守卫到达目标点后才执行下一条命令。{x, y} 移动。该方法不阻塞,可被后续命令打断。abilityName 可为:"roar"(让周围怪物都来攻击守卫)、"hide"(隐匿,丢失所有怪物仇恨)、"haste"(短时间提升守卫速度)。"roar" / "hide" / "haste")。booleandef guardAct(data): guard = data.guard while True: monster = guard.findNearestMonster() if monster: # 离得远先靠近,靠近后用咆哮聚怪再攻击 if guard.distanceTo(monster) > 5: guard.moveToward(monster.x, monster.y) else: if guard.isReady("roar"): guard.special("roar") guard.attack(monster) hero.on("spawn-guard", guardAct)
void guardAct(auto data) { auto guard = data.guard; while (true) { auto monster = guard.findNearestMonster(); if (monster) { // 离得远先靠近,靠近后用咆哮聚怪再攻击 if (guard.distanceTo(monster) > 5) { guard.moveToward(monster.x, monster.y); } else { if (guard.isReady("roar")) { guard.special("roar"); } guard.attack(monster); } } } } hero.on("spawn-guard", guardAct);
Vector(向量)类为单位提供了访问坐标与进行向量运算的能力。它在计算方向、距离、目标位置时非常有用。
| 成员 | 说明 |
|---|---|
Vector.x / .y / .z | 向量的 x / y / z 坐标(通常以米为单位) |
Vector.magnitude() | 返回向量的长度(模) |
Vector.heading() | 返回向量的朝向角度(弧度)。指向右为 0,指向上为 π/2 |
Vector.distance(other) | 返回到另一个向量的距离 |
Vector.dot(other) | 返回点积:this.x*other.x + this.y*other.y |
Vector.equals(other) | 返回此向量是否等于给定向量 |
Vector.copy() | 返回此向量的一个副本 |
| 类方法 | 说明 |
|---|---|
Vector.add(a, b) | 两个向量相加,返回新向量 |
Vector.subtract(a, b) | 一个向量减去另一个,返回新向量 |
Vector.multiply(n) | 向量乘以标量,返回新向量 |
Vector.divide(n) | 向量除以标量,返回新向量 |
Vector.limit(max) | 把向量限制到给定长度(更短则不变),返回新向量 |
Vector.normalize() | 把向量归一化为长度 1(长度为 0 时除外),返回新向量 |
Vector.rotate(vector, angle) | 把向量绕原点旋转给定角度,返回新向量 |
# 计算从基地指向某怪物的方向向量 base = Vector(hero.x, hero.y) target = Vector(monster.x, monster.y) # 方向 = 目标 - 基地,再归一化 direction = Vector.subtract(target, base) unit = direction.normalize() dist = base.distance(target) angle = direction.heading() # 在基地前方 15 米处释放推力 spot = Vector.add(base, Vector.multiply(unit, 15)) hero.special("push", spot.x, spot.y)
// 计算从基地指向某怪物的方向向量 Vector base(hero.x, hero.y); Vector target(monster.x, monster.y); // 方向 = 目标 - 基地,再归一化 auto direction = Vector::subtract(target, base); auto unit = direction.normalize(); auto dist = base.distance(target); auto angle = direction.heading(); // 在基地前方 15 米处释放推力 auto spot = Vector::add(base, Vector::multiply(unit, 15)); hero.special("push", spot.x, spot.y);
| 类别 | 常用成员 |
|---|---|
| Hero · 属性 | x y time health maxHealth mana towerTypes monsterTypes |
| Hero · 建造 | build(type, place) build(type, x, y) canBuildAt(x, y) |
| Hero · 技能 | special(type, x, y) isReady(type) |
| Hero · 查询 | findTowers() findMyTowers() findEnemyTowers() getEnemyHero() |
| Hero · 参数 | getTowerParameters(type, level) getMonsterParameters(type) |
| Hero · 波次 | getWaves() getWave(n) getWaveNumber() getCurrentWave() getNextWave() |
| Hero · 策略 | setTargeting(tower, type) |
| Hero · 技能/守卫 | findActiveAnomalies() wait(t) on("spawn-guard", fn) findMyGuards() findEnemyGuards() |
| Hero · 寻敌 | distanceTo(t) findMonsters() findNearest(targets) |
| Tower | x y attackDamage attackCooldown attackRange level type |
| Guard | moveTo(x,y) moveToward(x,y) attack(t) special(name) isReady(name) findNearestMonster() distanceTo(t) findMonsters() findNearest(targets) |
| Vector · 实例 | x y z magnitude() heading() distance(o) dot(o) equals(o) copy() |
| Vector · 类方法 | add subtract multiply divide limit normalize rotate |
掌握这些 API,你就握住了苔原塔的全部操控权 ⚔️❄️
把它们组合起来,写出属于你自己的制胜策略吧!🏰
CodeCombat 编程知识 · 多人竞技场:苔原塔(Tundra Tower)· 强化篇 API 大全
扣哒世界(CodeCombat)教研团队