Un petit Shoot em up en console

Un petit jeu de vaisseau

Voir version :

Pas de dépendances

Télécharger :

#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>

#define MAXMISSILES 40
#define MAXENNEMIS 100

void Color(int flags)
{
    HANDLE H=GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(H,(WORD)flags);
}

void Locate(int x,int y)
{
    HANDLE H=GetStdHandle(STD_OUTPUT_HANDLE);
    COORD C;
    C.X=(SHORT)x;
    C.Y=(SHORT)y;
    SetConsoleCursorPosition(H,C);
}

// ---------------------------------------

typedef struct Sprite
{
    int x,y;
    int xprev,yprev;
    int status;
    char graphisme;
    int color;
} Sprite;

void Initialiser(Sprite* sp,int x,int y,int status,char graphisme,int color)
{
    sp->x = sp->xprev = x;
    sp->y = sp->yprev = y;
    sp->status = status;
    sp->graphisme = graphisme;
    sp->color = color;
}

void Efface(Sprite* sp)
{
    if (sp->status == 0)
        return;
    Locate(sp->xprev,sp->yprev);
    printf(" ");
}

void Affiche(Sprite* sp)
{
    if (sp->status == 0)
        return;
    Locate(sp->x,sp->y);
    Color(sp->color);
    printf("%c",sp->graphisme);
    sp->xprev = sp->x;
    sp->yprev = sp->y;
}

void Supprime(Sprite* sp)
{
    Locate(sp->x,sp->y);
    printf(" ");
    sp->status = 0;
}

// ---------------------------------------

int TrouveLibre(Sprite tab[],int nb)
{
    int i;
    for(i=0;i<nb;i++)
        if (tab[i].status==0)
            return i;
    return -1;
}

void Controle(int touche,Sprite* v,Sprite missile[MAXMISSILES])
{
    if (v->status==0)
        return;
    if (touche=='q' && v->x>0)
        v->x--;
    if (touche=='d' && v->x<70)
        v->x++;
    if (touche=='z' && v->y>0)
        v->y--;
    if (touche=='s' && v->y<40)
        v->y++;
    if (touche==' ')
    {
        int ind = TrouveLibre(missile,MAXMISSILES);
        if (ind!=-1)
            Initialiser(&missile[ind],v->x+1,v->y,1,'-',FOREGROUND_RED|FOREGROUND_INTENSITY);
    }
}

void Asteroides(Sprite ennemi[MAXENNEMIS])
{
    int i;
// faire evoluer l'existant
    for(i=0;i<MAXENNEMIS;i++)
    {
        if (ennemi[i].status == 0)
            continue;
        if (ennemi[i].x == 0)  // disparaitre les asteroides qui sortent
            Supprime(&ennemi[i]);
        ennemi[i].x--; // mouvement
    }
// nouveau ?
    //if(rand()%3==0) // 1 chance sur 3 a chaque frame  // desactive -> toutes les frames, sinon c'est trop simple
    {
        int ind = TrouveLibre(ennemi,MAXENNEMIS);
        if (ind!=-1)
            Initialiser(&ennemi[ind],79,rand()%40,1,'*',FOREGROUND_GREEN|FOREGROUND_INTENSITY);
    }
}

void Missiles(Sprite missile[MAXMISSILES],Sprite ennemi[MAXENNEMIS],int* score)
{
    int i,j;
// collisions missiles : inoptimal mais ou s'en fout
    for(i=0;i<MAXMISSILES;i++)
    {
        for(j=0;j<MAXENNEMIS;j++)
        {
            if (missile[i].status==1 && ennemi[j].status==1 && missile[i].y == ennemi[j].y &&
                (missile[i].x == ennemi[j].x  || missile[i].x-1 == ennemi[j].x))
            {
                 (*score)++;
                 Supprime(&ennemi[j]);
                 Supprime(&missile[i]);
            }
        }
    }
// evolution missiles;
    for(i=0;i<MAXMISSILES;i++)
    {
        if (missile[i].status == 0)
            continue;
        if (missile[i].x == 70)  // disparaitre les missiles qui sortent
            Supprime(&missile[i]);
        missile[i].x++; // mouvement
    }
}

void Vaisseau(Sprite* v,Sprite ennemi[MAXENNEMIS])
{
    int i;
    for(i=0;i<MAXENNEMIS;i++)
    {
        if (v->status == 1 && ennemi[i].status==1 && v->y == ennemi[i].y &&
            (ennemi[i].x == v->x  || ennemi[i].x-1 == v->x))
        {
            Supprime(v);
        }
    }
}

void AfficheTout(Sprite* vaisseau,Sprite missile[MAXMISSILES],Sprite ennemi[MAXENNEMIS],int score)
{
    int i;
// erase
    Efface(vaisseau);
    for(i=0;i<MAXMISSILES;i++)
        Efface(&missile[i]);
    for(i=0;i<MAXENNEMIS;i++)
        Efface(&ennemi[i]);
// affiche
    Affiche(vaisseau);
    for(i=0;i<MAXMISSILES;i++)
        Affiche(&missile[i]);
    for(i=0;i<MAXENNEMIS;i++)
        Affiche(&ennemi[i]);
    Locate(0,0);
    Color(FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_INTENSITY);
    printf("Score : %d",score);
    if (vaisseau->status == 0)
    {
        Locate(35,20);
        Color(rand()%16);
        printf("Game Over");
    }
}

int main()
{
    int i;
    int touche = 0;
    int score = 0;
    Sprite vaisseau;
    Sprite missile[MAXMISSILES];
    Sprite ennemi[MAXENNEMIS];
    srand((unsigned int)time(NULL));
    system("MODE CON LINES=50 COLS=80");
    Initialiser(&vaisseau,5,15,1,'>',FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_INTENSITY);
    for(i=0;i<MAXMISSILES;i++)
        Initialiser(&missile[i],0,0,0,' ',0);
    for(i=0;i<MAXENNEMIS;i++)
        Initialiser(&ennemi[i],0,0,0,' ',0);
    while(touche!=27)  // ESCAPE
    {
        if (_kbhit())
        {
            touche = _getch();
            Controle(touche,&vaisseau,missile);
        }
        Missiles(missile,ennemi,&score);
        Asteroides(ennemi);
        Vaisseau(&vaisseau,ennemi);
        AfficheTout(&vaisseau,missile,ennemi,score);
        Sleep(50);
    }
    return 0;
}




Commentaires

	Voici un petit jeu de vaisseau en console. Utilisez QSDZ pour diriger, espace pour tirer, et esc pour quitter.

	Il se peut qu'il y ait quelques petits bugs d'affichage. Contrairement à un jeu 2D ou on redessine tout a chaque frame, ici, je dois effacer les 
	anciennes positions des missiles, astéroides et vaisseau.

	Explications plus tard.