Se connecter avec
S'enregistrer | Connectez-vous

Cherche aide pour "animation" de Sprites en C, avec SDL

Dernière réponse : dans Programmation

Salut salut ^^, svp j'aimerai savoir comment avoir l'effet d'un personnage qui marche (le verbe lol) lorsqu'on appui sur une touche spécifique, j'utilise la librairie SDL, voici un bout de mon code,( dsl je sais pas comment lui mettre que c'est un code en C pr laffichage, vous pourrez copier le texte sur votre IDE ) merci ;-)

#include <stdlib.h>
#include <stdio.h>
#include <SDL/SDL.h>
#include <fmod.h>
#include <SDL/SDL_ttf.h>
#include "mouvements.h"
#include "jeu.h"



void mouvements(SDL_Surface* ecran)
{
int continuer = 1;

SDL_Event event;
SDL_EnableKeyRepeat(100, 100);
SDL_Surface *yuri1 = NULL, *yuri2 = NULL, *yuri3 = NULL, *yuri4 = NULL, *Fond = NULL;

SDL_Rect positionyuri;

positionyuri.x = 50;
positionyuri.y = 404;

SDL_Rect positionFond;

positionFond.x = 0;
positionFond.y = 0;


Fond = SDL_LoadBMP("maptest.bmp");
yuri4 = SDL_LoadBMP("yuri4.bmp");
yuri3 = SDL_LoadBMP("yuri3.bmp");
yuri2 = SDL_LoadBMP("yuri2.bmp");
yuri1 = SDL_LoadBMP("yuri1.bmp");

SDL_SetColorKey(yuri1, SDL_SRCCOLORKEY, SDL_MapRGB(yuri1->format, 255, 255, 255));
SDL_BlitSurface(yuri1, NULL, ecran, &positionyuri);


while (continuer)
{
SDL_PollEvent(&event);
switch(event.type)
{
case SDL_QUIT:
continuer = 0;
break;
case SDL_KEYDOWN:
switch (event.key.keysym.sym)
{
case SDLK_ESCAPE: /* Appui sur la touche Echap, on arrête le programme */
continuer = 0;
break;
}
switch (event.key.keysym.sym)
{
//Déplacements du persos
case SDLK_UP: // Flèche haut
SDL_BlitSurface(Fond, NULL, ecran, &positionFond);
SDL_BlitSurface(yuri1, NULL, ecran, &positionyuri);
SDL_Flip(ecran);
break;

case SDLK_RIGHT: // Flèche droite
//************C'est ici ou j'ai besoin d'aide, je veux que mon perso ai un effet de marcher ou courir
//quand j'appui sur la fleche droite, oui j'ai plusieurs sprites de ce dernier avec une distance entre les pieds qui vari
//mais le probleme et que je n'arrive pas a lui donner cet effet de "courir" en les chargeant et affichant:
SDL_BlitSurface(Fond, NULL, ecran, &positionFond);
SDL_SetColorKey(yuri4, SDL_SRCCOLORKEY, SDL_MapRGB(yuri4->format, 255, 255, 255));
SDL_BlitSurface(yuri4, NULL, ecran, &positionyuri);
positionyuri.x+=2;
SDL_Flip(ecran);
break;

case SDLK_LEFT: // Flèche gauche
positionyuri.x-=2;
SDL_BlitSurface(Fond, NULL, ecran, &positionFond);
SDL_BlitSurface(yuri1, NULL, ecran, &positionyuri);
SDL_Flip(ecran);
break;
}
break;



case SDL_KEYUP :
switch (event.key.keysym.sym)
{
case SDLK_RIGHT:
SDL_BlitSurface(Fond, NULL, ecran, &positionFond);
SDL_SetColorKey(yuri1, SDL_SRCCOLORKEY, SDL_MapRGB(yuri1->format, 255, 255, 255));
SDL_BlitSurface(yuri1, NULL, ecran, &positionyuri);
SDL_Flip(ecran);
break;

}
break;


SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 255, 255, 255));
SDL_BlitSurface(Fond, NULL, ecran, &positionFond);
SDL_BlitSurface(yuri1, NULL, ecran, &positionyuri);
SDL_BlitSurface(yuri3, NULL, ecran, &positionyuri);
SDL_BlitSurface(yuri4, NULL, ecran, &positionyuri);


SDL_Flip(ecran);
SDL_FreeSurface(yuri3);
SDL_FreeSurface(yuri4);
SDL_FreeSurface(yuri1);
SDL_FreeSurface(Fond);
}
}
}

