GAME DEV: tools programming Parte 2: programming Marco Tarini Tools per programmare un tool: 1. Tools per GUI programming 2. API grafiche (opengl, directx) 3. Interfacciamento con SO (sist. op.) finestre (o fullscreen) mouse, keyboard, joystick timers eventi double buffering 4. Ambiente di sviluppo (IDE IDE) 5. libs per strutture dati come liste vettori alberi 6. libs per immagini geometria 1
QT fa anche strutture dati base + algoritmi (module: qtcore) qvector, qset, qlist, qstring, <== simile a STL, ma meno completo multi-threading (module: qtcore) networking (module: qtnetworking) TCP, UDP video e audio (module: qtphonon) formati file (mp3, mpeg) XML (e html) (module: qtxml) databases (module: qtsql) portable devices x Symbian: simulazione, OpenGL ES tools di supporto sviluppo: style sheets for GUI (QML) traduzioni (QT Linguist) version control (sia SVN che Hg-Mercury) GUIs: WYSIWYG editor in QT-creator Struttura programma nel paradigma Event-Based Sistema a eventi main() init(); while (true) ciclo get_event() ; degli process_event(); eventi eventi tipo: mouse, tastiera... sistema di finistre reshape, minimizzazione... generati dall'applicazione stessa o da thread differenti 2
Esempio: applicazione con lib SDL int main() SDL_Init(SDL_INIT_VIDEO); SDL_SetVideoMode(640, 480, 0, SDL_OPENGL); ciclo degli eventi bool done = false; while (! done ) /* ciclo degli eventi */ SDL_Event event; SDL_WaitEvent(&event); switch(event.type) case SDL_VIDEOEXPOSE: /* evento "ridisegnati" */ myrendering(); /* riempi screen buffer*/ break; case SDL_QUIT: done = true; break ; case SDL_KEYDOWN: if ( event.key.keysym.sym == SDLK_ESCAPE ) done = true; break; SDL_Quit(); return 1; Programmare un Event-Based con CallBack CallBack: funzione preposta alla gestione di un evento in (free)glut, un funtore da registrare per ogni evento void myrendering() // la mia callback per l evento disegnati... void main() glutdisplayfunc ( myrendering ); // registra la callback... 3
Programmare un Event-Based con CallBack void mia_display_callback() glclearcolor( 0,0,0,0); glclear( GL_COLOR_BUFFER_BIT ); glbegin(gl_triangles); glvertex2d(-1,-1); glvertex2d(0,1); glvertex2d(1,0); glend(); glutswapbuffers(); // x double buffering int main(int argc, char** argv) glutinit(&argc, argv); glutinitdisplaymode(glut_rgb GLUT_DOUBLE); glutcreatewindow("a test"); glutdisplayfunc( mia_display_callback ); return 0; Programmare un Event-Based con CallBack void mia_reshape_callback( int size_x, int size_y) // la finestra e cambiata // (ora e grande size_x X size_ypixel //... che voglio fare? int main(int argc, char** argv) glutinit(&argc, argv); glutinitdisplaymode(glut_rgb GLUT_DOUBLE); glutcreatewindow("a test"); glutdisplayfunc( mia_display_callback ); glutreshapefunc( mia_reshape_callback ); return 0; 4
Programmare un Event-Based con CallBack void mia_keyboard_callback( char c, int x, int y) // l utente ha premuto il tasto c // (mentre il pointer era in pos x,y (viewport coords) //... che voglio fare? int main(int argc, char** argv) glutinit(&argc, argv); glutinitdisplaymode(glut_rgb GLUT_DOUBLE); glutcreatewindow("a test"); glutdisplayfunc( mia_display_callback ); glutreshapefunc( mia_reshape_callback ); glutkeyboardfunc( mia_keyboard_callback ); return 0; Programmare un Event-Based con CallBack void mia_keyboard_callback( char c, int x, int y) // l utente ha premuto il tasto c // (mentre il pointer era in pos x,y (viewport coords) //... che voglio fare? int main(int argc, char** argv) glutinit(&argc, argv); glutinitdisplaymode(glut_rgb GLUT_DOUBLE); glutcreatewindow("a test"); glutdisplayfunc( mia_display_callback ); glutreshapefunc( mia_reshape_callback ); glutkeyboardfunc( mia_keyboard_callback ); return 0; 5
Parentesi: Double buffering Piccolo trucco utile nelle applicazioni interattive nascondere il frame buffer mentre viene riempito evita flickering ( sfarfallio ) Vertici proiettati (punti in R 2 ) punti triangoli segmenti frammenti (candidati pixels) computazioni per frammento frame buffer A [ pronto ] frame buffer B [ in costruzione ] al video A Parentesi: Double buffering Piccolo trucco utile nelle applicazioni interattive nascondere il frame buffer mentre viene riempito evita flickering ( sfarfallio ) Vertici proiettati (punti in R 2 ) punti triangoli segmenti frammenti (candidati pixels) computazioni per frammento frame buffer A [ in costruzione ] frame buffer B [ pronto ] al video B 6
Programmare un Event-Based con SIGNALS e SLOTS Object1 signal1 signal2 connect(object1, signal1, Object2, slot1) connect(object1, signal1, Object2, slot2) Object2 signal1 Object3 signal1 slot1 connect ( Object1, signal2, Object4, slot1 ) Object4 slot1 slot2 connect(object3, signal1, Object4, slot3) slot1 slot2 slot3 QT: slots, signals, e connect class A : public class QObject Q_OBJECT public: A(); // costruttore protected:...; public slots: void unmetodo( ); // uno slot! ; class B : public class QObject Q_OBJECT signals: void untrigger( ); // un signal! ; quando a emette quel segnale ==> b deve eseguire quel metodo (da B: emit untrigger( ); ) A *a = new A(); B *b = new B(); connect( b, SIGNAL( untrigger() ), a, SLOT( unmetodo() ) ); 7
QT: slots, signals, e connect class A : public class QObject Q_OBJECT public: A(); // costruttore protected:...; public slots: void unmetodo( int ); // uno slot! ; class B : public class QObject Q_OBJECT signals: void untrigger( int ); // un signal! ; quando a emette quel segnale ==> b deve eseguire quel metodo (da B: emit untrigger(5); ) A *a = new A(); B *b = new B(); connect( b, SIGNAL( untrigger( int ) ), a, SLOT( unmetodo( int ) ) ); QT: un hello-world #include <QApplication> class MiaMainWindow:public QWidget public: MiaMainWindow ():QWidget(0) setwindowtitle( Hello World"); ; int main(int argc, char** argv) QApplication app(argc, argv); MiaMainWindow win; win.show(); return app.exec(); 8
QT classes signals & slots QObject QWidget QSlider QWindow QButton Stringhe in QT #include <QString> void Pippo() Persona pers; QString a a = QString( La persona %1 ha %2 anni (%3 - %4 = %2) ).arg( pers.nome ) // argomento 1 (un char*).arg( pers.eta() ) // argomento 2 (un int).arg( pers.annonascita ) // argomento 3 (un int).arg( ANNO_CORRENTE ) // argomento 4 (un unsigned int) ; La persona Mario ha 22 anni (2012-1990 = 22) 9