Les forums de JeuxVideo.com
-
Kuroryuu
- Posté le
4 juillet 2009 à 23:26:40

-
Bien le bonjour à vous tous voila je me tourne vers vous car j'ai vu cette section création jeux vidéos.
Depuis quelque jours je travaille sur un systême de collision avec la librairie SDL en C. Mais voila soucis :D soit je ne peut plus bouger apret collision ou alors je passe tout de même à travers de mon image blitter... Voila mon code source :
<code type="c">
#include <stdio.h>
#include <stdlib.h>
#include <SDL/SDL.h>
#define HAUTEUR_FENETRE 250
#define LARGEUR_FENETRE 400
int main (int argc , char *argv [])
{
SDL_Surface *fenetre , *ichigo , *inoue ;
SDL_Rect position_ichigo , position_inoue ;
SDL_Event event ;
int continuer = 1 ;
int ichigo_gauche = position_ichigo.x , ichigo_droite = position_ichigo.x + position_ichigo.w ;
int ichigo_haut = position_ichigo.y , ichigo_bas = position_ichigo.y + position_ichigo.h;
long inoue_gauche = position_inoue.x , inoue_droite = position_inoue.x + position_inoue.w ;
long inoue_haut = position_inoue.y , inoue_bas = position_inoue.y + position_inoue.h ;
SDL_Init (SDL_INIT_VIDEO);
fenetre = SDL_SetVideoMode ( LARGEUR_FENETRE, HAUTEUR_FENETRE , 32 , SDL_HWSURFACE | SDL_DOUBLEBUF);
SDL_WM_SetCaption("collision",NULL) ;
ichigo = SDL_LoadBMP("ichigo.bmp");
inoue = SDL_LoadBMP("inoue.bmp");
position_ichigo.x = 50;
position_ichigo.y = 100;
position_inoue.x = 50;
position_inoue.y = 50;
SDL_SetColorKey(ichigo,SDL_SRCCOLORKEY,SDL_MapRGB(
ichigo->format,0,12,140));
SDL_SetColorKey(inoue,SDL_SRCCOLORKEY,SDL_MapRGB(i
noue->format,14,122,150));
SDL_EnableKeyRepeat(10 , 10);
while (continuer)
{
SDL_WaitEvent(&event);
switch(event.type)
{
case SDL_QUIT :
continuer =0;
break;
case SDL_KEYDOWN:
switch(event.key.keysym.sym)
{
case SDLK_UP :
if (ichigo_bas <= inoue_haut)
{
position_ichigo.y ++;
}
position_ichigo.y --;
break;
case SDLK_DOWN :
if (ichigo_haut >= inoue_bas)
{
position_ichigo.y --;
}
position_ichigo.y ++;
break ;
case SDLK_LEFT :
if (ichigo_droite <= inoue_gauche)
{
position_ichigo.x ++;
}
position_ichigo.x --;
break ;
case SDLK_RIGHT:
if (ichigo_gauche >= inoue_droite)
{
position_ichigo.x --;
}
position_ichigo.x ++;
break;
}
break;
}
SDL_FillRect(fenetre, NULL, SDL_MapRGB(fenetre->format, 0, 0, 0));
SDL_BlitSurface(inoue,NULL,fenetre,&position_inoue
);
SDL_BlitSurface(ichigo, NULL, fenetre, &position_ichigo);
SDL_Flip(fenetre);
}
SDL_FreeSurface(ichigo);
SDL_FreeSurface(inoue);
return EXIT_SUCCESS ;
}
</code>
Je vous remercie encore de votre aide
- Lien permanent
-
Kuroryuu
- Posté le
4 juillet 2009 à 23:49:37

-
Merci je ne connaisser pas ce site ^^ hum sinon aucune reponse car j'ai lus les tuto du devellopez.com et game network mais j'ai du foirer quelque chose ^^
- Lien permanent
-
Nymo
- Posté le
6 juillet 2009 à 22:10:57

