Archives for posts with tag: Gosu

Häromdagen stötte jag på ett riktigt trevligt projekt som jag känner att jag måste tipsa om: Pygame Zero. Det är ett litet ramverk som bygger på Pygame, ett spelbibliotek som används för att skapa spel i Python, och som främst är tänkt att användas för undervisning. Som upphovsmannen Daniel Pope själv beskriver det: Pygame Zero gör det möjligt för lärare att lära ut programmeringskoncept utan att först behöva förklara saker som spelloopar och händelseköer. De här sakerna, och mycket annat, är dolda för den som använder ramverket.

Jag har lekt lite grann med Pygame Zero och kan konstatera att det på många sätt liknar Gosu, det ramverk för spelprogrammering i Ruby som jag har tjatat om i många tidigare inlägg här på bloggen. Men Pygame Zero tar det här med att abstrahera bort ”krångliga” saker ytterligare några steg längre. Till exempel: För att öppna ett grafikfönster så behöver du inte skriva en enda klass. Faktum är att du inte behöver skriva någon kod alls. Du kan bara skapa en tom fil, döpa den till t ex ”game.py” och köra den med ett speciellt program som ingår i ramverket. Ett fönster med en rityta på 800 gånger 600 pixlar framträder på skärmen.

Skärmbild_2015-08-05_18-33-43

Är det här bra eller dåligt, att så pass mycket sker i bakgrunden utan att användaren kommer i kontakt med koden? Det är en fråga som man kan vrida och vända på länge. Den som på allvar vill lära sig att programmera i Python måste förstås, förr eller senare, även greppa saker som import av moduler och iteration över listor. Men det kanske inte är det allra första man behöver lära sig. Jag är inte pedagog, men jag tror att det är viktigt att programmeringen snabbt ger roliga resultat för att inte motivationen hos eleven ska tryta. Och en rymdvarelse som svävar i ett grafikfönster är definitivt roligare än en while-loop. Har du en åsikt i frågan, eller andra synpunkter, hör gärna av dig i kommentarsfältet nedan.

För att kunna använda Pygame Zero måste du först installera Python 3 och Pygame. Installationsanvisningar hittar du här. Jag har utan större problem installerat ramverket på tre olika datorer: En med Xubuntu 15.04, en med Windows 8.1 och en Raspberry Pi med Raspbian. I skrivande stund har gänget bakom Pygame Zero precis släppt en ny version, som förutom buggfixar och nya funktioner innehåller ett knippe exempelspel i form av implementationer av klassiska spel som Snake, Pong och Lunar Lander.

Själv tänker jag försöka skriva om en liten Space Invaders-klon som jag en gång kodade i Ruby till Python och använda Pygame Zero. Min förhoppning är att detta projekt så småningom ska mynna ut i en liten tutorial. Den som lever får se.

/Mats

Annonser

Tänkte bara kort berätta att jag har kompletterat min handledning för barn/unga (och andra nybörjare) som vill lära sig att koda spel i Ruby med ett par små videofilmer (som jag utan framgång har försökt bädda in i blogginlägget…).

I videorna beskriver jag hur man laddar ner och installerar verktyget Kids Ruby och hur man skapar ett spelfönster med Ruby och spelbiblioteket Gosu. Jag går inte på djupet i filmerna, utan de är tänkta att användas tillsammans med de skriftliga instruktionerna. Tanken är att nybörjare som har svårt att komma igång ska få ytterligare lite hjälp på traven. Eventuellt gör jag videoversioner av fler lektioner.

Förresten: Det lilla rymdspel som skapas i spelskolan ligger numera på Github. Kom gärna med förslag på tillägg/förbättringar. En extralektion om ljudeffekter är redan på gång.

/Mats

Vet ni vad jag upptäckte i höstas, då jag började söka efter olika sätt att inviga mina två äldsta barn i programmeringens värld? Jo, att information om programmering som är på svenska och vänder sig till barn och ungdomar i högsta grad är en bristvara. Det tycker jag att vi måste försöka ändra på.

För att dra ett litet strå till stacken har jag skrivit en tutorial, handledning, om hur man skapar ett spel i Ruby med hjälp av spelbiblioteket Gosu. Min förhoppning är att barn i, säg, mellanstadieåldern och uppåt ska kunna använda den. Men även vuxna nybörjare kan säkert lära sig ett och annat av de tio lektionerna, så titta gärna in på den sajt som jag har byggt för ändamålet: rorbecker.com/spelskola/

