Efter två lektioner har du redan lärt dig en hel del om spelprogrammering. Och nu börjar det börjar bli riktigt spännande – vi ska börja sätta saker och ting i rörelse! Men först ska jag berätta en hemlighet om vårt spelfönster.
Än så länge ser det kanske inte så märkvärdigt ut, spelfönstret. Men under ytan händer det intressanta saker. När vi kör programmet, och fönstret öppnas, startar samtidigt en loop. En loop använder man i datorprogram när man vill få något att upprepas. I vårt fall är det koden i Window
-klassens metoder update
och draw
som körs, om och om igen. Det här sker i en svindlande hastighet. Metoderna körs, eller anropas, som det heter, hela 60 gånger i sekunden!
Okej, men vad ska det här vara bra för? Jo, tack vare loopen går det smidigt att skapa animationer – bilder som rör sig i fönstret. Det ska vi göra nu.
Först lägger vi till några rader i Window
-klassens update
-metod, som än så länge är tom. Vi skriver:
def update
if button_down? Gosu::Button::KbRight
@hero.move_forward
end
end
Det här är en så kallad if-sats och sådana är mycket vanliga i datorprogram. Kan du klura ut vad den gör? Här får du en ledtråd: Översatt till svenska så betyder if button_down?
"om knapp nere". Och koden kontrollerar just om en viss tangent, i det här fallet höger piltangent, är nedtryckt. Om så är fallet anropas en metod i Hero
-klassen som heter move_forward
, vilket betyder typ "flytta framåt".
Men någon sådan metod finns ju inte! Det måste åtgärdas. Vi går till Hero
-klassen och gör några ändringar:
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
end
def draw
@icon.draw(@x, @y, 2)
end
end
Först ändrar vi metoden initialize
så att rymdskeppets startposition sparas i två variabler som heter @x
och @y
. Det gör vi för att vi senare ska kunna ändra positionen.
För att förstå vad en variabel är så kan du tänka dig datorns minne som en massa lådor där man kan spara olika saker, till exempel tal eller ord. När vi skapar en variabel så sätter vi en etikett på en sådan låda. På så vis kan vi hitta den när vi vill lägga något i den, eller ändra eller ta bort det som ligger där.
Nu har vi alltså lagt talen 100 och 215 i två "lådor" som heter @x
och @y
. De heter så eftersom man brukar kalla positionen i sidled för x-värde och positionen i höjdled för y-värde. (Varför namnen på variablerna börjar med "@", snabel-a, ska jag inte gå närmare in på här. Men det är för att @x
och @y
är en speciell sorts variabler som kallas instansvariabler.)
Den andra ändringen i Hero
-klassen är den nya metoden move_forward
. När den anropas så ökas x-värdet med 5, det vill säga skeppets position flyttas fem pixlar framåt.
Till sist har vi ändrat i draw
-metoden så att det står @x
och @y
i stället för 100 och 215.
Spara nu programmet, och kör det sedan. När du nu trycker på högerpilen ska skeppet röra sig framåt, fem pixlar i taget. Prova gärna att ändra i metoden move_forward
så att @x ökas med till exempel 3, eller 10. Vad händer då?
Här är nu vårt spelprogram i sin helhet:
require 'gosu'
class Window < Gosu::Window
def initialize
super(640, 480, false)
@hero = Hero.new(self)
end
def update
if button_down? Gosu::Button::KbRight
@hero.move_forward
end
end
def draw
@hero.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
end
def draw
@icon.draw(@x, @y, 2)
end
end
window = Window.new
window.show
Nu har vi alltså ett rymdskepp som kan flyga. Tjusigt! Men vi har ett par problem att lösa: Dels kan det bara flyga framåt, inte bakåt, uppåt eller nedåt. Dels så stannar inte skeppet om det råkar flyga för långt framåt – utan det flyger ut från spelfönstret och försvinner i tomma intet. Prova själv så får du se.
I nästa lektion ska vi lägga till fler move
-metoder – och sätta gränser för vårt skepp så att det inte kan rymma.