玩家1邀请玩家2与凤凰频道玩游戏

时间:2018-01-04 19:57:34

标签: elixir phoenix-framework otp gen-server phoenix-channels

我正在菲尼克斯创建一个使用Phoenix频道和GenServer的2名玩家的纸牌游戏。这就是我的Game Struct的样子:

  schema "games" do
    field :winner, :integer
    field :player_1, :id, default: nil
    field :player_2, :id, default: nil
    field :status, :string

    ## VIRTUAL FIELDS ##
    field :player_1_hand, :map, virtual: :true
    field :player_2_hand, :map, virtual: :true

    timestamps()
  end

所以,正如你所看到的,我会用虚拟场处理玩家手,然后将玩家和胜利者留在数据库中。

我现在有一个大堂频道,玩家可以聊天。我有一个没有功能的游戏频道。我如何允许玩家互相邀请玩游戏,接受或拒绝游戏,然后将两个玩家放在一起玩游戏?

这是我目前在大厅频道(关于游戏)的内容:

  def handle_in("game_invite", %{"username" => username}, socket) do
    data = %{"username" => username, "sender" => socket.assigns.current_player.username }
    broadcast! socket, "game_invite", data
    {:noreply, socket}
  end

  intercept ["game_invite"]
def handle_out("game_invite", %{"username" => username, "sender" => sender}, socket) do
  if socket.assigns.current_player.username == username do
    push socket, "game_invite", %{ username: sender}
  end
  {:noreply, socket}
end

我不知道我是否提出了正确的问题。我正在尝试生成一个新的游戏ID(来自postgres),在游戏中放入两个玩家ID,然后让GameServer使用GenServer来管理玩家的手。

1 个答案:

答案 0 :(得分:0)

这将是一个伪答案,因为你也提出了一个伪问题;一种方法:

假设您有一个用户频道,您可以通过该频道向每个玩家发送套接字事件(或任何其他单独到达玩家的方式)

Player_1从列表中选择一个Player_2,这会发送一个表示该事件的套接字事件,如{ action: 'create_invitation', invitee: 'player_2' },那么您有一个handle_in(%{'action' => 'create_invitation', 'invitee': invitee})

在这个handle_in上你检查发出邀请的玩家是否还没有打开游戏,也没有玩游戏,如果是这样,首先你给他的套接字分配他现在的信息有一个ID为例如“#{socket.current_player}#{invitee.id}”的游戏,你发起一个名为global的新gen_server,传递给{{1} }播放器邀请id和被邀请者id。

在gen_server init上,您向player_2广播一条消息,询问他是否想要使用您之前设置的全局ID加入游戏,并将其初始状态设置为,例如: start 并且你通过从%{ player_1: player_1_id, player_2: invitee_id, game_id: "#{player_1_id}#{player_2_id}", started: false }函数返回来为这个genserver设置一个合理的超时来接收回复,比如25秒。 init

现在在播放器2的前端,你需要接收这个收到的广播,说明他被邀请并把它变成一个可操作的东西,它将向大厅频道发送一条消息,如{:ok, state, 25_000}。你做了所有的检查以确定它是否有效,这个玩家还没有游戏,如果这样设置在他的套接字中,他现在有一个游戏,那么调用之前发起的gen_server,例如, %{action: "accept", game_id: "player_1_idplayer_2_id"}

然后在gen_server上你有一个handle_call

GenServer.call(game_id,{:accept_game, player_2_id})

你需要至少创建一个handle_info来处理邀请过期 - 这应该干净地终止gen_server,并触发清除player_1的套接字等等......