Forums Développement Multimédia

Aller au contenu

displaylist persistente.

CODE

46 réponses à ce sujet

#1 wozhdal

    Ceinture Jaune

  • Members
  • PipPip
  • 23 messages

Posté 20 April 2012 - 10:59 AM

Bonjour,

j'ai un souci avec la display list.


j'ai 5 cube. le héro tire avec une arme qui tire 8 balles donc 8 boucle pour tester les hitTest sur les 5 cubes.

le souci est ; quand une balle touche un cube, le cube appelle la fonction suivante:

parent.removethis(this)
 
le parent fait cette fonction :

function removethis(clip) {
        removeChild(clip)
        clip =null
}
 

pour chaque balle est calculé le long de la trajectoire le hitTest avec le clip CUBES contenant les cubes.
si ce hitTest est True, alors une fonction est appelée pour savoir quel cube est concerné:


function Quelcube() {

nc = CUBES.numChildren
for ( b = 0; b< nc; b++ ) {
        thecube= CUBES.getChildAt ( b );
        if(thecube.hitTestPoint(xx,yy,true)) {  
           res=theclip
           break;
        }
}
res.kill();
}
 

le problème est : lors que la première balle "kill" un cube, une deuxième balle dont la trajectoire serait tombé sur ce cube active de nouveau le kill de ce cube ce qui me donne "erreur : propriété d'un objet null". ce que je ne comprends pas car le cube a bien été effacé de la displaylist et "nullé".
c'est comme si il persistait dans la displaylist le temps de la frame.

comment faire?
merci d'avance




pour aider, voici une image de mon pb:

Image IPB

a noter que le cube avant d'appeller sa mort execute une animation reposant sur ses propriétés (x, y)

lors d'une deuxième for, il n'a plus accès a ses propriétés car il est mort!

#2 Monsieur Spi

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 7017 messages

Posté 20 April 2012 - 11:18 AM

Salut,

Je te conseillerai de passer par des tableaux pour stocker tes objets (cubes et balles).
Et de faire un test sur ces tableaux non pas avec un hitTest mais avec les coordonnées des clips.

Par exemple :

Tu as un tableau avec tous les objets cubes.
Tu ajoute à un autre tableau un nouvel objet "tir" lorsque ton joueur tire.

Tu fais une boucle sur le tableau de stockage des tirs.
Pour chaque tir tu fais une boucle sur le tableau de stockage des cubes.
Si le tir est à l'intérieur du cube (test effectué avec les coordonnées des objets) on retire le cube du tableau et on retire le tir du tableau, au passage on les retire aussi de la liste d'affichage pour qu'ils n'apparaissent plus.

Au prochain test tes deux objets (cube et tir) n'existent plus dans les tableaux donc ton programme ne fait pas le test de collision sur ces objets.

Quand à l'animation pour la mort de chaque cube tu as juste à faire un addchild de l'anim à la position du cube.



EDIT :

Voici un petit code d'exemple, là je crée des tableaux pré-remplis, à toi de les remplir dynamiquement lorsque le joueur tire.



var tirs:Array = [tir, tir, tir, tir];
var cubes:Array = [cube, cube, cube, cube];

function testCollision():void{
       
        var i:int=0;
        var j:int=0;
        var T:Object;
        var C:Object;
       
        for (i; i<tirs.length; i++){
                T = tirs[i];
                for (j=0; j<cubes.length; j++){
                        C = cubes[j];
                        if (T.x>C.x && T.x<C.x+C.width && T.y>C.y && T.y<C.y+C.height){
                                cubes.splice(j,1);
                                tirs.splice(i,1);
                         return;
                        }
                }
        }
}

Je crée donc deux tableaux de stockage.
Je fais une boucle sur le tableau le plus petit (normalement celui des tirs).
Pour chaque tir du tableau je crée une boucle sur le tableau des cubes.
Pour chaque cube je vérifies si le tir que je suis en train de tester se trouve à l'intérieur du cube que je teste.
Si c'est le cas on retire le tir de son tableau et le cube du sien.
Et on stoppe l'exécution de la boucle (à moins qu'il y ait d'autres tirs à tester en même temps).

Une fois que les calculs sont faits il ne reste plus qu'à gérer l'affichage en supprimant le cube et le tir concernés de ta displaylist, et si tu veux ajouter une animation de destruction de ton cube je conseille d'ajouter simplement à la position du cube une animation de ton cru qui se supprime d'elle même lorsqu'elle arrive en fin de lecture (timeline ou code).

Globalement, le but est de gérer les calculs indépendamment de ce qui est affiché, une fois tes calculs faits tu peux gérer ce que tu affiche comme tu le veux.

#3 wozhdal

    Ceinture Jaune

  • Members
  • PipPip
  • 23 messages

Posté 23 April 2012 - 18:34 PM

merci je vais tester ça même si je ne comprends pas pourquoi mon code de base ne marchait pas :P



le soucis pour les clips, c'est qu'il ne s'agit pas de cube mais de persos ou il faut un peu de précision pour faire une animation de ricochet/sang. donc en fait je fais un test hitTest avec false pour le masque de forme. si true, hittest avec true pour masque de forme.
je n'ai pas encore tester ce qui est le moins difficile pour le CPU entre :
un test par HitTest avec false sur forme
et une test par coordonnées .

#4 Monsieur Spi

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 7017 messages

Posté 23 April 2012 - 19:03 PM

Salut,

Citation

même si je ne comprends pas pourquoi mon code de base ne marchait pas

Il peut y avoir plein de raisons, mais je pencherai sur le fait qu'en fait l'objet que tu cible existe toujours dans la displaylist au moment où tu fais tes tests.

