IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Physique Discussion :

Problème gestion de collisions


Sujet :

Physique

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 9
    Points : 8
    Points
    8
    Par défaut Problème gestion de collisions
    Bonjour à tous,

    Je débute en SDL et j'ai entrepris la création d'un Pacman comme premier projet.
    La gestion des collisions marche impeccable mais est malheuresement trop "rigide". Le joueur doit être placé pil poil au pixel près pour pouvoir se déplacer, pas vraiment pratique si l'on doit tourner en vitesse car on n'est poursuivi par les fantômes. J'aimerai donc donner une meilleure "flexibilité" au joueur. Comment puis-je m'y prendre ?

    Voici mes 2 classes principales et la méthodes main.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    ...
    Labyrinthe lab1...
    ...
    			switch(event.key.keysym.sym){
    				case SDLK_ESCAPE :
    					boucleJeu = false;
    					break;
    				case SDLK_UP :
    					if((lab1.gestionCollision(posPacman.x, posPacman.y,HAUT))==false){
    						cout << "collisionHaut" << endl;
    					}
    					else{
    					posPacman.y-=2;
    					}
    					break;
    				case SDLK_DOWN :
    					if((lab1.gestionCollision(posPacman.x, posPacman.y,BAS))==false){
    						cout << "collisionBas" << endl;
    					}
    					else{					
    					posPacman.y+=2;
    					}
    					break;
    				case SDLK_LEFT :
    					if((lab1.gestionCollision(posPacman.x, posPacman.y,GAUCHE))==false){
    						cout << "collisionGauche" << endl;
    					}
    					else{
    					posPacman.x-=2;
    					}
    					break;
    				case SDLK_RIGHT :
    					if((lab1.gestionCollision(posPacman.x, posPacman.y,DROITE))==false){
    						cout << "collisionDroite" << endl;
    					}
    					else{
    					posPacman.x+=2;
    					}
    					break;
    				}
    			break;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
     
    bool Labyrinth::gestionCollision(int i, int j, Direction direction)
    {
    	char caractere1 = ' ';
    	char caractere2 = ' ';
    	int caseSuivante=1;	
     
    	if((direction==GAUCHE)||(direction==DROITE)){
    		// Si on est à la bonne hauteur
    		if(j%TAILLE_BLOC==0){
    			if(i%TAILLE_BLOC==0){
    			caractere1 =getElement(i/TAILLE_BLOC, j/TAILLE_BLOC,direction);
    			}
    		}
    		// caractere1 : Mise à la bonne hauteur 
    		// caractere2 : Verification de la case en dessous 
    		else{
    			if(i%TAILLE_BLOC==0){
    			j = j - j%TAILLE_BLOC;
    			caractere1 =getElement(i/TAILLE_BLOC, j/TAILLE_BLOC, direction);
    			caractere2 =getElement(i/TAILLE_BLOC, j/TAILLE_BLOC+caseSuivante, direction);
    			}
    		}
    	}
     
    	if((direction==BAS)||(direction==HAUT)){
    		// Si on est à la bonne largeur
    		if(i%TAILLE_BLOC>=0){//&&(i%TAILLE_BLOC<=4)){ // Un peu de "jus" à Pacman
    			if(j%TAILLE_BLOC==0){
    			caractere1 =getElement(i/TAILLE_BLOC, j/TAILLE_BLOC,direction);
    			}
    		}
    		// caractere1 : Mise à la bonne hauteur 
    		// caractere2 : Verification de la case en dessous 
    		else{
    			if(j%TAILLE_BLOC==0){
    			i = i - i%TAILLE_BLOC;
    			caractere1 =getElement(i/TAILLE_BLOC, j/TAILLE_BLOC, direction);			
    			caractere2 =getElement(i/TAILLE_BLOC+caseSuivante, j/TAILLE_BLOC, direction);
    			}
     
    		}
    	}
     
    	// Le switch prend en compte si Pacman est entre deux blocs
    	switch(caractere2){
    		case ' ' :
    			// Si pastille
    			if(caractere1==' '){
    				return true;
    			// Si vide
    			}else if(caractere1=='0'){
    				return true;
    			}else {
    				return false;
    			}
    	}
    	return false;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    char Labyrinth::getElement(int i, int j, Direction direction)
    {
    	int dimX = dimensionX / TAILLE_BLOC;
    	int dimY = dimensionY / TAILLE_BLOC;	
     
    	if((i <= dimX)&&(j <= dimY)) // On vérifie si l'élément est bien dans la map
    	{
    		int emplacement;	
     
    		// positionCourante, haut, bas, gauche, droite
    	int dx[]={ 0,  0, 0, -1, 1 };
    	int dy[]={ 0, -1, 1,  0, 0 };
    	int x=i+dx[direction], y=j+dy[direction]; // par rapport à l'autre méthode, on intervient en amont
     
    	emplacement = y*dimX+x;
    		return map.at(emplacement); // Afficher un seul élément d'un string
    	}
    	return '?';
    }

  2. #2
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20
    Points : 18
    Points
    18
    Par défaut
    Déja, dans un "vrai" pacman ton problème ne se pose pas car le pacman avance tant qu'il ne rentre pas dans un mur et on ne peut pas tourner de 90 degrées dans un couloir, alors que ton pacman n'avance que quand tu appuie sur une touche

    Si tu veux garder ton mode de fonctionnement, il va falloir ruser. Je ne sais pas si tu est déja en train de faire ça parceque j'ai pas lu tout ton code, mais l'idée c'est qu'il faut faire glisser le pacman quand il veut tourner alors qu'il n'est pas complètement aligné, de manière à ce qu'il devienne aligné.

  3. #3
    Membre éclairé
    Avatar de N_I_C_S
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    450
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 450
    Points : 681
    Points
    681
    Par défaut
    Salut,
    C'est clair, comme le dit Jyaif, 2 options.

    Soit tu veux faire un pacman "original", alors les évennements des touches doivent juste mettre à jour des flags qui ne seront interprétés que lors des collisions du perso en mouvement dans la boucle principale.

    Soit tu laisse un mouvement libre et ça implique de faire des procédures de collision plus complexes tenant compte de la géométrie exacte du tableau.

  4. #4
    Membre éprouvé
    Avatar de Sivrît
    Profil pro
    Inscrit en
    Février 2006
    Messages
    953
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Février 2006
    Messages : 953
    Points : 1 249
    Points
    1 249
    Par défaut
    Effectivement mieux vaudrait garder la direction du déplacement (quitte à avoir un "point mort"). Le code reste presque le même mais au lieu de déplacer le pacman on change de direction si le test de collision le permet (et donc s'il n'y a pas de couloir on va tout droit, ce qui permet de tourner facilement si l'on appuie sur la touche avant le passage et qu'on la garde enfoncée).

    Et la maj des coordonnées en fonction de la direction est reportée vers la boucle principale, ce qui permet de s'affranchir de la vitesse de répétission des touches.

    Flexible, agréable et à moindres frais

  5. #5
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Une autre solution est de garder ton système (donc si on appuie, on avance, sinon on est à l'arrêt) et de gérer le mouvement horizontal/vertical séparément.

    Supposons que j'appuie vers le bas et je veux aller à gauche à la prochaine intersection.
    J'appuie sur les deux fléches en même temps. Tant que je ne suis pas devant le couloir, la direction vers le bas est utilisée (pas de collision verticale), dès que j'arrive vers le couloir, la direction horizontale est prise en compte.

    Ceci supposera quelques hypothése sur le mouvement maximum entre deux tests de collisions mais est faisable rapidement aussi.

    Sinon, fait des couloirs plus larges

    Jc

    EDIT: Vu le code, j'ai l'impression que tu gères déjà ce genre de chose. Donc une des solutions déjà proposées me semble le mieux

  6. #6
    Futur Membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 9
    Points : 8
    Points
    8
    Par défaut
    Merci à tous pour vos conseils. :-)

    1/ Dans un vrai Pacman, il faut parfois tourner à 90°. :-)
    Voici une version Flash du jeu : http://www.ebaumsworld.com/pacman.html

    2/ J'ai essayé de "glisser" le pacman mais cela pose un petit problème esthétique. Même à 1 ou 2 pixels près, ca ne passe pas inaperçu.

    3/ En fait, je voulais réussir ce point dans un but pédagogique. J'ai donc suivi vos conseils : mon pacman avance désormais tout seul et si j'appuye sur une touche alors alors que cela engendrerait une collision, le pacman ne change pas de direction. :-)

    Pour que d'autres puissent en profiter :

    Méthode main :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    	// Boucle de Jeu
    	while(boucleJeu){
     
    	tempsActuel = SDL_GetTicks();
    	if (tempsActuel - tempsPrecedent > 30) /* Si 20 ms se sont écoulées */
    	{	
    	SDL_PollEvent(&event);
    	switch(event.type){
    		case SDL_QUIT : 
    			boucleJeu = false;
    			break;
    		case SDL_KEYDOWN :
    			switch(event.key.keysym.sym){
    				case SDLK_ESCAPE :
    					boucleJeu = false;
    					break;
    				case SDLK_UP :
    					if((lab1.gestionCollision(pacman.getPositionCouranteX(), pacman.getPositionCouranteY(),HAUT))==true){
    						direction = HAUT;
    						pacman.pacmanActuel = pacman.pacman[HAUT];
    					}
    					break;
    				case SDLK_DOWN :
    					if((lab1.gestionCollision(pacman.getPositionCouranteX(), pacman.getPositionCouranteY(),BAS))==true){
    						direction = BAS;
    						pacman.pacmanActuel = pacman.pacman[BAS];
    					}
    					break;
    				case SDLK_LEFT :
    					if((lab1.gestionCollision(pacman.getPositionCouranteX(), pacman.getPositionCouranteY(),GAUCHE))==true){
    						direction = GAUCHE;
    						pacman.pacmanActuel = pacman.pacman[GAUCHE];
    					}
    					break;
    				case SDLK_RIGHT :	
    					if((lab1.gestionCollision(pacman.getPositionCouranteX(), pacman.getPositionCouranteY(),DROITE))==true){
    						direction = DROITE;
    						pacman.pacmanActuel = pacman.pacman[DROITE];
    					}
    					break;
    				}
    				break;
    			}
    	if((lab1.gestionCollision(pacman.getPositionCouranteX(), pacman.getPositionCouranteY(),direction))==true){
    		pacman.seDeplacer(direction);
    	}
    	tempsPrecedent = tempsActuel; /* Le temps "actuel" devient le temps "precedent" pour nos futurs calculs */
     
    	}

    NB : Je gére désormais Pacman comme un objet. Il dispose également d'un attribut Vitesse désormais.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    void Hero::seDeplacer(Direction dir){
    	switch(dir){
    		case GAUCHE :
    			positionCourante.x-=vitesse;
    			break;
    		case DROITE :
    			positionCourante.x+=vitesse;
    			break;
    		case HAUT :
    			positionCourante.y-=vitesse;
    			break;
    		case BAS :
    			positionCourante.y+=vitesse;
    			break;
    	}
    }

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20
    Points : 18
    Points
    18
    Par défaut
    Citation Envoyé par kaien
    Merci à tous pour vos conseils. :-)
    2/ J'ai essayé de "glisser" le pacman mais cela pose un petit problème esthétique. Même à 1 ou 2 pixels près, ca ne passe pas inaperçu.
    Pour l'avoir déja fais je peux te dire que c'est pas normal, et que tu n'as pas du le faire correctement

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [CS5] Problèmes de gestion de collisions en AS3
    Par Eshra dans le forum ActionScript 3
    Réponses: 10
    Dernier message: 14/12/2011, 16h01
  2. Problème de gestion de collision [encore]
    Par _SamSoft_ dans le forum SDL
    Réponses: 3
    Dernier message: 27/02/2008, 12h28
  3. Problème de gestion de collision
    Par _SamSoft_ dans le forum Développement 2D, 3D et Jeux
    Réponses: 1
    Dernier message: 26/02/2008, 15h24
  4. Gros problème de gestion de collisions [C et SDL]
    Par _SamSoft_ dans le forum Développement 2D, 3D et Jeux
    Réponses: 13
    Dernier message: 06/12/2007, 13h09
  5. Gestion des collisions - terrains
    Par Dranor dans le forum DirectX
    Réponses: 1
    Dernier message: 26/06/2003, 18h50

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo