导轨转向基础的游戏经理

我正在写一个回合制的纸牌游戏(线上线上扑克)。 我有使用rails的经验,所以我想使用它的大部分的逻辑,如用硬币和统计pipe理用户,pipe理房间和游戏。 我打算使用节点js + socket.io + redis来提供实时消息服务器 – >客户端(基本上使用rails的redis发布消息,在node.js端监听它们并通过socket.io发布到客户端)和使用REST API从客户端 – >服务器进行通信。

我坚持的部分是试图pipe理轨道内的实际游戏逻辑。 我将需要一个正在进行的游戏的游戏pipe理器来评估游戏中发生的所有事情(交易卡,接受投注,通过玩家轮stream,评估结果等)。 特别是有两件事情对我来说似乎不太可能,那就是从我迄今为止使用rails构buildwebapp的经验来看这种情况:

  • 将游戏pipe理器作为内存中的单个共享对象:我认为这可能是一个rediscaching对象,将在每次状态更改时重新加载,并以新状态再次保存,这似乎是一个很大的开销。 另一件我正在考虑的事情是拿着一个游戏pipe理器对象的散列,每个正在进行的游戏作为一个静态对象,可以从rails应用程序的任何地方访问。 任何我在这里失踪? 这可以以某种方式改善或任何其他方法来做这种function?

  • 有一个计时器,在等待玩家进行动作时发出嘀嗒如同任何基于回合的游戏,我需要等待特定的秒数,直到玩家反应,如果玩家不采取行动让我们说20秒,那么服务器应该自动移动到下一个玩家。 我真的不知道如何在轨道上做到这一点。 我考虑的一种方法是延迟的任务,在20秒之后运行,并且如果用户在其之前行动,到期的玩家转向或被取消。 (使用sidekiq作为这些任务的例子)。

编辑

我被困在devise如何实现实际的游戏逻辑,这就是为什么我需要一个游戏经理,每个活跃的游戏(每个游戏至less有2个玩家)需要有一个计时器滴答滴答,那里需要一个如果玩家没有轮到下一个玩家,则在x秒后callback。 由于每个请求的无状态性质,我不明白我该如何做到这一点,我需要在内存中存储游戏状态并以某种方式运行计时器。 我相信我可以在node.js中的游戏逻辑中解决这个特定的问题,但我宁愿使用node.js来pipe理套接字连接,并通过redis pub / sub接收事件。

这将是相当抽象的,我希望你不介意。


游戏经理

game manager什么?

你说你想让它在记忆中运行 – 为什么? 应用程序基于input/输出运行。 除非你想以某种定时的响应格式(发送通知消息等)来使用它,否则游戏经理的想法实际上是无用的。

你需要的是处理系统中个人游戏的方法。 这可能需要大量的JavaScript实现,但从Rails的angular度来看,没有必要在后端过度。

记住,你只是在寻找实时逻辑 。 这并不意味着您必须在服务器上运行实时应用程序。 相反,你可以在后端使用Rails的模型和业务逻辑来处理它。

这只是一个基本的例子:

 #app/models/game.rb class Game < ActiveRecord::Base #columns id | name | active (bool) | created_at | updated_at has_many :players end #app/models/player.rb class Player < ActiveRecord::Base #columns id | game_id | user_id | created_at | updated_at belongs_to :game belongs_to :user alias_attribute :joined, :created_at end #app/models/user.rb class User < ActiveRecord::Base has_many :players has_many :games, through: :players end 

这是一个非常基本的例子,但它应该给你如下:

 #config/routes.rb resources :games, only: [:index, :show] do resources :sessions, path: "", path_names: { new: "join", destroy: "leave" show: "" }, only: [:new, :destroy] #-> url.com/games/:game_id/join end #app/controllers/games_controller.rb class SessionsController < ApplicationController def new @game = Game.find params[:game_id] @session = @game.players.new player_params if @session.save redirect_to @game #-> takes you to url.com/game/23 else redirect_to root_url, notice: "Sorry, you cannot join this game" end end private def player_params params.require(:user).permit(:x, :y, :z) end end 

我知道这不是严格的CRUD ,但我希望你感激它是如何工作的。

然后,您可以在模型中创build逻辑:

 #app/models/player.rb class Player < ActiveRecord::Base belongs_to :game belongs_to :user alias_attribute :joined, :created_at validates :user, uniqueness: { scope: :game, message: "You're already in this game!" } end 

这个实时方面将来自您的服务器响应请求的速度。 如果你有一个JS前端(为了让它看起来很漂亮),你可以用JSON(如API)来ping后端,并在前端使用它们。

消息

使用Redis Pusher

实时通知的东西将是一个多一点参与的事情来实现,而不是编程,但机智。

向连接的客户端发送推送通知相对简单 – 只需将消息排列在Redis中,然后使用Pusher将其发送出去。

但是,如果你想在没有input的情况下调用消息(如果有时间更新或者其他什么的话),你需要在服务器上每x秒运行一些CRON脚本。

这是你可能需要一些单独的function,虽然我觉得Rails可以用一些rake命令来处理它。 具有这种types的function的资源负载是必须理解的。