[Résolu] objectsConcerned : Ajouter des objets concernés

Bonjour 4ian,

J’ai créé une condition permettant de tester si un objet est sur une “ligne” d’un afficheur de Tableaux.
Ma condition marche, mais je m’attarde sur les objets concernés : je veux que la condition teste si un objet est sur la ligne, et qu’elle mette les instances de l’objet dans la liste des objets concernés.
J’ai donc fait comme ceci :

ObjList list = objectsConcerned.PickAndRemove(condition.GetParameter( 1 ).GetAsObjectIdentifier(), condition.IsGlobal());

Pour récupérer la liste des objets (du nom que l’utilisateur donne dans la condition) concernés.

Il y a ensuite une boucle qui passe sur tous les objets récupéré avec PickAndRemove. Et j’ajoute les objets pour lesquels la condition est valide dans la liste des objets concernés :

objectsConcerned.AddAnObjectConcerned((*obj)->GetObjectIdentifier())

Mais quand je teste, si un seul objet “bidule” est sur la bonne ligne, tous les objets “bidule” sont pris en compte…

C’est normal, car cette ligne :

objectsConcerned.AddAnObjectConcerned((*obj)->GetObjectIdentifier())

va dire à Game Develop que les objets qui ont le même identifiant que l’objet sont déjà concernés par les précédentes conditions / actions. En fait, l’identifiant d’un objet est simplement l’équivalent de son nom → Plutôt que d’utiliser les noms des objets, Game Develop utilise des identifiants numériques.
J’avoue que le nom “AddAnObjectConcerned” est peut être un peu mal choisi, il faut l’entendre dans le sens “Maintenant, les objets avec l’identifiant xxx sont déjà concernés par les précédentes instructions, donc tu va pas aller les chercher depuis la scène la prochaine fois que je t’en demanderai, mais bien dans la liste des objets que tu a en mémoire”. :stuck_out_tongue:

Ce que tu cherche, c’est plutôt :

objectsConcerned.objectsPicked.AddObject( pointeurIntelligentVersTonObjet );

Cette ligne parait déjà bien mieux : Ici, le pointeurIntelligentVersTonObjet caractérise bien de façon unique ton objet.

Je viens d’arriver sur cette fonction juste avant de lire ton message (en fouillant objectsconserned.h), mais comment j’obtiens un pointeur intelligent vers l’objet. :confused:
(Désolé, mais je me suis jamais servi de pointeur intelligents… :frowning: )

Parce que j’ai fait ça :

objectsConcerned.objectsPicked.AddObject(*obj)

(obj est un itérateur)

Vu que les pointeurs intelligents sont utilisés partout ( boost::shared_ptr ), il y a fort à parier que le “pointeur” que tu utilise pour accéder à ton objet en est déjà un. Les listes renvoyées par objectsConcerned.Pick*() sont des listes de pointeurs intelligents par exemple.

Donc sauf erreur grossière :

[code]ObjList list = objectsConcerned.PickAndRemove(condition.GetParameter( 1 ).GetAsObjectIdentifier(), condition.IsGlobal());

for(unsigned int i = 0;i<list.size(); ++i)
{
if ( ce qu’il faut )
objectsConcerned.objectsPicked.push_back(list[i]); //Aller hop, l’objet est concerné par la condition, il faut donc qu’il soit pris en compte par la suite.
}[/code]

EDIT : Normalement, ton code doit marcher, car là aussi je pense que ton itérateur est un itérateur qui pointe vers un pointeur intelligent. Normalement, ça le fait :

ObjList list = objectsConcerned.PickAndRemove(condition.GetParameter( 0 ).GetAsObjectIdentifier(), condition.IsGlobal());

