Jump to content
Rpg²S Forum

Creare giochi con le Ruby/SDL


Keroro
 Share

Recommended Posts

Molti di voi conoscono bene il ruby e magari si sentono limitati da rpgmaker xp o il vx o semplicemente vorrebbero creare qualcosa che sia completamente farina del proprio sacco e che magari si discosti molto da un rpg.

Vorrei mostrarvi la libreria che uso e che amo tanto (ci programmo in C), della quale esiste da qualche anno un porting funzionante in Ruby

 

Premessa

Ammetto che stanotte mi ci sono imbattuto per sbaglio perché cercavo una libreria per scrivere kanji, SDLSKK (sì, sono strano =D ), destino ha voluto fosse ospitata nello stesso sito delle Ruby/SDL.

Vorrei però cogliere l'occasione per aprire un nuovo filone di game making in questo sito ;D

 

Ruby/SDL

  • Che cos'è?
    SDL è una libreria cross-platform che permette di sviluppare facilmente un videogioco offrendo un accesso a basso livello all'audio, tastiera, mouse, joystick, 3d tramite OpenGL e funzioni 2d "veloci".
    L'implementazione ruby è più lenta (ma anche più semplice!) rispetto a quella C/C++, quindi l'autore del porting ruby consiglia di evitare il 3d mentre per il 2d va benissimo!
     
     
  • Come la installo?
    Io sono culoso e scrivo da linux (ubuntu) per installarla è bastato scrivere
    sudo apt-get install libsdl-ruby1.8


    I windowsiani trovano le istruzioni ed il download qui: http://www.kmc.gr.jp/~ohai/rubysdl_download.en.html
    Come potete notare quello è il sito ufficiale del porting ruby, era noto che i giapponesi avessero il pallino visto che questo linguaggio l'hanno creato loro ;)
    Se doveste avere problemi con l'installazione chiedete qui, e spero che qualche ruby windows guru risponderà :D
     
     

  • Premessa2
    Non conosco il ruby come le mie tasche perché non lo uso abitualmente (anzi se vedete nella sezione RGSS sono appena sopra la mezza sega :D), tutto il codice che scriverò sarà quindi evidentemente non ottimizzato, e non ha neanche la pretesa di esserlo visto che la sola pretesa è INSEGNARE qualcosa, sta poi a voi riunire in questo o quel modulo o in quella classe specifica.
    Utilizzerò il termine funzione piuttosto che metodo, del resto il metodo è una particolare funzione (perché non sono abituato a chiamarle metodi :Ok: )
     
     
  • Consiglio
    Programmate sempre con la documentazione/reference in background in modo programmare senza intoppi, trovate la reference delle Ruby/SDL alla pagina http://www.kmc.gr.jp/~ohai/rubysdl_doc.en.html

===== Hello World! =====

Il nostro primo programma non farà niente se non aprire una finestra in cui disegnamo qualche scarabocchio ;O;

Penso sia necessario anche per notare la fondamentale differenza con le librerie TK.

Le librerie TK sono a oggetti, mentre SDL è una libreria procedurale, seppur in Ruby costituita da classi e metodi.

Questo vi permette molta libertà nella programmazione, libertà che sfrutto al volo perché non sono ancora ferrato con gli oggetti XD.

 

Innanzitutto dobbiamo includere la libreria quindi nel nostro hello.rb metteremo

require 'sdl'