Merci bcp pour votre aide ;) 
Lassé par la pub ? Créez un compte

Déjà, une petite remarque : c'est pas très très joli de définir 4 surfaces séparément pour Yuri séparément... Tu ne pourrais pas faire un tableau ? Du style :

---------------------------------------
SDL_Surface* Yuri[4];
---------------------------------------

Ensuite, pour faire avancer ton perso, tu peux utiliser ceci :

---------------------------------------
for( char i = 0 ; i < 4 ; i++ )
{
SDL_BlitSurface(yuri, NULL, ecran, &positionyuri);
SDL_Flip(ecran);
}
---------------------------------------

Essaye alors le résultat.

oui justement je lai fait avec des timers et SDL_GetTicks();
sinon svp jai un autre ptit probleme, je voudrai afficher une image progressivement, j'ai pensé a utiliser le setalpha, mais puisque c un peu chiant d'ecrire la fonction 255 fois, j'ai fait ça :

int i;

for( i = 0 ; i <= 255 ; i+=1 )
{

SDL_Delay(30);

SDL_SetAlpha(createdby, SDL_SRCALPHA, i);
SDL_BlitSurface(imageDeFond, NULL, ecran, &positionFond);
SDL_BlitSurface(createdby, NULL, ecran, &positionCreatedby);
SDL_Flip(ecran);

}

l'effet d'apparition progressive du texte est tres convainctant, mais le probleme :s, c'est la boucle infinie... je peux plus fermer mon programme qu'avec ctrl+alt+supr, que faire pour remedier à cela svp ?

La boucle infinie ? Quelle boucle infinie ? Tout à l'air correct ici pourtant... Ta variable est incrémentée à chaque parcours de la boucle, et on passe bien à la valeur 255. Tu es sûr que c'est d'ici que vient le problème ? Essayes de commenter cette partie du code pour voir si cela résoud le problème ou non.

Excusez moi je suis vraiment dsl , c'est pas exactement ds ce code parceque quand je le teste seul jarrive a quitter, mais quand je teste ds tout mon programme j'y arrive pas, est-ce parceque apres cette fonction je fais appel a un autre fichier ? (jouer(ecran);) et que dans ce fichier jai encore la boucle for pour avoir le meme effet ?

En tout cas en testant tout le programme, jarrive pas a quitter une fois que je suis dans "jouer" :p .
Expert Programmation

Il ne faut pas faire de boucle dans ta fonction jouer() car ces boucles ne gèrent pas la gestion SDL clavier et autres.
Pour tout ce qui est boucles, tu dois utiliser une astuce avec la boucle des messages SDL. Cette boucle est la boucle prncipale de ton programme.

:o  Desolé j'ai trouvé d'ou provenait le probleme ... ma boucle while qui gerait les evenements :p  merci bcp pr votre aide ;)  sinon un autre tite question :D  quelle est la meilleure façon de faire sauter un perso , j'ai fait ça :

case SDLK_UP:

positionyuri.y-=8;

SDL_SetColorKey(yuri[INITIAL], SDL_SRCCOLORKEY, SDL_MapRGB(yuri[INITIAL]->format, 255, 255, 255));
SDL_BlitSurface(Fond, NULL, ecran, &positionFond);
SDL_BlitSurface(yuri[INITIAL], NULL, ecran, &positionyuri);
SDL_Flip(ecran);
SDL_Delay(20);

mais le perso va jusqu'à l'extremité de l'ecran(y), alors que j'aimerai qu'il sarrete apres quelques pixels ( et pourquoi pas qu'il revienne a sa position.y initial pour avoir l'effet d'un saut ), j'ai essayé avec tout ce que je connais sans y arriver ;-) Je suis encore débutant merci bcp pr votre aide ;-)
(la resolution de l'ecran que j'ai choisi est 800*600)
Expert Programmation

Bon j'en ai fait quelques uns alors je te donnes quelques pistes ;-)
La gravité ça donne quelque chose de parabolique.
Donc, pour ton jeu:
- soit tu fais le petit calcul de y au cours du temps
- soit tu ne fait pas vraiment une parabole mais un truc qui y ressemble.

