前言
本次更新是敌人的波次和干员撤退、释放技能的更新。下一次是数据库更新。我估计下一周就可以去弄前端了。学学unity,之后再自研引擎。
波次更新
首先我们要配置一些相关数据,并在快照保存中新增加波次下标、当前波次已生成数量、距离下一只生成时间、敌人ID。
Go
// Wave 一波敌人的配置
type Wave struct {
Count int // 本波敌人数量
HP int32 // 每只敌人血量
Speed float64 // 移动速度(格/秒)
IntervalSec float64 // 同波内相邻两只的出场间隔(秒)
}
// waves 波次表:按顺序生成,全部波次生成完且场上清空才算通关
var waves = []Wave{
{Count: 3, HP: 100, Speed: 1.2, IntervalSec: 2.0},
{Count: 5, HP: 120, Speed: 1.4, IntervalSec: 1.5},
}
// 关卡数值(硬编码,暂不读配置表)
const (
enemyConfigID = 1 // 敌人配置ID(下发 EnemyId 用)
baseMaxHP = 1 // 基地生命,漏一只怪即失败
operatorMaxHP = 100 // 干员血量(当前不会被攻击,仅展示)
attackRange = 2.5 // 干员攻击半径(格)
attackDamage = 12 // 干员每帧伤害
deployCost = 4 // 部署干员消耗
initCost = 10 // 开局费用
maxOperators = 1 // 场上干员上限
retreatRefund = deployCost / 2 // 撤回干员返还的费用
skillCost = 3 // 释放技能消耗的费用
skillCooldownFrames = 15 // 技能冷却(帧)
skillDamage = 60 // 技能对射程内敌人造成的一次性伤害
)
按波次表生成敌人,每帧最多生成一只;调用方需持有 r.mu。首先我们要检测当前波次是否小于波次总长,以及这波敌人是否生成完毕。如果都是True则进入下一波。
go
for r.waveIndex < len(waves) && r.spawned >= waves[r.waveIndex].Count {
r.waveIndex++
r.spawned = 0
}
如果当前波次大于总长则return。
如果这波敌人没有出完,就先减去一帧时间(0.2s)。减去后,生成的冷却时间没过完(时间>0)也是retuen。否则读取当前波次的数据,生成敌人,重置冷却时间。
Go
w := waves[r.waveIndex]
r.instanceSeq++
r.enemies = append(r.enemies, &Enemy{
InstanceID: r.instanceSeq,
HP: w.HP,
Speed: w.Speed,
})
r.spawned++
r.spawnTimer = w.IntervalSec
干员撤退与释放技能
撤回干员,要返还部分费用;返回错误码、提示与剩余费用
我们可以直接将第i个干员(要撤退的)以后的位置都向前移动一位,覆盖掉第i个干员。然后返还费用。这个简单
go
r.operators = append(r.operators[:i], r.operators[i+1:]...)
r.cost += retreatRefund
释放干员技能:校验在场、冷却与费用,对射程内敌人造成一次性伤害。
先循环检测到对应发干员,然后检测是否能放技能。
go
var op *Operator
for _, o := range r.operators {
if o.ID == opID {
op = o
break
}
}
if op == nil {
return codeBadParam, "干员不在场上", r.cost, 0, 0
}
if r.frame < op.SkillReadyFrame {
return codeBadParam, "技能冷却中", r.cost, 0, 0
}
if r.cost < skillCost {
return codeBadParam, "费用不足", r.cost, 0, 0
}
如果能放,减去对应的费用(暂时用费用代替技能条,方便点),并给予在范围内的敌人伤害。
Go
var damage, hits int32
for _, e := range r.enemies {
if e.HP <= 0 {
continue
}
p := pointAtDistance(e.Dist)
if math.Hypot(p.X-float64(op.X), p.Y-float64(op.Y)) <= attackRange {
e.HP -= skillDamage
damage += skillDamage
hits++
}
}
对于客户端的更新,今后就不多说了,因为都是一些简陋的临时测试代码。没什么技术含量。下周见,bey。