Dans tous les cas, mélanger calculs et affichage n'est pas une bonne solution, la preuve tu pense que ton clip n'existe plus alors qu'en fait c'est le cas, a mon sens en tout cas, c'est la même différence qui existe entre "je me déplace et je regarde si je suis dans un mur, ha oui tient merde, bon faut que je me déplace pour revenir à la bonne position" et "je regarde où je vais et si il n'y a pas de mur j'avance, sinon je me colle au mur".

C'est le même raisonnement, tu utilise un objet d'affichage pour savoir quel comportement adopter, c'est un raccourci pratique mais qui entraine ce genre de dérive, tu es confronté au résultat et doit agir en conséquence, plutôt que de regarder ce qu'il se passe par anticipation et réagir en conséquence.

C'est pour cette raison que je te recommande de passer par des tableaux indépendants de la displaylist pour faire tes calculs, puis d'agir sur la displaylist en conséquence de tes observations.

Quand au test de collision avec hitTest ou coordonnées, je préfères les coordonnées, c'est plus souple, plus précis et plus modulable que les classes de base.

Enfin, pour la précision, tu peux très bien combiner les choses, un hittest pour voir si les hitbox sont en contact, puis un test plus précis avec des pixels par exemple pour savoir où se fait la collision.

#5 wozhdal

    Ceinture Jaune

  • Members
  • PipPip
  • 23 messages

Posté 23 April 2012 - 20:55 PM

merci pour les conseils, c'est juste que je suis sur LE projet ou je me suis dit , allez on passe a l'AS3 et c'est un jeu vidéo que j'ai commencé ya >1an alors pas facile d'optimiser mes erreurs au fur et a mesure.

j'ai fait un ptit test intéressant mais pas forcément significatif en condition réelle.
avec un ptit getTimer et une boucle for



var ba = getTimer()
var a:int=0
for(a=0;a!=1000000;a++) {
//if( c.hitTestPoint(100,100,false)){
  if(100>c.x && 100<(c.x+c.width) && 100>c.y && 100<(c.y+c.height)) {
}
//}


}
trace(getTimer()-ba)
 

alors selon les cas voici les résultats en millisecondes:

hitTest true : 649
false : 507
coordonées : 76 !

donc ca semble en effet intéressante de faire une boucle coordonnées puis un hitTest true. :smile:

#6 dldler

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 4163 messages

Posté 24 April 2012 - 08:33 AM

Voir le messageMonsieur Spi, le 23 April 2012 - 19:03 PM, dit :

Salut,

Voir le messagewozhdal, le 23 April 2012 - 18:34 PM, dit :

merci je vais tester ça même si je ne comprends pas pourquoi mon code de base ne marchait pas


Il peut y avoir plein de raisons, mais je pencherai sur le fait qu'en fait l'objet que tu cible existe toujours dans la displaylist au moment où tu fais tes tests.

Je me permet d'intervenir sur ce point.

Le hit test est un test purement géométrique. Il n'a rien a voir avec la liste d'affichage(*) la visibilité des objets.
Pour t'en convaincre, tu peux créer un clip et un point, ne pas les afficher et tenter un hit test. Si le point est inclus dans la forme géométrique, le hit test répondra true. C'est aussi vrai pour deux clips affichés dans des conteneurs différents et distants : les objets peuvent ne pas se superposer visuellement mais le hit test ne regardant que la géométrie relative, il peut répondre true.(*)

Voilà pourquoi il vaut mieux stocker tes objets dans un tableau et faire le test sur les objets du tableau. Si le test est true, tu "tues" l'objet concerné et tu le supprimes du tableau. Et donc j'appuie la remarque de Mr Spi : la liste d'affichage est là pour afficher. Ce n'est pas une structure de travail, surtout pour un jeu, car elle est lente et inadaptée.
De plus, quand on fait le pas de coder dans l'autre sens, (objets de structure qui manipulent des objets graphiques), on gagne en abstraction et beaucoup de choses deviennent plus faciles.

*(précision et correction apportées suite à l'intervention de Nataly).

#7 Nataly

    Community Jane

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 5783 messages

Posté 24 April 2012 - 10:07 AM

Voir le messagedldler, le 24 April 2012 - 08:33 AM, dit :

C'est aussi vrai pour deux clips affichés dans des conteneurs différents et distants : les objets peuvent ne pas se superposer visuellement mais le hit test ne regardant que la géométrie relative, il peut répondre true.

Ah oui ? :)

je viens de faire mon st Thomas, toute contente de découvrir un truc, je n'aipas du bien comprendre :

si je pose côte à côte deux instances (truc et chose) du même clip contenant un clip nommé c1 et que j'écris
trace(truc.c1.hitTestObject(chose.c1))

les coordonnées de chaque c1 sont les mêmes, je devrais recevoir "true"…et ben non…

tu peux me re-expliquer ? ;)
Le savoir est le seul bien qui s'accroit quand on le partage
une tartine de tutos

#8 dldler

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 4163 messages

Posté 24 April 2012 - 10:08 AM

Ah ah :D Ça m'apprendra a vérifier.

je ressors mes tests et je fais le point.

#9 Nataly

    Community Jane

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 5783 messages

Posté 24 April 2012 - 10:48 AM

Du coup, j'y regarde de plus près à ta question ;)

Voir le messagewozhdal, le 20 April 2012 - 10:59 AM, dit :

quand une balle touche un cube, le cube appelle la fonction suivante:

parent.removethis(this)
 

ça ne peut pas tourner tu lèves forcément une erreur, parent étant un DisplayObject :roll:

A ce niveau tu aurais pu te contenter d'écrire

parent.removeChild(this)

et puis… pff… encore bien des choses…
Tu nous collerais l'ensemble du code (concernant cette affaire) ?
Le savoir est le seul bien qui s'accroit quand on le partage
une tartine de tutos

#10 dldler

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 4163 messages

Posté 24 April 2012 - 11:21 AM

Vérification effectué.
J'ai dans ma bibliothèque un symbole Forme qui consiste en un carré de 100 x 100 pixels.


