Forums Développement Multimédia

Aller au contenu

Stratégie Collision

CODE

3 réponses à ce sujet

#1 Jean-PierreM

    Ceinture Blanche

  • Members
  • Pip
  • 9 messages

Posté 11 August 2011 - 00:52 AM

Bonjour,

Développeur web AS3, je vais changer de domaine et vais travailler au développement d'un jeu 2D: un personnage/vélo se déplace dans les rues d'une ville, une carte en vue top-down. Néophyte pour le développement de jeux, j'ai lu nombre d'articles sur les collision, et j'aimerai savoir quelle serait la préparation et la stratégie la plus adaptée à mon jeu pour gérer la collision de mon personnage avec les éléments fixes du décor: arbres, murs, bâtiments. Ces éléments sont de formes irrégulières.
Ces éléments fixes on été créés sous Illustrator, importés dans Flash et disposés sur la carte. Certains sont devenus des Graphics, d'autres des Movie Clips, d'autres encore des Groups... Cette carte, 3000*2000, n'est pas isométrique, les rues sont sinueuses.

Créer une grille de tuiles vide/pleines semble inadapté pour gérer ces collisions. Dois-je alors créer une liste de tous mes objets fixes et tester une collision avec hitTestObject à chaque "EnterFrame event"?

Si le niveau jouable est la carte zoomée d'un facteur 2, cela laissera beaucoup d'éléments non-visibles, hors "stage" et donc des calculs pour rien. Dois-je alors partitionner ma carte en grille, recenser tous les objets fixes pour chaque tuile et tester les collisions uniquement pour les tuiles visibles sur la scène?

Le personnage se déplace sur la carte, la carte ne bouge pas. Quand le personnage atteint un bord du cadre de la scène, je pense le repositionner sur le bord opposé de la scène et charger la portion de carte qu'il aborde... Est-ce une idée raisonnable?

Qu'en pensez-vous? Merci d'avance

#2 Monsieur Spi

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 7017 messages

Posté 11 August 2011 - 16:46 PM

Salut,

Citation

Créer une grille de tuiles vide/pleines semble inadapté pour gérer ces collisions.

Pourquoi ?

Tu gères de toute façon pas les collisions via les tuiles mais via des grilles virtuelles normées et quelques formules, l'affichage (tuiles) ne doit pas intervenir là dedans.

Quand à différencier ton décor (map) et tes objets c'est autre chose, tu peux gérer les objets via de simples listes qui comprennent ses paramètres (position dans la map, forme, etat, type....). Tu parcours les listes pour savoir quand afficher un objet (quand il se trouve dans la zone visible) et quand le retirer de l'affichage (quand il sort de la zone visible).

Ensuite tu peux gérer différentes couches d'affichage supperposées, une pour le décor (géré avec des tuiles), une pour les objets (gérée avec des tableaux, des Sprites et quelques formules).

Sinon tu as d'autres pistes possibles comme utiliser deux bitmaps et un peu de copyPixel, un bitmap te sert à afficher le décor, il est en couleurs réelles, copyPixel sert à gérer les scrolling (n'afficher que la partie visible en retraçant la partie du bitmap d'origine). L'autre bitmap est simplement le tracé du décor en deux couleurs, avec un test de couleur (getPixel) sur ce bitmap tu sais si il y a collision avec le décor (blanc = terrain non solide, noir = terrain solide, ...). Tu peux ainsi gérer de multiples collisions en fonction des couleurs touchées, vert = herbe, gris = béton, jaune = sable, ...


Citation

tester une collision avec hitTestObject à chaque "EnterFrame event"?

Deux erreurs dans la même phrase ;-)

Evite hitTestObject, ce n'est pas recommandé pour les jeux, passes plutôt par des conditions et des formules de collisions classiques (voir : http://flash.mediabo...des-collisions/ ), une simple formule de math ou une série de conditions te permet de savoir si deux surfaces sont en contact.

Evite aussi EnterFrame qui à la fâcheuse tendance à ne pas être régulier et de dépendre de la machine sur laquelle le jeu tourne, et permet en outre de ralentir le jeu et donc de tricher, utilise plutôt un petit calcul basé sur le temps qui passe, un getTimer en somme, pour cadencer ton projet.

Citation

recenser tous les objets fixes pour chaque tuile et tester les collisions uniquement pour les tuiles visibles sur la scène?

Si tu utilise des listes et un calque d'affichage dédié pour tes objets le problème ne se pose plus.
Pour savoir si un objet doit être affiché ou pas on regarde sa position donnée par le tableau (ou la liste).
Si il est affiché c'est qu'il est dans la zone d'affichage (donc ajouté au calque dédié), on peut tester la collision.
Sinon c'est que l'objet est retiré du calque dédié donc pour ne tester la collision que sur les objets affichés tu regarde simplement tous les objets contenus dans le calque (conteneur) dédié.

Citation

Le personnage se déplace sur la carte, la carte ne bouge pas. Quand le personnage atteint un bord du cadre de la scène, je pense le repositionner sur le bord opposé de la scène et charger la portion de carte qu'il aborde... Est-ce une idée raisonnable?

