Why won't my dodgeCount variable work?

98 views Asked by At

I wrote a fairly simple game in ruby, where you are a space shuttle and you have to dodge a few meteorites. I decided to put in a dodge counter, but the alert message isn't showing the actual score. Here's the code:

@dodgeCount = 0
require 'gosu'

class  MyGame < Gosu::Window
  def initialize
    super(600, 400, false)
    @player1 = Player.new(self)
    @balls = 3.times.map {Ball.new(self)} 
    @running = true
  end

  def update
    if @running
      if button_down? Gosu::Button::KbLeft
        @player1.move_left
      end

      if button_down? Gosu::Button::KbRight
        @player1.move_right
      end

      if button_down? Gosu::Button::KbUp
        @player1.move_up
      end

      if button_down? Gosu::Button::KbDown
        @player1.move_down
      end

      @balls.each {|ball| ball.update} 

      if @player1.hit_by? @balls
        stop_game!
        alert "Your score is " + @dodgeCount.to_s
      end
    else
      #the game is now stopped
      if button_down? Gosu::Button::KbEscape
        restart_game
      end
    end
  end

  def draw
    @player1.draw
    @balls.each {|ball| ball.draw}
  end

  def stop_game!
    @running = false
  end

  def restart_game
    @running = true
    @balls.each {|ball| ball.reset!}
  end
end

class Player
  def initialize(game_window)
    @game_window = game_window
    @icon = Gosu::Image.new(@game_window, "gosu/player1.png", true)
    @x = 50
    @y = 330
  end

  def draw
    @icon.draw(@x, @y, 1)
  end

  def move_left
    if @x < 0
      @x = 0
    else
      @x = @x - 10
    end
  end

  def move_right
    if @x > (@game_window.width - 75)
      @x = @game_window.width - 75
    else
      @x = @x + 10
    end
  end

  def move_up
    if @y < 0
      @y = 0
    else
      @y = @y - 10
    end
  end

  def move_down
    if @y > (@game_window.height - 75)
      @y = @game_window.height - 75
    else
      @y = @y + 10
    end
  end

  def hit_by? (balls)
    balls.any? {|ball| Gosu::distance(@x, @y, ball.x, ball.y) < 50}
  end
end

class Ball
  def initialize(game_window)
    @game_window = game_window
    @icon = Gosu::Image.new(@game_window, "gosu/asteroid.png", true)
    reset!
  end

  def update
    if @y > @game_window.height
      reset!
      @dodgeCount = @dodgeCount + 1
    else
      @y = @y + 10
    end
  end

  def draw
    @icon.draw(@x, @y, 2)
  end

  def x
    @x
  end

  def y 
    @y
  end

  def reset!
    @y = 0
    @x = rand(@game_window.width)
  end

end

 window = MyGame.new
 window.show
1

There are 1 answers

0
Neil Slater On

The @dodgeCount variable that appears to be tracking the score is in class Ball, whilst you are using alert to display another (otherwise unused) variable in class MyGame. When Ruby sees an instance variable name (beginning with @), it will create that instance variable for you automatically if it doesn't already exist, so you end up with a nil value for the score, which then ends up displaying as "" (because nil.to_s == "").

There is also the problem that you have three balls, and each one will track the score separately.

You will be better off tracking the score in the same MyGame class where you want to display it. The easiest thing to do is move some of the code from Ball#update to MyGame#update.

You will need to initialise and re-set the score with

@dodgeCount = 0

In MyGame#initialize and MyGame#restart_game

Where you currently have in MyGame#update, @balls.each {|ball| ball.update} add code to detect dodges, and track the score:

@balls.each do |ball| 
  ball.update
  if ball.y > height
    ball.reset!
    @dodgeCount = @dodgeCount + 1
  end
end

And Ball#update is simplified:

def update
  @y = @y + 10
end

I hope this works for you, I don't have a copy of gosu available to check in detail.