Last active
December 14, 2015 05:29
-
-
Save v42/5035413 to your computer and use it in GitHub Desktop.
An old game I made in 2010 when I was learning OpenGL at college, just intending to save it here.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <c:/dev-cpp/include/gl/glut.h> | |
#include <math.h> | |
#include <stdio.h> | |
#include <string.h> | |
#define VALOR_PI 3.14159265; | |
// estrutura que descreve um ponto (x,y) | |
typedef struct ponto { | |
GLfloat x, y; | |
}p; | |
p tr; | |
typedef struct quad { | |
ponto p1, p2, p3, p4; | |
}q; | |
q carro, vf, vt, tr1, tr2, tr3, tr4, tr5, tr6, tr7, tr8, tr9, tr10; | |
q aq1, aq2, aq3, aq4, tp; | |
typedef struct curva{ | |
ponto v; | |
int tipo; //1, 2, 3, 4 indicando cantos, sentido anti-horário | |
}f; | |
f cr1, cr2, cr3, cr4, cr5, cr6, cr7, cr8, cr9, cr10; | |
typedef struct bbox{ | |
quad q; | |
int tipo; //0 = pista antiga / 1 = pista / 2 = chegada / 3 = arquibancada | |
bool c; //colisão | |
}bb; | |
bb bb1, bb2, bb3, bb4, bb5, bb6, bb7, bb8, bb9, bb10, bb11, bb12, bb13, bb14, bb15, bb16, bb17, bb18, bb19, bb20, bb_chegada; | |
bb ba1, ba2, ba3, ba4; | |
float zoom = 1, velocidade = 0 , angulo = 90, valor_pi = 3.14159265, escala = 0.5, tempo_voltas[10], volta_mais_rapida, volta_recorde, vel_maxima = 10; | |
//DEBUGS: 0 = off / 1 = velocidade / 2 = colisão / 3 = volta completa | |
//ESTADOS: 0 - tela inicial / 1 = menu / 2 - semáforo / 3 - jogando / 4 - pausado / 5 - game over | |
int giro = 200, debug = 0, max_debug = 3, voltas = 0, total_voltas = 3, estado = 0, vm = 0, vd = 0, az = 0, cor_selecionada = 0, logo1 = 0, logo2 = 0, logo3 = 0, cont_semaforo = 0; | |
bool esq, dir, cima, baixo, voltacompleta, tranca_teclas, baixo_aux, cima_aux; | |
quad getBox(curva c){ | |
q ret; | |
ret.p1 = c.v; | |
switch(c.tipo){ | |
case 1: | |
ret.p2.x = c.v.x + 100; ret.p2.y = c.v.y; | |
ret.p3.x = c.v.x + 100; ret.p3.y = c.v.y + 100; | |
ret.p4.x = c.v.x; ret.p4.y = c.v.y + 100; | |
break; | |
case 2: | |
ret.p2.x = c.v.x - 100; ret.p2.y = c.v.y; | |
ret.p3.x = c.v.x - 100; ret.p3.y = c.v.y + 100; | |
ret.p4.x = c.v.x; ret.p4.y = c.v.y + 100; | |
break; | |
case 3: | |
ret.p2.x = c.v.x - 100; ret.p2.y = c.v.y; | |
ret.p3.x = c.v.x - 100; ret.p3.y = c.v.y - 100; | |
ret.p4.x = c.v.x; ret.p4.y = c.v.y - 100; | |
break; | |
case 4: | |
ret.p2.x = c.v.x + 100; ret.p2.y = c.v.y; | |
ret.p3.x = c.v.x + 100; ret.p3.y = c.v.y - 100; | |
ret.p4.x = c.v.x; ret.p4.y = c.v.y - 100; | |
break; | |
} | |
return ret; | |
} | |
void desenha_carro(void){ | |
//****** CARRO ********* | |
//lataria | |
carro.p1.x = -40*escala; carro.p1.y = -20*escala; | |
carro.p2.x = 40*escala; carro.p2.y = -20*escala; | |
carro.p3.x = 40*escala; carro.p3.y = 20*escala; | |
carro.p4.x = -40*escala; carro.p4.y = 20*escala; | |
//vidro traseiro | |
vt.p1.x = -20*escala; vt.p1.y = -15*escala; | |
vt.p2.x = -10*escala; vt.p2.y = -10*escala; | |
vt.p3.x = -10*escala; vt.p3.y = 10*escala; | |
vt.p4.x = -20*escala; vt.p4.y = 15*escala; | |
//vidro frontal | |
vf.p1.x = 10*escala; vf.p1.y = 16*escala; | |
vf.p2.x = 15*escala; vf.p2.y = 16*escala; | |
vf.p3.x = 15*escala; vf.p3.y = -16*escala; | |
vf.p4.x = 10*escala; vf.p4.y = -16*escala; | |
} | |
// Inicializa cor de fundo da janela e o valor inicial dos pontos | |
void Inicio(void) { | |
glEnable(GL_LINE_SMOOTH); | |
glClearColor(0.35, 0.9, 0.25, 0); | |
//****** INÍCIO ******** | |
tr.x = 220; tr.y = 520; | |
desenha_carro(); | |
//****** PISTA ******** | |
//reta 1 | |
tr1.p1.x = 110; tr1.p1.y = 490; tr1.p2.x = 690; tr1.p2.y = 490; | |
tr1.p3.x = 690; tr1.p3.y = 590; tr1.p4.x = 110; tr1.p4.y = 590; | |
//curva 1 | |
cr1.v.x = 690; cr1.v.y = 490; cr1.tipo = 1; | |
//reta 2 | |
tr2.p1.x = 690; tr2.p1.y = 490; tr2.p2.x = 790; tr2.p2.y = 490; | |
tr2.p3.x = 790; tr2.p3.y = 450; tr2.p4.x = 690; tr2.p4.y = 450; | |
//curva 2 | |
cr2.v.x = 690; cr2.v.y = 450; cr2.tipo = 4; | |
//reta 3 | |
tr3.p1.x = 690; tr3.p1.y = 450; tr3.p2.x = 690; tr3.p2.y = 350; | |
tr3.p3.x = 550; tr3.p3.y = 350; tr3.p4.x = 550; tr3.p4.y = 450; | |
//curva 3 | |
cr3.v.x = 550; cr3.v.y = 350; cr3.tipo = 2; | |
//reta 4 | |
tr4.p1.x = 450; tr4.p1.y = 350; tr4.p2.x = 550; tr4.p2.y = 350; | |
tr4.p3.x = 550; tr4.p3.y = 320; tr4.p4.x = 450; tr4.p4.y = 320; | |
//curva 4 | |
cr4.v.x = 550; cr4.v.y = 320; cr4.tipo = 3; | |
//reta 5 | |
tr5.p1.x = 690; tr5.p1.y = 320; tr5.p2.x = 690; tr5.p2.y = 220; | |
tr5.p3.x = 550; tr5.p3.y = 220; tr5.p4.x = 550; tr5.p4.y = 320; | |
//curva 5 | |
cr5.v.x = 690; cr5.v.y = 220; cr5.tipo = 1; | |
//reta 6 | |
tr6.p1.x = 690; tr6.p1.y = 220; tr6.p2.x = 790; tr6.p2.y = 220; | |
tr6.p3.x = 790; tr6.p3.y = 110; tr6.p4.x = 690; tr6.p4.y = 110; | |
//curva 6 | |
cr6.v.x = 690; cr6.v.y = 110; cr6.tipo = 4; | |
//reta 7 | |
tr7.p1.x = 690; tr7.p1.y = 110; tr7.p2.x = 690; tr7.p2.y = 10; | |
tr7.p3.x = 300; tr7.p3.y = 10; tr7.p4.x = 300; tr7.p4.y = 110; | |
//curva 7 | |
cr7.v.x = 300; cr7.v.y = 110; cr7.tipo = 3; | |
//reta 8 | |
tr8.p1.x = 300; tr8.p1.y = 220; tr8.p2.x = 200; tr8.p2.y = 220; | |
tr8.p3.x = 200; tr8.p3.y = 110; tr8.p4.x = 300; tr8.p4.y = 110; | |
//curva 8 | |
cr8.v.x = 200; cr8.v.y = 220; cr8.tipo = 1; | |
//reta 9 | |
tr9.p1.x = 200; tr9.p1.y = 220; tr9.p2.x = 200; tr9.p2.y = 320; | |
tr9.p3.x = 110; tr9.p3.y = 320; tr9.p4.x = 110; tr9.p4.y = 220; | |
//curva 9 | |
cr9.v.x = 110; cr9.v.y = 320; cr9.tipo = 3; | |
//reta 10 | |
tr10.p1.x = 110; tr10.p1.y = 320; tr10.p2.x = 10; tr10.p2.y = 320; | |
tr10.p3.x = 10; tr10.p3.y = 490; tr10.p4.x = 110; tr10.p4.y = 490; | |
//curva 10 | |
cr10.v.x = 110; cr10.v.y = 490; cr10.tipo = 2; | |
//****** Arquibancadas ******** | |
aq1.p1.x = -50; aq1.p1.y = -50; aq1.p2.x = -50; aq1.p2.y = -100; | |
aq1.p3.x = 850; aq1.p3.y = -100; aq1.p4.x = 850; aq1.p4.y = -50; | |
aq2.p1.x = -50; aq2.p1.y = 700; aq2.p2.x = -50; aq2.p2.y = 650; | |
aq2.p3.x = 850; aq2.p3.y = 650; aq2.p4.x = 850; aq2.p4.y = 700; | |
aq3.p1.x = -50; aq3.p1.y = -50; aq3.p2.x = -50; aq3.p2.y = 650; | |
aq3.p3.x = -100; aq3.p3.y = 650; aq3.p4.x = -100; aq3.p4.y = -50; | |
aq4.p1.x = 850; aq4.p1.y = -50; aq4.p2.x = 850; aq4.p2.y = 650; | |
aq4.p3.x = 900; aq4.p3.y = 650; aq4.p4.x = 900; aq4.p4.y = -50; | |
//****** Bounding Boxes ********* | |
bb1.q = tr1; bb2.q = tr2; bb3.q = tr3; bb4.q = tr4; bb5.q = tr5; bb6.q = tr6; bb7.q = tr7; bb8.q = tr8; bb9.q = tr9; bb10.q = tr10; | |
ba1.q = aq1; ba2.q = aq2; ba3.q = aq3; ba4.q = aq4; | |
ba1.tipo = 3; ba2.tipo = 3; ba3.tipo = 3; ba4.tipo = 3; | |
bb11.q = getBox(cr1); bb12.q = getBox(cr2); bb13.q = getBox(cr3); bb14.q = getBox(cr4); bb15.q = getBox(cr5); | |
bb16.q = getBox(cr6); bb17.q = getBox(cr7); bb18.q = getBox(cr8); bb19.q = getBox(cr9); bb20.q = getBox(cr10); | |
bb_chegada.q.p1.x = 255; bb_chegada.q.p1.y = 490; | |
bb_chegada.q.p2.x = 275; bb_chegada.q.p2.y = 490; | |
bb_chegada.q.p3.x = 275; bb_chegada.q.p3.y = 590; | |
bb_chegada.q.p4.x = 255; bb_chegada.q.p4.y = 590; | |
bb_chegada.tipo = 2; | |
//tela preta | |
tp.p1.x = -400; tp.p1.y = -300; | |
tp.p2.x = 400; tp.p2.y = -300; | |
tp.p3.x = 400; tp.p3.y = 300; | |
tp.p4.x = -400; tp.p4.y = 300; | |
} | |
void Rotacao(float ang, quad &qu){ | |
float auxx, auxy; | |
auxx = qu.p1.x*cos(ang) - qu.p1.y*sin(ang); | |
auxy = qu.p1.x*sin(ang) + qu.p1.y*cos(ang); | |
qu.p1.x = auxx; | |
qu.p1.y = auxy; | |
auxx = qu.p2.x*cos(ang) - qu.p2.y*sin(ang); | |
auxy = qu.p2.x*sin(ang) + qu.p2.y*cos(ang); | |
qu.p2.x = auxx; | |
qu.p2.y = auxy; | |
auxx = qu.p3.x*cos(ang) - qu.p3.y*sin(ang); | |
auxy = qu.p3.x*sin(ang) + qu.p3.y*cos(ang); | |
qu.p3.x = auxx; | |
qu.p3.y = auxy; | |
auxx = qu.p4.x*cos(ang) - qu.p4.y*sin(ang); | |
auxy = qu.p4.x*sin(ang) + qu.p4.y*cos(ang); | |
qu.p4.x = auxx; | |
qu.p4.y = auxy; | |
} | |
void CalculaRotacao(char op){ | |
//http://www.convertworld.com/pt/angulo/ | |
//15° = 0.2618 rad | |
//30° = 0.5236 rad | |
float ang = 0; | |
if(op == 'A'){ | |
ang += 0.2618; | |
angulo += 15; | |
} | |
else if(op == 'H'){ | |
ang -= 0.2618; | |
angulo -= 15; | |
} | |
Rotacao(ang, carro); | |
Rotacao(ang, vf); | |
Rotacao(ang, vt); | |
} | |
void reseta_boxes(void){ | |
bb1.c = 0; bb2.c = 0; bb3.c = 0; bb4.c = 0; bb5.c = 0; | |
bb6.c = 0; bb7.c = 0; bb8.c = 0; bb9.c = 0; bb10.c = 0; | |
bb11.c = 0; bb12.c = 0; bb13.c = 0; bb14.c = 0; bb15.c = 0; | |
bb16.c = 0; bb17.c = 0; bb18.c = 0; bb19.c = 0; bb20.c = 0; | |
} | |
void reinicia_jogo(void){ | |
//ESTADOS: 0 - tela inicial / 1 = menu / 2 - semáforo / 3 - jogando / 4 - pausado / 5 - game over | |
tr.x = 220; tr.y = 520; | |
voltas = 0; | |
for(int i=0;i<10;i++) tempo_voltas[i] = 0; | |
volta_mais_rapida = 0; | |
voltacompleta = 0; | |
reseta_boxes(); | |
velocidade = 0; | |
angulo = 90; | |
desenha_carro(); | |
cont_semaforo = estado==5?5:15; | |
estado = 2; | |
} | |
void muda_cor(void){ | |
cor_selecionada++; | |
if(cor_selecionada>3) cor_selecionada = 0; | |
switch(cor_selecionada){ | |
case 0: vm = 0; vd = 0; az = 0; break; | |
case 1: vm = 250; vd = 20; az = 20; break; | |
case 2: vm = 0; vd = 0; az = 150; break; | |
case 3: vm = 255; vd = 255; az = 255; break; | |
} | |
} | |
void TeclasNormais(unsigned char tecla, int x, int y){ | |
//ESTADOS: 0 - tela inicial / 1 = menu / 2 - semáforo / 3 - jogando / 4 - pausado / 5 - game over | |
if(estado == 3){ | |
if((tecla == 'Z' || tecla == 'z') && zoom < 3){zoom += 0.1;} | |
if((tecla == 'X' || tecla == 'x') && zoom > 0.4){zoom -= 0.1;} | |
if(tecla == 'C' || tecla == 'c'){muda_cor();} | |
} | |
if(tecla == 'I' || tecla == 'i'){if(estado==1 || estado == 5) reinicia_jogo();} | |
//if(tecla == 'R' || tecla == 'r'){if(estado>1){reinicia_jogo();} | |
if(tecla == 'B' || tecla == 'b'){ | |
debug = debug==max_debug?0:debug + 1; | |
printf("DEBUG MODE: %i\n", debug); | |
} | |
if(tecla == 'P' || tecla == 'p'){ | |
if(estado==3) estado = 4; | |
else if(estado==4) estado = 3; | |
} | |
if(tecla == 'V' || tecla == 'v'){ | |
//velocidade = 300; | |
//vel_maxima = 300; | |
//escala = 2; | |
tempo_voltas[voltas] +=10; | |
voltacompleta = 1; | |
} | |
//redesenha cena aplicando as mudanças | |
glutPostRedisplay(); | |
} | |
void TeclasEspeciais(int tecla, int x, int y){ | |
//ESTADOS: 0 - tela inicial / 1 = menu / 2 - semáforo / 3 - jogando / 4 - pausado / 5 - game over | |
if(!tranca_teclas){ | |
if(tecla == GLUT_KEY_UP){ | |
cima = 1; | |
baixo_aux = 0; | |
} | |
if(tecla == GLUT_KEY_DOWN){ | |
baixo = 1; | |
cima_aux = 0; | |
} | |
if(estado == 3){ | |
if(tecla == GLUT_KEY_LEFT) esq = 1; | |
if(tecla == GLUT_KEY_RIGHT) dir = 1; | |
} | |
} | |
} | |
void TeclasEspeciaisUp(int tecla, int x, int y){ | |
if(tecla == GLUT_KEY_UP){cima = 0; cima_aux = 0;} | |
if(tecla == GLUT_KEY_DOWN){baixo = 0; baixo_aux = 0;} | |
if(tecla == GLUT_KEY_LEFT) esq = 0; | |
if(tecla == GLUT_KEY_RIGHT) dir = 0; | |
} | |
void SoltaTeclas(int timer){ | |
tranca_teclas = 1; | |
cima = 0; baixo = 0; | |
timer--; | |
if(timer > 0) glutTimerFunc(100, SoltaTeclas, timer); | |
else{tranca_teclas = 0;} | |
} | |
void FuncaoMove(int valor){ | |
//ESTADOS: 0 - tela inicial / 1 = menu / 2 - semáforo / 3 - jogando / 4 - pausado / 5 - game over | |
if(estado==3 || estado==5){ | |
if(estado == 3){ | |
if(cima) velocidade += 0.5; | |
if(baixo) velocidade -= 0.3; | |
} | |
velocidade = velocidade * 0.98; | |
if(estado == 5){ | |
velocidade = velocidade * 0.95; | |
if(velocidade<1) velocidade = 0; | |
} | |
if(velocidade > vel_maxima) velocidade = vel_maxima; | |
if(velocidade < -vel_maxima/2) velocidade = -vel_maxima/2; | |
if(debug == 1) printf("%f || X: %f - Y: %f\n", velocidade, tr.x, tr.y); | |
tr.x += sin((angulo * valor_pi)/180) * velocidade; | |
tr.y += cos((angulo * valor_pi)/180) * -velocidade; | |
if(velocidade > 7 || velocidade <-7) giro = 50; | |
if(velocidade < 7 && velocidade >-7) giro = 100; | |
if(velocidade < 5 && velocidade >-5) giro = 200; | |
if(velocidade < 3 && velocidade >-3) giro = 500; | |
glutPostRedisplay(); | |
} | |
glutTimerFunc(30, FuncaoMove, 1); | |
} | |
void FuncaoGira(int valor){ | |
if(dir && (velocidade > 2||velocidade < -2)) CalculaRotacao('H'); | |
if(esq && (velocidade > 2||velocidade < -2)) CalculaRotacao('A'); | |
glutPostRedisplay(); | |
glutTimerFunc(giro, FuncaoGira, 1); | |
} | |
//desenha quadriláteros | |
void quads(quad q){ | |
glBegin(GL_QUADS); | |
glVertex2f(q.p1.x, q.p1.y); | |
glVertex2f(q.p2.x, q.p2.y); | |
glVertex2f(q.p3.x, q.p3.y); | |
glVertex2f(q.p4.x, q.p4.y); | |
glEnd(); | |
} | |
//quadrados sem preenchimento | |
void quad_borda(quad q){ | |
glBegin(GL_LINE_LOOP); | |
glVertex2f(q.p1.x, q.p1.y); | |
glVertex2f(q.p2.x, q.p2.y); | |
glVertex2f(q.p3.x, q.p3.y); | |
glVertex2f(q.p4.x, q.p4.y); | |
glEnd(); | |
} | |
//desenha as bounding boxes | |
void box(bbox b) { | |
glLineWidth(4.0f); | |
if(b.c) glColor4ub(0, 255, 0, 150); | |
else glColor4ub(255, 0, 0, 150); | |
if(b.tipo == 2) glColor4ub(0, 0, 255, 150); | |
else if(b.tipo == 3) glColor4ub(255, 255, 0, 150); | |
quad_borda(b.q); | |
//glutPostRedisplay(); | |
} | |
//desenha a chegada | |
void desenha_chegada() { | |
glPointSize(15/zoom); | |
float px = 260, py = 495; //490 a 590 | |
bool preto = 0; | |
glBegin(GL_POINTS); | |
for(int i=0;i<20;i++){ | |
if(preto){glColor3ub(255, 255, 255); preto = 0;} | |
else{glColor3ub(0, 0, 0); preto = 1;} | |
glVertex2f(px, py); | |
if(i==9){py-=90;px+=10; preto=1;} | |
else py += 10; | |
} | |
glEnd(); | |
} | |
void bitmap_output(GLfloat x, GLfloat y, char *string, void *font){ | |
int len, i; | |
glRasterPos2f(x, y); | |
len = (int) strlen(string); | |
for (i = 0; i < len; i++) glutBitmapCharacter(font, string[i]); | |
} | |
void stroke_output(GLfloat x, GLfloat y, float esc, float larg, bool mono, char *format, ...){ | |
va_list args; | |
char buffer[200], *p; | |
va_start(args, format); | |
vsprintf(buffer, format, args); | |
va_end(args); | |
glPushMatrix(); | |
glTranslatef(x, y, 0); | |
glScalef(esc*zoom,esc*zoom,0); | |
glLineWidth(larg); | |
for(p = buffer; *p; p++) glutStrokeCharacter(mono?GLUT_STROKE_MONO_ROMAN:GLUT_STROKE_ROMAN, *p); | |
glPopMatrix(); | |
} | |
void escreve_velocidade(void){ | |
char vel[20]; | |
sprintf(vel,"Velocidade: %3.0fkm/h", velocidade*10); | |
stroke_output(tr.x - 255*zoom, tr.y - 190*zoom, 0.08, 1.8, 1, vel); | |
} | |
void escreve_voltas(void){ | |
char vt[20]; | |
sprintf(vt,"Voltas: %d/%d", voltas<total_voltas?voltas+1:voltas, total_voltas); | |
stroke_output(tr.x - 255*zoom, tr.y + 180*zoom, 0.1, 1.8, 1, vt); | |
} | |
void escreve_tempo(void){ | |
char vt[20]; | |
sprintf(vt,"Tempo: %3.1fs", tempo_voltas[voltas]); | |
stroke_output(tr.x - 40*zoom, tr.y + 182*zoom, 0.08, 1.8, 1, vt); | |
} | |
void escreve_melhor_volta(void){ | |
char vt[20]; | |
sprintf(vt,"Melhor: %3.1fs", volta_mais_rapida); | |
stroke_output(tr.x + 155*zoom, tr.y + 182*zoom, 0.08, 1.8, 1, vt); | |
} | |
void escreve_recorde(void){ | |
char vt[20]; | |
sprintf(vt,"Recorde: %3.1fs", volta_recorde); | |
stroke_output(tr.x + 145*zoom, tr.y -190*zoom, 0.08, 1.8, 1, vt); | |
} | |
void escreve_pause(void){ | |
glColor3ub(255,255,255); | |
stroke_output(tr.x-40*zoom, tr.y, 0.1, 1.8, 1, "Pausado"); | |
} | |
void escreve_fim_jogo(void){ | |
char vt[30]; | |
bool vtr = 0; | |
glColor3ub(255,255,255); | |
stroke_output(tr.x-80*zoom, tr.y+100*zoom, 0.2, 1.8, 0, "Fim de jogo"); | |
stroke_output(tr.x-80*zoom, tr.y+70*zoom, 0.08, 1.8, 1, "Voltas:"); | |
for(int i=0;i<total_voltas;i++){ | |
if(tempo_voltas[i] == volta_mais_rapida && !vtr){glColor3ub(255,0,0); vtr=1;} | |
else glColor3ub(255,255,255); | |
sprintf(vt,"Volta %i: %3.1fs", i+1, tempo_voltas[i]); | |
stroke_output(tr.x-80*zoom, tr.y+(40-14*i)*zoom, 0.08, 1.8, 1, vt); | |
} | |
if(volta_mais_rapida == volta_recorde){ | |
glColor3ub(0,255,0); | |
stroke_output(tr.x-80*zoom, tr.y+(40-14*total_voltas-20)*zoom, 0.08, 1.8, 1, "Novo Recorde! :)"); | |
} | |
} | |
void escreve_tela(void){ | |
glColor3ub(255,255,255); | |
escreve_velocidade(); | |
escreve_voltas(); | |
//ESTADOS: 0 - tela inicial / 1 = menu / 2 - semáforo / 3 - jogando / 4 - pausado / 5 - game over | |
if(estado > 1 && estado < 5) escreve_tempo(); | |
if(volta_recorde) escreve_recorde(); | |
escreve_melhor_volta(); | |
} | |
void tela_preta(int opac){ | |
glPushMatrix(); | |
glTranslatef(tr.x, tr.y, 0); | |
glScalef(zoom,zoom,20); | |
glColor4ub(0, 0, 0, opac); | |
quads(tp); | |
glPopMatrix(); | |
} | |
void tela_ini(int i){ | |
int c1 = 100; | |
int c2 = 230; | |
int vtr[16][2] = {{1,2},{1,3},{0,3},{0,10},{2,10},{2,3},{4,3},{4,10},{6,10},{6,3},{5,3},{5,2},{4,2},{4,1},{2,1},{2,2}}; | |
int quar[18][2] = {{1,0},{1,5},{0,5},{0,7},{4,7},{4,9},{6,9},{6,7},{7,7},{7,6},{6,6},{6,2},{4,2},{4,6},{2,6},{2,5},{3,5},{3,0}}; | |
int dois[30][2] = {{1,0},{5,0},{5,1},{6,1},{6,4},{5,4},{5,5},{4,5},{4,6},{3,6},{3,7},{2,7},{2,8},{6,8},{6,9},{0,9},{0,7},{1,7},{1,6},{2,6},{2,5},{3,5},{3,4},{4,4},{4,1},{2,1},{2,3},{0,3},{0,1},{1,1}}; | |
int esc = 20; | |
//glPushMatrix(); | |
glPushMatrix(); | |
glColor3ub(logo1, logo1, logo1); | |
glTranslatef(tr.x - 11*esc, tr.y-100, 0); | |
glBegin(GL_LINE_LOOP); | |
for(int j=0;j<16;j++) glVertex2f(vtr[j][0]*esc,vtr[j][1]*esc); | |
glEnd(); | |
glPopMatrix(); | |
glPushMatrix(); | |
glColor3ub(logo2, logo2, logo2); | |
glTranslatef(tr.x-4*esc, tr.y-100, 0); | |
glBegin(GL_LINE_LOOP); | |
for(int j=0;j<18;j++) glVertex2f(quar[j][0]*esc,(10-quar[j][1])*esc); | |
glEnd(); | |
glPopMatrix(); | |
glPushMatrix(); | |
glColor3ub(logo3, logo3, logo3); | |
glTranslatef(tr.x + 4*esc, tr.y-100, 0); | |
glBegin(GL_LINE_LOOP); | |
for(int j=0;j<30;j++) glVertex2f(dois[j][0]*esc,(10-dois[j][1])*esc); | |
glEnd(); | |
glPopMatrix(); | |
//glPopMatrix(); | |
stroke_output(tr.x-50*zoom, tr.y-125*zoom, 0.08, 1.8, 0, "v42.com.br"); | |
if(i==-1){ | |
if(logo1 < c1) logo1+=15; | |
if(logo2 < c2){logo2+=15;logo3+=15;} | |
else if(i==-1) glutTimerFunc(30, tela_ini, 2); | |
printf("Tela 1 \n"); | |
}else{ | |
glColor3ub(255, 255, 255); | |
if(i>1 && estado == 0)glutTimerFunc(500, tela_ini, i-1); | |
else estado = 1; | |
printf("Segurando \n"); | |
} | |
} | |
void semaforo(int i){ | |
if(cont_semaforo>0 && estado == 2){ | |
cont_semaforo--; glutTimerFunc(3000, semaforo, cont_semaforo); | |
printf("Semaforo: %d \n",cont_semaforo); | |
} | |
else { | |
estado = 3; | |
} | |
printf("Estado %d ",estado); | |
} | |
//desenha chegada da tela inicial | |
void menu(void){ | |
float px = tr.x-200, py = tr.y - 200; | |
bool preto = 0; | |
quad qdr; | |
int esc = 5; | |
qdr.p1.x = -5; qdr.p1.y = -5; qdr.p2.x = 5; qdr.p2.y = -5; | |
qdr.p3.x = 5; qdr.p3.y = 5; qdr.p4.x = -5; qdr.p4.y = 5; | |
for(int i=0;i<20;i++){ | |
if(preto){glColor3ub(255, 255, 255); preto = 0;} | |
else{glColor3ub(0, 0, 0); preto = 1;} | |
glPushMatrix(); | |
glTranslatef(px, py, 0); | |
glScalef(esc,esc,0); | |
glRotatef(-3.6, 0, 0, 1); | |
quads(qdr); | |
glPopMatrix(); | |
if(i==9){py-=90.55*esc;px-=0.05*esc; preto=1;} | |
else {px += 1*esc; py += 10*esc;} | |
} | |
glColor3ub(255, 255, 255); | |
stroke_output(tr.x-50*zoom, tr.y+100*zoom, 0.4, 3, 0, "Carro.exe"); | |
stroke_output(tr.x-50*zoom, tr.y+50*zoom, 0.08, 1.8, 1, "Pressione i para Iniciar"); | |
stroke_output(tr.x-50*zoom, tr.y-20*zoom, 0.08, 1.8, 1, "Comandos"); | |
stroke_output(tr.x-50*zoom, tr.y-45*zoom, 0.08, 1.8, 1, "Setas: Mover Carro"); | |
stroke_output(tr.x-50*zoom, tr.y-65*zoom, 0.08, 1.8, 1, "C: Mudar Cor"); | |
//stroke_output(tr.x-50*zoom, tr.y-85*zoom, 0.08, 1.8, 1, "P: Pausar o jogo"); | |
stroke_output(tr.x-50*zoom, tr.y-85*zoom, 0.08, 1.8, 1, "R: Reiniciar o jogo"); | |
stroke_output(tr.x-50*zoom, tr.y-105*zoom, 0.08, 1.8, 1, "B: Debugs"); | |
} | |
//desenha as telas de apresentação e game over | |
void desenha_telas(void){ | |
//ESTADOS: 0 - tela inicial / 1 = menu / 2 - semáforo / 3 - jogando / 4 - pausado / 5 - game over | |
switch(estado){ | |
case 0: | |
tela_preta(255); | |
tela_ini(-1); | |
break; | |
case 1: | |
tela_preta(255); | |
menu(); | |
break; | |
case 2: | |
semaforo(0); | |
break; | |
case 4: | |
tela_preta(130); | |
escreve_pause(); | |
break; | |
case 5: | |
tela_preta(200); | |
escreve_fim_jogo(); | |
break; | |
} | |
} | |
//desenha o carro | |
void desenhaCarro(void){ | |
glColor3ub(vm, vd, az); | |
glBegin(GL_QUADS); | |
glVertex2f(carro.p1.x + tr.x, carro.p1.y + tr.y); | |
glVertex2f(carro.p2.x + tr.x, carro.p2.y + tr.y); | |
glVertex2f(carro.p3.x + tr.x, carro.p3.y + tr.y); | |
glVertex2f(carro.p4.x + tr.x, carro.p4.y + tr.y); | |
glEnd(); | |
if(cor_selecionada == 1){ | |
glLineWidth(1.8/zoom); | |
glColor3ub(120, 20, 20); | |
glBegin(GL_LINE_LOOP); | |
glVertex2f(carro.p1.x + tr.x, carro.p1.y + tr.y); | |
glVertex2f(carro.p2.x + tr.x, carro.p2.y + tr.y); | |
glVertex2f(carro.p3.x + tr.x, carro.p3.y + tr.y); | |
glVertex2f(carro.p4.x + tr.x, carro.p4.y + tr.y); | |
glEnd(); | |
} | |
glColor3ub(180, 180, 250); | |
if(cor_selecionada>0)glColor3ub(70, 70, 40); | |
glBegin(GL_QUADS); | |
glVertex2f(vt.p1.x + tr.x, vt.p1.y + tr.y); | |
glVertex2f(vt.p2.x + tr.x, vt.p2.y + tr.y); | |
glVertex2f(vt.p3.x + tr.x, vt.p3.y + tr.y); | |
glVertex2f(vt.p4.x + tr.x, vt.p4.y + tr.y); | |
glEnd(); | |
glBegin(GL_QUADS); | |
glVertex2f(vf.p1.x + tr.x, vf.p1.y + tr.y); | |
glVertex2f(vf.p2.x + tr.x, vf.p2.y + tr.y); | |
glVertex2f(vf.p3.x + tr.x, vf.p3.y + tr.y); | |
glVertex2f(vf.p4.x + tr.x, vf.p4.y + tr.y); | |
glEnd(); | |
if(cor_selecionada == 1){ | |
glLineWidth(0.8/zoom); | |
glColor3ub(120, 20, 20); | |
glBegin(GL_LINE_LOOP); | |
glVertex2f(vt.p1.x + tr.x, vt.p1.y + tr.y); | |
glVertex2f(vt.p2.x + tr.x, vt.p2.y + tr.y); | |
glVertex2f(vt.p3.x + tr.x, vt.p3.y + tr.y); | |
glVertex2f(vt.p4.x + tr.x, vt.p4.y + tr.y); | |
glEnd(); | |
glBegin(GL_LINE_LOOP); | |
glVertex2f(vf.p1.x + tr.x, vf.p1.y + tr.y); | |
glVertex2f(vf.p2.x + tr.x, vf.p2.y + tr.y); | |
glVertex2f(vf.p3.x + tr.x, vf.p3.y + tr.y); | |
glVertex2f(vf.p4.x + tr.x, vf.p4.y + tr.y); | |
glEnd(); | |
} | |
} | |
void testes(void){ | |
GLint mv[4]; | |
glGetIntegerv( GL_VIEWPORT, mv ); | |
printf("%i, %i, %i, %i\n", mv[0], mv[1], mv[2], mv[3]); | |
for(float ang=0;ang<=90;ang+=30){ | |
printf("ANG: %f - sin: %f - cos: %f\n", ang, sin(ang), cos(ang)); | |
} | |
printf("ANGULO: %f \n", angulo); | |
} | |
//desenha bounding boxes | |
void desenhaCaixas(void){ | |
if(debug == 2){ | |
box(bb1); box(bb2); box(bb3); box(bb4); box(bb5); | |
box(bb6); box(bb7); box(bb8); box(bb9); box(bb10); | |
box(bb11); box(bb12); box(bb13); box(bb14); box(bb15); | |
box(bb16); box(bb17); box(bb18); box(bb19); box(bb20); | |
box(bb_chegada); | |
box(ba1); box(ba2); box(ba3); box(ba4); | |
} | |
} | |
//testa se completou a volta | |
bool volta_completa(void){ | |
if(bb1.c && bb2.c && bb3.c && bb4.c && bb5.c && bb6.c && | |
bb7.c && bb8.c && bb9.c && bb10.c && bb11.c && bb12.c && | |
bb13.c && bb14.c && bb15.c && bb16.c && bb17.c && bb18.c && | |
bb19.c && bb20.c){ | |
reseta_boxes(); | |
voltacompleta = 1; | |
return true; | |
} | |
return false; | |
} | |
void FuncaoVoltas(int i){ | |
float tempo_total; | |
//ESTADOS: 0 - tela inicial / 1 = menu / 2 - semáforo / 3 - jogando / 4 - pausado / 5 - game over | |
if(estado == 3){ | |
if(voltas<total_voltas){ | |
if(voltacompleta){ | |
if(!volta_mais_rapida || tempo_voltas[voltas]<volta_mais_rapida) volta_mais_rapida = tempo_voltas[voltas]; | |
if(debug == 3) printf("*** VOLTA %i COMPLETA! ***\n Tempo: %5.2fs\n", voltas+1, tempo_voltas[voltas]); | |
if(!volta_recorde || volta_mais_rapida<volta_recorde) volta_recorde = volta_mais_rapida; | |
voltacompleta = 0; | |
voltas++; | |
} | |
if(voltas<total_voltas)tempo_voltas[voltas] += 0.1; | |
}else{ | |
estado = 5; | |
for(int i=0;i<total_voltas;i++) tempo_total += tempo_voltas[i]; | |
if(debug == 3) printf("*** GAME OVER ***\n Tempo total: %5.2fs\nMelhor volta: %5.2fs\nVolta Recorde: %5.2fs", tempo_total, volta_mais_rapida, volta_recorde); | |
} | |
} | |
glutTimerFunc(100, FuncaoVoltas, 1); | |
} | |
//colisão de um ponto com um quadrilátero | |
bool colidiu_pquad(ponto p, quad b){ | |
GLfloat xi, xf, yi, yf; | |
if(b.p1.x != b.p2.x){ | |
if(b.p1.x < b.p2.x){xi = b.p1.x; xf = b.p2.x;} | |
else{xi = b.p2.x; xf = b.p1.x;} | |
}else{ | |
if(b.p1.x < b.p3.x){xi = b.p1.x; xf = b.p3.x;} | |
else{xi = b.p3.x; xf = b.p1.x;} | |
} | |
if(b.p1.y != b.p2.y){ | |
if(b.p1.y < b.p2.y){yi = b.p1.y; yf = b.p2.y;} | |
else{yi = b.p2.y; yf = b.p1.y;} | |
}else{ | |
if(b.p1.y < b.p3.y){yi = b.p1.y; yf = b.p3.y;} | |
else{yi = b.p3.y; yf = b.p1.y;} | |
} | |
if(p.x + tr.x>=xi && p.x + tr.x<=xf && p.y + tr.y>=yi && p.y + tr.y<= yf){ | |
if(debug == 2) printf("%f,%f / X: %f a %f / Y: %f a %f\n", p.x + tr.x, p.y + tr.y, xi, xf, yi, yf); | |
return true; | |
} | |
return false; | |
} | |
//colisão entre um quadrilátero e uma box | |
bool colidiu(quad q, bbox &b){ | |
if(b.tipo!=2 && b.c) return true; | |
if(colidiu_pquad(q.p1, b.q)) b.c = 1; | |
if(!b.c && colidiu_pquad(q.p2, b.q)) b.c = 1; | |
if(!b.c && colidiu_pquad(q.p3, b.q)) b.c = 1; | |
if(!b.c && colidiu_pquad(q.p4, b.q)) b.c = 1; | |
if(b.c && b.tipo==2){ | |
b.c = 0; | |
volta_completa(); | |
} | |
if(b.c && b.tipo == 3){ | |
b.c = 0; | |
if(!tranca_teclas){ | |
velocidade = -velocidade; | |
SoltaTeclas(3); | |
} | |
} | |
} | |
void testa_colisao(int i){ | |
//colisão retas | |
colidiu(carro, bb1); colidiu(carro, bb2); colidiu(carro, bb3); | |
colidiu(carro, bb4); colidiu(carro, bb5); colidiu(carro, bb6); | |
colidiu(carro, bb7); colidiu(carro, bb8); colidiu(carro, bb9); | |
colidiu(carro, bb10); | |
//colisão curvas | |
colidiu(carro, bb11); colidiu(carro, bb12); colidiu(carro, bb13); | |
colidiu(carro, bb14); colidiu(carro, bb15); colidiu(carro, bb16); | |
colidiu(carro, bb17); colidiu(carro, bb18); colidiu(carro, bb19); | |
colidiu(carro, bb20); | |
//colisão chegada | |
colidiu(carro, bb_chegada); | |
//colisão arquibancada | |
colidiu(carro, ba1); colidiu(carro, ba2); | |
colidiu(carro, ba3); colidiu(carro, ba4); | |
glutTimerFunc(70, testa_colisao, 1); | |
} | |
//desenha curvas | |
void curvas(curva c){ | |
glBegin(GL_TRIANGLE_FAN); | |
glVertex2f(c.v.x, c.v.y); | |
switch(c.tipo){ | |
case 1: | |
glVertex2f(c.v.x + 100, c.v.y); | |
glVertex2f(c.v.x + 90, c.v.y + 40); | |
glVertex2f(c.v.x + 70, c.v.y + 70); | |
glVertex2f(c.v.x + 40, c.v.y + 90); | |
glVertex2f(c.v.x, c.v.y + 100); | |
break; | |
case 2: | |
glVertex2f(c.v.x - 100, c.v.y); | |
glVertex2f(c.v.x - 90, c.v.y + 40); | |
glVertex2f(c.v.x - 70, c.v.y + 70); | |
glVertex2f(c.v.x - 40, c.v.y + 90); | |
glVertex2f(c.v.x, c.v.y + 100); | |
break; | |
case 3: | |
glVertex2f(c.v.x - 100, c.v.y); | |
glVertex2f(c.v.x - 90, c.v.y - 40); | |
glVertex2f(c.v.x - 70, c.v.y - 70); | |
glVertex2f(c.v.x - 40, c.v.y - 90); | |
glVertex2f(c.v.x, c.v.y - 100); | |
break; | |
case 4: | |
glVertex2f(c.v.x + 100, c.v.y); | |
glVertex2f(c.v.x + 90, c.v.y - 40); | |
glVertex2f(c.v.x + 70, c.v.y - 70); | |
glVertex2f(c.v.x + 40, c.v.y - 90); | |
glVertex2f(c.v.x, c.v.y - 100); | |
break; | |
} | |
glEnd(); | |
} | |
// Desenha cena | |
void DesenhaCena(void) { | |
GLint mv[4]; | |
glGetIntegerv( GL_VIEWPORT, mv ); | |
// Limpa a janela com a cor especificada como cor de fundo | |
glClear(GL_COLOR_BUFFER_BIT); | |
//transparência | |
glEnable(GL_BLEND); | |
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |
//glViewport(mv[0}, mv[1}, mv[2}, mv[3}); //viewport: Xmin, Ymin, Xmax, Ymax | |
glMatrixMode(GL_PROJECTION); // indica que a matriz a seguir deve ser carregada | |
glLoadIdentity(); // na matriz de transformacao de visualizacao | |
gluOrtho2D(-266*zoom + tr.x, 266*zoom + tr.x, -200*zoom + tr.y, 200*zoom + tr.y); | |
glMatrixMode(GL_MODELVIEW); // recoloca a OpenGL em estado de transformacoes de modelagem | |
glLoadIdentity(); | |
//pista | |
glColor3ub(50, 50, 50); | |
quads(tr1); quads(tr2); quads(tr3); quads(tr4); quads(tr5); quads(tr6); quads(tr7); quads(tr8); quads(tr9); quads(tr10); | |
curvas(cr1); curvas(cr2); curvas(cr3); curvas(cr4); curvas(cr5); curvas(cr6); curvas(cr7); curvas(cr8); curvas(cr9); curvas(cr10); | |
//arquibancadas | |
glColor3ub(0, 0, 0); | |
quads(aq1); quads(aq2); quads(aq3); quads(aq4); | |
//chegada | |
desenha_chegada(); | |
//carro | |
desenhaCarro(); | |
//desenha bounding boxes | |
desenhaCaixas(); | |
//textos | |
escreve_tela(); | |
//telas | |
desenha_telas(); | |
glutSwapBuffers(); //Alterna buffers | |
} | |
// Parte principal - ponto de início de execução | |
// Cria janela | |
// Inicializa aspectos relacionados a janela e a geracao da imagem | |
// Especifica a função callback de desenho | |
main() | |
{ | |
// Indica que devem ser usados dois buffers para armazenamento da imagem e | |
//representacao de cores RGB | |
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); | |
// Cria uma janela com o titulo especificado | |
glutInitWindowSize(800,600); | |
glutCreateWindow("Carros"); | |
Inicio(); | |
//testes(); | |
//mapeamento de teclas | |
glutKeyboardFunc(TeclasNormais); | |
//mapeamento teclas especiais | |
glutSpecialFunc(TeclasEspeciais); | |
//mapeamento teclas especiais up | |
glutSpecialUpFunc(TeclasEspeciaisUp); | |
// Especifica a função de desenho | |
glutDisplayFunc(DesenhaCena); | |
//função pra animar a cena | |
glutTimerFunc(30, FuncaoMove, 1); | |
glutTimerFunc(50, FuncaoGira, 1); | |
glutTimerFunc(75, testa_colisao, 1); | |
glutTimerFunc(100, FuncaoVoltas, 1); | |
// Dispara a "maquina de estados" de OpenGL | |
glutMainLoop(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment