4 votes

Ruby game of life avec Gosu - l'action de mise à jour ne fonctionne pas

Je suis en train de créer Game of Life en Ruby en utilisant Gosu. Mon code est ci-dessous. Actuellement, lorsque j'exécute 'ruby gosu.rb', la fenêtre s'ouvre avec les dimensions appropriées et le monde pré-rempli comme il se doit.

Mais dès que je décommente '@game.tick!' dans l'action de mise à jour du fichier gosu, en exécutant 'ruby gosu.rb', j'obtiens un écran noir sans monde prérempli que je ne peux pas fermer. Pourquoi cela et comment y remédier ?

Vous pouvez trouver le repo github avec le reste du code ici. Toute aide est la bienvenue.

Voici mon 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

Voici mon code 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

2voto

oFca Points 751

Ok, je sais maintenant que le code est correct, c'est juste qu'il faut beaucoup de temps pour que le cycle de la tick! par le biais de la méthode.

J'ai réalisé des tutoriels vidéo sur la création du jeu de la vie en Ruby en utilisant TDD avec Rspec et la bibliothèque de jeux Gosu. Vous pouvez les consulter ici >. http://svenduplic.com/2013/03/25/conways-game-of-life-in-ruby.html

Ils contiennent le making of du jeu du début à la fin, avec moi expliquant chaque ligne. À la fin, j'explique pourquoi le code ici prend beaucoup de temps à compléter et à l'optimiser correctement.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X