Jag har hämtat mycket inspiration och kunskap från befintliga, engelskspråkiga tutorials, framför allt den som är ”inbyggd” i verktyget Kids Ruby och den som ligger här. En bild på det spel som steg för steg skapas – Asteroid Storm – ligger nedan. Någon kanske uppfattar en liten blinkning till min barndoms favoritspel Uridium?

spel

Jag har redan fått en hel del feedback och hjälp. Men eftersom jag vill att handledningen ska bli så bra som möjligt så tar jag tacksamt emot ytterligare synpunkter på den. Så hör gärna av er, antingen i kommentarsfältet eller på Twitter!

/Mats

PS. Om du undrar hur det går med den svenska översättningen av Kids Ruby så är den klar sedan länge. Men tyvärr vet jag inte när en svensk version kommer att finnas tillgänglig.

Att rita geometriska figurer på skärmen, det är ju sådant som exempelvis Javascript är bra på. Men hur gör man bäst om man vill använda Ruby? Det har jag funderat på de senaste dagarna. Efter att ha testat ett par olika sätt har jag skrivit, eller snarare börjat skriva på, ett litet program som jag har tänkt att ungarna ska få leka med framöver.

Programmet, som jag kallar för Canvas (”canvas.rb” i exemplen nedan), ger tillgång till en ”målarduk” (”canvas” på engelska) och ett knippe metoder för att rita olika figurer. Följande kodsnutt visar hur det kan användas.

require_relative 'canvas.rb'

canvas = Canvas.new

canvas.paint_background("lightblue")
canvas.draw_circle(250, 250, 100, "red", true)
canvas.draw_box(50, 100, 200, 100, "darkblue", true)
canvas.draw_triangle(275, 250, 350, 125, 425, 250, "green")
canvas.draw_polygon(400, 400, 75, 9, "pink", 10)
canvas.fill(400, 400, "yellow")
canvas.draw_line(50, 475, 475, 175, "orange", 7)

canvas.show

Den första raden exekverar ”canvas.rb” som ska ligga i samma katalog som koden ovan. Sedan skapas ett nytt objekt av klassen Canvas, det vill säga själva ”målarduken”. Därefter ritar och målar jag på duken med de olika metoderna, innan konstverket till sist visas på skärmen med metoden show. Resultatet ser ut så här:

konst

Inte särskilt vackert, det medges. Men ett hyfsat smidigt sätt att skapa grafik av det här slaget. Jag måste dock erkänna att det inte är mitt program som står för magin här. I stället är det Gosu – ramverket för spelprogrammering som jag har skrivit om tidigare – och det tillhörande verktyget Texplay som gör jobbet. Syftet med Canvas är främst att göra de metoder som redan finns i Texplay lite lättare att använda och att minska mängden omgivande kod. Jag har också lagt till en metod för att rita trianglar samt så kallade RGB-värden för ytterligare några färger.

Jag ska strax gå närmare in på hur metoderna används. Men först lite mer lek. I koden nedan tar jag hjälp av slumpen (metoden rand returnerar ett slumptal) och en loop…

require_relative 'canvas.rb'

canvas = Canvas.new

canvas.paint_background("red")
100.times do
  canvas.draw_line(250, 250, rand(500), rand(500), "white")
  canvas.draw_line(250, 250, rand(500), rand(500), "yellow")
  canvas.draw_line(250, 250, rand(500), rand(500), "green")
  canvas.draw_line(250, 250, rand(500), rand(500), "turquoise")
  canvas.draw_line(250, 250, rand(500), rand(500), "tyrian")
  canvas.draw_line(250, 250, rand(500), rand(500), "orange")
  canvas.draw_line(250, 250, rand(500), rand(500), "cyan")
end

canvas.show

… för att skapa denna färgexplosion:

canvas

När mina barn premiärtestade programmet häromkvällen ritade vi flaggor. Med den här koden…

require_relative 'canvas.rb'

canvas = Canvas.new(800, 400)