Pour le 2ème point (le plus simple je pense), je te suggère ceci:
1. Sur l'appui d'une touchen mémoriser le fait que l'on effectue un saut:
int saut; mis à 0 si on ne saute pas et mis à 1 si l'on saute:

  1. // init: on saute pas
  2. int saut = 0;
  3. ...
  4. case SDLK_UP:
  5. if( !saut )
  6. {
  7. // Si on n'est pas en train de faire un saut précédent
  8. // On fait un nouveau saut, alors on saute
  9. saut = 1;
  10. }


Ensuite pour faire un saut joli, au lieu de faire un décalage de 8 pixels, on commence par 8 et on diminue jusqu'à -8. Comme ça, ça monte jusqu'à atteindre 0, puis ça redescend jusqu'à -8.
Pour cela, tu peut utiliser une variable (par exemple int decalage;) pour faire la variation du saut.

Dans ce cas, à chaque saut, tu dois tu doit remettre le compteur décalage à sa valeur initial (c'est-à-dire remettre dealage à 8 à chaque nouveau saut):
  1. // init: on saute pas
  2. int saut = 0;
  3. int decalage = 8;
  4. ...
  5. case SDLK_UP:
  6. if( !saut )
  7. {
  8. // Si on n'est pas en train de faire un saut précédent
  9. // On fait un nouveau saut, alors on saute
  10. saut = 1;
  11. decalage = 8;
  12. }


plus propre:
  1. #define DECALAGE_INITIAL 8
  2.  
  3. // init: on saute pas
  4. int saut = 0;
  5. int decalage = DECALAGE_INITIAL;
  6. ...
  7. case SDLK_UP:
  8. if( !saut )
  9. {
  10. // Si on n'est pas en train de faire un saut précédent
  11. // On fait un nouveau saut, alors on saute
  12. saut = 1;
  13. decalage = DECALAGE_INITIAL;
  14. }


Ensuite, tu effectues le saut dans ta boucle de message, mais en dehors du traitement des messages !
En faisant cela, que l'on appuie sur une touche ou pas, le saut se termine (après tout, l'impulsion est déjà faite, et la gravité n'est pas déclenchée par l'appuie d'une touche ;-) ).
Bref, en dehors de la gestion des évènements, tu sais si le bonhomme fait un saut ou pas grace à la variable "saut". Donc, là tu fait le saut avec le décalage. Et, en même temps, tu fais baisser le décalage.
  1. // Après le switch case, mais dans la boucle
  2.  
  3. // On teste si le joueur effectue un saut
  4. if( saut )
  5. {
  6. // c'est le cas ici
  7. // on fait bouger le joueur selon le décalage
  8. positionyuri.y -= decalage;
  9.  
  10. // On teste si le joueur a retouché le sol
  11. if (positionyuri.y >= positionSol)
  12. {
  13. // On repositionne le joueur sur le sol (car il se peut qu'il ait dépassé de quelques pixels)
  14. positionyuri.y = positionSol;
  15.  
  16. // Et surtout, on arrête le saut !
  17. saut = 0;
  18. }
  19.  
  20. // on fait ralentir la montée, voire accélérer la descente
  21. decalage -= 1;
  22.  
  23. }


Pour ce dernier bout de code, il faut penser à utiliser un timer (http://www.libsdl.org/intro.fr/usingtimersfr.html), car, sinon ça sera très très rapide ;-)
Ceci en utilisant SDL_GetTicks() et pas SDL_Delay().
D'ailleurs, il faut éviter au maximum d'utiliser SDL_Delay(), car s'il bloque les évènements et que tu les accumules, le programme mettra du temps à réagir au touches.

J'ai fait ce post rapidement, sans relire, alors s'il y a un truc bizarre ou mal expliqué faut dire :-D

:-D c'est bon j'ai pu le faire :

while (positionyuri.y >= 10 && (positionyuriyinitial - positionyuri.y) < 100) // quand le personnage monte
{
positionyuri.y-=2;
SDL_SetColorKey(yuri[INITIAL], SDL_SRCCOLORKEY, SDL_MapRGB(yuri[INITIAL]->format, 255, 255, 255));
SDL_BlitSurface(Fond, NULL, ecran, &positionFond);
SDL_BlitSurface(yuri[INITIAL], NULL, ecran, &positionyuri);
SDL_Flip(ecran);
}
while (positionyuri.y <= 403) // quand le personnage redescend
{
positionyuri.y+=3;
SDL_SetColorKey(yuri[INITIAL], SDL_SRCCOLORKEY, SDL_MapRGB(yuri[INITIAL]->format, 255, 255, 255));
SDL_BlitSurface(Fond, NULL, ecran, &positionFond);
SDL_BlitSurface(yuri[INITIAL], NULL, ecran, &positionyuri);
SDL_Flip(ecran);
}


cette fois il saute si je clique sur le fleche de haut, arrivé a une hauteur precise il redescent, et meme si pendant sa montée le joueur clique sur la fleche haute, il ne ressaute pas :)  , voila vai ajouter un vecteur vitesse qui diminu en montant et augmente en descendant pour avoir un effet plus realiste ;-)
...:s difficile a faire lol, Merci.

