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