canvas.draw_line(0, 400, 280, 0, "darkblue")
canvas.fill(10, 10, "darkblue")
canvas.draw_line(0, 400, 500, 0, "yellow")
canvas.fill(290, 10, "yellow")
canvas.draw_line(0, 400, 800, 130, "red")
canvas.fill(510, 10, "red")
canvas.draw_line(0, 400, 800, 270, "darkgreen")
canvas.fill(790, 390, "darkgreen")

canvas.show

… skapade vi till exempel Seychellernas flagga (med reservation för att färgnyanserna inte är helt korrekta):

seychellerna

Om du själv vill prova att rita med Canvas måste du förstås ha installerat Ruby på din dator. Därutöver måste du ha installerat Gosu och Texplay (görs enkelt genom att skriva gem install gosu respektive gem install texplay vid kommandoprompten). Och så måste du ha filen ”canvas.rb” i din arbetskatalog. Längst ner i inlägget hittar du en länk till källkoden som får kopieras fritt. Programmet är på intet sätt färdigt, utan jag planerar att lägga till fler metoder, bland annat för animering. Kom gärna med synpunkter och förslag!

Okej, här följer nu en genomgång av metoderna och de argument (det som står inom parenteserna) de tar:

paint_background("färg")

Målar bakgrunden i angiven färg. Färgen måste skrivas på engelska, inom citattecken. De färger som i skrivande stund stöds är: ”black”, ”blue”, ”brown”, ”cyan”, ”green”, ”grey”, ”orange”, ”purple”, ”red”, ”turquoise”, ”tyrian”, ”white”, ”yellow”, ”darkblue”, ”lightblue”, ”darkgreen”, ”tomato”, ”darkred”, ”pink” och ”deeppink”.

draw_circle(x, y, r, "färg", true/false)

Ritar en cirkel med mittpunkten x, y och radien r (mätt i pixlar). Målarduken är i standardläget 500 gånger 500 pixlar. Längst upp i vänstra hörnet är koordinaterna 0, 0 och längst ner i högra hörnet är de 500, 500. Det femte och sista argumentet anger om cirkeln ska vara fylld (true) eller ej (false). Standardvärdet är false, så om cirkeln inte ska vara fylld behövs inget femte argument. (Även färgargumentet är egentligen frivilligt, standardfärgen är svart.)

draw_box(x, y, bredd, höjd, "färg", true/false)

Ritar en rektangel/kvadrat vars övre vänstra hörn får positionen x, y.

draw_triangle(x1, y1, x2, y2, x3, y3, "färg", tjocklek)

Drar linjer mellan de tre angivna punkterna, dvs ritar en triangel. Här saknas möjlighet att fylla triangeln direkt, utan det får i stället göras med fill-metoden nedan (detsamma gäller månghörningar). Det sista argumentet avser linjens tjocklek, standardvärdet är 1.

draw_polygon(x, y, r, antal sidor, "färg", tjocklek)

Ritar en regelbunden polygon/månghörning med mittpunkten x, y och radien r.

draw_line(x1, y1, x2, y2, "färg", tjocklek)

Drar en linje mellan två punkter.

fill(x, y, "färg")

Fyller ett avgränsat område med färg genom att man anger en punkt inuti området. Fungerar alltså på samma sätt som ”flood fill” i ett ritprogram. Kan användas för att fylla trianglar och månghörningar.

Till sist några ord om storleken på målarduken. Som flaggexemplet ovan visar går det att ändra storleken genom att skicka med måtten när Canvas-objektet bildas (t ex canvas = Canvas.new(800, 400)). Det här funkar dock inte helt perfekt. Gosu gillar nämligen inte när fönstret blir för stort, och vad som är ”för stort” tycks bero på skärmens upplösning. På min dator verkar maxstorleken vara 1000 gånger 600 pixlar. Om jag överskrider den gränsen börjar programmet bete sig knasigt.

Det var allt för den här gången. Låt mig gärna veta vad du tycker om inlägget, antingen här på bloggen eller på Twitter. Vi hörs!

/Mats

Du hittar källkoden till Canvas här.

Ni vet rymdspelet som påbörjades i förra bloggposten, Så gör du ett spel med Ruby? Jag kunde inte låta bli att fortsätta på det, trots att jag skrev att ni skulle få klara resten själva. Så i slutet av detta inlägg ligger nu en tidig julklapp till er som kört fast eller behöver ytterligare inspiration: ett färdigt litet spel, med en del kommentarer till den nya koden.

