[SDL] Besoin d'aide sur un jeu type "snake"
Résolu
Gregdeimos
Messages postés
4
Statut
Membre
-
Gregdeimos Messages postés 4 Statut Membre -
Gregdeimos Messages postés 4 Statut Membre -
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
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:
- [SDL] Besoin d'aide sur un jeu type "snake"
- 94 jeu - Télécharger - Puzzle & Réflexion
- 94 degrés jeu - Télécharger - Divers Jeux
- Jeu zuma - Télécharger - Jeux vidéo
- Jeu logo - Télécharger - Jeux vidéo
- Clear type - Guide
4 réponses
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.
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.
Impeccable je viens de tester, mon prog est bien plus compréhensible et ça marche nickel !
Encore merci Hxyp ;)
Encore merci Hxyp ;)
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
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