[SDL] Besoin d'aide sur un jeu type "snake"

Résolu/Fermé
Gregdeimos Messages postés 4 Date d'inscription lundi 24 juin 2013 Statut Membre Dernière intervention 7 août 2013 - 24 juin 2013 à 16:34
Gregdeimos Messages postés 4 Date d'inscription lundi 24 juin 2013 Statut Membre Dernière intervention 7 août 2013 - 7 août 2013 à 22:02
Bonjour à tous,

Voilà je débute en C et SDL et je tente de faire un clone du "snake" Anaconda présent dans Timesplitters 2 (pour ceux qui ne connaissent pas : https://www.youtube.com/watch?v=h22thYhPCNw ceci afin de m'entraîner avant de passer au C++.

Pour bien faire il aurait fallu le réaliser en vectoriel mais bon j'aimerai faire plus simple avec des sprites. Néanmoins je coince pour afficher le reste du snake, pour l'heure je n'ai que la tête qui se déplace et je voudrai que le corps et la queue suivent le parcours de la tête. J'ai donc créé 2 tableaux, l'un contenant les coordonnées en x et en y à chaque passage dans la boucle de la tête et l'autre contenant les différents angles aux même instants. Le corps du serpent n'aurais plus qu'à piocher dans les tableaux des coordonnées quelques passages de boucles plus tard afin d'être décalés. Je trouve cette technique assez lourde et en plus je n'ai pas réussi à l'appliquer correctement (le corps se blitté sur la tête). J'ai donc supprimé ce qui ne fonctionné pas afin de rendre mon programme plus clair pour vous le présenter.

Pour faire court, je voudrai savoir comment faire pour afficher le corps et la queue du Snake à la suite de la tête et qu'ils suivent ses mouvements.

Je poste donc sur ce forum afin d'obtenir un peu d'aide étant donné que je ne trouve pas de tutos ou d'autres sujets pouvant me faire avancé. Je ne souhaite pas avoir des bouts de codes tout fait mais juste une manière de procéder ou une piste, après je pourrai me débrouiller. Je vous met mon code ci-dessous en 3 fichiers.

Merci par avance

/* main.c
---------
Rôle : Fichier principal
 
Par GregDeimos // Modification le 10/06/2013
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>
#include "constantes.h"
 
int main ( int argc, char* argv[] )
{
    // Déclaration des structures de surfaces puis variables
    SDL_Surface *ecran = NULL, *titre = NULL;
    SDL_Rect posTitre;
    SDL_Event event; // Pour les évènements
    TTF_Font *police = NULL;
    SDL_Color couleurVerte = {0, 255, 0}; // Définition de la couleur Verte
    int continuer = 1; // Variable booléenne pour quitter
 
    // Mise à l'origine des coordonnées
    posTitre.x = LARGEUR_ECRAN/2 - 160;
    posTitre.y = HAUTEUR_ECRAN/2 - 160;
 
    // Initialisation de la SDL et de la fenêtre
    SDL_Init(SDL_INIT_VIDEO); // Initialisation SDL
    TTF_Init(); // Initialisation TTF pour écrire
    ecran = SDL_SetVideoMode(LARGEUR_ECRAN, HAUTEUR_ECRAN, 32, SDL_HWSURFACE | SDL_DOUBLEBUF); // Création de la fenêtre
    SDL_WM_SetCaption("ANACONDA", NULL); // Changement du nom de la fenêtre
    police = TTF_OpenFont("game_over.ttf",150); // Assignation d'une police à la surface
    titre = TTF_RenderText_Solid(police, "ANACONDA", couleurVerte); // Modif de la surface avec la chaine de caractère
 
    // Boucle principale de la fonction "main" qui gère le menu principal
    while (continuer)
    {
        SDL_WaitEvent(&event); // Attente qu'une des actions suivantes soit faite
        switch (event.type)
        {
            case SDL_QUIT: // Si l'on clique sur la croix rouge de la fenêtre
            continuer = 0; // Sortie de la boucle pour quitter
                break;
 
            case SDL_KEYDOWN: // Si l'on presse une touche du clavier
                switch(event.key.keysym.sym)
                {
                    case SDLK_ESCAPE: // Touche "Echap"
                        continuer = 0; // Sortie de la boucle pour quitter
                        break;
                    case SDLK_UP: // Touche "haut"
                        break;
                    case SDLK_DOWN: // Touche "bas"
                        break;
                    case SDLK_RIGHT: // Touche "droite"
                        break;
                    case SDLK_LEFT: // Touche "gauche"
                        break;
                    case SDLK_RETURN:
                        jeu(ecran);
                        break;
                }// Fin du switch Keydown
                break;
            case SDL_MOUSEBUTTONDOWN:
                break;
            case SDL_MOUSEBUTTONUP:
                break;
            case SDL_MOUSEMOTION:
                break;
        }// Fin du Switch Event.Type
        SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 30, 30, 30)); // Ecran noir pour effacer l'ancienne image
        SDL_BlitSurface(titre, NULL, ecran, &posTitre); // Affichage du texte/variable
        SDL_Flip(ecran); // Actualisation de l'affichage
    }// Fin de la boucle Principale
 
    // Libération de la mémoire
    TTF_Quit(); // Fermeture TTF
    SDL_FreeSurface(ecran); // Libération mémoire de la surface
    SDL_Quit(); // Fermeture SDL
 
    return EXIT_SUCCESS; // Fermeture du programme proprement
}


/* jeu.c
---------
Rôle : Fichier gérant le moteur du jeu
 
Par GregDeimos // Modification le 24/06/2013
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>
#include <SDL_rotozoom.h>
#include <math.h>
#include "jeu.h"
#include "constantes.h"
 
void jeu(SDL_Surface *ecran)
{
    // Déclaration des structures de surfaces puis variables
    SDL_Surface *teteAna = NULL, *rotationTete = NULL; // Déclaration des surfaces
    SDL_Surface *textVerif1 = NULL, *textVerif2 = NULL, *textVerif3 = NULL, *textVerif4 = NULL; // Déclaration des surfaces
    SDL_Rect posTeteAna, posTeteAnaTemp, posText1, posText2, posText3, posText4; // Déclaration des variables structure Rect pour la position des surfaces
    TTF_Font *police = NULL; // Création d'une variable pour mémoriser la police
    SDL_Event event; // Pour les évènements
    SDL_Color couleurVerte = {0, 255, 0}; // Définition de la couleur Verte
    double angle = 0; // Angle de rotation de la tête d'Ana
    int continuer = 1, parcourir = 0, verifAngle = 0, compteur = 0, i = 0; // Variables diverses
    char variable[20] = "", variable2[20] = "", variable3[20] = "", variable4[20] = ""; // Chaine de caractères pour enregistrer une variable
 
    // Mise à l'origine des coordonnées
    posTeteAna.x = LARGEUR_ECRAN/2 - TAILLE_SPRITE/2, posTeteAna.y = HAUTEUR_ECRAN - TAILLE_SPRITE;
    posText1.x = LARGEUR_ECRAN-200, posText1.y = 40;
    posText2.x = LARGEUR_ECRAN-250, posText2.y = 10;
    posText3.x = LARGEUR_ECRAN-150, posText3.y = 70;
    posText4.x = LARGEUR_ECRAN-150, posText4.y = 100;
    posTeteAnaTemp.x = LARGEUR_ECRAN/2 - TAILLE_SPRITE/2, posTeteAnaTemp.y = HAUTEUR_ECRAN - TAILLE_SPRITE*3;
 
    // Initialisation des contenus
    teteAna = IMG_Load("Sprites/TeteAna.tga"); // Assignation d'une image à la surface
    police = TTF_OpenFont("game_over.ttf",40); // Assignation d'une police à la surface
 
    // Boucle principale de la fonction "main" qui gère le menu principal
    while (continuer)
    {
        sprintf(variable, "ANGLE : %f", angle); // Enregistrement de la variable en chaine de caractères ||| METTRE VARIABLE A TESTER EN FIN DE PARENTHESE
        sprintf(variable2, "QUART D'ANGLE : %d", verifAngle); // Enregistrement de la variable en chaine de caractères ||| METTRE VARIABLE A TESTER EN FIN DE PARENTHESE
        sprintf(variable3, "MOUV. X : %d", posTeteAnaTemp.x); // Enregistrement de la variable en chaine de caractères ||| METTRE VARIABLE A TESTER EN FIN DE PARENTHESE
        sprintf(variable4, "MOUV. Y : %d", posTeteAnaTemp.y); // Enregistrement de la variable en chaine de caractères ||| METTRE VARIABLE A TESTER EN FIN DE PARENTHESE
        textVerif1 = TTF_RenderText_Solid(police, variable, couleurVerte); // Modif de la surface avec la chaine de caractère
        textVerif2 = TTF_RenderText_Solid(police, variable2, couleurVerte); // Modif de la surface avec la chaine de caractère
        textVerif3 = TTF_RenderText_Solid(police, variable3, couleurVerte); // Modif de la surface avec la chaine de caractère
        textVerif4 = TTF_RenderText_Solid(police, variable4, couleurVerte); // Modif de la surface avec la chaine de caractère
        SDL_PollEvent(&event); // Attente qu'une des actions suivantes soit faite
        switch (event.type)
        {
            case SDL_QUIT: // Si l'on clique sur la croix rouge de la fenêtre
                TTF_Quit(); // Fermeture TTF
                SDL_FreeSurface(ecran); // Libération mémoire de la surface
                SDL_FreeSurface(textVerif1); // Libération mémoire de la surface
                SDL_FreeSurface(textVerif2); // Libération mémoire de la surface
                SDL_FreeSurface(textVerif3); // Libération mémoire de la surface
                SDL_FreeSurface(textVerif4); // Libération mémoire de la surface
                SDL_FreeSurface(teteAna); // Libération mémoire de la surface
                SDL_FreeSurface(rotationTete); // Libération mémoire de la surface
                SDL_Quit(); // Fermeture SDL
                break;
 
            case SDL_KEYDOWN: // Si l'on presse une touche du clavier
                switch(event.key.keysym.sym)
                {
                    case SDLK_ESCAPE: // Touche "Echap"
                        continuer = 0; // Sortie de la boucle pour quitter
                        break;
                    case SDLK_UP: // Touche "haut"
                        break;
                    case SDLK_DOWN: // Touche "bas"
                        break;
                    case SDLK_RIGHT: // Touche "droite"
                        if (angle >= 0 && angle <= 90)
                        {
                            angle -= VITESSE_ROTATION; // Changement de la valeur de l'angle
                            verifAngle = 1; // Changement du quart d'angle
                        }
                        else if (angle > 180 && angle <= 270)
                        {
                            angle -= VITESSE_ROTATION;
                            verifAngle = 3;
                        }
                        else if (angle > 90 && angle <= 180)
                        {
                            angle -= VITESSE_ROTATION;
                            verifAngle = 2;
                        }
                        else if (angle > 270 && angle <= 360)
                        {
                            angle -= VITESSE_ROTATION;
                            verifAngle = 4;
                        }
                        break;
                    case SDLK_LEFT: // Touche "gauche"
                        if (angle >= 0 && angle <= 90)
                        {
                            angle += VITESSE_ROTATION;
                            verifAngle = 1;
                        }
                        else if (angle > 180 && angle <= 270)
                        {
                            angle += VITESSE_ROTATION;
                            verifAngle = 3;
                        }
                        else if (angle > 90 && angle <= 180)
                        {
                            angle += VITESSE_ROTATION;
                            verifAngle = 2;
                        }
                        else if (angle > 270 && angle <= 360)
                        {
                            angle += VITESSE_ROTATION;
                            verifAngle = 4;
                        }
                        break;
 
                }
                break;
            case SDL_MOUSEBUTTONDOWN:
 
                break;
            case SDL_MOUSEBUTTONUP:
 
                break;
            case SDL_MOUSEMOTION:
 
                break;
        }// Fin du Switch Event.Type
        if(angle >= 360){angle = 0;} // Si la variable angle dépasse 359 alors elle repasse à 0
        else if (angle < 0){angle = 360;} // Si la variable angle deviens négative, c'est que ça tourne dans le sens inverse : mise à 359 degrés
 
        SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 30, 30, 30)); // Ecran noir pour effacer l'ancienne image
        SDL_BlitSurface(textVerif1, NULL, ecran, &posText1); // Affichage du texte/variable
        SDL_BlitSurface(textVerif2, NULL, ecran, &posText2); // Affichage du texte/variable
        SDL_BlitSurface(textVerif3, NULL, ecran, &posText3); // Affichage du texte/variable
        SDL_BlitSurface(textVerif4, NULL, ecran, &posText4); // Affichage du texte/variable
        if(compteur == VITESSE_ANACONDA) // Réglage de la vitesse
        {
            posTeteAnaTemp.x -= sin(angle*PI/180)*10; // Actualisation de la trajectoire XY -> X
            posTeteAnaTemp.y -= cos(angle*PI/180)*10; // Actualisation de la trajectoire XY -> Y
            compteur = 0; // Remise à zéro du compteur
        }
        rotationTete = rotozoomSurface(teteAna, angle, 1.0, 1); // Paramêtrage de la surface rotation
        posTeteAna.x =  posTeteAnaTemp.x - rotationTete->w / 2; // Mise à jour de la position du sprite par rapport à sa nouvelle dimension
        posTeteAna.y =  posTeteAnaTemp.y - rotationTete->h / 2; // Mise à jour de la position du sprite par rapport à sa nouvelle dimension
 
        SDL_BlitSurface(rotationTete, NULL, ecran, &posTeteAna); // Affichage de la surface rotation (de la tête)
        SDL_Flip(ecran); // Actualisation de l'affichage
        compteur ++; // incrémentation du compteur
        SDL_Delay(2); // petite pause afin de gérer la vitesse de la boucle principale du jeu
    }// Fin de la boucle Principale du jeu
 
    // Libération de la mémoire
    SDL_FreeSurface(textVerif1); // Libération mémoire de la surface
    SDL_FreeSurface(textVerif2); // Libération mémoire de la surface
    SDL_FreeSurface(textVerif3); // Libération mémoire de la surface
    SDL_FreeSurface(textVerif4); // Libération mémoire de la surface
    SDL_FreeSurface(teteAna); // Libération mémoire de la surface
    SDL_FreeSurface(rotationTete); // Libération mémoire de la surface
    SDL_FreeSurface(ecran); // Libération mémoire de la surface
}


/* constantes.h
---------
Rôle : Fichier header du fichier principal contenant les constantes
 
Par GregDeimos // Modification le 10/06/2013
*/
 
#define PI                  3.14159265
#define VITESSE_ROTATION    1
#define VITESSE_ANACONDA    12
#define LARGEUR_ECRAN       1024
#define HAUTEUR_ECRAN       768
#define TAILLE_SPRITE       64
A voir également:

4 réponses

Hxyp Messages postés 401 Date d'inscription vendredi 28 janvier 2011 Statut Membre Dernière intervention 27 avril 2014 54
25 juin 2013 à 01:30
Bonjour,
En utilisant un tableau qui représente le serpent ça pourrait le faire, exemple :
struct cellule{
int x,y,rot,size;
};
la structure sert à sauvegarder les données de la tête et en décalant les données dans les cellules suivantes du tableau on obtient le serpent complet; à chaque tour de la boucle principal on appel la fonction qui affiche le tableau/serpent et fait le décalage des coordonnées&rotation dans le tableau, ou ajout d'une cellule qui reprend les données de la cellule précédente avec une modification sur sa taille genre décrémentation ou autre avec l'aide d'une moyenne sur la taille du serpent faut voir..
struct cellule *serpent;
serpent = malloc(sizeof(cellule)*10); /* tableau représentant un serpent de taille 10 cellules */
Peut faire simple en allouant directement une taille max et mettre en negatif (valeur par default) les cellules non encore utilisées.
0
Gregdeimos Messages postés 4 Date d'inscription lundi 24 juin 2013 Statut Membre Dernière intervention 7 août 2013
25 juin 2013 à 17:39
Merci pour ta réponse Hxyp, je vais me pencher là-dessus tout de suite ^^
0
Gregdeimos Messages postés 4 Date d'inscription lundi 24 juin 2013 Statut Membre Dernière intervention 7 août 2013
3 juil. 2013 à 21:59
Impeccable je viens de tester, mon prog est bien plus compréhensible et ça marche nickel !

Encore merci Hxyp ;)
0
Gregdeimos Messages postés 4 Date d'inscription lundi 24 juin 2013 Statut Membre Dernière intervention 7 août 2013
7 août 2013 à 22:02
Salut à tous,
Pour ceux que ça intéresse j'ai bien avancé sur ce jeu, il est en téléchargement sur mon site en beta. N'hésitez pas à le tester et à me faire part de vos remarques ! Merci d'avance pour vos retours, quand il sera fini je partagerai les sources.

http://www.gregdeimosgames.sitew.fr
0