I korthet så har jag lagt till ytterligare en klass, Asteroid, som används för att skapa asteroider (om man ska vara petig är det en enda asteroid som dyker upp om och om igen) som vårt rymdskepp ska försöka undvika att krocka med. Den bildfil som jag hänvisar till i programmet, ”asteroid.png”, följer med när man laddar ner verktyget Kids Ruby. Och så har jag stulit en bakgrundsbild, ”Space.png”, från ett av de exempelspel som ingår i Rubyinstallationen, fast jag har beskurit den så den passar in i vårt spelfönster och döpt om den till ”space2.png”. Precis som när det gällde rymdskeppet så kan man, om man så föredrar, förstås rita både asteroid och bakgrund själv i Paint eller annat ritprogram. Till sist har jag lagt in en poängräknare samt metoder som stoppar spelet om skeppet träffas av en asteroid.

Ni som har läst de två senaste inläggen om Ruby vet redan det här, men för eventuella nytillkomna läsares skull: För att spelet ska funka på din egen dator måste du ha installerat Rubytolken (hur du gör beskrivs här), sparat själva programmet som en Ruby-fil och så måste de bildfiler som används ligga i samma katalog som programfilen. Sedan är det bara att starta spelet via Rubys kommandoprompt. Mitt eget high score är, i skrivande stund, 380. Kan någon av er slå det, tro?

Nu tar jag bloggledigt över jul- och nyårshelgerna, så det här blir sista inlägget i år. Sedan starten i oktober har bloggen haft cirka 500 besök – tack för det! Och välkomna åter 2013, då jag bland annat ska ta mig an Javascript och kanske prova på Arduino. Dessutom ska jag, har jag tänkt, försöka bygga en egen liten applikation som ungarna kan träna programmering med. Hej!

/Mats

Det utbyggda programmet hittar du här.

Att kunna skapa sina egna datorspel – det är vad många, i synnerhet kanske barn, ser som själva poängen med att lära sig programmering. När mina egna ungar gör spel så använder de än så länge Scratch, ett lättanvänt och roligt verktyg som jag har skrivit om tidigare. Men även med Ruby är det relativt enkelt att skapa ett spel. Tricket är att använda sig av något som heter Gosu, och som jag strax ska berätta mer om.

Först några rader om vad som väntar. Det här långa inlägget handlar om hur man kan göra ett enkelt rymdspel, eller i alla fall början på ett, med Rubykod. För att du ska kunna hänga med på ”lektionen” krävs att du har installerat Ruby på din dator, och att du vet hur man skriver program i en texteditor och kör dem via kommandoprompten. Det vill säga precis vad bloggposten Kom igång med Ruby handlade om. Har du dessutom ett hum om vad begrepp som objekt, klasser, metoder och variabler betyder i det här sammanhanget så underlättas förståelsen, men det är inte nödvändigt.

Så där. Åter till Gosu, som rent konkret är ett bibliotek med programsnuttar. I de här snuttarna definieras klasser och metoder som används vid spelprogrammering, för att exempelvis skapa grafikfönster, spela upp ljud och musik och känna av när spelaren rör på musen eller trycker på tangentbordet. Grovjobbet är, med andra ord, redan gjort. Men för att kunna använda Gosu måste du först installera det. Starta Rubys kommandoprompt och skriv gem install gosu följt av return. Klart!

Nu är det dags att börja på själva programmet. Öppna ett nytt dokument i din texteditor. Allra överst ska det stå:

require 'gosu'

Denna rad ger oss tillgång till Gosu-biblioteket. Sedan är det dags att skriva den första så kallade klassdefinitionen, som ska se ut så här (du kan, om du vill, bortse från att vissa rader är indragna men var noga med små/stora bokstäver):

class Window < Gosu::Window
  def initialize
    super(300, 400, false)
  end

  def update
  end

  def draw
  end
end

window = Window.new
window.show