-
En fait ce code est plein de problèmes.
1/ Variables et valeurs
case SDLK_UP :
if (ichigo_bas <= inoue_haut)
{
position_ichigo.y ++;
}
les variables ichigo_bas, ichigo_gauche, inoue_haut, etc sont initialisées une fois pour toutes avant ta boucle principale et ne sont jamais mises à jour.
Ainsi, quand Ichigo entrera en collision avec Inoue, il passera à travers car la comparaison se fait uniquement sur leurs positions initiales respectives.
ichigo_gauche devra donc systématiquement être remplacé par position_ichigo.x ou à chaque déplacement d'Ichigo vers la gauche il faudra mettre la variable ichigo_gauche à jour (ce qui est bien moins optimisé)
2/ Comparaisons et logique
Petit problème de logique :
case SDLK_UP :
if (ichigo_bas <= inoue_haut)
{
position_ichigo.y ++;
}
Traduction :
- Quand j'appuie sur haut
- si le bas de l'image d'Ichigo est plus haut que le haut de l'image d'Inoue
- Je monde Ichigo
Donc je ne peux faire monter Ichigo que si il est déjà positionné au dessus d'Inoue ?
Il faudrait plutôt vérifier si le haut d'Ichigo n'est pas égal au bas d'Inoue (+1 pixel)..
donc :
case SDLK_UP :
if (position_ichigo.y != (position_inoue.y + position_inoue.h + 1) )
{
position_ichigo.y ++;
}
3/ Insuffisance de la comparaison
Même en réglant les deux problèmes précédents, la detection de collision ne marcherait toujours pas.
En effet tu n'autoriserait Ichigo à Monter que s'il est placé plus bas qu'Inoue, mais tu ne vérifie jamais si ils sont sur la même "colonne".
Admettons qu'Ichigo le haut d'ichigo est très exactement placé un pixel plus bas que le bas d'Inoue, il ne monterait pas, même si ichigo est placé tout à droite de la fenêtre et Inoue tout à gauche.
Il faut aussi détecter si les deux images partagent une ligne verticale de pixels en commun.
Une détection complète serait donc :
case SDLK_UP :
if (position_ichigo.y != (position_inoue.y + position_inoue.h + 1)
|| ( (position_ichigo.x > (position_inoue.x + position_inoue.w))
|| ((position_ichigo.x + position_ichigo.w) < position_inoue.x) )
{
position_ichigo.y --;
}
Ca charabia peut être traduit simplement par "Si Ichigo n'est pas placé juste sous Inoue ou s'il est placé à gauche ou à droite d'Inoue (sans possibilité de collision), alors on augmente sa position en Y de 1.
Bien sûr pour plus de lisibilité, il est fortement conseillé de déporter ce test dans une fonction, par exemple :
bool ichigo_peut_monter(SDL_rect *position_ichigo, SDL_rect *position_inoue)
{
return (*position_ichigo.y != (*position_inoue.y + *position_inoue.h + 1)
|| ( (*position_ichigo.x > (*position_inoue.x + *position_inoue.w))
|| ((*position_ichigo.x + *position_ichigo.w) < *position_inoue.x) ) ? true : false;
}
(on utilise des pointeurs pour car le passage de paramètre en c/c++ se fait par recopie, ici, on passe donc juste une seule adresse par image, ce qui est bien plus optimisé)
il suffirait ensuite de tester la possibilité de monter de cette façon :
if ( ichigo_peut_monter(&position_ichigo, &position_inoue) )
{
position_ichigo.y --;
}
Mais ça serait oublier de tester si Ichigo n'est pas déja tout en haut de l'écran, il faudrait donc rajouter dans notre test :
&& (*position_ichigo.y >= 0)
Pareil pour le bas, la droite et la gauche, mais pour la droite et la gauche on aura besoin de la taille de la fenêtre, il faudra donc également passer SDL_Surface* fenetre aux fonctions qui vérifieront cela
OUF !
- Lien permanent
-
Nymo
- Posté le
6 juillet 2009 à 22:21:33

-
Bon en me relisant je me rend compte que j'ai écrit plein de bêtises mais l'essentiel est la.
Autre faute dans ton code :
Tu initialises ichigo_gauche et toutes tes variables
int ichigo_gauche = position_ichigo.x , ichigo_droite = position_ichigo.x + position_ichigo.w ;
AVANT d'initialiser effectivement position_ichigo.x etc :
position_ichigo.x = 50;
Donc tes variables (en plus d'être constantes pour le coup) pointent vers des valeurs désuètes inconnues qui ne correspondent à rien de viable dans ton code.
- Lien permanent
-
Paulop
- Posté le
6 juillet 2009 à 22:29:15

-
Il me parait sur le coup plus intéressant de faire une fonction qui prend en paramètre t'es deux SDLRect et qui renvoie s'ils sont en collisions ou non, et avant chaque déplacement tu vérifies.
- Lien permanent
-
Nymo
- Posté le
6 juillet 2009 à 22:40:17

-
Des fonctions spécialisées offrent un calcul plus rapide dans ce cas simple.
Évidemment quand il faudra détecter d'éventuelles collisions avec plusieurs objets dans diverses directions cette méthode devient désuète.
Mais bon le but c'est surtout qu'il comprenne comment ça fonctionne, car vu son code, m'est avis que ses connaissances en programmation sont très partielles/récentes ;)
- Lien permanent
-
Kuroryuu
- Posté le
29 juillet 2009 à 20:02:30

-
merci de vos reponses desoler je n'etait pas la pednant un bout de temps mais j'ai trouver une autre solution merci tout de même
- Lien permanent
Sujet : « [SDL] Systême de collision pixel »