// La cible en (10/10)
var cible:Forme=new Forme();
cible.x=10;
cible.y=10;
// 2 projectiles
var projectile_1:Forme=new Forme();
var projectile_2:Forme=new Forme();
projectile_2.x=400;
// Personne n'est affiché :
// Le hit test fonctionne quand même
trace(projectile_1.hitTestObject(cible)); // true
trace(projectile_2.hitTestObject(cible)); // false
// La cible est affichée, pas les projectiles
// Le hit test fonctionne quand même
addChild(cible);
trace(projectile_1.hitTestObject(cible)); // true
trace(projectile_2.hitTestObject(cible)); // false

// dans un conteneur :
var conteneur:Forme = new Forme();
conteneur.x=400;
// La cible est affichée dans le conteneur,
// mais pas sur la scène.
// Les projectiles ne sont pas affichés
conteneur.addChild(cible);
// Le hit test fonctionne en tenant compte des coordonnées relatives au conteneur
trace(projectile_1.hitTestObject(cible)); // false
trace(projectile_2.hitTestObject(cible)); // true
 


On peut constater que :
- l'affichage ou non sur la scène ne modifie pas le résultat du hit test
- le hit test est calculé en fonction es coordonnées relatives au conteneur le plus haut de la liste d'affichage de l'objet.


En conséquence :
- mon affirmation comme quoi l'affichage ou non de l'objet n'intervient pas est exacte.
- mon affirmation comme quoi la géométrie relative n'intervient pas est fausse : les coordonnées de l'objet sont transposées dans le contexte global de l'objet d'affichage le plus élevé dans la liste d'affichage de chaque objet.

:) En espérant être clair (et juste, cette fois).
Je corrige mon post précédent pour éviter d'induire des passants en erreur ;-)

#11 wozhdal

    Ceinture Jaune

  • Members
  • PipPip
  • 23 messages

Posté 24 April 2012 - 13:54 PM

concernant le "removethis"
j'ai appliqué la méthode indiqué dans le PDF AS3 de thibault imbert indiquant qu'un clip ne peut pas se "nuller" lui même or c'est nécessaire pour libérer la mémoire.

j'ai donc un clip "ObjetDurs" (c'est a dire pouvant recevoir un impact) et chaque sous clip appelle sa propre mort par son parent (ce clip objetdurs) dès qu'il n'a plus de vie. (comme indiqué dans premier post)

je mets en place les tableaux et les coordonnées, ca va me permettre d'optimiser un peu le code car il en a besoin :D



concernant le hitTest sur objet n'étant pas dans la liste d'affichage : je conaissais cette particularités, c'est pour ça que je nullais le clip mais ca ne semble pas suffire ou cela ne s'applique peut-être qu'a la fin de la frame.

#12 dldler

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 4163 messages

Posté 24 April 2012 - 14:09 PM

Voir le messagewozhdal, le 24 April 2012 - 13:54 PM, dit :

concernant le hitTest sur objet n'étant pas dans la liste d'affichage : je conaissais cette particularités, c'est pour ça que je nullais le clip mais ca ne semble pas suffire ou cela ne s'applique peut-être qu'a la fin de la frame.

Tu n'as pas une vision claire du phénomène.
Ce que tu mets à null, c'est ta variable. Pas le clip.
La variable est un lien, un petit élastique auquel on accroche l'objet. Quand on tire sur l'élastique, on récupère l'objet.
Faire :
mavariable=null;
c'est accrocher null à l'élastique et pour cela, le programme détache "le truc" qui était accroché avant et le lâche.
S'il n'y avait pas d'autres élastiques accrochées au truc, celui ci tombe par terre… mais il existe encore.
Quand l'agent de surface appelé garbage collector passe, il ramasse ce qui traîne par terre. Là, on peut dire que le truc disparaît.

Vu comme ça, je pense qu'on comprend qu'il ne faut pas espérer sur l'existence (ou non) d'un objet pour coder. (*)
Il faut utiliser une élastique capable de s'accrocher à plusieurs objets : un tableau. Tu accroches et décroches tes trucs et là tu es sûr de toi.

#13 Monsieur Spi

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 7017 messages

Posté 24 April 2012 - 14:24 PM

(* +1 Didier pour le chat de Schrödinger :lol:, une référence pour les geeks)

#14 wozhdal

    Ceinture Jaune

  • Members
  • PipPip
  • 23 messages

Posté 24 April 2012 - 14:49 PM

ok merci je vois mieux :mrgreen:

#15 wozhdal

    Ceinture Jaune

  • Members
  • PipPip
  • 23 messages

Posté 24 April 2012 - 15:16 PM

Donc j'ai des jolis tableaux donc plus de soucis de propriétés nulle
mais un autre problème parallèle a celui-ci existe : l'optimisation de la détection de mes clips.
je garde le même post car Monsieur psi m'indiquait une solution.

je m'explique, pendant une frame, plusieurs tirs sont lancés,
il s'agit donc de boucle for qui vérifie point par point (a 4 pixels d'espace) le long d'une ligne la présence ou l'absence de clip.
si présence : il vérifie dans un tableaux ( et non dans les sous clip ;) ) quel clip est concerné, lui enlève de la vie puis break; de la boucle for.

je cherche la meilleure optimisation.

ainsi ma première option était : un gros clip contenant les sous clip. a chaque point XY un hitTest "true" sur le gros clip puis on cherche le sous clip concerné par des hitTest false puis un hitTest true pour la haute précision. dès que ca touche quelque chose, on break;

