我正在尝试构建一个MUD(多人互动小说游戏)
我正处于设计/概念化阶段,我遇到了一个我无法想出解决方案的问题。我希望一些更有经验的程序员会有一些建议。
这是我能解释的问题。当玩家决定执行动作时,他向服务器发送命令。然后,服务器处理该命令,确定是否可以执行该操作,或者执行该操作,或者为什么无法完成该操作而作出响应。动作可能失败的一个原因是玩家正忙于做其他事情。例如,如果一名球员处于战斗中并刚刚摆出一条巨大的大刀,可能需要3秒才能重复这一动作。如果玩家再次尝试再次挥杆,游戏将响应,表明他必须等待x秒才能做到这一点。现在,我可以设计没有太多麻烦。我遇到的问题是如何从AI生物中复制这种行为。服务器在其自身上执行的所有事件,即不是对玩家所做的事情的直接反应,都必须是时间敏感的。一些邪恶的怪物已经施放了你的咒语但是必须等待30秒然后再做一次...我想我可能会将所有这些事件添加到某种事件队列中,但是我怎样才能使该事件队列时间敏感?
答案 0 :(得分:3)
MUD的动作通常是在'ticks'而不是立即执行 - 这样可以减少延迟的影响,并且可以将怪物的命令插入队列并进行公平处理。
就个人而言,我不喜欢这种方法,但99%的MUD都使用它。您需要设计一个健壮的命令队列&事件队列,可以处理AI和用户命令。然后,您可以向AI命令添加“虚拟延迟”,这些命令可能是预定义的,也可能是所有用户延迟的平均值,或者您喜欢的任何内容。
答案 1 :(得分:2)
你的AI控制的实体有某种“我接下来要做什么?”方法,对吗?只是让那个方法返回“我很忙,继续做我正在做的事情”的结果,而另一个行动正在进行中。
E.g。
class ToughGuy(AI):
Action_Idle, Action_BroadswordSwing, Action_CastingMagic = range(3)
MagicRange = 10
MagicTime = 8
MeleeRange = 4
MeleeTime = 2
def __init__(self):
self.action = ToughGuy.Action_Idle
self.actiontimer = 0
def Update(self, timestep):
if self.actiontimer <= 0:
self.action = ToughGuy.ActionIdle
else
self.actiontimer -= timestep
if self.action == ToughGuy.Action_Idle:
global player # don't do this
if self.AmIFacing(player):
distance = DistanceBetween(self, player)
if distance < ToughGuy.MeleeRange:
self.action = ToughGuy.Action_BroadswordSwing
self.actiontimer = ToughGuy.MeleeTime
elif distance < ToughGuy.MagicRange:
self.action = ToughGuy.Action_CastingMagic
self.actiontimer = ToughGuy.MagicTime
等。对不起,可变编码标准......;)
答案 2 :(得分:2)
AI是客户。
只有在最远的视野中,它们才是“服务器的一部分”。它们实际上是在主游戏引擎之外。他们是没有人的专业客户。
AI客户端与人类客户端的服务器具有相同的接口。
答案 3 :(得分:2)
您可以使用线程来处理特定类型的Mob,并将所有实例放入某种类型的数组中。然后,线程简单地通过列表重复应用逻辑。 DelayTimeStart和Delay可以是父Mob类的属性,当线程经过循环时,它可以推迟处理Mob中存在延迟时间的任何实例。
答案 4 :(得分:1)
你可以在这里找到实现的例子:
答案 5 :(得分:0)
一种基本方法是拥有一个数据结构,代表邪恶怪物的法术实例,并在其上设置一个冷却计时器。当使用力量时,设定冷却时间(大概是由法术的主要定义所定义的秒数);尝试再次使用它将失败,就像玩家的能力一样。这可以通过让队列检查冷却时间与事件队列集成,如果它没有到期,则等待它过期,或中止操作,或者根据需要重新安排操作。
答案 6 :(得分:0)
我会从LPMud / LDMud的角度为您提供答案。
MUD中的每个玩家都是player.c的一个实例。 Player.c继承自living.c。生活中的事情有一个心跳。对于泥浆上的每个生物(或任何具有心跳()功能的物体,心跳功能每2秒处理一次。定时事件通常不是基于秒来完成的,而是基于对象内的计数器经过的心跳数。
适用于你的问题的好消息是怪物也从living.c继承。这意味着如果您有只能定期执行的操作,则可以根据已发生的滴答数在心跳内管理这些操作。