Partie 17: Portes - Partie 1: Editeur et affichage
Téléchargements
Les graphismes
Dans l'éditeur
<?xml version="1.0" encoding="ISO-8859-1"?>
<doors>
<door name="Herse">
<image1>Porticullis_1.png</image1>
<image2>Porticullis_2.png</image2>
<image3>Porticullis_3.png</image3>
</door>
<door name="Porte en Bois">
<image1>Wooden_Door_1.png</image1>
<image2>Wooden_Door_2.png</image2>
<image3>Wooden_Door_3.png</image3>
</door>
<door name="Porte en Fer">
<image1>Iron_Door_1.png</image1>
<image2>Iron_Door_2.png</image2>
<image3>Iron_Door_3.png</image3>
</door>
<door name="Porte Ra">
<image1>Ra_Door_1.png</image1>
<image2>Ra_Door_2.png</image2>
<image3>Ra_Door_3.png</image3>
</door>
</doors>
Dans l'éditeur, on voudrait voir les portes dans différentes orientations.
<?xml version="1.0" encoding="ISO-8859-1"?>
<walls>
<wall name="Nothing">
</wall>
<wall name="Simple">
[...]
</wall>
<wall name="Portrait">
[...]
</wall>
<wall name="Door Side">
<image>DoorSide.png</image>
</wall>
</walls>
De cette façon, c'est facile de dessiner n'importe quel type de porte dans l'éditeur en positionnant simplement ses
Paramètres d'une porte
<?xml version="1.0" encoding="ISO-8859-1"?>
<tiles>
<tile name="Vide">
</tile>
<tile name="Sol">
[...]
</tile>
<tile name="Porte">
<image>Tile.png</image>
<param type="door">Type</param>
<param type="door_ornate">Decor</param>
<param type="bool">aUnBouton</param>
<param type="bool">estHorizontale</param>
<param type="bool">estCassable</param>
<param type="bool">estOuverte</param>
<param type="bool">estEnMouvement</param>
<param type="int">pos</param>
</tile>
</tiles>
Tous ces types de paramètres ont déjà ata utilisés pour les murs, c'est simplement un travail de copier/coller de
#define LOAD_PARAM(_enum,_struct,_type,_expr) \
case _enum: \
{ \
_type value; \
fread(&value, sizeof(value), 1, handle); \
((_struct*)mParams[i])->mValue = (_expr); \
} \
break;
void CWall::load(FILE* handle)
{
uint8_t type;
fread(&type, 1, 1, handle);
setType(type);
std::vector<CParamType>& paramTypes = map.mWallsParams[mType];
for (size_t i = 0; i < paramTypes.size(); ++i)
{
switch (paramTypes[i].mType)
{
LOAD_PARAM(eParamOrnate, CParamOrnate, uint8_t, value)
LOAD_PARAM(eParamInt, CParamInt, int32_t, value)
LOAD_PARAM(eParamBool, CParamBool, uint8_t, (value == 0 ? false : true))
default:
break;
}
}
}
Et le chargement d'une case ressemble à ça:
void CTile::load(FILE* handle)
{
uint8_t type;
fread(&type, 1, 1, handle);
setType(type);
std::vector<CParamType>& paramTypes = map.mTilesParams[mType];
for (size_t i = 0; i < paramTypes.size(); ++i)
{
switch (paramTypes[i].mType)
{
LOAD_PARAM(eParamOrnate, CParamOrnate, uint8_t, value)
LOAD_PARAM(eParamDoor, CParamDoor, uint8_t, value)
LOAD_PARAM(eParamDoorOrnate, CParamDoorOrnate, uint8_t, value)
LOAD_PARAM(eParamInt, CParamInt, int32_t, value)
LOAD_PARAM(eParamBool, CParamBool, uint8_t, (value == 0 ? false : true))
default:
break;
}
}
}
Affichage dans le jeu
// table pour la partie gauche de l'encadrement
SDoorElem tabLeftFrame[WALL_TABLE_HEIGHT][WALL_TABLE_WIDTH] =
{
// Rang 3 (le plus loin)
{
{"", 0, 0, 0, 0, 0, 0}, // 03
{"Frame_Far_Left_0.png", 16, 59, 16, 59, 31, 101}, // 13
{"Frame_Left_0.png", 82, 60, 82, 60, 91, 101}, // 23
{"Frame_Far_Left_0.png", 141, 60, 147, 60, 150, 102}, // 33
{"", 0, 0, 0, 0, 0, 0} // 43
},
[...]
}
Le dessin est fait dans la fonction draw():
void CDoors::draw(QImage* image, CTile* tile, CVec2 tablePos)
{
if (isFacing(tile) == true)
{
drawFrameElement(image, tablePos, tabTopFrame, false);
drawFrameElement(image, tablePos, tabLeftFrame, false);
drawFrameElement(image, tablePos, tabRightFrame, true);
SDoorElem& cell = tabDoor[tablePos.y][tablePos.x];
if (cell.file[0] != 0)
{
int doorType = tile->getDoorParam("Type");
int doorNum = cell.file[0] - '0';
std::string fileName = doorsDatas[doorType].files[doorNum].toUtf8().constData();
drawDoor(image, tablePos, fileName);
}
}
}
Je ne vais pas expliquer les fonctions drawFrameElement() et drawDoor() car elles sont faciles à comprendre. Elles
void CGame::displayMainView(QImage* image)
{
[...]
for (int y = 0; y < WALL_TABLE_HEIGHT; ++y)
for (int x = 0; x < WALL_TABLE_WIDTH; ++x)
{
[...]
if (tile != NULL)
{
// dessine les murs
[...]
// dessine les décors au sol
if (tile->getType() == eTileGround)
{
[...]
}
// dessine les objets de la ligne arrière
// dessine les portes
if (tile->getType() == eTileDoor)
{
doors.draw(image, tile, tablePos);
}
// dessine les objets de la ligne avant
// dessine les ennemis
}
}
}
}
Le dernier graphisme
CWall* wall = &tile->mWalls[playerSide];
if (wall->getType() == eWallSimple)
{
//------------------------------------------------------------------------------
// mur simple
int ornate = wall->getOrnateParam("Decor");
walls.drawOrnate(image, tablePos, side, ornate);
}
else if (wall->getType() == eWallPortrait)
{
//------------------------------------------------------------------------------
// mur simple
// miroir de champion
walls.drawOrnate(image, tablePos, side, ORNATE_MIRROR);
if (tablePos == CVec2(2, 3) && side == eWallSideUp)
{
// si le miroir est juste en facede nous, on dessine la tête du champion
int champion = wall->getIntParam("Champion");
bool isEmpty = wall->getBoolParam("estVide");
if (isEmpty == false)
{
CRect rect = interface.getChampionPortraitRect(champion);
QImage portraits = fileCache.getImage("gfx/interface/ChampPortraits.png");
CVec2 pos(96, 68);
graph2D.drawImageAtlas(image, pos, portraits, rect);
int lastChampChosed;
for (lastChampChosed = 0; lastChampChosed < 4; ++lastChampChosed)
if (characters[lastChampChosed].portrait == -1)
break;
if (lastChampChosed != 4)
{
CRect mouseRect(pos, CVec2(pos.x + CHAMP_PORTRAIT_WIDTH - 1, pos.y + CHAMP_PORTRAIT_HEIGHT - 1));
mouse.addArea(eMouseAreaG_Champion, mouseRect, (void*)wall);
}
}
}
}
else if (wall->getType() == eWallDoorSide)
{
//------------------------------------------------------------------------------
void CGame::drawWall(QImage* image, CTile* tile, CVec2 tablePos, EWallSide side, bool flip)
{
[...]
// dessine les décors
CWall* wall = &tile->mWalls[playerSide];
if (wall->getType() == eWallSimple)
{
//------------------------------------------------------------------------------
// mur simple
[...]
}
else if (wall->getType() == eWallPortrait)
{
//------------------------------------------------------------------------------
// miroir de champion
[...]
}
else if (wall->getType() == eWallDoorSide)
{
//------------------------------------------------------------------------------
// coté d'une porte
if (tablePos == CVec2(2, 3) && side == eWallSideUp)
{
QImage doorFrame = fileCache.getImage("gfx/3DView/doors/Frame_Face_2.png");
graph2D.drawImage(image, CVec2(96, 33), doorFrame);
}
}
[...]
}
Maintenant on a dessiné toutes les portes du premier niveau si vous testez le jeu, vous verrez qu'on peut les