deuxième option: a chaque point, on fait une recherche sur le tableau de sous clips afin de vérifier si XY est (>x,<x+width,>y,<y+width) du sous-clip. bien que rapide cette option ne me convient pas. car mes clips ne sont pas tous accroché en haut a droite ! en effet, beaucoup son centrés (pour les roues, persos, etc..).
alternative : utiliser le getBound ou getRect afin de faire le (>x,<x+width,>y,<y+width) sur le rectangle obtenu et obtenir les vrais coordonées.
problème : getRec et getBound pompe 2 fois + de CPU que hitTest false! (selon tests avec for(a=100000 et getTimer )



avez vous une solution :eusa_doh:

#16 Monsieur Spi

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 7017 messages

Posté 24 April 2012 - 15:35 PM

Re,

Moi j'essayerai plutôt un premier test avec un hitTestObject entre le tir et les cubes (tableaux) simplement pour voir si les hitBox sont en contact, si c'est le cas tu lance une vérification point par point pour connaitre la position exacte de la collision.

Citation

car mes clips ne sont pas tous accroché en haut a droite !

Par défaut il vaut mieux toujours essayer de respecter la même mécanique pour tes objets.
Normalement tu devrais travailler avec une feuille de sprites externe (ou spritesheet : http://slick.cokeand...?id=spritesheet ) et quand tu travaille comme ça il n'y a plus de clips, et les repères de position sont toujours en haut à gauche par défaut.

Si tu ne peux pas faire autrement il te faut compenser dans tes calculs en ajoutant ou retirant la moitié de la largeur et de la hauteur du clip pour "replacer virtuellement" le point d'ancrage pour tes calculs.

#17 dldler

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 4163 messages

Posté 24 April 2012 - 15:39 PM

Pas de solution précise…
Tout juste une hypothèse, sans certitudes de gain en perfs, que je testerais personnellement…
… mais sur une alternative tout à fait différente.
Est-ce que ça t'intéresse vraiment que je développe ?

#18 wozhdal

    Ceinture Jaune

  • Members
  • PipPip
  • 23 messages

Posté 24 April 2012 - 21:55 PM

le problème du hitTestobject, c'est que sur un tir, vu la taille du niveau, il y aura quasi obligatoirement un impact contre le niveau/objet . c'est pour ca que je n'ai pas utilisé cette soluce.

pour les sprites sheet, c'est vrai que j'aurai du mais au début j'étais partis sur que vectoriel. je n'ai bitmapisé qu'au fur et a mesure que ca devenait lourd.

histoire de voir ce dont je parle depuis le début quand même :mrgreen: :
Image IPB

merci dldler mais si ca t'embete, pas grave =) je vais essayer d'optimiser dans mon coin

#19 Monsieur Spi

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 7017 messages

Posté 24 April 2012 - 22:05 PM

Citation

le problème du hitTestobject, c'est que sur un tir, vu la taille du niveau, il y aura quasi obligatoirement un impact contre le niveau/objet .

Et en quoi cela pose problème ?
Logiquement, dés qu'un tir touche quelque chose il y a impact, donc ça me semble être un comportement correct.

De plus le hitTestObject n'est là que pour vérifier si deux hitBox se superposent, le véritable test de collision ne commence qu'a cette condition. Tu peux donc ajouter tout un tas de conditions entre les deux si ça te chante.

#20 wozhdal

    Ceinture Jaune

  • Members
  • PipPip
  • 23 messages

Posté 24 April 2012 - 22:12 PM

Oui je vois ce que tu veux dire, j'avais mal lu, je pensais un hitTestObject avec "true" comme masque de forme.
c'est sur qu'il est inutile d'impliquer des clips qui sont a 2000 pixels du tirs et ca permettrait de faire une selection.

#21 dldler

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 4163 messages

Posté 25 April 2012 - 08:15 AM

Voir le messagewozhdal, le 24 April 2012 - 21:55 PM, dit :

merci dldler mais si ca t'embete, pas grave =) je vais essayer d'optimiser dans mon coin

:D On s'est mal compris.
Ça ne m'embête jamais de développer.
Juste que si Ça n'a aucun d'intérêt pour toi, Ça devient un hors sujet, aggravé par le fait que je n'ai aucune garantie à apporter.

Mr Spi est un bien meilleur interlocuteur que moi sur ce genre de sujet. Profites-en.

Pour amorcer seulement l'alternative, je travaillerais avec une double scène : le décor visible et une map d'impact.
Sur cette map, chaque objet susceptible d'être "impacté" serait dessiné d'une couleur différente. Le hit test devient beaucoup plus simple : dessiner la zone de tir sur un bitmapdata, récupérer la couleur du pixel ou se trouve le projectile. La couleur servant comme un id, on obtient automatiquement une référence à l'objet impacté.

Ça peut sembler gourmand, au premier abord, de dessiner 2 scènes différentes, sauf que :
  • les opés sur les bitmapdata sont quand même rapides
  • si on a beaucoup d'objet impactables, on évite énormément de calcul
  • on peut optimiser de différentes faÇons :

- réduction de la zone de tir par une bonne gestion des projectiles (obtenir un bitmapdata exploitable pour tous les projectiles, par exemple)

- réduction de la map des collisions en fonction du diamètre des projectiles. En effet, si un projectile a un diamètre de 10 pixels, une map des collisions au 10ème est suffisante…


Les plus :
  • possibilité d'utiliser la map des tirs pour d'autres infos : passages secrets, objets cachés (ou non)
  • le nombre de projectiles et d'objets impactables devrait jouer peu sur les perfs
Les moins :
  • beaucoup de travail graphique préparatoire (ce qui moi ne me gênerais pas, je suis graphiste plus que programmeur)
  • attention à la gestion des compressions jpeg et de l'anti-alliasing qui rendent les maps de ce type impraticables
Voilà pour ce qui n'est qu'une intuition assez tentante à aller vérifier, mais pas forcément tentante pour réorienter un projet bien avancé.

#22 wozhdal

    Ceinture Jaune

  • Members
  • PipPip
  • 23 messages

Posté 25 April 2012 - 09:23 AM

ta solution est intéressante mais si je comprends bien, elle ne s'applique pas a des objets en mouvements (mes caisses tombent et peuvent être poussé, les persos bougent).

il n'est pas difficile en AS3 de générer un bitmap data au début du niveau a partir d'objets en coloriant différement la zone par objet.
mais modifier ce bitmapdata chaque frame est beaucoup trop lourd.
cela s'appliquerait par contre sans soucis a un RPG isométrique zelda avec des tiles.

mon niveau général est déja un grand bitmapData ce qui permet de profiter du getPixel bien plus rapide
mais c'est les objets qui bougent, une centaine par niveau qui prennent + de CPU.
je vais essayer la methode du hitTestObject de monsieurPsi.

#23 dldler

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 4163 messages

Posté 25 April 2012 - 09:52 AM

Voir le messagewozhdal, le 25 April 2012 - 09:23 AM, dit :

mais modifier ce bitmapdata chaque frame est beaucoup trop lourd.
C'est bien pourtant ma suggestion : dessiner à chaque frame une map des objet.
J'ai un doute sur la lourdeur, mais pas assez de pratique pour promettre un niveau de performances.
Manipuler des objets graphiques hors affichage est très (très) rapide, c'est le rendu video qui est pénalisant.
Reste le draw du bitmapdata. Toute la difficulté est de le faire le moins souvent possible, sur une surface la moins grande possible…

Mais je suis bien d'accord avec toi : suivre l'avis de Mr Spi est le meilleur pour toi…

#24 Monsieur Spi

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 7017 messages

Posté 25 April 2012 - 10:00 AM

Hello,

Merci Didier, mais tu es bien meilleur que moi dans les optimisations etc... ;-)

Pour avancer sur ton idée, il y aurait en fait deux méthodes que je vois comme ça qui permettraient d'améliorer.

La première phase serait de dessiner deux bitmaps en dehors de Flash, le premier en jpeg ou png avec toutes les couleurs, il servirait de décor, pour le scroller on se sert juste de copypixel et d'une zone à retracer (la zone visible de l'écran), comme ça plus besoin de tuiles.

