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