Poi dobbiamo inizializzare la libreria: il sistema SDL è costruito da più "sottosistemi" attivabili a nostro piacimento passandoli come argomento (combinati con l'OR |) alla funzione SDL.init

  • SDL::INIT_AUDIO
  • SDL::INIT_VIDEO
  • SDL::INIT_CDROM
  • SDL::INIT_JOYSTICK

Penso siano autoesplicativi, vediamo un po' se indovinate cosa ci serve...

Soltanto il sistema video!

quindi da bravi amanuensi scriviamo

SDL.init( SDL::INIT_VIDEO)

NB: devi inizializzare la libreria prima di usare una qualsiasi funzione SDL!

 

Adesso è ora di creare la nostra finestra ma prima un piccolo excursus

Alla base di tutto c'è la classe SDL::Surface, essa rappresenta un'area di memoria che funziona come una immagine virtuale:

  • ha una sua larghezza, altezza e profondità (bits per pixel)
  • puoi disegnarci su tramite molti metodi ed in maniera diversa, puoi disegnare pixel o primitive quali linee, rettangoli, cerchi, puoi copiarci una immagine bmp, png, jpeg con o senza alpha channel e definire eventualmente un colore alpha (come rpgmaker 2000)
  • puoi copia incollarla su altre Surface (così come le immagini in paint)

Le SDL associano una Surface alla Finestra dell'applicazione ed il giocatore vedrà tutto e soltanto quello che disegnamo dentro questa Surface.

 

Per crearla dobbiamo usare la funzione SDL.setVideoMode( width, height,bpp,flags)

Analizziamo gli argomenti:

width è la larghezza della finestra

height è l'altezza della finestra

bpp sono i bitsperpixel

flags (si compongono sempre tramite operatore OR)

  • SDL::SWSURFACE crea la Surface nella Memoria di Sistema, da evitare come la peste (è per i pc senza scheda video)
  • SDL::HWSURFACE crea la Surface nella Memoria Video (ovvero accellerazione hardware!)
  • SDL::FULLSCREEN abilita il fullscreen
  • SDL::SDL_DOUBLEBUF abilita il doppio buffer (RULES!)

La funzione restituisce l'istanza della SDL::Surface associata alla Finestra

 

ho creato anche delle variabili (che potete benissimo inglobare in una classe) per semplificare il tutto:

width = 640
height = 480
bpp = 32
schermo = SDL.setVideoMode(width,height,bpp,SDL::HWSURFACE|SDL::DOUBLEBUF)

 

nota: il signore tra SDL::HWSURFACE e SDL::DOUBLEBUF è l'operatore OR e si ottiene con la combinazione di tasti SHIFT + \ (quella a sx dell'1)

 

abbiamo creato la nostra finestra e dobbiamo porre particolare attenzione a schermo visto che come ho nerettizzato prima vedremo solo quello che disegneremo dentro questa SDL::Surface!! (ennesima volta che lo scrivo)

 

Modifichiamo qualche parametro estetico così prendete familiarità con le classi

#SDL::WM.Caption stringa1, stringa2

Imposta il titolo della finestra a stringa1 e il titolo nella icon bar a stringa2

Il # indica il commento, lo metto in modo che un eventuale neofita non mi chieda perché non funziona perché ruby non trova stringa1

SDL::WM.Caption "Hello World!", "Hello World!"

e nascondiamo il mouse

SDL::Mouse.hide

 

Ora arriva un passo importante ed un concetto difficile:

 

Controllo degli eventi

La programmazione delle SDL è fatta ad eventi, che significa?

La pressione di un tasto genera un evento, il rilascio di un tasto un altro evento, la chiusura della finestra, il movimento del mouse, la pressione ed il rilascio dei tasti del mouse, altri eventi, una caterva di eventi sul joystick e TANTI ALTRI.

Che cosa deve fare la nostra applicazione o gioco?

Reagire agli eventi, magari :)

Come reagire lo decidiamo noi (se preme la freccetta si muove in basso o se premo esc esco dal gioco), ma per reagire bisogna accorgercene!

E come ce ne accorgiamo con le SDL/Ruby?

Ci sono diversi metodi, per ora ho provato solo il metodo classico (e presente nella controparte C) mentre esiste un metodo ancora più semplice (ma che non ho voglia di vedere come funzioni, per gli interessati nella Ruby/SDL reference la classe è la SDL::Event2)

Metodo classico: Uso di SDL::Event