Ensuite il faut dessiner le même bitmap avec une palette de couleurs réduite, genre 1 couleur par type d'objet/collision, on peut imaginer un truc du genre : noir = sol, cyan = vide, rouge = objet, ....
Il faut ensuite enregistrer le bitmap en PNG avec un nombre de couleurs limitées au strict minimum (évite les bavures de pixels lors de la compression).

Bien, à partir de ces deux bitmaps on peut se lancer sur des tests par getPixel pour récupérer la couleur de la colormap pour les collisions.

Pour optimiser, sachant que faire du getPixel en permanence est un peu lourd surtout si on le fait dans un tableau à deux dimensions, on peut transformer la colomap (le bitmap de collision) en une liste à une dimension (tableau simple) où on stocke avant de lancer le level l'ensemble des valeurs de couleur des pixels (on fait un getPixel de la colomap et on place le résultat dans un tableau avant de lancer le level). Il ne reste plus qu'à faire les tests de collisions sur le tableau ainsi généré, ce qui devrait être beaucoup plus rapide.

Maintenant, je pense que c'est partir dans des choses un peu complexes pour débuter.

Là il faut faire une pause et se poser les bonnes questions.
De ce que je vois de ton jeu (capture) tu es sur du jeu de plateforme, et ces jeux là se font avec des tuiles et quelques bidouilles pour affiner les collisions quand tu veux vraiment être précis.

Je te recommande d'aller lire (survoler dans un premier temps) ce tuto : http://forums.mediab...eux/arcade-base
Ce n'est pas l'idéal mais ça donne pas mal de clés utiles pour optimiser l'ensemble.
Essayes d'en tirer ce que tu peux pour mener une vraie réflexion, et demande toi si tu ne fais pas fausse route en essayant d'être le plus précis possible avec une détection de ton décor par pixels etc... Le risque c'est de devoir refaire ton moteur après réflexion, c'est pour ça qu'il faut bien réfléchir avant, mais c'est sans doute une bonne solution car tu maîtriserai plus le processus.



EDIT : ha zut, je parlais en intro de deux solutions envisageables à partir des deux bitmaps.
La seconde c'est de faire ce qu'on a fait avec Lilive sur le jeu de voiture ici : http://forums.mediab...-ca-vous-tente/
On ne dessine qu'un tout petit rectangle autour du vaisseau sur lequel on fait nos tests, c'est plus rapide.
Dans cet exercice on s'amuse justement à se servir de bitmaps pour les collisions ;-)



EDIT 2 : dans ma solution d'optimisation donnée plus haut j'ai oublié de prendre en compte les objets qui se déplacent et ne peuvent donc pas appartenir à une map fixe (la colormap). Pour les objets je reviens à la solution des tableaux tout bêtes avec une détection d'abord par hitTestObject puis un affinage par pixels ou via du raycasting.

#25 wozhdal

    Ceinture Jaune

  • Members
  • PipPip
  • 23 messages

Posté 25 April 2012 - 10:30 AM

je vais voir tout ça, merci ;)

#26 Monsieur Spi

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 7017 messages

Posté 25 April 2012 - 10:39 AM

Ha oui tient au passage, tu as ici le moteur de N+ : http://www.metanetso.../technique.html

C'est un jeu de plateforme à la physique excellente (voir le jeu ici : http://www.metanetsoftware.com/ ), mais qui utilise une autre méthode, basée sur les maths, les formes géométriques et le raycasting. Pour avoir jeté un œil au moteur, c'est des malades, et c'est chaud à prendre en main, mais ça donne encore une autre manière de faire (même si c'est un peu vers là qu'on essayais de t’emmener au début avec les tests par points) et pour le coup c'est optimisé et précis.

#27 dldler

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 4163 messages

Posté 25 April 2012 - 13:17 PM

Petits essais entre midi et 2.