Slt , j'ai pour projet de créer un jeu style gta avec SDL comme toi!
Au debut je voulais le faire en 3D (du faux) c'est à dire que on gere un personnage 2D sur un décor 2D en perspective.

mais le manque de décor ma limité a un jeu 2D (pour le moment)

j'ai aussi un autre probleme:
j'ai chercher de sprites , j'en ai trouver un exelent mais que de TONY , dnc sa ma bloquer!

ps: pour la gestion des collision , j'ai écrit ce qui avait droit de faire:

(j'écri juste un bout de la boucle while)

case SDLK_RIGHT:

if(positionTony.x < positionVoiture.x) //tony peut à marcher vers la droite tant qu'il est avant la voiture
{


mouv++;
positionTony.x++;

if(mouv = 1)
{

Tony = SDL_LoadBMP("GtaSprites/Tony/TonyDroite1.bmp")

}

if(mouv = 2)
{

Tony = SDL_LoadBMP("GtaSprites/Tony/TonyDroite2.bmp")
mouv = 0;
}

}

Mon code est plus complexe car il gere plusieur objet de différent type et pour faire un mouvement il y a plus que 2 sprites


Revenons a mon probleme:
comme je ne trouve pas assez de sprites jaimerais les créer moi meme!
y a t'il un logiciel gratuis ou payant qui me permetteré de créer des perso et des décor , si possible 3D!

msn:
Axeel@skyrock.fm

Alors, je ne sais pas si cela va pouvoir aider (surtout que le précédent message date un peu ^^ !
Je crée actuellement un jeu en 2D avec SDL ! Je me suis aussi poser la question si je voulais faire ce jeu en 2D simple ou en 2D isométrique !

Différence 2D simple :
http://img13.imageshack.us/img13/4302/map2d.png

2D isométrique:
http://img502.imageshack.us/img502/4157/map2diso.png


Finalement j'ai choisit la 2D isométrique, mais il me restait à créer les blocs, ce qui n'était pas très simple : je faisais plusieurs transformations avec Gimp pour avoir un bloc isométrique utilisable !

J'ai donc appris à écrire un script-fu pour Gimp et j'ai ainsi créer un script qui converti en un clic une image carré (ou rectangulaire) en un bloc isométrique de 100x50 !

Exemple:

Avant la manip, j'ai ceci:
http://img121.imageshack.us/img121/3796/testto.png

Après avoir appliqué le script avec Gimp, j'obtiens :
http://img341.imageshack.us/img341/7282/testisom.png

(les bandes blanches me servent pour mon jeu: cela fait des cases sur la map)

Enfin bref, si ce script vous intéresse, le voici : http://dl.free.fr/pochED1NB

Il est à placer (par défaut) dans C:\Documents and Settings\MonCompte\.gimp-2.6\scripts
et s'utilise donc avec la version 2.6 de Gimp (la plus récente)!

Ce script apparait dans Gimp dans la barre de fonction lorsqu'il est installé (RPG/Bloc Map isométrique) !

Après, vous pouvez partir de ce script pour le modifier un peu afin de créer vos blocs personnalisés !
Si besoin d'aide, n'hésitez pas à me demander, sinon, j'espère avoir été utile ^^!
Lassé par la pub ? Créez un compte
Tom's guide dans le monde