Elixir游戏服设计三

玩家进程用gen_server来建模,我不直接使用 use GenServer, 而是使用exactor,该库可以去掉反锁的接口定义。

我们新建一个 player_server_manager app吧, 使用 mix new player_server_manager --sup, 会给我们增加sup。然后在mix.exs里增加exactor的依赖如下:

  defp deps do
    [{:exactor, "~> 2.2"}]
  end

跑 mix deps.get,成功了依赖就准备好了。

默认生成的player_server_manager.ex

defmodule PlayerServerManager do
  use Application

  # See http://elixir-lang.org/docs/stable/elixir/Application.html
  # for more information on OTP Applications
  def start(_type, _args) do
    import Supervisor.Spec, warn: false

    children = [
      # Define workers and child supervisors to be supervised
      # worker(PlayerServerManager.Worker, [arg1, arg2, arg3]),
    ]

    # See http://elixir-lang.org/docs/stable/elixir/Supervisor.html
    # for other strategies and supported options
    opts = [strategy: :one_for_one, name: PlayerServerManager.Supervisor]
    Supervisor.start_link(children, opts)
  end
end

玩家进程就叫player_server吧。把它改成我需要的。

defmodule PlayerServerManager do
  use Application

  # See http://elixir-lang.org/docs/stable/elixir/Application.html
  # for more information on OTP Applications
  def start(_type, _args) do
    import Supervisor.Spec, warn: false

    children = [
      # Define workers and child supervisors to be supervised
      worker(PlayerServer, [], restart: :temporary),
    ]

    # See http://elixir-lang.org/docs/stable/elixir/Supervisor.html
    # for other strategies and supported options
    opts = [strategy: :simple_one_for_one, name: PlayerServerManager.Supervisor]
    Supervisor.start_link(children, opts)
  end
end

因为玩家进程是动态创建的,因此采用simple_one_for_one, 同时我不需要默认传参数,还有我不需要重启。

好了现在让我们编写PlayerServer模块(现在是简单的,而且我还未知有什么需要调整的,后续随着服务器设计而演化吧)。

让我们先增加个查询钻石的接口吧。

defmodule PlayerServer do

    use ExActor.GenServer

    defstart start_link(player), do: initial_state(%{player: player, socket: nil})
    defcall gem, state: state, do: reply(state.player.base_info.gem)
end

我们在PlayerServerManager里增加启动接口如下

 def start_player_server(%Player{} = player) do
    Supervisor.start_child(PlayerServerManager.Supervisor, [player])
  end

在player_server_manager_test.exs里增加测试代码

defmodule PlayerServerManagerTest do
  use ExUnit.Case
  doctest PlayerServerManager

  setup do
    Application.stop(:player_server_manager)
    :ok = Application.start(:player_server_manager)
  end

  setup do
      player = Player.new(0)
      {:ok, player: player}
  end
  test "start player_server", %{player: player} do
    assert {:ok, pid} = PlayerServerManager.start_player_server(player)
    assert  PlayerServer.gem(pid) == 0
  end
end

测试通过。

写到这里发现之前Player和BaseInfo @behavior 实际上应该为@hehaviour, 既然之前没报错,我就把它去掉了,测试依然通过。说明其实可能只需要

defdelegate。

好了,这一章就到这。遗留的问题有,我们通常需要给玩家进程一个名字,而不是通过pid,如果是单节点的话, local 注册已经足够,如果是跨服访问,我们需要一个分布式的注册机制(实际上分布式注册机制容易有坑,如无必要,千万别)。比如gporc,比如syn。 前者比较有名,我以前在erlang用过,之前有碰到莫名奇妙的问题。所以下章试试syn吧。

时间: 2024-12-17 22:01:55

Elixir游戏服设计三的相关文章

关于Elixir游戏服设计系列

写着写着就废球了,感觉空对空,实在没什么意思. 另外很快就要搞新项目,决定新项目就直接上elixir了.目前该做的准备工作已经探索了一些了. 以下的东西是写给同事参考的,感兴趣的可以看看,提建议更好. 游戏大体分为如下服务器 1. 网关服务器(必须) 2. 游戏服务器(必须) 3. 后台管理服务器(一般必须) 4. 数据存储服务器(必须) 5. 支付服务器(安桌或者第三方回调的话,必须) Elixir umbrella 项目目录结构可大概如下 1. 游戏数据模型(包括简单的获取更新逻辑) 2.

简单Elixir游戏服设计-玩家进程跑起来