Praticamente creiamo questo evento generico che sarà da ricettacolo a tutti gli eventi che si manifestano e che estrarremo, uno alla volta, con il metodo poll, una volta estratto vediamo che tipo di evento si tratta e agiamo di conseguenza

 

Ma non basta!

Vogliamo che il gioco continui ad andare fino a quando lo vogliamo noi, quindi ci serve prima di tutto un ciclo quasi infinito, che io abitualmente creo con

fine = 0

while (fine == 0)
#controllo gli eventi
#aggiorno il mondo (le variabili)
#disegno tutto
#flippo il backbuffer
end

 

Come vedete metterò tutto il mio programma dentro al while

 

Per uscire basterà porre fine = 1 o brutalmente un break e grazie a Dio (per ora) non serve altro dopo il while per deinizializzare la libreria perché il porting Ruby si deinizializza da solo!

 

 

Torniamo ad i nostri eventi, questa volta analizziamo in pseudocodice

-Finché poll mi restituisce un evento

-controllo l'evento, se è tizio faccio questo, se è caio faccio quest'altro

 

Passiamo al codice, vi avverto, per i neofiti (e per me lo è stato) può essere abbastanza spaventoso, il while dentro il while (DEN DEN DEN!)

evento = SDL::Event.new #creo l'istanza prima dei while!

while (fine == 0) #già inserito
#controllo gli eventi
while (evento.poll != 0)
	if (evento.type == SDL::Event::QUIT) then
		fine = 1
		break
	end
	if (evento.type == SDL::Event::KEYDOWN) then
		if (evento.keySym == SDL::Key::Escape) then
			fine = 1
			break
		end		
	end
end
 
#aggiorno il mondo (le variabili)
#disegno tutto
#flippo il backbuffer
end

 

>>>Riprendo la trattazione

 

Come avete visto il metodo type restituisce il tipo di evento che la nostra applicazione ha INTERCETTATO

Tipi di Evento

  • SDL::Event::ACTIVEEVENT non trovo documentazione in ruby, in c è quando il mouse entra/esce nella finestra dell'applicazione o quando l'applicazione è minimizzata (penso che da minimizzata continui ad andare, se volete frozzare il gioco mettete un flag dopo aver ricevuto questo evento e controllato sia in state == SDL::APPACTIVE, gain = 0 se minimizzata, gain = 1 se ripristinata)
  • SDL::Event::KEYDOWN un qualsiasi tasto premuto
  • SDL::Event::KEYUP un qualsiasi tasto rilasciato
  • SDL::Event::MOUSEMOTION movimento del mouse
  • SDL::Event::MOUSEBUTTONDOWN pressione di un tasto del mouse
  • SDL::Event::MOUSEBUTTONUP rilascio di un tasto del mouse
  • SDL::Event::JOYAXISMOTION movimento di un asse del joystick
  • SDL::Event::JOYBALLMOTION movimento di palla XD del joystick
  • SDL::Event::JOYHATMOTION movimento dell'hat del joystick (non ho idea di cosa sia ;D)
  • SDL::Event::JOYBUTTONDOWN pressione bottone joystick
  • SDL::Event::JOYBUTTONUP rilascio bottone joystick
  • SDL::Event::QUIT quando si preme alt+f4 o si clicca sulla croce in alto a destra
  • SDL::Event::SYSWMEVENT dipende dal windows manager del sistema (ovvero intercetti chiamate a eventi aggiuntivi, sapete che tutti i wm funzionano a eventi?) (è il modo per implementare il copia incolla, ad esempio), se volete una applicazione crossplatform e non sapete come individuare il sistema di riferimento, ignoratelo
  • SDL::Event::VIDEORESIZE se ridimensionano la tua finestra, ma puoi ottenere questo evento solo se metti in setVideoMode la flag SDL::RESIZABLE (e perché in un gioco dovremmo farlo? anzi non ho messo il fullscreen per non essere invadente, lo lascio restringere per distruggermi tutte le proporzioni :D? avrebbe senso soltanto se l'applicazione fosse 3d :) )

Come vedete gli eventi di pressione e rilascio sono generici e dobbiamo vedere con altri metodi che tipo di tasto/bottone è stato premuto, per quanto riguarda la tastiera si fa con il metodo keySym che restituisce il codice corrispondente al tasto premuto (per una lista di tasti guardate la reference ;) )

