【问题标题】:Good way to handle ability usage within a multiplayer game?在多人游戏中处理能力使用的好方法?
【发布时间】:2009-09-17 19:00:55
【问题描述】:

我已经编写了一个客户端基于服务器的多人游戏,并且已经完成了基础(这是一个用 actionscript 3 编写的 flash 客户端)。下一步将实施一个系统,让我可以轻松地为游戏添加能力。

这里的问题是一个能力可以做很多事情。例如。玩家 A 对玩家 B 使用能力“修复”,将会发生以下情况:

  • 玩家 A 向服务器发送消息,告知该操作
  • 玩家 A 现在在自己的船上显示“修复铸造”动画
  • 服务器必须通知船 A 附近的所有玩家现在有“修复铸造”动画
  • 服务器必须增加玩家 B 的“生命值”,因为它已被玩家 A 修复
  • 服务器必须通知附近的所有玩家,玩家 B 现在有不同的健康值
  • 服务器必须通知附近的所有玩家,玩家 B 应该显示“正在修复”动画

这只是一个例子,对于一个简单的能力,很多事情都必须发生。我可以进入每个对象并为这个咒语添加代码行。但是,当我需要添加很多(约 50 个)能力时,这将变得一团糟。另请注意,有些能力与其他能力完全不同,有些必须显示动画,有些则不需要。有些必须损坏,有些必须增加统计数据,等等。

那么,这种“能力系统”通常是如何处理客户端和服务端的呢?

【问题讨论】:

    标签: actionscript-3


    【解决方案1】:

    在客户端,未经服务器同意,切勿做任何事情。所以客户端应该只发送一个能力和一个可选目标或一些值的请求。客户端也应该监听服务器的任何命令。另一方面,服务器应该实现一个函数或类(任何你觉得舒服的)来控制能力动作。每当客户请求一个能力施放能力功能时,应该调用。作为第一个任务,函数应该检查先决条件。如果失败,应通知客户。否则,应将使用修复能力 ok 信号传递给客户端。然后,该功能会在更新其状态的同时查找并向附近的任何船只发送所需的命令。这种方法将保证能力不会被客户滥用。

    为了理解它检查以下内容,这是为了说明方法,所以不要告诉我使用这么多ifs不好。

    客户

    function massRepair() {
        server.send("USE mass_repair;"); //no decisions in here
    }
    
    function recive(command, target) {
        if(command=="USE mass_repair OK")
            massRepairAnim.gotoAndPlay(0);
    
        if(command=="ANIM mass_repair") {
            massRepairAnim.setTarget(target);
            massRepairAnim.gotoAndPlay(0);
        }
    
        if(command==/SET ENERGY [0-9]/) {
             value=getValue(command);
             setEnergy(value);
        }
    
        if(command==/SET HEALTH [0-9]/) {
             value=getValue(command);
             setHealth(value);
        }
    
        if(command=="ANIM self_repair") {
            selfRepairAnim.gotoAndPlay(0);
        }
    
        if(command=="USE mass_repair FAIL NOENERGY") {
            display("Not enough energy to use the skill");
        }
    }
    
    somebutton.click=function() { massRepair(); }
    

    服务器

    function userMassRepair(Ship owner) {
        if(owner.energy<30) {
            send(owner, "USE mass_repair FAIL NOENERGY");
            return false;
        }
    
        owner.energy-=30;
        send(owner, "SET ENERGY "+owner.energy); //every data sent is absolute
        send(owner, "USE mass_repair OK");
    
       foreach(ship in owner.shipsInRange(100)) {
            if(owner.ally(ship)) {
                 ship.health+=10;
                 ship.send("SET HEALTH " + ship.health);
                 ship.send("ANIM mass_repair "+owner.position);
                 ship.send("ANIM self_repair");
            }
       }
    }
    

    【讨论】:

      【解决方案2】:

      看起来很多东西,但实际上只是几个标准组件的排列。大多数操作将包括对内在属性的更改和一些要在客户端显示的外观,并且只有少数几种不同的方法可以做到这一点。

      你需要类似以下的东西:

      • 一种向服务器发送动作的标准方式,可以方便地提取任意参数(因为每个动作可能有一些非常具体的参数)
      • 从服务器到客户端的消息类型,用于开始在指定船上播放指定动画
      • 一种从服务器到客户端的消息类型,可增加船上的健康值

      那么您提到的操作的服务器代码如下所示:

      if (message.type == REPAIR)
      {
          repairer = message.actor;
          repaired = message.target;
      
          // Insert verification code here to check that the 2 ships are close enough,
          // that the repairer is entitled to perform this action, etc
      
          // Verification has passed: do the work
          broadcastToAllClients(new Message(type=PLAY_ANIM, target=repairer, value=REPAIR_CASTED));
          broadcastToAllClients(new Message(type=CHANGE_PROPERTY, target=repaired, proerty=HEALTH, value=5)); // 5 is the amount 
          broadcastToAllClients(new Message(type=PLAY_ANIM, target=repaired, value=BEING_REPAIRED));
      }
      

      这很容易扩展到任意数量的操作,并且只需要一些额外的消息类型来适应可以更改或可以显示的不同内容。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-09-10
        • 1970-01-01
        • 2017-01-15
        • 2023-03-19
        • 1970-01-01
        • 1970-01-01
        • 2012-06-01
        相关资源
        最近更新 更多