Всякий раз, когда игра достигает метода 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.