0

我对多人游戏设计相当陌生,并且正在努力寻找我需要在我的同步游戏中继续的信息(你不能断开连接并在以后继续,类似于炉石),基于回合的 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);
    }  
}
4

1 回答 1

0

关于卡片组装 - 您应该将数据存储在不需要重新计算的数据库中,因此如果卡片是由多个“构建块”构建的,例如,您可以将一系列块存储在单行数据库中,以便当检索到对手的卡信息时,您只需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 端定期向服务器发送拉取请求,服务器应该快速解析这些请求并尽快返回提交的敌人/服务器操作,这也将确保处理断开连接并允许重新连接。

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

于 2015-03-11T03:28:15.240 回答