fichiers utilisees pour la création d'un labyrinthe 3D

Files at this revision

API Documentation at this revision

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);