我最初在programmers.stackexchange.com上问过this question,因为我认为答案对于stackoverflow来说太主观了。但是,在评论Muad'Dib中指出了这一点:
这可能更适合StackOverflow ...这是一个与编程问题直接相关的问题,并讨论了编程解决方案。一种解决方案可能与另一种解决方案相同,其中它们之间的选择是主观的,但对整体问题本身的讨论并不是因为某些解决方案显然不适用。所以这个问题确实有一个或几个好的答案,而诸如“哪个是最好的文本编辑器?”之类的问题。没有......
所以,在稍微考虑一下这种情况之后(看一些似乎不适合的模式),这就是我的困境:
我正在设计一款简单的战斗策略游戏。
我不确定哪种设计模式最能让我完成上述任务。我正在寻找一种模式,这将使我能够增加“战斗”的复杂性。可能通过在战斗中添加更多对象(更多战斗员,可能是新的环境对象等)
起初我认为Observer模式可行。我会有一个代表“观察者/主体”的战斗对象。它跟踪一个计时器,当计时器递增时,它会更新所有参与者观察者对象。然而,很多后卫战斗员的参数会影响攻击者战斗员的行为,所以那个场景中的“观察者”需要彼此了解,所以我不确定这是否是正确的方法。
最后,我并没有试图完美地设计出一种设计模式。也许没有“最合适的”。我只是在寻找一个坚实的基础来建立。
答案 0 :(得分:2)
尝试为相当详细的情况找到一个“正确”的设计模式是徒劳无功的搜索。设计模式可以解决某些特定编程语言或语言中出现的常见低级情况 - 对于您可能找到的每种可能情况,都不一定存在特定的情况,也不一定只使用一个单独的情况来解决您的问题。问题
特别是这种情况并不是真正的设计模式 - 设计模式主要涉及类和对象之间的静态关系,而你在这里谈论的本质上是算法本质上。设计模式提供了实现算法的方法,但实际上并不是算法。
这应该非常简单。你有一个运行指定持续时间的while循环。每次迭代代表经过时间的一秒,并且在该迭代中,它将在战斗中涉及的每个相关对象上调用一个或多个方法 - 战斗员,天气等。(多少种方法和哪些是游戏设计问题,而不是(还)一个编程问题。)这些对象可以来自一个战斗对象,如果你愿意,它可以保存整个上下文。
这里没有真正需要观察者模式,事实上,通过将其从易于理解的迭代过程变为事件驱动过程,它将使事情变得非常复杂。如果需要访问各种属性,战斗员可以直接查询其他战斗员。
答案 1 :(得分:1)
如果你真的想在这里使用一个模式,我会考虑一个命令模式。 例如,您可以将一串命令“争取移动”排成一段时间来执行。您还可以根据对手的操作轻松而一般地轻松取消命令。随着您开发游戏,您可以轻松地添加移动/策略。
但这不是整个游戏的模式,它更像是一个方面的解决方案。
答案 2 :(得分:0)
好吧,一切都可以通过对象建模:)
让我们假设你不需要“真正的”秒 - 你可以计算整个战斗,保存日志中的每一步,在数据库中的某个地方保持日志,然后每秒向玩家显示一行“行”。你的日志不仅仅是字符串,而且可以包含“此刻”的序列化战斗员数据,因此你甚至可以进行“互动”战斗(玩家可以在战斗中改变他们的战斗策略,你可以重新计算作为新起点的反序列化战斗状态的战斗点)。
下一个。让每个战士都是对象:
class Combatant {
public $strategy;
public takeDamage($damageType,$damageAmount){
if($this->strategy->tryAvoidDamage($damageType,$damageAmount)) return;
$newDamageAmount=$this->reduceDamageByArmor($damageType,$damageAmount);
$newDamageAmount=$this->reduceDamageByAbilities($damageType,$newDamageAmount);
// change your health below...
}
public dealDamage($weapoon, $enemy){
$damageType = $weapoon->damageType;
$damageAmount = $weapoon->damageAmount;
$damageAmount = this->applySkills($weapoon, $damageType, $damageAmount);
$enemy->takeDamage($damageType, $damageAmount);
}
}
策略也是对象:
class Strategy{
public $combatant;
public tryAvoidDamage($damageType,$damageAmount){
if($damageType=="melee" && $combatant->actionPoints>10){
// try to block punch (roll dice for skills etc)
return $combatant->tryBlockPunch();
}
return false; // can't avoid bullet
}
public DoAction($enviroment){
if($combatant->hp<10){
$combatant->tryCastHealing();
} else {
var $enemy = $enviroment->findEnemes()->whereDistanceLessThan(2)->mostWeak();
if($enemy != null) {
$combatant->dealDamage($combatant->hands, $enemy)
}
}
}
}
您需要的下一件事是在运行循环时创建和初始化正确的对象
while($combatantA->isAlive() && $combatantB->isAlive()){
$combatantA->strategy->DoAction(...)
$combatantB->strategy->DoAction(...)
}