J'ai un fichier main de 1600 x 800 pixels.
5000 cercles qui se déplacent (chute simple).
Recherche des collisions entre cercle et souris.

Sur un fps max de 60 :
- tout activé : 22 fps
- uniquement les mouvements : 30 fps
- uniquement les collisions : 52 fps
- rien (fps réel observé) : 55 fps

Les chiffres sont un peu obscurs.

Ce que j'en pense, c'est qu'en mode statique : la gestion des collisions pénalise de 3 images le fps ce qui est très peu. Une optimisation possible serait sans doute d'avoir une telle map pour tous les éléments fixes (ou se déplaçant rarement).

En mode animé : l'animation est la plus coûteuse,elle fait perdre 25 fps quand le test de collision n'en fait perdre que 8

Le code est optimisé sur une map réduite (ça correspond à la variable précision de la classe Target).
Pas d'optimisation de type recadrage autour du pointeur, a tester…
De plus c'est un premier jet, je pense qu'on doit pouvoir gagner à plusieurs endroits.

Voilà.
Maintenant, comment comparer avec d'autres méthodes, je ne sais pas trop.
As-tu 5000 éléments mobiles… ça me semble beaucoup ?
A toi de voir. De mon côté, je continue d'y croire avec un peu plus de conviction maintenant. ;-)

Fichier(s) joint(s)



#28 dldler

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 4163 messages

Posté 25 April 2012 - 13:38 PM

PS : je viens de voir en réduisant le nombre d'objets qu'il y a une imprécision importante sur l'axe vertical. Je regarderai quand j'aurai le temps. Je ne pense pas que ce soit grave, ni que ça joue sur les perfs, mais on ne sait jamais. Plutôt un défaut logique dans mes arrondis de précision.

#29 dldler

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 4163 messages

Posté 25 April 2012 - 13:49 PM

Re PS : en fait, je n'avais pas mis de fond à la map des collisions, d'où une traînée de la couleur de l'objet sur le bitmapdata.
Corrigé, sans modification des fps constatée. J'ai mis à jour le lien au dessus.

#30 wozhdal

    Ceinture Jaune

  • Members
  • PipPip
  • 23 messages

Posté 25 April 2012 - 14:44 PM

c'est vraiment intéressant.
je regarde ton code. ( pas commenté d'ailleurs ;-) )
je n'ai que max 300 elements mobiles donc ça va le faire..
j'essaye de tester ça si j'arrive a modifier tout ce qui faut dans mon bordel de code. :smile:

#31 dldler

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 4163 messages

Posté 25 April 2012 - 14:49 PM

Voir le messagewozhdal, le 25 April 2012 - 14:44 PM, dit :

je regarde ton code. ( pas commenté d'ailleurs ;-) )

:D désolé et honte à moi. Je suis plutôt habitué à trop de commentaires plutôt que pas assez. Mais c'est vrai, là je me suis juste amusé pour tester. Si tu as des soucis de compréhension, je te fais ça ce soir.

Pour 300 éléments, la gestion des collisions n'a pas d'influence sur le fps. Faudrait voir au niveau de la décimale, et surtout faire des tests sur une machine moins puissante que la mienne.

#32 Monsieur Spi

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 7017 messages

Posté 25 April 2012 - 15:07 PM

Citation

Faudrait voir au niveau de la décimale, et surtout faire des tests sur une machine moins puissante que la mienne

Fait.

AMD Sempron 1,3 Ghz monocore avec 1Go de ram (le vieux machin quoi).

Collisions + Animation = 7 fps
Collisions seules = 20 fps sans bouger la souris, 16 fps en bougeant la souris
Animation seule = 10 fps

#33 wozhdal

    Ceinture Jaune

  • Members
  • PipPip
  • 23 messages

Posté 25 April 2012 - 15:19 PM

vieux machin ou netbook! or le netbook est quand même une bonne population des pcs aujourd'hui ;)

#34 dldler

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 4163 messages

Posté 25 April 2012 - 16:07 PM

Voir le messageMonsieur Spi, le 25 April 2012 - 15:07 PM, dit :

Fait.
J'espère qu'il s'agit des stats pour 5000 et pas pour 300 sinon rien ne va plus :-/

Bon, sinon, j'ai pris le temps : nettoyage du nom des variables + quelques commentaires.
( pas d'optimisation, pas d'amélioration ;-) )

Bonne lecture.

Fichier(s) joint(s)



#35 wozhdal

    Ceinture Jaune

  • Members
  • PipPip
  • 23 messages

Posté 25 April 2012 - 16:15 PM

merci beaucoup pour tes sources, ca a du te prendre du temps.


J'ai enfin compris ce qui n'allait pas dans le post du début !!!! :o
ce n'était pas un problème de child persistant mais c'est tout bete !!

lors que le hitTest est positif sur un objet, 2 fonctions s'executait:
onde de choc : detecte ce qu'il y a autour de l'objet (comme pour une explosion) ainsi que l'objet lui-même et enlève de la vie au prorata de la distance avec la fonction "impact" du clip
impact : le clip touché perd de la vie...

le clip touché etait déja tué par l'onde de choc : c'est donc normal que la fonction impact ne marche plus, le clip a déja été supprimé !
en tout cas, ça m'aura permis de rationaliser avec les tableaux et d'optimiser avec du bitmap :D

edit:
j'ai donc juste interverti : le clip perd de la vie et meurt eventuellement, puis une onde de choc enlève de la vie ou tue les clips de la zone. l'onde de choc ne se référant pas du tout au clip.

#36 wozhdal

    Ceinture Jaune

  • Members
  • PipPip
  • 23 messages

Posté 27 April 2012 - 16:22 PM

Autre dilemme :

comment feriez vous pour déplacer le personnage (clip) qui est sur un autre clip (plate-forme) en mouvement?

perso, dès qu'une tween bouge la plate-forme, j'ajoute la plateforme a un tableau.
si tableau.length>1 , on vérifie si le héro est dessus ( avec un hitTest 5px en dessous) et on le bouge.
souci : si la plate-forme est trop fine : les 5 px vont trop loin et le perso tombe.
si le perso tombe avec une inertie y importante, il risque de dépasser la plate-forme

comment font-il dans mario bros? ^^

que feriez-vous?

#37 Monsieur Spi

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 7017 messages

Posté 27 April 2012 - 16:33 PM

Salut,

Citation

que feriez-vous?

Moi je ferais ça : http://forums.mediab...eux/arcade-base
J'ai écrit ce tuto pour justement répondre à ces questions, je préfère te filer le lien que de me répéter, même si ce n'est pas un moteur pro et que ce n'est pas la meilleure des solutions, je pense que cela t'apportera les réponses ou au moins les éléments de réponse dont tu as besoin.

Bon courage.

#38 wozhdal

    Ceinture Jaune

  • Members
  • PipPip
  • 23 messages

Posté 27 April 2012 - 16:46 PM

en fait j'avais commencer a lire ton tuto très bien fait mais je me suis arrêter avant la fin puis je l'ai oublié ;) merci