ObjList::iterator obj = list.begin();
ObjList::const_iterator obj_end = list.end();
for ( obj = list.begin(); obj != obj_end; ++obj )
{
    if ( ce qu'il faut )
        objectsConcerned.objectsPicked.AddObject( *obj );
}

Pourtant, en faisant un test dans lequel je colorie en rouge l’objet sprite qui est sur une ligne d’un afficheur de Tableaux, tous se colorient en rouge…

Je pourrai voir le code de la fonction en entière, ou alors sans les parties (réellement) non importantes ?

Voici :

[code]bool ok = false;

ObjList list = objectsConcerned.PickAndRemove(condition.GetParameter( 1 ).GetAsObjectIdentifier(), condition.IsGlobal());
int rowNumber = condition.GetParameter(2).GetAsMathExpressionResult(scene, objectsConcerned);

ObjList::iterator obj = list.begin();
ObjList::const_iterator obj_end = list.end();
for (obj = list.begin(); obj != obj_end; ++obj )
{
    //float objX = (*obj)->GetX();
    float objY = (*obj)->GetY();
    //float objWidth = (*obj)->GetWidth();
    float objHeight = (*obj)->GetHeight();

    float previousRowPos = (rowNumber + 1 > 1 ? GetYOfRow(rowNumber) : 0) + GetY();
    float currentRowPos = GetYOfRow(rowNumber + 1) + GetY();
    if(objY + objHeight > previousRowPos && objY <= currentRowPos)
    {
        objectsConcerned.objectsPicked.AddObject(*obj);
        ok = true;
    }
}

return ok;[/code]

Là tu fais un teste juste en Y, mais je pense que c’est normal. Faut juste que tous tes objets soient pas sur la même colonne quoi.

Je vois vraiment pas de soucis, le mieux est peut être d’éliminer ta condition pour en mettre une plus simple ( genre si la coordonnée X de l’objet est = à 50 ). Ensuite, tu met plusieurs objets, dont un ou deux avec la coordonnée X à 50, et tu lance ta condition pour voir si il prend bien en compte uniquement ceux là.

Je viens de tester, ça ne marche pas :frowning: .
N’y aurait-il pas une des extensions qui utilise objectPicked ?

EDIT :
Est-ce que la condition est bien déclarée (et le true dans le 2ème paramètre est-il juste ?)

[code] DECLARE_OBJECT_CONDITION(“ArrayShowerTestLineObject”,
_(“Un objet est sur une ligne”),
_(“Tester si un objet est sur une ligne d’un afficheur de Tableaux.”),
("L’objet PARAM1 est sur la ligne n°_PARAM2 de PARAM0"),
_(“Afficheur de tableau”),
“Extensions/arrayShower24.png”,
“Extensions/arrayShower16.png”,
&ArrayShowerObject::CondObjectOnLine);

                                DECLARE_PARAMETER("object", _("Objet Afficheur de Tableau"), true, "ArrayShower")
                                DECLARE_PARAMETER("object", _("Objet à tester"), true, "")
                                DECLARE_PARAMETER("expression", _("Ligne"), false, "")
                                MAIN_OBJECTS_IN_PARAMETER(0)

                    DECLARE_END_OBJECT_CONDITION()[/code]

Oui, le true est correct, je vois pas de problème dans la déclaration.
A titre d’exemple, voilà la déclaration de la condition de collision pour les objets Sprite :

[code] DECLARE_CONDITION(“Collision”,
_(“Collision”),
_(“La condition est vraie si il y a collision entre les deux objets donnés.\nLa collision est faite au pixel près.\nAttention ! Cette condition est couteuse pour l’ordinateur en terme de perfomance.”),
_(“PARAM0 est en collision avec PARAM1”),
_(“Collision”),
“res/conditions/collision24.png”,
“res/conditions/collision.png”,
&CondCollision);

    DECLARE_PARAMETER("object", _("Objet 1"), true, "Sprite")
    DECLARE_PARAMETER("object", _("Objet 2"), true, "Sprite")

DECLARE_END_CONDITION()[/code]

La condition est un peu différente de la tienne dans le sens où ce n’est pas une condition spécifique à un objet.
Il faut donc que je récupère moi même une liste supplémentaire d’objets à traiter, et que je procède à un static_cast pour signaler au compilateur que je sais que les objets sont des Sprite ( Il y a des protections dans GD qui vérifient que les objets passés aux conditions sont bien du même type que ceux déclarés dans la déclaration de la condition ).

[code]
/**

  • Test a collision between two sprites objects
    */
    bool CondCollision( RuntimeScene & scene, ObjectsConcerned & objectsConcerned, const Instruction & condition )
    {
    bool isTrue = false;

    ObjList list = objectsConcerned.PickAndRemove(condition.GetParameter( 0 ).GetAsObjectIdentifier(), condition.IsGlobal());
    ObjList list2 = objectsConcerned.PickAndRemove(condition.GetParameter( 1 ).GetAsObjectIdentifier(), condition.IsGlobal());
    if ( condition.GetParameter( 1 ).GetAsObjectIdentifier() == condition.GetParameter( 0 ).GetAsObjectIdentifier())
    list2 = list;

    ObjList::iterator obj = list.begin();
    ObjList::const_iterator obj_end = list.end();

    ObjList::iterator obj2 = list2.begin();
    ObjList::const_iterator obj2_end = list2.end();

    //On teste la collision entre chaque objets
    for ( obj = list.begin(); obj != obj_end; ++obj )
    {
    for (obj2 = list2.begin(); obj2 != obj2_end; ++obj2 )
    {
    //On vérifie que ce n’est pas le même objet
    if ( *obj != *obj2 &&
    CheckCollision( boost::static_pointer_cast(*obj), boost::static_pointer_cast(*obj2) ) ^ condition.IsInverted() )
    {
    objectsConcerned.objectsPicked.AddObject( *obj );
    objectsConcerned.objectsPicked.AddObject( *obj2 );
    isTrue = true;
    }
    }
    }

    return isTrue;
    }[/code]

Donc, normalement, je ne dois pas faire de double boucle comme toi ? Je dois juste faire une boucle pour l’objet en 2ème paramètre ?

Ce qui est assez bizarre, c’est que ma conditions renvoie bien true ou false quand il le faut, mais si c’est true, tous les objets sont pris, si c’est false, ben, rien est fait. :wink:

Oui voilà.

Tu as essayé en supprimant en remplaçant comme je te l’avais suggeré le test par un test tout bête de position, et en vérifiant alors si seul les objets qui étaient à cette position était pris en compte ?

Je l’ai fait : lorsque la condition renvoyait true, tout était pris en compte et quand la condition était false, évidemment rien ne se passait

Il y a bien une fonction de collision aussi dans l’extension PhysicsAutomatism ( Fichier PhysicsAutomatismConditions.cpp, tout en bas, la condition PhysicsAutomatism::CondCollisionWith ). Mais cette condition ne va pas prendre en compte les objets passés en paramètres, mais uniquement les objets pour qui on appelle cette condition si ils sont effectivement en collision.

C’est vraiment bizarre que ça ne fonctionne pas… Tu peux essayer de transférer ta condition en une condition qui n’est pas membre d’un objet.
Il suffit alors de procéder comme la condition de collision que j’ai posté plus haut ( En utilisant alors boost::static_pointer_cast quand tu sais que l’objet que tu manipule est un de tes objets, et en remplacant CheckCollision par tes tests en X/Y ), et de modifier la déclaration pour que ça n’appartienne plus à l’objet.

Ok, j’essaie ça demain. :wink:

Ca marche, mais ça reste bizarre que ça ne marche pas avec une condition d’objet… :wink: