Я пытаюсь включить сцены в мою мини космическую стрелялку, но частная ошибка метода продолжается - PullRequest
0 голосов
/ 11 июля 2019

Всякий раз, когда игра достигает метода draw_end, она вылетает. Методы draw_start и draw_game работают отлично, но игра вылетает, когда она достигает draw_end, и, следовательно, конечные кредиты не могут быть отображены. Ошибка такова:

Traceback (most recent call last):
    9: from sector_five_scenes.rb:275:in `<main>'
    8: from /Users/skynet/.rvm/rubies/ruby-2.6.3/lib/ruby/gems/2.6.0/gems/gosu-0.14.5/lib/gosu/patches.rb:72:in `tick'
    7: from /Users/skynet/.rvm/rubies/ruby-2.6.3/lib/ruby/gems/2.6.0/gems/gosu-0.14.5/lib/gosu/patches.rb:72:in `tick'
    6: from sector_five_scenes.rb:29:in `draw'
    5: from sector_five_scenes.rb:237:in `draw_end'
    4: from /Users/skynet/.rvm/rubies/ruby-2.6.3/lib/ruby/gems/2.6.0/gems/gosu-0.14.5/lib/gosu/compat.rb:165:in `block (2 levels) in <class:Window>'
    3: from /Users/skynet/.rvm/rubies/ruby-2.6.3/lib/ruby/gems/2.6.0/gems/gosu-0.14.5/lib/gosu/compat.rb:165:in `clip_to'
    2: from sector_five_scenes.rb:238:in `block in draw_end'
    1: from sector_five_scenes.rb:238:in `each'
sector_five_scenes.rb:239:in `block (2 levels) in draw_end': private method `draw' called for #<Credit:0x00007ff1b48ad448> (NoMethodError)


I have tried renaming the methods in the credits file. I have tried adding  and removing the require_relative 'credit'. I removed the @credits array from the initialize_end method and  placed  it into the initialize method 

Aside from that I'm really out of ideas of where to go from here  and would really appreciate your help.

Эта часть соединяет все классы с основным файлом

 require 'gosu'
 require_relative 'credit'
 require_relative 'player'
 require_relative 'enemy'
 require_relative 'bullet'
 require_relative 'explosion'

Эта часть открывает окно и устанавливает первую сцену.

 class SectorFive < Gosu::Window
   WIDTH =  800
   HEIGHT = 600
   ENEMY_FREQUENCY = 0.05
   MAX_ENEMIES = 100
   def initialize
     super(WIDTH, HEIGHT)
     self.caption =  "Sector Five"
     @background_image = Gosu::Image.new('ima/start.png')
     @scene = :start
   end

#The draw method below is  the guide for this program.

 def  draw
   case @scene
  when:start
    draw_start
  when:game
    draw_game
  when:end
    draw_end
  end
end

Это устанавливает фоновое изображение def draw_start @ Background_image.draw (0,0,0) конец

Рисует всех врагов, игроков, пули и взрывы

def draw_game
    @player.draw
    @background_image.draw(0,0,0)

    @enemies.each  do |enemy|
          enemy.draw
    end
    @enemybullets.each do |bullet|
          bullet.draw
    end
    @bullets.each do |bullet|
      bullet.draw_two
    end
    @explosions.each do |explosion|
      explosion.draw
    end
    @playerexplosions.each do |explosion|
      explosion.draw_two
    end
 end

Это позволяет игре обновлять каждый кадр

 def update
   case @scene
   when :game
     update_game
  when :end
     update_end
   end
 end

Выполняется запуск игры после первой сцены

 def button_down(id)
   case @scene
  when :start
    button_down_start(id)
  when :game
    button_down_game(id)
  when :end
    button_down_end(id)
  end
end

Этот метод вызывает метод initialize_game

def button_down_start(id)
  initialize_game
end