#39 Monsieur Spi

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 7017 messages

Posté 27 April 2012 - 16:50 PM

Lis le jusqu'au bout et pioche dedans ce qui te semble intéressant (si tu n'as pas le courage de le faire entièrement), ça te donnera déjà les pistes de départ, reviens nous en causer quand tu aura avancé, mais en attendant parcours au moins le tuto pour ces questions, sinon nous on se répète à chaque jeu de chaque nouveau membre ;-)

#40 wozhdal

    Ceinture Jaune

  • Members
  • PipPip
  • 23 messages

Posté 06 June 2012 - 15:02 PM

voici le jeu final ;)

http://www3.jeux.com...php?IDJeux=5704

participant a la casualgamescup.com

malheureusement, jeux.com restreint l'affichage du jeu a 605px de largeur par défau : il faut mettre "jouer en plein écran"

#41 Monsieur Spi

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 7017 messages

Posté 06 June 2012 - 15:11 PM

Salut,

Bravo, le jeu est fluide, propre et plutôt bien réalisé.
Je n'aime pas les jeux avec des bonhommes en stick (batons), je trouve ça assez dommage alors que le reste du jeu est plutôt bien dessinné. Ceci dit cela donne un petit côté humoristique donc ce n'est pas forcément plus mal, mais dans ce cas j'aurai un peu plus développé l'intro.

Peux-tu nous dire les choix que tu as fait au final pour ton jeu afin que les autres membres puissent s'appuyer sur ces choix pour leurs propres réalisations. N'hésites pas non plus si tu as le temps à nous faire un petit retour d'expérience, ce serait sympa là aussi pour les autres membres.

#42 dldler

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 4163 messages

Posté 06 June 2012 - 15:23 PM

Pas mal, pour le game play en tous cas.
Graphiquement, je suis beaucoup moins fan (décors et personnage).

PS : si vous prenez le bazooka, prenez également quelques cours pour ne pas vous le faire exploser à la figure :D

#43 Monsieur Spi

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 7017 messages

Posté 06 June 2012 - 18:19 PM

Re,

J'ai voulu réessayer le jeu et je suis tombé sur quelques bugs, du coup je ne suis pas allé plus loin.

1 - juste au départ du jeu je me retrouve dans une zone noire située à premuère vue entre le loading et le décor (voir les deux captures).

Image attachée: pb2.jpg

Image attachée: pb3.jpg

2 - changer d'arme avec la molette de la souris est une bonne idée, sauf que c'est la page HTML qui a le focus sur la molette et c'est elle qui bouge pour le coup.

#44 wozhdal

    Ceinture Jaune

  • Members
  • PipPip
  • 23 messages

Posté 06 June 2012 - 20:56 PM

salut! content que ca plaise un peu.

concernant ton carré noir, il semblerait que le chargement du level ne se soit pas passé comme prévu ce qui fait que l'écran de chargement a persisté. étrange, je n'ai jamais eut ce souci sur mon quadcore 12 go ou sur mon netbook 2go. (je parle de la ram car l'écran de chargement correspond a la bitmapisation des niveaux vectoriels et c'est la ou flash peut dire hop hop hop, trop gros ton bitmap :P )

pour la molette en effet, c'est une fonction inutile mais indispensable car c'est un reflexe que l'on a de changer avec la molette et certain se retrouverait frustré (comme moi ) . cette fonction est très utilisable en mode projection flash.

pour les bonhomme en stick, j'ai toujours apprécié ce style simple qui fait un peu dessiné a la main. de plus, étant graphiquement nul, c'est beaucoup plus simple a dessiner.


Concernant la conception, je rappelle comme indiqué plus haut dans le post que j'ai commencé l'AS3 (ainsi que la notion de classes) avec ce jeu commencé il y a 2 ans et conçu par saccades en fonction des mes envies de jeter l'ordi par la fenêtre.

c'est je penses l'exemple de code qu'il ne faut pas faire ! donc je n'ai pas de conseil a donner.
j'entends par la :
- 4 enterframes pour chaque objet :P (physique, IA, controle, déplacement bras et tir) ce qui fait >50 enterframes en marche chaque frame =)
- des variables plus ou moins publiques, plus ou moins nullées, plus ou moins typées.
- des classes recopié entièrements au lieu d'utiliser l'héritage (pour les ennemis par exemple)
bref codé avec les pieds.

