rubylibgosu

Ruby can't find class when I use require_relative


as part of an assignment im trying to use the gosu gem to make a simple snake game. i was instructed to follow this guide: https://github.com/gosu/gosu/wiki/ruby-tutorial

i had gotten quite far and could initialize a snake game but had put it in the snake.rb file and realized it was supposed to be in the game.rb file. i linked to snake.rb with require_relative and tried to create a new instance of the snake class, which gave me:

uninitialized constant Snake (NameError)

i went back to the snake.rb file and tried to create a new snake from there, as i had done before. now also in this file, i get:

uninitialized constant Game (NameError)

seems like snake.rb can't find game.rb and vice versa, although they are in the same folder and i use require_relative. here is the code:

game.rb:

require 'gosu'
require_relative 'snake'

class Game < Gosu::Window
  def initialize(width, height)
    super width, height
  end
end

snake.rb (showing only beginning of file):

require 'gosu'
require_relative 'game'
require_relative 'food'

class Snake < Game
  SIZE = 20

  def initialize
    super SIZE * 20, SIZE * 20
    self.caption = '"SNAKE"'
    @x = (width / 2) - (SIZE / 2)
    @y = (height / 2) - (SIZE / 2)
    @dead = false
    @direction = nil
    @food = nil
    @snake_length = 1
    @score = 0
    @speed = 1
  end

from what i understand, i should now be able to make a new instance of snake, either in snake.rb or in game.rb, using

Snake.new.show

however it does not work. any ideas?

EDIT: the requirements are that the game only consists of 3 .rb files. one called game.rb which has the game class and also starts the game when it is run. one called snake.rb which only has the snake class. one called food.rb which only has a food class for the food items that the snake is trying to catch. the snake class inherits from game and game inherits from gosu::window


Solution

  • Those NameError exceptions happen because the constants are referenced before they are actually defined.

    This is due to a cyclic dependency:

    You have to:

    In order to meet your structural requirements, you could do something along these lines:

    # game.rb
    require 'gosu'
    
    class Game < Gosu::Window
      def initialize(width, height)
        super width, height
      end
    end
    
    require_relative 'snake'
    
    Snake.new.show
    

    And in snake.rb:

    # snake.rb
    class Snake < Game
      SIZE = 20
    
      def initialize
        # ...
      end
    end