【问题标题】:XMLSocket approach for a multiplayer card/pet game多人纸牌/宠物游戏的 XMLSocket 方法
【发布时间】:2015-05-12 12:02:45
【问题描述】:

我对多人游戏设计相当陌生,并且正在努力寻找我需要在我的同步(您不能断开连接并在以后继续,类似于炉石)、回合制、pvp“纸牌”游戏中继续的信息。我使用 AS3 (flash) 作为客户端,使用 node.js 和 javascript + mysql 进行服务器端处理。

在这个游戏中,卡片是由玩家自己创建的。重要的是要注意这些“卡片”是由单独的构建块(库 swf 文件)组装而成的;数据库跟踪这些卡片是如何制作/组装的。 因为每个玩家可能有数百张独一无二的卡片,所以我需要一种很好的方法来按需加载有关这些卡片的信息,以用于 pvp 战斗或改装/套牌构建目的。

到目前为止我所取得的成就:

  • 我已成功将数据发送到服务器,并通过 XMLSocket 将数据发送回闪存。
  • 我已经从数据库信息中成功组装了一张“卡片”。

我真正需要回答哪些问题:

Flash 异步加载内容,所以我不确定如何为(有时同时)战斗动作、卡片信息或卡片组合发出多个数据请求(可能有很多卡片和卡片构建块,所以我觉得使用单个请求加载所有数据效率低下)。我可以让负责进行这些调用的类或创建一个信使类来处理整个游戏的所有请求/断开/重新连接/消息。

  • 对于全局信使类方法,我不确定如何通过上游代码从信使中检索完全加载的数据(即使数据不存在,as3 也会继续执行)或如何确保请求与适当的调用有关

    • 我可以使用 ID 请求系统来唯一标识套接字请求
    • 我可以开发自定义事件驱动系统
    • 我可以在我需要的每个类中生成多个信使对象。
  • 类似地,也许我应该在卡片对象中处理数据库请求或在游戏开始之前预加载所有数据(这将限制我只能即时查询对手卡片和战斗数据)。使用每卡对象一次调用的方法,我不确定每个玩家每张卡的#requests 是否会压倒我的服务器。 Node.js 的扩展性很好,但我没有网络知识来了解单个端口上的所有这些同时请求是否太多。

编辑: 我强烈倾向于使用单例 XMLSocket Wrapper 或某种扩展类来处理所有网络事务,因为这对我来说似乎很直观。我非常感谢您对通知我的代码的最佳方法的反馈,信使收到并解析了它要求的消息(因为即使数据不存在,flash 也会继续执行,我需要一个好的方法来做到这一点。)。我读到使用自定义事件并不是那么好,还有更好的方法......但这就是我解决问题的方式。

例如我可以做(伪代码)。

m:Messenger = new Messenger(); //this is my wrapper
m.addEventListener(new CustomEvent(CustomEvent.EVENTSTRING, parseData));
m.sendData(DataObject); //calls 

function parseData(e:CustomEvent) {
    xml(e.data);
}

import flash.net.XMLSocket;
import globals.*;
public class Messenger 
{
    public static var _Socket:XMLSocket; 
    public var xml:XML;

    public function Messenger() 
    {
        _Socket = new XMLSocket(vars._Server, vars._Port);
        _Socket.addEventListener(Event.CONNECT, onConnect);  
        _Socket.addEventListener(IOErrorEvent.IO_ERROR, onError); 
    }

    private function onConnect(evt:Event):void  {  
        trace("Connected");  
        _Socket.removeEventListener(Event.CONNECT, onConnect);  
        _Socket.removeEventListener(IOErrorEvent.IO_ERROR, onError);  

        _Socket.addEventListener(DataEvent.DATA, onDataReceived);
        _Socket.addEventListener(Event.CLOSE, onSocketClose);              
    }  

    private function onDataReceived(evt:DataEvent):void  {  
        //trigger correct event here based on data identifier w/ dispatchEvent(EVENTSTRING);
    }  
}

【问题讨论】:

    标签: actionscript-3 multiplayer flash-cs3 xmlsocket


    【解决方案1】:

    关于卡片组装 - 您应该将数据存储在不需要重新计算的数据库中,因此如果卡片是由多个“构建块”构建的,您可以将一系列块存储在单行数据库中,这样当检索到对手的卡片信息时,您只需select from player_cards where player_id=... and deck_id=...,然后在 AS3 端组装收集的数据。你绝对不应该把这个负载放在服务器上。

    关于异步加载 - 确保您的 PVP 握手等待双方成功处理己方和敌方的卡片。您可以异步加载数据,但最好在向播放器显示“Loading bla-bla”屏幕的同时进行完整的预加载,然后使用接收到的数据进行操作。是的,您可以向您的服务器发出多个请求,是的,您可以在显示“战斗开始”屏幕之前等待所有请求成功,同时 AS3 将等待加载完成。但是,关于单个请求和多个请求 - 我说尽可能少,因为在 init 阶段添加的每个请求都有可能向单个服务器添加一千个左右的请求,并且可能会给服务器带来太大的压力您的服务器端,从而导致自发起的 DDoS。确保您的数据库结构允许将数据读取操作简化到客户端,这样您的服务器就不会因为准备数据而承受沉重的负载。但也要确保仔细检查客户端向服务器报告的任何内容,因为客户端-服务器游戏的主要规则是“客户端总是撒谎”假设。

    由于您计划在战斗中让服务器处理玩家操作,因此您可以在服务器上创建临时表(基于 SQL)或状态对象(基于进程),其中将包含当前游戏状态以及指向任何能力的链接卡片具有及其状态(在手、已弃、在场、已销毁等),因此当玩家采取行动时,说“这张卡片将状态从 A 更改为 B”,您可以轻松验证该卡片是否在A 状态,然后将其切换到 B 状态,在服务器端和客户端执行此状态更改导致的任何操作。确保在战斗结束后清理这组数据。这需要对您的服务器端进行彻底的规划,以便您的游戏引擎在运行某些动作序列时不会因为过多的 SQL 请求而停止服务器。

    关于信使——也许你应该使用会话方法,连同登录/密码验证,这样你就可以使用会话作为密钥来确定这个数据包属于哪个战斗。我认为还要让AS3端定期向服务器发送拉取请求,服务器应该快速解析并尽快返回提交的敌人/服务器动作,这也将确保处理断开连接并允许重新连接。

    总的来说,这个问题非常宽泛,只能给出提示,甚至不能给出示例。

    【讨论】:

    • 非常感谢您的回复!我同意并将在我的代码中使用您的许多观点。我在我的广泛要求中添加了一个具体问题,并希望您是否可以根据经验来决定是否同意,或者建议一种替代方法来交换 XMLSocket 数据。
    • 据我通过阅读手册可以看出,基本上你的方法在客户端看起来是正确的。您建立连接,然后开始向双方抛出请求,根据从服务器接收到的信息,使您的应用程序行为不同。是的,自定义事件驱动机制可以实现此目的,但您仍然应该根据玩家对他显示的对象所做的任何事情进行必要的更改,比如他的敌人是否对玩家玩了“弃牌”并且他说正在摆弄卡片丢弃,它应该被正确丢弃,没有 UI 剩余。
    • 感谢您的反馈。我担心由于不断创建事件对象,使用事件会很麻烦。我会发布我的代码,以防将来有人有类似的问题。如果可以,请竖起大拇指。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-11
    • 1970-01-01
    相关资源
    最近更新 更多