voici qu'elle ont été mes principaux problèmes :
1) un niveau destructible: comment le réaliser? > il y a pour cela au chargement du niveau une bitmapisation de 4 couches:
- le fond (décor du niveau et du terrain quand détruit)
- le terrain (terre avec une couche de bitmap flouté pour enlever le coté uni d'une texture infinie)
- le "block" : un bitmap transparent avec les zones indestructibles
- le niveau : un bitmap noir et blanc pour indiquer les zones ou on peut être.
ca fait tout de même 4 bitmap de 3500*2600px a générer avec des draws et a mettre dans la ram. puis tout est cloné dans un tableau en cas de restart de niveau afin d'éviter de tout recharger (long pour les petits ordis, de quoi perdre le joueur)
(les bitmaps doivent être gardé en mémoire et non réutilisées car je créé du sang et des impacts sur ces bitmaps)
ce qui fait quand même 400 mo de ram nécessaire.

tout est copyPixels() a chaque frame dans l'ordre logique : terrain , fond avec niveau en alpha, block

au début, j'affichais simplement les grand bitmaps sur la scène et ca marchais très bien mais ca faisait pas pro =) .


2 ) la physique des particules : je n'ai aucune notion de math a part celle de terminale que j'ai vite fait d'oublier. ca a donc été beaucoup d'essais a gérer les cos et les tans. en effet, le niveau étant destructibles, ce n'est pas vraiment des carrés, rond, etc...
a chaque impact, il y a donc une detection en cercle a 10px de diamètre du niveau afin de détecter dans quel sens la particule doit repartir ( ce n'est d'ailleur pas totalement au point : lancer une grenade au plafond, elle revient vers vous... certaines particules s'enfonce hors du niveau..)

3) juste avant de finir le jeu se posait le problème de ralentissement important qui disparaissait d'un coup mais qui rendait le jeu injouable.
il se trouve que lancer un garbage collector redonnait la fluidité au jeu. il s'agissait de la création des particles, tirs, explosions, flash qui faisait ramer a fond et leur non suppression de la mémoire. (attention au new Objet() ! )
j'ai donc fait pour tout ces éléments un "pool" ("stock") créé dès le début du niveau que j'utilise et restocke dès que nécessaire comme indiqué sur certains sites : quel soulagement de retrouver la fluidité (merci d'ailleurs au ptit logiciels de débogage : theminer.com qui permet de voir les fonctions consommant le plus d'un swf)

4) la détection des clips lors d'un tir, ou toutes les secondes pour voir si un ennemi voit le perso... beaucoup de getPixels et hitTest par frame!

5) rester dans une taille raisonnable tout en proposant assez de contenus : 20 samples de musique différents, 50 textures png 64*64 ou 128*128 pour les décors. le tout en restant dans <4mo.

6) comment faire les niveaux : un éditeur de niveau? une movieclip pour chaque niveau?
j'ai finalement fait un clip complet avec 2 frame pour chaque niveau ce qui fait 40 frames.
1 frame avec les 5 clips de niveaux : fond, terrain, block, zone cachées, qui seront bitmapisé au chargement.
1 frame avec les enemis, triggerzone, deadzone, portes, bonus,...

ce clip très lourd a permis d'être très visuel dans la conception des niveaux étant donné qu'il était réalisé avec Flash professional
donc a la main. pas mal d'utilisation de texture réalisées avec Genetica 3.5 pour enlever l'effet horrible des aplats unis et dégradés.
pour rajouter de la profondeur, les clips "block indestructible" et "niveau" avaient un filtre de "rayonnement/glow" externe et interne. le souci, c'est que c'est sur pour flash de faire des filtres sur des clips de 3500*2600px.
bien entendu, je ne pouvais pas faire mes niveaux entièrement sous toshop, la taille aurait été trop importante et cela aurait été trop compliqué de différencier le terrain, le fond, le block.

j'aurais retenu de ce jeu (que je pense être le dernier car adieu flash, bonjour html5..) :
- bien dissocier les objets en mémoire et leur affichage. notamment ne pas se fier au getChildAt
- flash, ça rame. j'aurais bien fait en starling mais j'était déja trop loin.
- bien détruire et nuller tout les objets !
- la physique : c'est dur.



le but premier était de réaliser un jeu comme "worms" et "soldat" en solo, en 2D, avec plein d'armes, de sang, des références geek, et la possibilité de détruire le décor. c'est chose réussie

(référence geek = l'histoire, des armes uniques comme le lance boulet de serious sam, le dégraviteur de half life, il y a même un portal gun quelque part mais qui ne marche pas parfaitement, il y a aussi une arme permettant de prendre le controle des enemis!
un des niveaux ressemble au niveau 1 de mario. un reprend le principe du jeu cube..)
si vous cherchez bien, il y a une sainte grenade dans le jeu =)

concernant les conseils qui m'ont été gentiment donné pour l'utilisation de bitmap de collision, j'ai essayer de l'appliquer mais ça a ramé a fond, du coup j'ai abandonné.
et j'aurais du lire le tutoriel de création du jeu avant de commencer, j'aurais éviter des erreurs!

je vous invite a essayer de finir le jeu! =)
même avec les cheats codes ce n'est pas facile :

iamabiglooser : toutes armes, clés, jetpack
(a taper pdt le jeu, pour essayer toutes les armes)

#45 wozhdal

    Ceinture Jaune

  • Members
  • PipPip
  • 23 messages

Posté 06 June 2012 - 21:01 PM

un des grand plaisir que j'ai eu a été de mettre des fonctions +/- uniques que l'on retrouve éparpillées dans d'autre jeux:

- destruction décor (worms)
- jetpack (soldat)
- recul des armes importants et qu'il faut gérer
- un peu de gore et de sang projeté partout
- une interface de hack ou il faut taper vite au clavier/jeu de snake pour ouvrir certaines portes.
- les clés sont des clés usb
- possibilité de prendre controle des enemis (tourelles, soldats,..)
- un système de code niveau a l'ancienne ou il faut le noter sur un papier.
- mettre des zombies
- avoir vraiment l'impression de détruire quelque chose avec une gatling et lance-roquette.



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

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