在多人游戏中处理能力使用的好方法?

时间:2009-09-17 09:11:53

标签: actionscript-3

我已经编写了一个基于客户端<>服务器的多人游戏并完成了基础知识(这是一个用动作脚本3编写的flash客户端)。下一步将是实现一个允许我轻松添加游戏能力的系统。

这里的问题是能力可以做很多事情。例如。玩家A在玩家B上使用“修复”能力,必须发生以下情况:

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

这只是一个例子,一个简单的能力必须要做很多事情。我可以进入每个对象并为此法术添加代码行。然而,当我需要添加很多(~50)能力时,这将变得一团糟。另外请注意,有些技能完成其他功能,有些功能必须显示动画,有些功能则不显示。有些必须损坏,有些则需要增加统计数据等。

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

2 个答案:

答案 0 :(得分:4)

在未经服务器同意的情况下,客户端永远不会做任何事情。因此,客户端应该只发送能力和可选目标或某个值的请求。客户端也应该监听服务器以获取任何命令。另一方面,服务器应该实现一个或多个类(无论你感觉舒服)来控制能力动作。每当客户端请求能力转换能力时,应该调用。作为第一项任务,功能应检查先决条件。如果失败,应通知客户。否则,应将使用修复能力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");
        }
   }
}

答案 1 :(得分: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));
}

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