fichiers utilisees pour la création d'un labyrinthe 3D
Revision 0:1f10f1e735e0, committed 2020-04-30
- Comitter:
- kangulu
- Date:
- Thu Apr 30 08:19:00 2020 +0000
- Commit message:
- first commit
Changed in this revision
GAME_ENGINE.cpp | Show annotated file Show diff for this revision Revisions of this file |
GAME_ENGINE.h | Show annotated file Show diff for this revision Revisions of this file |
diff -r 000000000000 -r 1f10f1e735e0 GAME_ENGINE.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GAME_ENGINE.cpp Thu Apr 30 08:19:00 2020 +0000 @@ -0,0 +1,648 @@ +#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; +} \ No newline at end of file
diff -r 000000000000 -r 1f10f1e735e0 GAME_ENGINE.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GAME_ENGINE.h Thu Apr 30 08:19:00 2020 +0000 @@ -0,0 +1,78 @@ +#include "mbed.h" +#include "LCD_DISCO_F746NG.h" +#include "stm32746g_discovery_ts.h" + +#include <stdio.h> +#include <stdlib.h> + +#include <math.h> +#include <time.h> +//taille de la map généré aléatoirement +#define LONGUEUR 7 +#define LARGEUR 7 +//taille de la map qui sera "réellement" utilisée :: map aléatoire multipliée par 3 +#define MAP_WIDTH 21 +#define MAP_HEIGHT 21 + +# define M_PI 3.14159265358979323846 + +#define TICKS_PER_SEC 64 + +#define WALL_SIZE 64 +#define CAMERA_HEIGHT 32 +#define SCREEN_WIDTH 480 +#define SCREEN_HEIGHT 272 +#define DISTANCE_SCREEN_CAMERA 640 + +void screen_init(); +void screen_draw(); + +typedef int color; +typedef char ident; //contiendra 5 bits (54321)b, le 5 pour la verif, 4 pour haut, 3 droite, 2 bas et 1 gauche +//en binaire, si l'un des 4 derniers bit est à 1, le mur associé est fermé + +typedef color worldmap[MAP_HEIGHT][MAP_WIDTH]; +typedef ident minimap[LARGEUR][LONGUEUR]; + +typedef struct position{ + double x; + double y; +}position; + +typedef struct inputState{ + int x; + int y; +}inputState; + +typedef struct dist_and_color{ + double distance; + color color; +}dist_and_color; + +void show_world(position pos,worldmap map); + +void arrow_up(position *pos,double vx,double vy); +void arrow_down(position *pos,double vx,double vy); + + +void rotation(double * vx,double * vy, double theta); +void arrow_right(double * vx,double * vy); +void arrow_left(double * vx,double * vy); + + +color tangent_wall_h(double xprime,int yprime,double vy, worldmap map); +color tangent_wall_v(int xprime,double yprime,double vx, worldmap map); + +dist_and_color dda_h(position pos,double vx, double vy,worldmap map); +dist_and_color dda_v(position pos,double vx, double vy,worldmap map); +dist_and_color dda(position pos,double vx, double vy,worldmap map); + + +void display(position pos, double vx, double vy, worldmap map); + +int getInputState(inputState *iS); + +void createMap(minimap mini, worldmap world); +void gerenatePosition(int* i_pt, int* j_pt, worldmap world); +void generateSortie(int i, int j, worldmap world); +int verificationFin(position pos, worldmap world);