多人游戏 - 同步球

时间:2015-12-10 12:09:44

标签: socket.io webrtc game-physics phaser-framework

我正在使用惊人的phaser.io在HTML5中开发一个非常简单的游戏。游戏非常简单:2D中的1vs1凌空游戏......实际上它是伟大的“皮卡丘凌空”(http://imagenes.es.sftcdn.net/es/scrn/12000/12531/pikachu-volleyball-2.jpg)的“复制”。

正如我所说,游戏非常简单,我有:

  • PLAYER1
  • Player2
  • 静态元素

而我只能控制: - 球员动作 - 球运动(实际上由Arcade Physics控制) - 球员 - 球碰撞

我只是为了好玩,将我朋友的面孔添加到玩家手中。 游戏运行得很好,我和朋友一起玩真的很开心。所以我想,为什么不在线进行多人游戏,所以我们可以从不同地点远程玩游戏?

在阅读了多人HTML5游戏后,我开始使用带有nodeJS服务器的websocket(socket.io)进行开发。 socket.io的实现非常简单,通信工作正常。

事情是让游戏真正可玩。

这是我现在的步骤:

在客户端连接上,创建它:

  • PLAYER1(自己)
  • 静态元素

客户端等待新的客户端连接创建:

  • 远程播放器

因此,在连接两个客户端之后,我在每个客户端上都有:

  • OwnPlayer
  • RemotePlayer
  • 静态元素

然后游戏开始...在这个阶段它不是很公平,因为远程播放器它根本不移动。所以,为了让远程播放器移动(经过一些尝试),我决定实现一种权威的服务器,就像那样工作。

  • 本地玩家移动(输入已注册) - >客户端将输入发送到服务器 - >服务器将输入发送到两个客户端 - >每个客户应用移动(通过改变速度)

这种机制让玩家的动作在过去时起作用,但是“同步”(等待时间可以接受)。

这看起来很棒,每个客户正在播放移动他们的播放器,而另一个播放器则由远程客户端移动。

问题是球......

在每个客户端都有一个球,随着Arcade物理移动(在每个玩家的网中弹跳)...所以经过很少的动作,因为球员位置的同步不完美,球每个客户的位置都不一样。

您将如何实施球同步?

我在想的一些选择:

  • 定期将球位置发送到服务器 - >服务器向客户发送球位置 - >客户更新球位置(带一些插值)

  • 仅在一个客户端(主站)中启用球物理,然后定期将球位置从“主客户端”发送到“从客户端”(可能使用webRTC)

  • 重新开始并制作一个真正的'权威服务器',在服务器上使用Arcade Physics(如果可能的话),只在客户端进行插值?

2 个答案:

答案 0 :(得分:1)

要解决您的问题,您可以轻松解决 你转移到服务器,附加的玩家的攻击状态, 现在,所有玩家都从服务器订阅了攻击信息,现在是" clints"必须渲染子弹。

这是一个小代码示例

第1部分:[发布数据]

            transferData = [
            {
                id: id,
                name: Player.name,
                position: Player.position,
                facing: Player.facing,
                hitFacing: Player.hitFacing,
                health: Player.health,
                energie: Player.energie,
                healtbar: {width: Player.healthbar.width},
                energiebar: {width: Player.energiebar.width},
                isAttacking: Attack.isAttacking
            }
        ];

        session.publish('org.example.character.data', transferData);
        Attack.isAttacking = false;

第2部分:[订阅数据]

 // get player position
    session.subscribe('org.example.character.data',function (args) {
        var player = args[0];
        var exists = false;
        for (var i = 0; i < onlinePlayer.length; i++) {

            if (onlinePlayer[i].uid == player.uid) {
                var tmp = onlinePlayer[i];
                player.sprite = tmp.sprite;
                player.label = tmp.label;
                player.status = tmp.status;


                if (player.isAttacking && player.sprite != undefined) {
                    // HERE RENDER THE BALL
                    renderBall(player, this.game);
                }

                onlinePlayer[i] = player;
                exists = true;
            }
        }

        if (!exists)
            onlinePlayer.push(player);

    }).then(
        function (sub) {
            //console.log('subscribed to topic');
        },
        function (err) {
            console.log('failed to subscribe to topic', err);
        }
    );

此示例适用于websocket-server,例如crossbar.io,节点库上有autobahn.js。

http://crossbar.io/docs/Quick-Start/ 但您也可以使用其他服务器

答案 1 :(得分:0)

你的问题让我想起了我过去的一个微笑的问题。我正在网上开发地图应用程序。所有客户端的Map对象必须相同(已同步)。

我是如何解决这个问题的,我已经将类库移动到服务器端并使地图对象成为单例。看看单身模式。 Singleton对象不能多次实例化。我的意思是每个游戏都会有一个球对象,客户端会用它来更新它们的本地对象。

以下是维基百科页面:https://en.wikipedia.org/wiki/Singleton_pattern

之后,在客户端做的第一件事就是获取最近的地图实例(在你的情况下是球),在服务器上修改和更新。

另一点是,多个客户端可能希望在sime时更新服务器上的共享对象。这会导致一致性问题。许多实现包括锁定变量以限制访问。其他客户端等待锁定释放和更新。

无论如何,在客户端拥有同一个对象的多个实例并不是一个好方法。