rails turn based based game manager

时间:2015-09-26 23:28:03

标签: ruby-on-rails ruby node.js multiplayer

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

我坚持的部分是试图管理rails内部的实际游戏逻辑。我需要一个正在进行中的游戏的游戏管理器,它将评估游戏中发生的所有事情(处理牌,接受投注,通过玩家转弯,评估结果等等)。特别是对我来说两件事情似乎不太可能,这就是我迄今为止使用rails构建webapps的经验:

  • 将游戏管理器作为内存中的单个共享对象: 我认为这可能是一个redis缓存对象,并将在每个状态更改时重新加载,并再次使用新状态保存,这似乎是一个很大的开销。 我正在考虑的另一件事是持有一个游戏管理器对象的哈希值,每个正在进行的游戏一个作为可从rails应用程序中的任何位置访问的静态对象。我在这里缺少什么?这可以通过某种方式得到改进,还是采用其他任何方法来实现这种功能?

  • 在等待玩家移动时有一个计时器 像任何基于回合的游戏一样,我需要等待特定的秒数直到玩家做出反应,如果玩家没有采取行动,比如20秒,则服务器应该自动移动到下一个玩家。 我真的不知道如何在rails中做到这一点。我正在考虑的一种方法是延迟任务,该任务将在20秒后运行并且如果用户在其之前行动则使玩家转身或被取消。 (例如,使用sidekiq执行这些任务)。

编辑

我坚持设计如何实现真正的游戏逻辑,这就是为什么我需要一个游戏管理器,每个活动游戏需要有一个计时器每1秒钟一次(有至少2个玩家的游戏),需要如果玩家没有轮到他们移动到下一个玩家,则在x秒后回调。由于每个请求的无状态特性,我不知道如何在rails中做到这一点我需要将游戏状态存储在内存中并以某种方式运行计时器。 我相信我可以解决node.js中游戏逻辑的这个特定问题,但我宁愿使用node.js来管理套接字连接并通过redis pub / sub接收事件。

1 个答案:

答案 0 :(得分:2)

这将是非常抽象的,我希望你不要介意。

游戏经理

game manager实际做什么

你说你希望它在内存中运行 - 为什么?应用程序基于输入/输出运行。除非您想以某种定时响应格式(发送通知消息等)使用它,否则游戏管理员的想法确实没用。

您需要的是一种处理系统中各个游戏的方法。这可能需要大量的javascript实现,但从Rails的角度来看,没有必要在后端过火。

请记住,您只是在寻找实时逻辑。这并不意味着您必须在服务器上运行实时应用程序。相反,你可以用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,但我希望你能理解它是如何运作的。

然后,您可以在模型中制作逻辑:

#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后端,获取响应并在前端使用它们。

-

讯息

PusherRedis一起使用。

实时通知的内容将是一个更复杂的实现,而不是以编程方式,但是有条不紊。

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

但是,如果你想在没有输入的情况下调用消息(IE,如果有时间更新或其他什么),你需要在x秒内运行某种CRON脚本。服务器

这是您可能需要一些单独功能的地方,尽管我认为Rails可以使用一些rake命令来处理它。具有此类功能的资源负载是必须要理解的。