Marco Tarini
Part Part Part
Part 2: 2: 2: 2: programming
GAME DEV - Uni Verona:
tools programming
Tools to program a tool:
1. Tools for GUI GUI GUI programming GUI 2. Graphics API API API API (openGL, directX) 3. Interfacing with OS OS OS (operative syst.) OS
– windows (or fullscreen) – mouse, keyboard, joystick…
– timers – events – double buffering
– …
4. Dev environment (IDE IDE IDE) IDE 5. libs for data structures
– like vectors lists hashes heaps….
6. libs for
– immages
– geometry …
QT fa anche
• strutture dati base + algoritmi (module: qtCore)
– qVector, qSet, qList, qString, … <== simile a
STLSTLSTLSTL, 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
M a r c o T a r i n i ‧ G A M E D E V ‧ 2 0 1 4 ‧ V e r o n a
Program structure with Event Event----Based Event Event Based Based Based paradigm
• Event based system
main() {
init();
while (true) { get_event() ; process_event();
}
} eventi tipo:
• mouse, tastiera...
• sistema di finistre
• reshape, minimizzazione...
• generati dall'applicazione stessa
• o da thread differenti
{
main event
loop
Esempio: applicazione con lib SDL SDL SDL SDL
int main() {
SDL_Init(SDL_INIT_VIDEO);
SDL_SetVideoMode(640, 480, 0, SDL_OPENGL);
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;
}
M a r c o T a r i n i ‧ G A M E D E V ‧ 2 0 1 4 ‧ V e r o n a
c i c l o d e g l i e v e n t i
Programmare un Event-Based con CallBack
• CallBack CallBack CallBack CallBack:
– funzione preposta alla gestione di un evento evento evento evento – in (free)glut,
un funtore da registrare per ogni evento
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 1 / 1 2 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
void myRendering() // la mia callback per l’evento “disegnati”
{ ...
}
void main(){
glutDisplayFunc ( myRendering ); // registra la callback ...
glutMainLoop();
}
Programmare un Event-Based con CallBack
M a r c o T a r i n i ‧ G A M E D E V ‧ 2 0 1 4 ‧ V e r o n a
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 1 / 1 2 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
int main(int argc, char** argv) { glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutCreateWindow("A test");
glutDisplayFunc( mia_display_callback );
glutMainLoop();
return 0;
}
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 }
Programmare un Event-Based con CallBack
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 1 / 1 2 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
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 );
glutMainLoop();
return 0;
}
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?
}
Programmare un Event-Based con CallBack
M a r c o T a r i n i ‧ G A M E D E V ‧ 2 0 1 4 ‧ V e r o n a
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 1 / 1 2 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
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 );
glutMainLoop();
return 0;
}
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?
}
Programmare un Event-Based con CallBack
M a r c o T a r i n i ‧ C o m p u t e r G r a p h i c s ‧ 2 0 1 1 / 1 2 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
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 );
glutMainLoop();
return 0;
}
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?
}
Parentesi: Double buffering
• Piccolo trucco utile nelle applicazioni interattive
– nascondere il frame buffer mentre viene riempito – evita “flickering” (“sfarfallio”)
M a r c o T a r i n i ‧ G A M E D E V ‧ 2 0 1 4 ‧ V e r o n a
fra m m en ti (c an di da ti pi xe ls ) frame buffer A
[ pronto ]
Ve rti ci pr oi et ta ti (p un ti in R
2)
rasterizer triangoli
co m pu ta zi on i pe r f ra m m en to set- up
rasterizer segmenti set- up
rasterizer punti set- up
frame buffer B
[ in costruzione ]
video al
A
Parentesi: Double buffering
• Piccolo trucco utile nelle applicazioni interattive
– nascondere il frame buffer mentre viene riempito – evita “flickering” (“sfarfallio”)
fra m m en ti (c an di da ti pi xe ls ) frame buffer A
[ in costruzione ]
Ve rti ci pr oi et ta ti (p un ti in R
2)
rasterizer triangoli
co m pu ta zi on i pe r f ra m m en to set- up
rasterizer segmenti set- up
rasterizer punti set- up
frame buffer B
[ pronto ]
video al
B
Programmare un Event-Based con SIGNALS SIGNALS SIGNALS SIGNALS e SLOTS SLOTS SLOTS SLOTS
M a r c o T a r i n i ‧ G A M E D E V ‧ 2 0 1 4 ‧ V e r o n a
Object2 signal1
slot1 slot2 Object4
slot1 slot2 slot3 Object1
signal1 signal2
Object3 signal1
slot1
connect(Object1, signal1, Object2, slot1) connect(Object1, signal1, Object2, slot2)
connect (
Object1, signal2, Object4, slot1 )
connect(Object3, signal1, Object4, 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!
};
{
A *a = new A();
B *b = new B();
connect( b, SIGNAL( unTrigger()
) , a, SLOT( unMetodo() ) );
quando a “emette” quel segnale
==>
b deve eseguire quel metodo
(da B: ) emit unTrigger( );
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!
};
{
A *a = new A();
B *b = new B();
connect( b, SIGNAL( unTrigger( int ) ) , a, SLOT( unMetodo( int ) ) );
}
M a r c o T a r i n i ‧ G A M E D E V ‧ 2 0 1 4 ‧ V e r o n a
quando a “emette” quel segnale
==>
b deve eseguire quel metodo (da B: ) emit unTrigger(5);
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();
}
QT classes
M a r c o T a r i n i ‧ G A M E D E V ‧ 2 0 1 4 ‧ V e r o n a