Att vårt rymdskepp kan fortsätta att flyga även om det träffas av en asteroid, det är ju inte särskilt realistiskt. Så i den här lektionen ska vi se till så att spelet stoppas om skeppet och asteroiden krockar. I Window
-klassens metod initialize
ska vi lägga till den nya variabeln @running
:
def initialize
super(640, 480, false)
@hero = Hero.new(self)
@asteroid = Asteroid.new(self)
@running = true
end
Ordet "running" betyder ungefär "körs". När vi startar spelet vill vi ju att det ska köras, så från början får @running
värdet true
, som betyder "sant".
Vi ska också "rama in" allting som står i Window
-klassens metod update
i en if-sats, som börjar med if @running
och slutar med end
. Så här ska det se ut:
def update
if @running
if button_down? Gosu::Button::KbRight
@hero.move_forward
end
if button_down? Gosu::Button::KbLeft
@hero.move_back
end
if button_down? Gosu::Button::KbUp
@hero.move_up
end
if button_down? Gosu::Button::KbDown
@hero.move_down
end
@asteroid.update
end
end
If-satsen gör så att koden i update
– som ju sköter uppdateringen av alla bilder i spelet – bara körs så länge värdet på @running
är true
. Det ska vi utnyttja senare, genom att sätta @running
till false
("falskt") när vi vill stoppa spelet.
Men först ska vi ordna så att rymdskeppet kan känna av om det träffas av en asteroid. Vi går till Hero
-klassen, och lägger till den nya metoden hit_by?
("hit by" betyder "träffad av") allra sist i klassen:
def hit_by?(asteroid)
Gosu::distance(@x, @y, asteroid.x, asteroid.y) < 50
end
Den här metoden mäter avståndet, distansen, mellan skeppets position och asteroidens position. Om avståndet är mindre än 50 pixlar så är det en krock!
I Asteroid
-klassen måste vi fixa så att asteroidens position går att läsa av "utifrån", till exempel i rymdskeppets hit_by?
-metod. Det gör vi genom att lägga till denna lilla rad direkt efter class Asteroid
:
attr_reader :x, :y
Okej. Till sist går vi tillbaka till Window
-klassens metod update
. Det är där vi ska känna av om skeppet och asteroiden har krockat. Om så är fallet ska @running
få värdet false
, och spelet stoppas. Vi lägger till ännu en if-sats, direkt efter raden @asteroid.update
:
if @hero.hit_by?(@asteroid)
@running = false
end
Man kan se det som att if-satsen ställer en fråga till rymdskeppet: Är du träffad? (Det är därför som det är ett frågetecken i hit_by?
-metodens namn.)
Det här var en lite rörig lektion, med hoppande mellan olika klasser. Titta igenom programmet här nedanför, och kontrollera så att du har skrivit rätt.
require 'gosu'
class Window < Gosu::Window
def initialize
super(640, 480, false)
@hero = Hero.new(self)
@asteroid = Asteroid.new(self)
@running = true
end
def update
if @running
if button_down? Gosu::Button::KbRight
@hero.move_forward
end
if button_down? Gosu::Button::KbLeft
@hero.move_back
end
if button_down? Gosu::Button::KbUp
@hero.move_up
end
if button_down? Gosu::Button::KbDown
@hero.move_down
end
@asteroid.update
if @hero.hit_by?(@asteroid)
@running = false
end
end
end
def draw
@hero.draw
@asteroid.draw
end
end
class Hero
def initialize(window)
@window = window
@icon = Gosu::Image.new(@window, "spaceship.png", true)
@x = 100
@y = 215
end
def move_forward
@x = @x + 5
if @x > @window.width - @icon.width
@x = @window.width - @icon.width
end
end
def move_back
@x = @x - 5
if @x < 0
@x = 0
end
end
def move_up
@y = @y - 5
if @y < 0
@y = 0
end
end
def move_down
@y = @y + 5
if @y > @window.height - @icon.height
@y = @window.height - @icon.height
end
end
def draw
@icon.draw(@x, @y, 2)
end
def hit_by?(asteroid)
Gosu::distance(@x, @y, asteroid.x, asteroid.y) < 50
end
end
class Asteroid
attr_reader :x, :y
def initialize(window)
@window = window
@icon = Gosu::Image.new(@window, "asteroid.png", true)
@x = @window.width
@y = rand(@window.height - @icon.height)
end
def update
@x = @x - 5
if @x < -@icon.width
@x = @window.width
@y = rand(@window.height - @icon.height)
end
end
def draw
@icon.draw(@x, @y, 2)
end
end
window = Window.new
window.show
Om du nu sparar och kör spelet så märker du att bilden mycket riktigt "fryser" om rymdskeppet och asteroiden krockar.
Men det är fortfarande inte särskilt svårt att undvika den ensamma asteroiden. Vi ska nu skruva upp svårighetsgraden rejält – genom att skapa en hel svärm av asteroider!