Il ruby per quanto riguarda gli eventi è ridondante perché permette diverse vie per controllare l'input, che vedremo nel prossimo tutorial/esempio ;)

Come vedete nel codice sopra non ho fatto che dire: se tentano di chiudere la finestra o se premono esc, chiuditi

 

Andiamo avanti, per ora non abbiamo nessuna istanza che si muove o viene aggiornata quindi la parte di aggiorno il mondo la ignoriamo, altrimenti cosa ci andrebbe?

Qui non esistono variabili predefinite per la velocità degli oggetti, ogni deltat dovete sommarla voi (e qui si entra in un discorso complicato, l'esecuzione non va alla stessa velocità su tutti i computer, un pentium 2 con scheda video cacca magari impiega 1 secondo per girare il while mentre un computer decente di 5 anni fa con scheda video carina ce ne impiega 0.05) quindi quando ci toccherà muovere un evento prima dovremo calcolare il tempo intercorso tra un while ed un altro e poi incrementare le variabili controllate in proporzione al tempo (ma questa è un'altra storia)

 

Siamo finalmente arrivati alla fine, disegnamo sullo schermo!

In teoria qui dovremmo gestire tutte le Surface e riversarle (copiarle) come vogliamo sullo schermo (immagini che fungono da sprite, background ecc...) ma visto che non ne abbiamo possiamo disegnare direttamente sullo schermo!

Piuttosto che disegnare qualche funzione malata pixel per pixel preferisco che usiate i molteplici metodi offerti dalle SGE (una parte di Ruby/SDL) (che trovate nella reference nella sezione SDL::Surface)

#qualche mio disegnino a caso, volevo fare una faccina
schermo.fillRect 0,0,640,480,0xF0F6FA
schermo.fillRect 50,50,50,50,0xCACCAA #questo colore mi fa morire XD
schermo.drawRect 540,50,50,100,0x215571 #per creare un rettangolo più spesso
schermo.drawRect 541,51,48,98,0x215571 #ne disegno due uno dentro l'altro
schermo.drawLine 340,100,300,200,0xFF0000
schermo.drawLine 300,200,330,220,0xFF0000
schermo.drawLine 300,200,330,201,0xFF0000
schermo.drawLine 330,220,330,201,0xFF0000
schermo.drawCircle 250,150,40,0x0
schermo.drawFilledCircle 400,150,30,0x000090
schermo.drawFilledCircle 400,150,10,0x0

(spiego sotto questa sezione)

bisogna poi aggiungere il flip del backbuffer, che cos'è il backbuffer? praticamente piuttosto che scrivere direttamente in faccia al monitor, al monitor sono associate due Surface, una davanti e una dietro. Noi possiamo disegnare e fare quello che ci pare su quella dietro (sul di dietro :Q_) mentre l'utente continuerà a vedere quella avanti, dopo che abbiamo finito di disegnare possiamo versare la faccia di dietro su quella davanti tramite questo semplice comando!

#fine
schermo.flip
end #già scritto, è quello del while (fine == 0) !!!!!

 

Così siamo arrivati alla fine, provate il gioco con ruby hello.rb e vedrete gli scarabocchi che facevo stanotte (belli no?)

adesso indaghiamo su quel mucchio di funzioni grafiche e intellegibili che ho usato

Metodi di SDL::Surface

  • fillRect x,y,width,height,colore crea un rettangolo pieno colorato di dimensioni widthxheight in (x,y)
  • drawRect x,y,width,height,colore crea un rettangolo vuoto ma come sopra
  • drawLine x0,y0,x1,y1,colore disegna una linea
  • drawCircle x,y,raggio,colore disegna una circonferenza
  • drawFilledCircle x,y,raggio,colore disegna un cerchio

