2010-03-30 4 views
-1

J'ai quelques classes configurées pour un jeu, avec XMapObject comme base, et XEntity, XEnviron et XItem en héritant.Les variables héritées ne lisent pas correctement lors de l'utilisation de comparaisons au niveau du bit

Les MapObjects ont un certain nombre de drapeaux, l'un d'entre eux étant MAPOBJECT_SOLID. Mon problème est que XEntity est la seule classe qui détecte correctement MAPOBJECT_SOLID. Les deux éléments sont toujours considérés comme solides par le jeu, quel que soit l'état du drapeau. Ce qui est important, c'est que Environs et Item ne soient presque jamais solides.

Chaque classe a un constructeur préliminaire très basique, initialisant toutes les variables à zéro ou NULL. Pendant la phase CreateX(), les objets sont liés à la carte, définis dans une liste liée liée.

XItem et XEnviron sont tous deux un peu négligé. Ils sont tous deux nouveaux, et au milieu ou mes tentatives de débogage.

Voici les exemples de code relevent:

XMapObject:

#define MAPOBJECT_ACTIVE 1 
#define MAPOBJECT_RENDER 2 
#define MAPOBJECT_SOLID 4 

class XMapObject : public XObject 
{ 
    public: 
    Uint8 MapObjectType,Location[2],MapObjectFlags; 

    XMapObject *NextMapObject,*PrevMapObject; 

    XMapObject(); 

    void CreateMapObject(Uint8 MapObjectType); 
    void SpawnMapObject(Uint8 MapObjectLocation[2]); 
    void RemoveMapObject(); 
    void DeleteMapObject(); 

    void MapObjectSetLocation(Uint8 Y,Uint8 X); 
    void MapObjectMapLink(); 
    void MapObjectMapUnlink(); 
}; 

XMapObject::XMapObject() 
{ 
    MapObjectType = 0; 
    Location[0] = 0; 
    Location[1] = 1; 
    NextMapObject = NULL; 
    PrevMapObject = NULL; 
} 

void XMapObject::CreateMapObject(Uint8 Type) 
{ 
    MapObjectType = Type; 
} 

void XMapObject::SpawnMapObject(Uint8 MapObjectLocation[2]) 
{ 
    if(!(MapObjectFlags & MAPOBJECT_ACTIVE)) { MapObjectFlags += MAPOBJECT_ACTIVE; } 

    Location[0] = MapObjectLocation[0]; 
    Location[1] = MapObjectLocation[1]; 

    MapObjectMapLink(); 
} 

XEntity:

XEntity *StartEntity = NULL,*EndEntity = NULL; 

class XEntity : public XMapObject 
{ 
    public: 
    Uint8 Health,EntityFlags; 
    float Speed,Time; 
    XEntity *NextEntity,*PrevEntity; 
    XItem *IventoryList; 

    XEntity(); 

    void CreateEntity(Uint8 EntityType,Uint8 EntityLocation[2]); 
    void DeleteEntity(); 

    void EntityLink(); 
    void EntityUnlink(); 

    Uint8 MoveEntity(Uint8 YOffset,Uint8 XOffset); 
}; 

XEntity::XEntity() 
{ 
    Health = 0; 
    Speed = 0; 
    Time = 1.0; 
    EntityFlags = 0; 
    NextEntity = NULL; 
    PrevEntity = NULL; 
    IventoryList = NULL; 
} 