Этот метод определяет метод initialize_game путем определения переменных
def initialize_game @background_image = Gosu :: Image.new ('ima / space.png') @player = Player.new (самостоятельно) @enemies = [] @bullets = [] @enemybullets = [] @random_enemy_bullets = [] @explosions = [] @playerexplosions = [] @framecounter = 0 @scene =: игра @enemies_appeared = 0 @enemies_destroyed = 0 @credits = [] конец

Это то, что позволяет игре функционировать. Он говорит игре, что делать!

def update_game
  @framecounter += 1
@player.turn_left if button_down?(Gosu::KbLeft)
@player.turn_right if  button_down?(Gosu::KbRight)
@player.accelerate if button_down?(Gosu::KbUp)
@player.backward if  button_down?(Gosu::KbDown)
@player.move
   if rand < ENEMY_FREQUENCY
      @enemies.push Enemy.new(self)
      @enemies_appeared += 1
   end
   @enemies.each do |enemy|
      enemy.move
    end
    #Fires a bullet
    @enemies.select do |enemy|
      if @framecounter % 600 == 0
        @enemybullets.push Bullet.new(self, @enemies[-1].x, @enemies[-1].y, @enemies[-1].angle)
        if @enemies.length >  3
          @enemybullets.push Bullet.new(self, enemy.x, enemy.y, enemy.angle)
        end
      end
   end
# Detects whether there is a collision between a player bullet and an  enemy.
   @enemies.dup.each do |enemy|
     @bullets.dup.each do  |bullet|
       distance = Gosu.distance(enemy.x, enemy.y, bullet.x, bullet.y)
       if distance < enemy.radius + bullet.radius
         @enemies.delete enemy
         @bullets.delete bullet
         @explosions.push Explosion.new(self, enemy.x, enemy.y)
         @enemies_destroyed += 1
       end
     end
   end
   @explosions.dup.each do |explosion|
    if @explosions.length > 15
     @explosions.delete explosion
     @explosions.delete explosion
   end
end
    @explosions.dup.each do |explosion|
      @enemies.dup.each do |enemy|
        distance = Gosu.distance(explosion.x, explosion.y, enemy.x, enemy.y)
        if distance  < explosion.radius + enemy.radius
          @enemies.delete enemy
          @explosions.push Explosion.new(self, enemy.x, enemy.y)
          @enemies_destroyed += 1
        end
      end
    end

#Explosions on the player
@enemybullets.each  do |bullet|
  distance = Gosu.distance(bullet.x, bullet.y, @player.x, @player.y)
  if distance < bullet.radius + @player.radius
    @enemybullets.delete bullet
    @playerexplosions.push Explosion.new(self, @player.x, @player.y)
  end
end
@playerexplosions.dup.each do |explosion|
  @explosions.delete explosion unless explosion.finishedtwo
end

@playerexplosions.dup.each do |explosion|
  @enemies.dup.each do |enemy|
    distance = Gosu.distance(explosion.x, explosion.y, enemy.x, enemy.y)
    if distance < explosion.radius + enemy.radius
      @enemies.delete enemy
      @playerexplosions.delete explosion
      @explosions.push Explosion.new(self, enemy.x, enemy.y)
    end
  end
end
   @enemies.dup.each do |enemy|
     if enemy.y > HEIGHT + enemy.radius
       @enemies.delete enemy
     end
   end
   @bullets.dup.each do |bullet|
     @bullets.delete bullet unless bullet.onscreen?
   end
   @enemybullets.each do |bullet|
     bullet.enemy_move
   end
   @bullets.each do |bullet|
     bullet.move
   end
   @explosions.each  do |explosion|
     explosion.move
   end
    @playerexplosions.each do |explosion|
      explosion.move
    end