Tutte molto isy e sul manuale ne trovate altre ;D

 

Allego il file hello.rb per chi si fosse perso

 

require 'sdl'

SDL.init( SDL::INIT_VIDEO)

width = 640
height = 480
bpp = 32
fine = 0

schermo = SDL.setVideoMode(width,height,bpp,SDL::HWSURFACE|SDL::DOUBLEBUF)

SDL::WM.setCaption "Hello World!","Hello World!"
SDL::Mouse.hide

evento = SDL::Event.new()

while (fine == 0)
while (evento.poll != 0)
	if (evento.type == SDL::Event::QUIT) then
		fine = 1
		break
	end
	if (evento.type == SDL::Event::KEYDOWN) then
		if (evento.keySym == SDL::Key::Escape) then
			fine = 1
			break
		end		
	end
end
schermo.fillRect 0,0,640,480,0xF0F6FA
schermo.fillRect 50,50,50,50,0xCACCAA
schermo.drawRect 540,50,50,100,0x215571
schermo.drawRect 541,51,48,98,0x215571
schermo.drawLine 340,100,300,200,0xFF0000
schermo.drawLine 300,200,330,220,0xFF0000
schermo.drawLine 300,200,330,201,0xFF0000
schermo.drawLine 330,220,330,201,0xFF0000
schermo.drawCircle 250,150,40,0x0
schermo.drawFilledCircle 400,150,30,0x000090
schermo.drawFilledCircle 400,150,10,0x0
schermo.flip
end

 

 

fatemi sapere che ne pensate per domande/approfondimenti

 

nel prossimo tutorial creeremo una istanza che si muoverà con le freccette :)

Edited by Keroro

I Miei Script:
Salva Schermata (3 Aprile 2012)
Attacco Personalizzabile (2 Aprile 2012)
Keyboard Input (Porting) (17 Marzo 2012)
Continua...

Link to comment
Share on other sites

Tempo fai provai a programmare con le tk però lasciai subito perdere perchè erano obbrobriose, le sdl sembrano davvero belle toste, casomai provo a fare qualcosina anche io dopo gli esame :Ok:

Cmq sei il solito malato xD

TPC Radio Site | Blog | Big-Bug

http://img102.imageshack.us/img102/4332/slackware2userbarok0.gif

http://img141.imageshack.us/img141/1571/nokappams1cf8.png

 

http://i29.tinypic.com/2vijdlh.jpg

Link to comment
Share on other sites

mmm tutto ciò mi ispira, ora provo a fare esperimenti °_°

Progetti:

 http://i.imgur.com/jmLkIqi.png

http://i54.tinypic.com/2rh4ojq.png

https://github.com/ProGM

 

Crea anche tu il tuo gioco per Game Boy!
http://rpg2s.net/gif/SCContest3Oct.gifhttp://www.rpg2s.net/img/fablecontest1st.pnghttp://i43.tinypic.com/1zokd2s.png


http://i.imgur.com/BEu6G.gif

http://i.imgur.com/H1ARhq7.gif

http://i.imgur.com/Af6ijZN.gif

AOT: Associazione Odiamo la Telecom:

http://i.imgur.com/aYJs89E.png

"4 gattini... 4 stelline... E le 4 paperelle non ci stavano :3"

Flame


http://i30.tinypic.com/i27ypj.png

Link to comment
Share on other sites

hanno letto in tanti ma risposto solo in 2 :(

per quelli che hanno letto e vogliono fare prove potete giocare con hello.rb modificando le figure da disegnare sopra lo schermo :S.

non so se fare un ulteriore tutorial sull'argomento quindi ditemi voi (anche via mp, msn o quello che volete) se lo volete :)

I Miei Script:
Salva Schermata (3 Aprile 2012)
Attacco Personalizzabile (2 Aprile 2012)
Keyboard Input (Porting) (17 Marzo 2012)
Continua...

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...