0

每当游戏到达 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) end

这会吸引所有敌人、玩家、子弹和爆炸

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

该方法通过定义变量
def initialize_game @background_image = Gosu::Image.new('ima/space.png') @player = Player.new(self) @enemies = [] @bullets = [] @来定义initialize_game方法enemybullets = [] @random_enemy_bullets = [] @explosions = [] @playerexplosions = [] @framecounter = 0 @scene = :game @enemies_appeared = 0 @enemies_destroyed = 0 @credits = [] end

这就是允许游戏运行的原因。它告诉游戏该做什么!

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

这是产生私有方法错误的方法。我不知道为什么。

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

下面的方法也不起作用。产生相同的私有方法错误。我不明白为什么这不起作用,因为我在信用红宝石文件上使用了 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) if id == Gosu::KbP initialize_game elsif id == Gosu::KbQ close end end

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 方法的一部分,用于将行推入 credits 数组。”

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.
4

0 回答 0