Эта часть метода обновления определяет, когда заканчивается игра.

    initialize_end(:count_reached) if @enemies_appeared > MAX_ENEMIES
    @enemies.each do |enemy|
      distance = Gosu::distance(enemy.x, enemy.y, @player.x, @player.y)
    initialize_end(:hit_by_enemy) if distance < @player.radius + enemy.radius
    end
    initialize_end(:off_top) if @player.y < -@player.radius
  end

Этот метод позволяет игроку стрелять пулями

def button_down_game(id)
  if  id == Gosu::KbSpace
    @bullets.push Bullet.new(self, @player.x, @player.y, @player.angle)
  end
end

Этот метод устанавливает конечную сцену («Сцена, которая не работает») и отображает сообщения в нижней части экрана и в верхней части экрана в зависимости от судьбы игроков, а также предполагает отображение конечных кредитов в центре. экрана, созданного файлом credits.txt. Кредиты должны медленно выходить из окна.

def initialize_end(fate)
  case fate
  when :count_reached
    @message = "You Made it! You destroyed #{@enemies_destroyed} ships"
    @message2 = "and #{100 - @enemies_destroyed} reached the base."

  when :hit_by_enemy
    @message = "You were struck by an enemy ship"
    @message2 = "Before your ship was destroyed, "
    @message2 += "you took out #{@enemies_destroyed} enemy ships!"

  when :off_top
    @message = "You got too close to the enemy mothership."
    @message2 = "Before your ship was destroyed, "
    @message2 += "you took out #{@enemies_destroyed} enemy ships!"
  end
  @bottom_message = "Press P to play again, or Q to quit."
  @message_font = Gosu::Font.new(28)
  y = 700
  File.open('credits.txt').each do |line|
    @credits.push(Credit.new(self,line.chomp,100,y))
    y+=30
 end
 @scene = :end
end

Это метод, который выдает ошибку Private Method. Я не могу понять, почему.

def draw_end
   clip_to(50,140,700,360) do
  @credits.each do |credit|
    credit.draw
  end
 end
draw_line(0,140,Gosu::Color::RED,WIDTH,140,Gosu::Color::RED)
@message_font.draw(@message,40,40,1,1,1,Gosu::Color::FUCHSIA)
@message_font.draw(@message2,40,75,1,1,1,Gosu::Color::FUCHSIA)
draw_line(0,500,Gosu::Color::RED,WIDTH,500,Gosu::Color::RED)
@message_font.draw(@bottom_message,180,540,1,1,1,Gosu::Color::AQUA)
end

Методы ниже также не работают. Выдает ту же ошибку метода Private. Я не понимаю, почему это не работает, потому что я использовал require_relative в файле кредитного рубина.

def update_end
  @credits.each do |credit|
    credit.move
  end
  if @credits.last.y < 150
    @credits.each do |credit|
      credit.reset
    end
  end
end

# Этот метод дает игроку возможность снова играть или выйти из игры, и игрок выбирает кнопку в зависимости от своих предпочтений. def button_down_end (id) если id == Gosu :: KbP initialize_game elsif id == Gosu :: KbQ близко конец конец

end

window = SectorFive.new
window.show


----------------------------------------------------------------------

"Это кредитный класс"

класс Кредит СКОРОСТЬ = 1 attr_reader: y,: x,: text

  def initialize(window,text, x, y)
    @x = x
    @y = @initial_y =  y
    @text = text
    @font = Gosu::Font.new(24)
  end
end


  def move
    @y -= SPEED
  end

  def draw
    @font.draw(@text, @x, @y, 1)
  end

  def reset
    @y = @initial_y
  end

-----------------------------------------------------------------------
"""The credits.txt file"""

"Это часть метода File.open, используемого для вставки строки в массив кредитов."

SectorFive 

By: John Jordan Shelley 

Based on a Tutorial from 

Learn Game Programming with Ruby 
By Mark Sobkowicz

—Images——
Game art from OpenGameArt.org
Licensed under Creative Commons: Domain CC0

The game should smoothly execute the initialize end method and give the player options depending on the player's fate and play the ending credits.
...