Här definieras klassen Window, som vi först låter ärva egenskaper från Gosu-klassen med samma namn. Sedan definieras tre metoder: initialize, update och draw. I initialize-metoden talar vi om att grafikfönstret ska vara 300 pixlar brett och 400 pixlar högt, samt att det inte ska fylla upp hela skärmen (annars hade vi skrivit ”true” i stället för ”false”). De två sista raderna i programmet skapar ett nytt objekt av klassen Window, innan själva grafikfönstret framkallas med metoden ”show”. Om du tycker att det här låter krångligt är det helt i sin ordning – det hade jag också tyckt för bara några veckor sedan.

När det här programmet körs visas alltså ett grafikfönster. Dessutom startas en loop som hela tiden anropar metoderna update och draw som, än så länge, inte utför något alls. Nu vill vi ha någonting som symboliserar spelaren: en bild av ett rymdskepp. Här tar jag en genväg och använder en bildfil som följer med Rubyinstallationen och som heter ”Starfighter.bmp” (sök på filnamnet och du lär hitta den i din dator). Om du vill rita ett rymdskepp själv i ett ritprogram kan du förstås göra det – se bara till att bilden är 50 gånger 50 pixlar stor. Annars: kopiera ”Starfighter.bmp” och lägg bilden i samma mapp som ditt program.

Nu är det dags att definiera ytterligare en klass, som får namnet Player:

class Player
  def initialize(window)
    @window = window
    @icon = Gosu::Image.new(@window, "Starfighter.bmp", true)
    @x = 125
    @y = 175
  end

  def draw
    @icon.draw(@x, @y, 1)
  end
end

Här berättar vi för datorn vilken bild som ska användas samt, med variablerna @x och @y, vilket utgångsläge den ska ha i grafikfönstret. Vi måste också göra några ändringar i klassen Window. I metoden initialize lägger vi, på en egen rad, till @player1 = Player.new(self) som skapar ett nytt objekt av klassen Player när spelet startas. I metoden draw låter vi rymdskeppet framträda på skärmen med raden @player1.draw, som helt enkelt anropar motsvarande metod i Player-objektet.

Om vi nu sparar programmet, förslagsvis som ”spel.rb”, och provkör det genom att skriva ruby spel.rb vid kommandprompten öppnas ett fönster som ser ut så här:

spel

Vackert så. Men vi vill ju kunna styra vårt rymdskepp också. Vi tar återigen hjälp av Gosu, som innehåller metoder som känner av om olika tangenter är nedtryckta. I Window-klassens metod update lägger vi till följande så kallade villkorssatser:

if button_down? Gosu::Button::KbLeft
  @player1.move_left
end

if button_down? Gosu::Button::KbRight
  @player1.move_right
end

if button_down? Gosu::Button::KbUp
  @player1.move_up
end

if button_down? Gosu::Button::KbDown
  @player1.move_down
end

Och så måste vi, i klassen Player, lägga till de metoder som anropas ovan och som, beroende på vilken piltangent som är nedtryckt, ska ändra värdena på variablerna @x och @y:

def move_left
  @x = @x - 5
  if @x < 0
    @x = 0
  end
end

def move_right
  @x = @x + 5
  if @x  > @window.width - 50
    @x = @window.width - 50
  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 - 50
    @y = @window.height - 50
  end
end

Om du nu kör programmet igen ska du kunna styra rymdskeppet över hela grafikfönstret. Går det för snabbt eller för långsamt? Ändra då move-metoderna ovan och låt @x och @y minska/öka med mer/mindre än 5 (t ex @x = @x - 10). Funkar det inte alls? Allra sist i inlägget länkar jag till en textfil som innehåller programmet i sin helhet. Jämför med din egen kod. Kanske har du stavat fel någonstans, eller missat något tecken?

Vi har nu kommit en bra bit på väg. Men det är fortfarande mycket som saknas: någon form av motståndare eller hinder, poängräkning, en bakgrundsbild osv. Fast vet du vad? Hädanefter får du klara dig på egen hand!

Lugn, bara lugn. På nätet finns flera bra tutorials, kurser, om hur man använder Gosu, och som jag själv lärt mig mycket av och lånat friskt ifrån när jag skrev det här inlägget. Till exempel tar tredje lektionen i den här kursen vid där jag slutade. Det finns också en bra kurs inbyggd i verkyget Kids Ruby, som kan laddas ner här.

Lycka till! Och berätta gärna hur det gick, eller lämna synpunkter, i kommentarsfältet nedan.

/Mats

Programmet i sin helhet hittar du här.