Skip to content

Instantly share code, notes, and snippets.

@v42
Last active December 14, 2015 05:29
Show Gist options
  • Save v42/5035413 to your computer and use it in GitHub Desktop.
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.
#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