Partie 24: Objets - Partie 4: Dans l'inventaire
Téléchargements
Positions des objets
<items>
<!-- ======================== Armes ======================== -->
<!-- OEIL DU TEMPS -->
<item name="ITEM001">
<category>Weapon</category>
<floor_image>00W_Ring.png</floor_image>
<image_file>Items0.png</image_file>
<image_num>17</image_num>
<position>hBCP</position>
</item>
[...]
</items>
Les parties du corps
#define BACKPACK_SIZE 17
class CCharacter
{
public:
enum EBodyParts
{
eBodyPartHead = 0, // tête
eBodyPartNeck, // cou
eBodyPartTorso, // torse
eBodyPartLeftHand, // main gauche
eBodyPartRightHand, // main droite
eBodyPartLegs, // jambes
eBodyPartFeet, // pieds
eBodyPartPouch1, // poche 1
eBodyPartPouch2, // poche 2
eBodyPartQuiver1, // carquois 1
eBodyPartQuiver2, // carquois 2
eBodyPartQuiver3, // carquois 3
eBodyPartQuiver4, // carquois 4
eBodyPartBackpack, // sac à dos
eBodyPartCount = eBodyPartBackpack + BACKPACK_SIZE
};
Le tableau qui contient les objets de notre personnage va changer aussi. Auparavant on avait un tableau temporaire
CObject bodyObjects[eBodyPartCount];
Définir les slots d'objets
class CInterface
{
public:
[...]
struct SBodyInfos
{
CVec2 pos;
char type;
int defaultImage;
};
[...]
private:
[...]
SBodyInfos bodyInfos[CCharacter::eBodyPartCount];
};
Ce tableau est initialisé dans le constructeur de CInterface:
CInterface::CInterface()
{
[...]
// initialise les positions des objets dans la feuille de personnage
bodyInfos[CCharacter::eBodyPartHead].pos = CVec2(34, 59);
bodyInfos[CCharacter::eBodyPartNeck].pos = CVec2( 6, 66);
bodyInfos[CCharacter::eBodyPartTorso].pos = CVec2(34, 79);
bodyInfos[CCharacter::eBodyPartLeftHand].pos = CVec2( 6, 86);
bodyInfos[CCharacter::eBodyPartRightHand].pos = CVec2(62, 86);
bodyInfos[CCharacter::eBodyPartLegs].pos = CVec2(34, 99);
bodyInfos[CCharacter::eBodyPartFeet].pos = CVec2(34, 119);
bodyInfos[CCharacter::eBodyPartPouch1].pos = CVec2( 6, 106);
bodyInfos[CCharacter::eBodyPartPouch2].pos = CVec2( 6, 123);
bodyInfos[CCharacter::eBodyPartQuiver1].pos = CVec2(62, 106);
bodyInfos[CCharacter::eBodyPartQuiver2].pos = CVec2(79, 106);
bodyInfos[CCharacter::eBodyPartQuiver3].pos = CVec2(62, 123);
bodyInfos[CCharacter::eBodyPartQuiver4].pos = CVec2(79, 123);
bodyInfos[CCharacter::eBodyPartHead].type = 'H';
bodyInfos[CCharacter::eBodyPartNeck].type = 'N';
bodyInfos[CCharacter::eBodyPartTorso].type = 'T';
bodyInfos[CCharacter::eBodyPartLeftHand].type = 'h';
bodyInfos[CCharacter::eBodyPartRightHand].type = 'h';
bodyInfos[CCharacter::eBodyPartLegs].type = 'L';
bodyInfos[CCharacter::eBodyPartFeet].type = 'F';
bodyInfos[CCharacter::eBodyPartPouch1].type = 'P';
bodyInfos[CCharacter::eBodyPartPouch2].type = 'P';
bodyInfos[CCharacter::eBodyPartQuiver1].type = 'Q';
bodyInfos[CCharacter::eBodyPartQuiver2].type = 'q';
bodyInfos[CCharacter::eBodyPartQuiver3].type = 'q';
bodyInfos[CCharacter::eBodyPartQuiver4].type = 'q';
for (int i = 0; i < BACKPACK_SIZE; ++i)
{
int x = 66 + ((i + 1) % 9) * 17;
int y = 49 + ((i + 1) / 9) * 17;
bodyInfos[CCharacter::eBodyPartBackpack + i].pos = CVec2(x, y);
bodyInfos[CCharacter::eBodyPartBackpack + i].type = 'B';
}
// images par défaut pour les parties du corps
for (int i = 0; i < CCharacter::eBodyPartCount; ++i)
bodyInfos[i].defaultImage = -1;
bodyInfos[CCharacter::eBodyPartHead].defaultImage = 24;
bodyInfos[CCharacter::eBodyPartNeck].defaultImage = 16;
bodyInfos[CCharacter::eBodyPartTorso].defaultImage = 26;
bodyInfos[CCharacter::eBodyPartLeftHand].defaultImage = 20;
bodyInfos[CCharacter::eBodyPartRightHand].defaultImage = 22;
bodyInfos[CCharacter::eBodyPartLegs].defaultImage = 28;
bodyInfos[CCharacter::eBodyPartFeet].defaultImage = 30;
bodyInfos[CCharacter::eBodyPartPouch1].defaultImage = 17;
bodyInfos[CCharacter::eBodyPartQuiver1].defaultImage = 18;
bodyInfos[CCharacter::eBodyPartBackpack + 8].defaultImage = 19;
}
Dessin et zones souris
void CInterface::drawBodyPart(QImage* image, CVec2 pos, int championNum, CCharacter::EBodyParts part, bool enableArea)
Elle commence avec la partie dessin. On teste si il y a un objet dans le tableau bodyObjects du personnage donné.
{
CCharacter* c = &game.characters[championNum];
int objType = c->bodyObjects[part].getType();
if (objType != 0)
{
// dessine l'objet dans ce slot
CObjects::CObjectInfo object = objects.mObjectInfos[objType - 1];
QImage objImage = fileCache.getImage(object.imageFile.toLocal8Bit().constData());
CRect rect = getItemRect(object.imageNum);
graph2D.drawImageAtlas(image, pos, objImage, rect);
}
else if (bodyInfos[part].defaultImage != -1)
{
// dessine l'image par défaut
QImage bodyParts = fileCache.getImage("gfx/interface/Items6.png");
CRect rect = getItemRect(bodyInfos[part].defaultImage);
graph2D.drawImageAtlas(image, pos, bodyParts, rect);
}
La deuxième partie de la fonction définit la zone souris.
// zone souris
int objHandType = mouse.mObjectInHand.getType();
CRect mouseRect(pos, pos + CVec2(ITEM_WIDTH - 1, ITEM_HEIGHT - 1));
bool isPositionCompatible = true;
// Teste si l'objet qu'on tient peut être mis dans ce type de slot
if (objHandType != 0)
{
QString& positions = objects.mObjectInfos[objHandType - 1].positions;
isPositionCompatible = positions.contains(bodyInfos[part].type);
}
if (isPositionCompatible == true && enableArea == true)
mouse.addArea(eMouseArea_InvObject, mouseRect, eCursor_Hand, (void*)championNum, (void*)part);
}
Maintenant, dans drawInventory(), on peut dessiner tous les objets avec cette simple boucle:
for (int i = 0; i < CCharacter::eBodyPartCount; ++i)
drawBodyPart(image, bodyInfos[i].pos, currentChampion, (CCharacter::EBodyParts)i);
Tester les zones souris
void CInterface::update(SMouseArea* clickedArea)
{
[...]
if (clickedArea != NULL)
{
if (mouse.mButtonPressing == true)
{
switch (clickedArea->type)
{
[...]
// slot d'objet dans l'inventaire
case eMouseArea_InvObject:
{
// récupère le perso courant et la position dans l'inventaire
int champNum = (int)clickedArea->param1;
CCharacter* c = &game.characters[champNum];
int objectPos = (int)clickedArea->param2;
// échange l'objet que l'on tient avec celui dans l'inventaire
CObject temp = mouse.mObjectInHand;
mouse.mObjectInHand = c->bodyObjects[objectPos];
c->bodyObjects[objectPos] = temp;
}
break;
default:
break;
}
}
[...]
}
On échange simplement l'objet que l'on tient avec celui dans le slot.
Les objets de départ des champions
<!-- ELIJA -->
<champion firstName="CHAMP_FNAME00" lastName="CHAMP_LNAME00">
[...]
<object pos="T">52</object>
<object pos="L">53</object>
<object pos="F">50</object>
<object pos="21">133</object>
</champion>
pour la position, vous pouvez soit mettre le numéro du slot en suivant l'enum EBodyParts, soit utiliser un de ces
class CCharacter
{
[...]
private:
struct SDBObject
{
int pos;
int type;
};
struct SChampDBData
{
[...]
std::vector<SDBObject> objects;
};
[...]
};
Quand on appelle fromDB() pour initialiser un personnages, ses objets sont créés à partir de cette liste:
void CCharacter::fromDB(int num)
{
[...]
for (size_t i = 0; i < eBodyPartCount; ++i)
bodyObjects[i].setType(0);
for (size_t i = 0; i < db.objects.size(); ++i)
{
int pos = db.objects[i].pos;
int type = db.objects[i].type;
bodyObjects[pos].setType(type);
}
}
Les mains en haut
void CInterface::drawChampion(QImage* image, int num)
{
[...]
// dessine les mains
mouse.addArea(eMouseArea_None, handMouseRect, eCursor_Hand);
drawBodyPart(image, CVec2(69 * num + 4, 10), num, CCharacter::eBodyPartLeftHand, !isResurrecting);
drawBodyPart(image, CVec2(69 * num + 24, 10), num, CCharacter::eBodyPartRightHand, !isResurrecting);
Vous pouvez voir qu'on positionne aussi le dernier paramètre de cette fonction (le flag enableArea).