void XEntity::CreateEntity(Uint8 EntityType,Uint8 EntityLocation[2]) 
{ 
    CreateMapObject(EntityType); 
    SpawnMapObject(EntityLocation); 

    if(!(MapObjectFlags & MAPOBJECT_SOLID) { MapObjectFlags += MAPOBJECT_SOLID; } 
    EntityFlags = ENTITY_CLIPPING; 
    Time = 1.0; 
    Speed = 1.0; 

    EntityLink(); 
} 

void XEntity::EntityLink() 
{ 
    if(StartEntity == NULL) 
    { 
     StartEntity = this; 
     PrevEntity = NULL; 
     NextEntity = NULL; 
    } 
    else 
    { 
     EndEntity->NextEntity = this; 
    } 

    EndEntity = this; 
} 

XEnviron:

class XEnviron : public XMapObject 
{ 
    public: 
    Uint8 Effect,TimeOut; 

    void CreateEnviron(Uint8 Type,Uint8 Y,Uint8 X,Uint8 TimeOut); 
}; 

void XEnviron::CreateEnviron(Uint8 EnvironType,Uint8 Y,Uint8 X,Uint8 TimeOut) 
{ 
    CreateMapObject(EnvironType); 

    Location[0] = Y; 
    Location[1] = X; 

    SpawnMapObject(Location); 

    XTile *Tile = GetTile(Y,X); 
    Tile->Environ = this; 

    MapObjectFlags = MAPOBJECT_ACTIVE + MAPOBJECT_SOLID; 
    printf("%i\n",MapObjectFlags); 
} 

XItem:

class XItem : public XMapObject 
{ 
    public: 
    void CreateItem(Uint8 Type,Uint8 Y,Uint8 X); 
}; 

void XItem::CreateItem(Uint8 Type,Uint8 Y,Uint8 X) 
{ 
    CreateMapObject(Type); 

    Location[0] = Y; 
    Location[1] = X; 

    SpawnMapObject(Location); 
} 

Et enfin, le code de déplacement d'entité. Seules les entités sont capables de se déplacer.

Uint8 XEntity::MoveEntity(Uint8 YOffset,Uint8 XOffset) 
{ 
    Uint8 
     NewY = Location[0] + YOffset, 
     NewX = Location[1] + XOffset; 

    if((NewY >= 0 && NewY < MAPY) && (NewX >= 0 && NewX < MAPX)) 
    { 
     XTile *Tile = GetTile(NewY,NewX); 

     if(Tile->MapList != NULL) 
     { 
      XMapObject *MapObject = Tile->MapList; 

      while(MapObject != NULL) 
      { 
       if(MapObject->MapObjectFlags & MAPOBJECT_SOLID) 
       { 
        printf("solid\n"); 
        return 0; 
       } 

       MapObject = MapObject->NextMapObject; 
      } 
     } 

     if(Tile->Flags & TILE_SOLID && EntityFlags & ENTITY_CLIPPING) 
     { 
      return 0; 
     } 

     this->MapObjectSetLocation(NewY,NewX); 

     return 1; 
    } 

    return 0; 
} 

Ce qui est étrange, est que l'opérateur retourne toujours vrai au niveau du bit lorsque le MapObject est un ou un élément Environ, mais il fonctionne correctement pour les entités. Pour le débogage, j'utilise le printf "Solid", et aussi un printf contenant la valeur du drapeau pour les Environs et les Items.

Toute aide est grandement appréciée, car c'est un bug majeur pour le petit jeu sur lequel je travaille. Je suis aussi très nouveau dans la programmation orientée objet, tout conseil, suggestion et/ou critique sont les bienvenus.

+3

Comme vous ne nous montrez pas des constructeurs, la définition de 'MAPOBJECT_SOLID' ou tous les endroits où la' MapObjectFlags' sont fixés, il est un peu difficile de vous aider. –

+1

Juste une supposition: vous n'êtes pas downcasting êtes-vous? –

+2

Je suis curieux de connaître votre interface. Que fait 'CreateEntity()'? En tant que fonction membre non statique, vous ne pouvez l'appeler que sur un objet 'XEntity' déjà construit, mais il ne retourne pas un nouvel objet' XEntity'? (De même 'CreateEnviron',' CreateItem', 'CreateMapObject'.) –

Répondre

0

J'ai trouvé le problème plus tôt aujourd'hui - Il n'avait aucune relation avec la programmation OO, l'héritage, ou au niveau du bit; c'était une simple erreur de portée. Le problème tenait au fait que lors de mon test rapide pour obtenir un Environ dans le jeu, j'ai déclaré la nouvelle variable à l'intérieur de la séquence du commutateur de contrôle, donc la prochaine fois qu'un contrôle était utilisé, l'Environ agirait de manière imprévisible .

switch(Event.key.keysym.sym) 
{ 
    ... 
    case SDLK_c: { XEnviron Environ; Environ.InitEnviron(...); } 
    ... 
} 
0

Vous ne pouvez pas (légalement) appeler XEntity :: MoveEntity sur un objet MapObject ou Environ car ils ne disposent pas d'une telle méthode. Si vous utilisez static_cast pour transformer votre pointeur d'objet en XEntity afin que vous puissiez appeler MoveEntity, alors vous n'avez aucune garantie sur le fonctionnement de l'opération. Dans certaines implémentations, les choses peuvent sembler fonctionner dans MoveEntity, mais ce qui se passe réellement, c'est l'interprétation de la mémoire de l'autre objet en tant que XEntity. Lorsqu'il essaie d'accéder au décalage où il croit que MapObjectFlags existe, il n'est pas réellement là et a toujours ce bit à 1.

1

Votre problème semble être que vous n'initialisez jamais MapObjectFlags dans toutes les classes autres que XEnviron, donc, en tant que type de base, il aura une valeur non spécifiée dans XItem, XEntity et d'autres objets dérivés XMapObject. Je suggère que, en tant que membre de XMapObject vous explicitement l'initialiser à une valeur connue.

En règle générale, il est généralement recommandé de s'assurer que tous les membres de type basique sont explicitement initialisés dans la liste d'initialisation de chaque constructeur que vous définissez.

par exemple.

XMapObject() 
    : MapObjectFlags(0) 
    , // ... other initializers 
{ 
    // Other initializations 
} 
+0

Il ressemble à ça. Le code pourrait utiliser un peu de nettoyage, et les suggestions que vous avez postées sont utiles. –

Questions connexes