代码之家  ›  专栏  ›  技术社区  ›  Stephen

为这组对象寻找一个好的设计模式

  •  2
  • Stephen  · 技术社区  · 14 年前

    我最初问过 this question 在programmers.stackexchange.com上,因为我认为答案对于stackoverflow来说太主观了。但是,在评论中 Muad'Dib 指出这一点:

    这可能更适合stackoverflow…这是一个与编程问题直接相关的问题,并讨论了编程解决方案。一个解决方案可能等于另一个解决方案,其中的选择是主观的,但对整个问题本身的讨论并不是因为某些解决方案显然不适用。所以这个问题确实有一个或几个很好的答案,而诸如“哪一个是最好的文本编辑器?”不…

    因此,在多考虑了一些情况之后(并研究了一些似乎不适合的模式),我的困境是:

    设立

    我正在设计一个简单的战斗策略游戏。

    1. 两个战士在一定时间内互相攻击。
    2. 比赛结束后,健康状况最好的选手获胜。
    3. 在比赛中,运动员没有直接的干预。玩家在战斗前为他们的战斗人员定义一些策略,“人工智能”(这个术语比较宽松)决定了战斗人员将要做什么。
    4. 战斗由一个任意的“滴答”秒计时器组成,战斗人员的攻击速度(除其他因素外)决定他们做事情的频率。
    5. 除了作战对象之外,还有一个“天气”对象可以对作战人员的能力产生一些随机的环境影响。
    6. 整个过程只需每秒钟循环一次,环境影响和攻击都会被确定并执行,所有的日志都会被记录下来,日志随后会作为一个游戏一个一个地显示给用户。

    问题

    我不确定什么样的设计模式最能让我完成上述任务。我正在寻找一种模式,可以让我在这条路上增加“战斗”的复杂性。可能是通过在战斗中添加更多的对象(更多的战斗人员,可能是一个新的环境对象等)

    起初,我认为观察者模式是可行的。我会有一个代表“观察者/主体”的战斗对象。它跟踪一个计时器,随着计时器的增加,它会更新所有参与者观察者对象。但是,很多防御者战斗人员的参数都会影响攻击者战斗人员的行动,因此在这种情况下,“观察员”需要相互了解,所以我不确定这是否是正确的方法。

    最后,我并不是想完美地钉上一个设计图案。也许没有“最合适的”,我只是在寻找一个坚实的基础。

    3 回复  |  直到 11 年前
        1
  •  1
  •   dubbeat    14 年前

    如果您真的想在这里使用模式,我会考虑使用命令模式。 例如,您只需编出一系列命令“战斗动作”来执行一段时间。你也可以很容易地根据对手所做的事情取消命令。随着游戏的发展,你可以很容易地增加动作/策略。

    但这并不是整个游戏的模式,而是一个解决方案。

        2
  •  2
  •   Kylotan    14 年前

    试图为相当详细的情况找到一个“正确”的设计模式是徒劳的搜索。设计模式解决了特定编程语言中出现的某些常见低级情况——对于您可能发现的每个可能的情况,都不一定存在特定的情况,也不一定只使用一个模式来解决您的问题。

    尤其是这种情况并不是真正的设计模式——设计模式主要关注类和对象之间的静态关系,而您在这里所说的本质上是算法。设计模式提供了实现算法的方法,但它们本身并不是真正的算法。

    这应该很简单。您有一个while循环在指定的持续时间内运行。每次迭代代表经过的时间的一秒钟,在该迭代中,它将对参与战斗的每个相关对象调用一个或多个方法-战斗人员、天气等(有多少种方法,哪些方法是 游戏设计 问题而不是编程问题。如果你愿意,这些对象可以来自一个包含整个上下文的战斗对象。

    这里并不真正需要观察者模式,事实上,它将把问题从一个易于理解的迭代过程更改为一个事件驱动的过程,从而严重地使问题复杂化。如果需要访问各种属性,则战斗人员可以直接查询其他战斗人员。

        3
  •  0
  •   dimzon    11 年前

    好吧,所有东西都可以通过对象建模:)

    假设你不需要“真实”秒-你可以计算整个战斗,将每一步保存在日志中,将日志保存在数据库的某个位置,然后每秒向玩家显示一行日志。您的日志不仅可以是字符串,还可以包含“此时”的序列化战斗数据,因此您甚至可以进行“交互式”战斗(玩家可以在战斗中更改其战斗策略,您可以重新计算战斗,将反序列化战斗状态作为新的起点)。

    下一个。让我们每个战士都成为目标:

    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(...)
    } 
    
    推荐文章