有了玩家模型,我们试试让玩家进程跑起来. 需要搞个PlayerSupervisor来负责启动和监控玩家进程. defmodule PlayerSupervisor do use Supervisor def start_link(_opts) do Supervisor.start_link(__MODULE__, :ok, name: __MODULE__) end def init(:ok) do Supervisor.init([PlayerServer], strategy: :simp

Elixir游戏服设计四

上章说到我们要引入syn https://github.com/ostinelli/syn/ 看过文档,它并没有直接提供{via, Module, Name} 相关的方法.我们需要封装一下. Name暂时可以用id,如果有需要再调整 以后有回调需求的话,刚好也可以做在那个模块里. 在player_server_manager项目里增加{:syn, "1.4.0"} 运行命令获取依赖 修改application 方法,增加依赖 def application do [applicatio

Elixir游戏服设计六

接上章,我新建了个app做包含Table模型, TableServer等.Table桌子的代码暂时如下, 有一些状态还没用上 defmodule Table do @state_accept 0 #准备接入玩家 @state_ready 1 #开局准备? defdelegate [fetch(t, key), get_and_update(t, key, list)], to: Map defstruct [:config, :seats, :state] def new(config) do

简单Elixir游戏服设计- 创建项目

反正是写到哪算哪. 创建umbrella项目 mix new simple_game --umbrella 创建model项目 cd simple_game\apps mix new model 创建 game_server 项目 同样在apps目录下 mix new game_server 最后项目结构如下 我尝试把它发布出去,结果 https://github.com/rubyist1982/simple.git 和我预期的不一样,我初始应该以项目做仓库好点.

Erlang游戏服设计总结

这主要是一年多来,个人从事Erlang游戏服开发中对一些事情的思考. 想到哪说到哪,没有条理可言. 欢迎讨论. 通常Erlang游戏服务的设计涉及到的东东包括如下: 任务系统 活动系统 公会系统 玩法系统 好友系统 聊天系统 商城 转盘 以及其他 我经历过的项目不多,只有2个.在这2个项目中我看到系统建模都采用如下一锅端的方式: 即玩家进程加载了所有玩家数据,处理所有可能的系统: 整个游戏服通常只有玩家进程.公会进程.玩法进程以及一些公共进程. 整个游戏服里你看到的都是进程,看不到应用. 通常玩

游戏开发经验谈(二):对战类全球服游戏的设计与实现

上篇文章<游戏开发经验谈(一):游戏架构里隐藏的五个坑及其应对方案>,我们主要讲解了游戏架构设计当中隐藏的一些坑及其应对方案,错过的小伙伴可以点击链接回溯之前的内容.本期内容,将会重点介绍对战类全球服游戏的设计思路与技术实现. 对战类游戏的设计思路 协议的选择 游戏设计之初,需要决定选择哪种协议来进行通讯.对于对战类游戏来说,首先推荐的肯定是UDP. 尽管UDP对开发基础有较高的要求,需要开发者自己实现传输成功检验.重传以及可靠性保证等,但相对于低开发成本的TCP,UDP在效率和时效性上都有极

游戏UI框架设计(三) : 窗体的层级管理

游戏UI框架设计(三) ---窗体的层级管理 UI框架中UI窗体的"层级管理",最核心的问题是如何进行窗体的显示管理.窗体(预设)的显示我们前面定义了三种类型: 普通.隐藏其他.反向切换.代码如下: "普通显示"模式允许多个窗体同时显示,这种类型应用最多.例如RPG中的主城界面(见下图). "隐藏其他界面" 模式一般应用于全局性的窗体.我们在开发此类窗体时,为了减少UI渲染压力.提高Unity渲染效率,则设置被覆盖的窗体为"不可见&qu

游戏开发(三)——WIN32 黑白棋(一)——棋局逻辑的设计

今天以黑白棋为例,开始给一个win32的小游戏设计, 这里打算分3部分介绍 1.棋盘,棋局的现实 2.玩家.AI的现实(且听下回分解) 3.游戏画面的现实(且听下下回分解) 其中第一部分为黑白棋游戏的主要逻辑: 1.棋盘,以及棋盘上的棋子的存储形式.这里用到了位图. 2.是否可以落子的判断(黑白棋是只有你落子的位置,在横竖斜八个方向中任意一个方向,能吃掉对方的子,你才可以落在该位置,八个方向都吃不掉对方子的位置是不能下的),以及吃子的逻辑(吃子的逻辑同样是八个方向,两个己方棋子之间夹住的对方棋子