Faire un scrolling n'est pas la fin du monde non plus, mais si tu préfères ce type de Gameplay c'est possible, cependant il comporte un gros défaut, ce n'est pas fluide et le joueur est obligé de se coller à un bord pour changer de map, ce qui ne lui laisse pas beaucoup de champ d'action si un ennemi ou un objet se trouve juste derrière au prochain pas dans la prochaine map.


Je ne suis pas un pro du dev de jeux mais j'ai monté un petit tuto qui devrait sans doute te donner quelques idées : http://ressources.me...eux/arcade-base

Dans le dernier exercice (Outils) je file l'éditeur et le moteur du jeu (lire tous les exercices pour les explications détaillées). Avec l'éditeur tu peux construire des maps jusqu'à 1500*1500 tuiles (la taille dépend de la norme utilisée, pour mon jeu j'ai choisi 32 pixels, donc des maps de 32 000 * 32 000 pixels) ce qui laisse pas mal de marge, et ca ne rame pas pour autant. La différence entre ton jeu et le tuto que je te propose (si j'ai bien compris) concerne juste l'affichage qui est en Top Down pour toi et en latéral pour moi, et que tu n'utilise bien sur pas la gravité, ce sont des modifications simples à faire. Tu supprime la gravité (et les codes associés) et tu remplace les sprites de profil par des sprites Top Down.

Bon courage.


EDIT :

J'ai oublié ça :

Citation

Ces éléments sont de formes irrégulières.

Là c'est déjà plus complexe si tu veux de la collision réaliste (c'est à dire sur la forme précise), avec un hitTestObject tu peux oublier déjà, ensuite tu as des lib comme Box2D qui vont te permettre de gérer une physique propre mais là encore on reste sur des éléments simples comme un cercle ou un rectangle. Il existe bien sur des solutions pour faire des collisions propres sur des surfaces complexes mais ca devient coton : http://www.siteduzer...-complexes.html

#3 Jean-PierreM

    Ceinture Blanche

  • Members
  • Pip
  • 9 messages

Posté 11 August 2011 - 18:40 PM

Tout d'abord un grand merci pour tes réponses. Elles m'aident beaucoup pour tenter de comprendre les tenants et aboutissants et ouvrent pas mal de pistes, notamment l'usage de bitmaps et d'un timer. Je vais les étudier pour bien les comprendre, et voir lesquelles sont adaptés à mon jeu, qui ne nécessite pas l'usage d'algorithmes de collision poussés.

Juste une petite réponse : pourquoi créer une grille de tuiles vide/pleines me semblait inadapté pour gérer ces collisions?
Les formes des bâtiments, des objets fixes sont irrégulières, et ne remplissent pas forcément toute une tuile. La tuile étant à moitié pleine...
Après je me dis que je peux diminuer la taille de mes tuiles pour accommoder ces formes, 32px vers 16px ou plus petit suivant le niveau de granularité que je souhaite.
Je pensais plutôt appeler hitTestPoint sur mes objets fixes et tester sur mon personnage, ou alors créer des "masques" regroupant des objets et tester sur ces masques. Bon il me reste beaucoup à étudier !

#4 Monsieur Spi

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 7017 messages

Posté 11 August 2011 - 19:09 PM

Citation

Les formes des bâtiments, des objets fixes sont irrégulières, et ne remplissent pas forcément toute une tuile. La tuile étant à moitié pleine...

Si tu dois faire des collisions précises sur des formes complexes tu devras passer par des algorithmes plus ou moins complexes.
La solution pour rester simple c'est de faire toujours des collisions sur des formes simples, et la plus facile c'est le rectangle (on peut d'ailleurs passer par la méthode "intersect" de la classe "rectangle" pour simplifier encore).

Citation

Après je me dis que je peux diminuer la taille de mes tuiles pour accommoder ces formes, 32px vers 16px ou plus petit suivant le niveau de granularité que je souhaite.

Oui, ou ajouter une condition sur certaines tuiles.
Tu as 4 types de demi tuiles, droite, gauche, haut, bas.
Tu connais ces tuiles grâce à leur référence dans la map :

tuiles 32 à 39 = gauche
tuiles 40 à 47 = droite
tuiles 48 à 55 = haut
tuiles 56 à 63 = bas

Quand tu teste la collision sur ces groupes de tuiles tu modifie le test de collision pour qu'il prenne en compte la marge supplémentaire (une demi tuile).

Pour une collision entre un point A et un rectangle B tu as par exemple :


// tuile pleine
if (A.x>B.x && A.x<B.x+B.width && A.y>B.y && A.y<B.y+B.height) {
    // les deux objets se touchent
}

Dans le cas ou B est une demi tuile (pour l'exemple, de type "haut", c'est à dire espace vide en bas) :


// demi tuile haut
if (A.x>B.x && A.x<B.x+B.width && A.y>B.y && A.y<B.y+B.height*.5) {
    // les deux objets se touchent
}




1 utilisateur(s) li(sen)t ce sujet

0 membre(s), 1 invité(s), 0 utilisateur(s) anonyme(s)