fichiers utilisees pour la création d'un labyrinthe 3D
GAME_ENGINE.cpp
- Committer:
- kangulu
- Date:
- 2020-04-30
- Revision:
- 0:1f10f1e735e0
File content as of revision 0:1f10f1e735e0:
#include "GAME_ENGINE.h" LCD_DISCO_F746NG lcd; int active_layer = 0; void screen_init() { lcd.Clear(LCD_COLOR_BLACK); BSP_LCD_SelectLayer(active_layer); BSP_LCD_SetLayerVisible(active_layer, ENABLE); BSP_LCD_SetLayerVisible((active_layer+1)%2, DISABLE); } uint32_t ARGBtoColor(int A,int R,int G,int B) { //A correspond à la transparence return (uint32_t) (A*(1<<24)+R*(1<<16)+G*(1<<8)+B); } void draw_seg_v(int c, int l1, int l2, color couleur) { /* c : coordonnée x i : coordonnée y et couleur */ for(int i=0;i<271;i++) { if(i>l1 && i<l2) { if(couleur == 2) { lcd.DrawPixel(c,i,ARGBtoColor(255,146,72,0)); } else if(couleur == 1) { lcd.DrawPixel(c,i,ARGBtoColor(255,0,180,0)); } else { lcd.DrawPixel(c,i,ARGBtoColor(255,0,0,0)); } } else { lcd.DrawPixel(c,i,ARGBtoColor(255,0,0,0)); } } } //Commandes pour se déplacer void arrow_up(position *pos,double vx,double vy) { pos->x += vx; pos->y += vy; } void arrow_down(position *pos,double vx,double vy) { pos->x -= vx; pos->y -= vy; } void rotation(double *vx,double *vy, double theta) { double tvx = *vx; double tvy = *vy; *vx = cos(theta)*tvx + sin(theta)*tvy; *vy = - sin(theta)*tvx + cos(theta)*tvy; } void arrow_right(double *vx,double *vy) { rotation(&(*vx),&(*vy),0.5); } void arrow_left(double *vx,double *vy) { rotation(&(*vx),&(*vy),0.5); } // color tangent_wall_h(double xprime, int yprime, double vy, worldmap map) { int i=(int) (xprime/WALL_SIZE), j=yprime/WALL_SIZE; if (vy<0){ j--; } if ((i<0)||(j<0)||(i>=MAP_WIDTH)||(j>=MAP_HEIGHT)){ /* sortie de la carte */ return 3; }else{ return map[j][i]; } } color tangent_wall_v(int xprime, double yprime, double vx, worldmap map) { int j = xprime / WALL_SIZE; int i = (int) (yprime / WALL_SIZE); if (vx < 0) { j--; } if (i < 0 || i >= MAP_WIDTH || j < 0 || j >= MAP_HEIGHT) { return 3; } else { return map[i][j]; } } dist_and_color dda_v(position pos, double vx, double vy, worldmap map) { dist_and_color dc; int i=pos.x/WALL_SIZE,di=1; if (vx>0){ i++; }else{ di=-1; } double dx=fabs(WALL_SIZE*i-pos.x); /* distance horizontale au premier bord vertical dans la direction d'observation (en pixels) */ double d1; /* distance au premier bord vertical dans la direction d'observation (en pixels) */ double Dy=vy/fabs(vx); /* distance verticale (en cases) parcourue quand une case est parcourue horizontalement */ double du=WALL_SIZE*sqrt(1+Dy*Dy); /* increment de distance lors du passage au bord vertical suivant (en pixels) */ if (vx==0) { /* dans le cas dégénéré où la direction d'observation est pile verticale */ dc.distance = INFINITY; dc.color=tangent_wall_v( pos.x, pos.y, vx, map); return dc; } pos.y += dx*Dy; /* first vertical line crossing coordinate */ d1 = dx*du/WALL_SIZE; dc.distance = d1; while ((dc.color=tangent_wall_v( WALL_SIZE*i, pos.y, vx, map))==0){ i += di; pos.y += WALL_SIZE*Dy; dc.distance += du; } return dc; } dist_and_color dda_h(position pos, double vx, double vy, worldmap map) { dist_and_color dc; int j=pos.y/WALL_SIZE,dj=1; if (vy>0){ j++; }else{ dj=-1; } double dy=fabs(WALL_SIZE*j-pos.y); /* distance verticale au premier bord horizontal dans la direction d'observation (en pixels) */ double d1; /* distance au premier bord horizontal dans la direction d'observation (en pixels) */ double Dx = vx/fabs(vy); /* distance horizontale (en cases) parcourue quand une case est parcourue verticalement */ double du=WALL_SIZE*sqrt(1+Dx*Dx); /* increment de distance lors du passage au bord horizontal suivant (en pixels) */ if (vy==0){ /* dans le cas dégénéré où la direction d'observation est pile horizontale, on évite éventuellement la division par 0 */ dc.distance = INFINITY; dc.color=tangent_wall_h( pos.x, pos.y, vy, map); return dc; } pos.x += dy*Dx; /* first horizontal line crossing coordinate */ d1 = dy*du/WALL_SIZE; dc.distance = d1; while ((dc.color=tangent_wall_h( pos.x, WALL_SIZE*j, vy, map))==0) { j += dj; pos.x += WALL_SIZE*Dx; dc.distance += du; } return dc; } dist_and_color dda(position pos,double vx, double vy,worldmap map) { dist_and_color v = dda_v(pos,vx,vy,map); dist_and_color h = dda_h(pos,vx,vy,map); if(v.distance < h.distance) { return v; } else { return h; } } void display(position pos, double vx, double vy, worldmap map) { active_layer = (active_layer+1)%2; BSP_LCD_SelectLayer(active_layer); int hauteur; dist_and_color dc; rotation(&vx,&vy, M_PI/6); for(int i=0;i<SCREEN_WIDTH;i++) { dc = dda(pos,vx,vy,map); hauteur = (int)WALL_SIZE*SCREEN_HEIGHT/dc.distance; hauteur = hauteur/fabs(cos((30-60*i/SCREEN_WIDTH)*2*M_PI/360)); if(hauteur>SCREEN_HEIGHT) { hauteur = SCREEN_HEIGHT; } draw_seg_v(i,(SCREEN_HEIGHT-hauteur)/2,(hauteur+SCREEN_HEIGHT)/2,dc.color); rotation(&vx,&vy,2*M_PI-M_PI/3/SCREEN_WIDTH); } BSP_LCD_SetLayerVisible((active_layer+1)%2, DISABLE); BSP_LCD_SetLayerVisible(active_layer, ENABLE); } int getInputState(inputState *iS) { TS_StateTypeDef TS_State; BSP_TS_GetState(&TS_State); if (TS_State.touchDetected==1) { iS->x =TS_State.touchX[0]; iS->y =TS_State.touchY[0]; return 1; } return 0; } // //Generation du labyrinhe // // void createMap(minimap mini, worldmap world) { int i = 0; int j = 0; int k = 0; int memPosition = 0; int memi[LONGUEUR*LARGEUR]; //memoire de la coordonnee i int memj[LONGUEUR*LARGEUR]; //memoire de la coordonnee j int memalea[4] = {0,0,0,0}; //memoire des alea non utilisable float alea = 0; int aleaInt = 0; int verif = -1; //creation du labyrinthe mini de facon aleatoire for(i=0;i<LARGEUR;i++) { for(j=0;j<LONGUEUR;j++) { mini[i][j] = 15; } } int compteur = 0; //compteur pour savoir le nombre de cases que nous avons fait do { i = rand()%LONGUEUR; j = rand()%LARGEUR; alea = rand()%4; if((alea == 0 & j == 0) | (alea == 1 & i == LONGUEUR - 1) | (alea == 2 & j == LARGEUR - 1) | (alea == 3 & i == 0)) { verif = -1; } else { verif = 0; } }while(verif == -1); memi[memPosition] = i; memj[memPosition] = j; mini[i][j] += 16; //bit de verif de la case mis à 1 mini[i][j] -= pow(2, alea); //ouverture d'un des murs memPosition += 1; compteur += 1; aleaInt = alea; switch(aleaInt) { case 0: j--; alea = 2; aleaInt = 2; break; case 1: i++; alea = 3; aleaInt = 3; break; case 2: j++; alea = 0; aleaInt = 0; break; case 3: i--; alea = 1; aleaInt = 1; break; default: break; } mini[i][j] -= pow(2, alea); //ouverture de l'autre partie du mur mini[i][j] += 16; //bit de verif de la case mis à 1 memalea[aleaInt] = 1; memi[memPosition] = i; memj[memPosition] = j; memPosition += 1; compteur += 1; do { //do while pour savoir quel mur ouvrir do { alea = rand()%4; aleaInt = alea; switch(aleaInt) { case 0: if(j == 0) { memalea[aleaInt] = 1; } else { if(mini[i][j-1] >= 16) {memalea[aleaInt] = 1;} } break; case 1: if(i == LONGUEUR-1) { memalea[aleaInt] = 1; } else { if(mini[i+1][j] >= 16) {memalea[aleaInt] = 1;} } break; case 2: if(j == LARGEUR-1) { memalea[aleaInt] = 1; } else { if(mini[i][j+1] >= 16) {memalea[aleaInt] = 1;} } break; case 3: if(i == 0) { memalea[aleaInt] = 1; } else { if(mini[i-1][j] >= 16) {memalea[aleaInt] = 1;} } break; } if(memalea[aleaInt] == 1) { if(memalea[0] == 1 & memalea[1] == 1 & memalea[2] == 1 & memalea[3] == 1) { verif = 2; } else { verif = 0; } } else { verif = 1; } }while(verif == 0); for(k=0;k<4;k++) { memalea[k] = 0; } switch(verif) { case 1: mini[i][j] -= pow(2, alea); //ouverture d'un des murs switch(aleaInt) { case 0: j--; alea = 2; aleaInt = 2; break; case 1: i++; alea = 3; aleaInt = 3; break; case 2: j++; alea = 0; aleaInt = 0; break; case 3: i--; alea = 1; aleaInt = 1; break; default: break; } mini[i][j] -= pow(2, alea); //ouverture de l'autre partie du mur mini[i][j] += 16; //bit de verif de la case mis à 1 memalea[aleaInt] = 1; memi[memPosition] = i; memj[memPosition] = j; memPosition += 1; compteur += 1; break; case 2: memPosition -= 1; i = memi[memPosition]; j = memj[memPosition]; break; } } while(compteur < LONGUEUR*LARGEUR); //remplissage de world a partir de mini for(i=0;i<MAP_HEIGHT;i++) { for(j=0;j<MAP_WIDTH;j++) { if(i == 0 || i == MAP_HEIGHT - 1 || j == 0 || j == MAP_HEIGHT - 1) { world[i][j] = 2; } else if((i%3 == 2 || i%3 == 0) && (j%3 == 2 || j%3 == 0)) { world[i][j] = 2; } else { world[i][j] = 0; } } } for(i=0;i<LARGEUR;i++) { for(j=0;j<LONGUEUR;j++) { verif = mini[i][j] & 0x1; //1er bit soit mur de gauche if(verif == 0x1) { world[3*i + 1][3*j] = 2; } verif = mini[i][j] & 0x2; //2eme bit soit mur du bas if(verif == 0x2) { world[3*i + 2][3*j + 1] = 2; } verif = mini[i][j] & 0x4; //3eme bit soit mur de droite if(verif == 0x4) { world[3*i + 1][3*j + 2] = 2; } verif = mini[i][j] & 0x8; //4eme bit soit mur du haut if(verif == 0x8) { world[3*i][3*j + 1] = 2; } } } } void gerenatePosition(int* i_pt, int* j_pt, worldmap world) { int i, j; int verif = 0; do { i = rand()%MAP_WIDTH; j = rand()%MAP_HEIGHT; if(i == 0) { if(world[i + 1][j] == 0) { i ++; verif = 1; } else { verif = 0; } } else if(j == 0) { if(world[i][j + 1] == 0) { j++; verif = 1; } else { verif = 0; } } else { verif = 0; } }while(verif != 1); *i_pt = i; *j_pt = j; } void generateSortie(int i, int j, worldmap world) { int i2 = 0; int j2 = 0; if(i == 1) { i2 = MAP_WIDTH - 1; if(j <= MAP_HEIGHT/2) { j2 = j + MAP_HEIGHT/2; while(world[i2 - 1][j2] != 0) { j2--; } world[i2][j2] = 1; } else if(j >= MAP_HEIGHT/2) { j2 = j - MAP_HEIGHT/2; while(world[i2 - 1][j2] != 0) { j2++; } world[i2][j2] = 1; } else { j2 = j; while(world[i2 - 1][j2] != 0) { j2++; } world[i2][j2] = 1; } } else if(j == 1) { j2 = MAP_HEIGHT - 1; if(i <= MAP_WIDTH/2) { i2 = i + MAP_WIDTH/2; while(world[i2][j2 - 1] != 0) { i2--; } world[i2][j2] = 1; } else if(i >= MAP_WIDTH/2) { i2 = i - MAP_WIDTH/2; while(world[i2][j2 - 1] != 0) { i2++; } world[i2][j2] = 1; } else { i2 = i; while(world[i2][j2 - 1] != 0) { i2++; } world[i2][j2] = 1; } } } int verificationFin(position pos, worldmap world) { int retour = 0; int i = 0; int j = 0; int k = 0; for (k = 0; k<MAP_WIDTH; k++) { if(pos.x/64>=k && pos.x/64<k + 1) { i = k; } } for (k = 0; k<MAP_HEIGHT; k++) { if(pos.y/64>=k && pos.y/64<k + 1) { j = k; } } if(world[i][j] == 1) { retour = 1; } return retour; }