Ruby生活游戏用Gosu更新动作不工作



我正在使用Gosu用Ruby创建Game of Life。代码如下:现在,当我运行ruby gosu。[/p]它打开窗口,适当的尺寸和预填充的世界,因为它应该。

但是一旦我取消注释"@game.tick!"在gosu文件更新操作中,运行ruby gosu。我看到黑屏,没有预填充的世界,我无法关闭。为什么是这样,如何解决这个问题?

您可以在这里找到github repo和其余代码。任何帮助都是了不起的。

这是我的game_of_life.rb

class Game
  attr_accessor :world
  def initialize(world=World.new, seeds=[])
    @world = world
    seeds.each do |seed|
      world.cell_board[seed[0]][seed[1]].alive = true
    end
  end
  def tick!
    next_round_live_cells = []
    next_round_dead_cells = []
    world.cells.each do |cell|
      # Rule 1: 
      # Any live cell with fewer than two live neighbours dies
      if cell.alive? && world.live_neighbours_around_cell(cell).count < 2
        next_round_dead_cells << cell
      end
      # Rule 2:
      # Any live cell with two or three live neighbours lives on to the next generation
      if cell.alive? && world.live_neighbours_around_cell(cell).count == (2 || 3)
        next_round_live_cells << cell
      end
      # Rule 3:
      # Any live cell with more than three live neighbours dies
      if cell.alive? && world.live_neighbours_around_cell(cell).count > 3
        next_round_dead_cells << cell
      end
      # Rule 4:
      # Any dead cell with exactly three live neighbours becomes a live cell
      if cell.dead? && world.live_neighbours_around_cell(cell).count == 3
        next_round_live_cells << cell
      end
    end
    next_round_live_cells.each do |cell|
      cell.revive!
    end
    next_round_dead_cells.each do |cell|
      cell.die!
    end
  end
end
class World
  attr_accessor :rows, :cols, :cell_board, :cells
  # Scheme of default initialized world matrix
  #------------------------
  #     0     1     2
  # 0 [ dead, dead, dead ]
  # 1 [ dead, alive, dead ]
  # 2 [ dead, dead, dead ]
  #-----------------------
  def initialize(rows=3, cols=3)
    @rows = rows
    @cols = cols
    @cells = []
    @cell_board = Array.new(rows) do |row|
      Array.new(cols) do |col|
        Cell.new(col, row) # note col is 1st, than is row
      end
    end
    cell_board.each do |row|
      row.each do |element|
        if element.is_a?(Cell)
          cells << element
        end
      end
    end
  end
  def live_cells
    cells.select { |cell| cell.alive }
  end
  def dead_cells
    cells.select { |cell| cell.alive == false }
  end
  def live_neighbours_around_cell(cell)
    live_neighbours = []
    live_cells.each do |live_cell|
      # Neighbour to the North
      if live_cell.x == cell.x - 1 && live_cell.y == cell.y
        live_neighbours << live_cell
      end
      # Neighbour to the North-East
      if live_cell.x == cell.x - 1 && live_cell.y == cell.y + 1
        live_neighbours << live_cell
      end
      # Neighbour to the East
      if live_cell.x == cell.x && live_cell.y == cell.y + 1
        live_neighbours << live_cell
      end
      # Neighbour to the South-East
      if live_cell.x == cell.x + 1 && live_cell.y == cell.y + 1
        live_neighbours << live_cell
      end
      # Neighbour to the South
      if live_cell.x == cell.x + 1 && live_cell.y == cell.y
        live_neighbours << live_cell
      end
      # Neighbour to the South-West
      if live_cell.x == cell.x + 1 && live_cell.y == cell.y - 1
        live_neighbours << live_cell
      end
      # Neighbour to the West
      if live_cell.x == cell.x && live_cell.y == cell.y - 1
        live_neighbours << live_cell
      end
      # Neighbour to the North-West
      if live_cell.x == cell.x - 1 && live_cell.y == cell.y - 1
        live_neighbours << live_cell
      end
    end
    live_neighbours
  end
  def randomly_populate
    cells.each do |cell|
      cell.alive = [true, false].sample
    end
  end
end
class Cell
  attr_accessor :x, :y, :alive #, :height, :width
  def initialize(x=0, y=0)
    @x = x
    @y = y
    @alive = false
    # Gosu
    # @height = height
    # @width = width
  end
  def alive?
    alive
  end
  def dead?
    !alive
  end
  def die!
    @alive = false
  end
  def revive!
    @alive = true # same as > self.alive = true
  end
end

这是我的gosu代码

require 'gosu'
require_relative 'gol.rb'
class GameOfLifeWindow < Gosu::Window
  def initialize(height=800, width=600)
    # Basics
    @height = height
    @width = width
    super height, width, false, 500
    self.caption = 'My Game of Life'
    # Colors
    @white = Gosu::Color.new(0xffededed)
    @black = Gosu::Color.new(0xff121212)
    # Game world
    @rows = height/10
    @cols = width/10
    world = World.new(@cols, @rows)
    @game = Game.new(world)
    @row_height = height/@rows
    @col_width = width/@cols
    @game.world.randomly_populate
    @generation = 0
  end
  def update
#    unless @game.world.live_cells.count == 0
#      @game.tick!
      @generation += 1
#    end
  end
  def draw
    @game.world.cells.each do |cell|
      if cell.alive?
        draw_quad(cell.x * @col_width, cell.y * @row_height, @black,
                  cell.x * @col_width + @col_width, cell.y * @row_height, @black,
                  cell.x * @col_width + @col_width, cell.y * @row_height + @row_height, @black,
                  cell.x * @col_width, cell.y * @row_height + @row_height, @black)
      end
    end
  end
  def button_down(id)
    case id
    when Gosu::KbSpace
      @game.world.randomly_populate
    when Gosu::KbEscape
      close
    end
  end
  def draw_background
    draw_quad(0, 0, @white,
              width, 0, @white,
              width, height, @white,
              0, height, @white)
  end
end
window = GameOfLifeWindow.new
window.show

好了,我现在知道代码是正确的,只是需要花很多时间来循环tick!方法。

我制作了视频教程,介绍了使用Rspec和Gosu游戏库使用TDD在Ruby中制作生命游戏,您可以在这里查看> http://svenduplic.com/2013/03/25/conways-game-of-life-in-ruby.html

它们包含了游戏从头到尾的制作过程,我解释了每一行。最后,我解释了为什么这里的代码需要很长时间来完成和优化它。

最新更新