Partie 13: Les décors des murs - Partie 2
Téléchargements
Charger les bases de données
//--------------------------------------------------------------------------------------------------------
void CWalls::readOrnatesDB()
{
QDomDocument doc;
QFile f("databases/ornates.xml");
f.open(QIODevice::ReadOnly);
doc.setContent(&f);
f.close();
QDomElement root = doc.documentElement();
QDomElement ornate = root.firstChild().toElement();
while(!ornate.isNull())
{
if (ornate.tagName() == "ornate")
{
COrnateData newOrnate;
newOrnate.name = ornate.attribute("name");
QDomElement ornateInfo = ornate.firstChild().toElement();
while(!ornateInfo.isNull())
{
if (ornateInfo.tagName() == "image_front")
{
newOrnate.imageFront = QString("gfx/3DView/ornates/") + ornateInfo.text();
}
else if (ornateInfo.tagName() == "image_side")
{
newOrnate.imageSide = QString("gfx/3DView/ornates/") + ornateInfo.text();
}
else if (ornateInfo.tagName() == "pos_front")
{
newOrnate.posFront.x = ornateInfo.attribute("x").toInt();
newOrnate.posFront.y = ornateInfo.attribute("y").toInt();
}
else if (ornateInfo.tagName() == "pos_side")
{
newOrnate.posSide.x = ornateInfo.attribute("x").toInt();
newOrnate.posSide.y = ornateInfo.attribute("y").toInt();
}
ornateInfo = ornateInfo.nextSibling().toElement();
}
ornatesDatas.push_back(newOrnate);
}
ornate = ornate.nextSibling().toElement();
}
}
//---------------------------------------------------------------------------------------------
void CWalls::readWallsDB()
{
QDomDocument doc;
QFile f("databases/walls.xml");
f.open(QIODevice::ReadOnly);
doc.setContent(&f);
f.close();
QDomElement root = doc.documentElement();
QDomElement wall = root.firstChild().toElement();
while(!wall.isNull())
{
std::vector<CParamType> paramsTypesList;
if (wall.tagName() == "wall")
{
CWallData newWall;
newWall.name = wall.attribute("name");
QDomElement wallInfo = wall.firstChild().toElement();
while(!wallInfo.isNull())
{
if (wallInfo.tagName() == "param")
{
QString paramType = wallInfo.attribute("type");
if (paramType == "ornate")
{
CParamType newParamType;
newParamType.mType = eParamOrnate;
newParamType.mName = wallInfo.text();
paramsTypesList.push_back(newParamType);
}
}
wallInfo = wallInfo.nextSibling().toElement();
}
wallsDatas.push_back(newWall);
map.mWallsParams.push_back(paramsTypesList);
}
wall = wall.nextSibling().toElement();
}
}
Une autre table de murs
// table avec les positions et tailles de chaque mur pour les décors
struct SWallInfos
{
CVec2 pos;
CVec2 size;
};
static const SWallInfos gWallsInfos[WALL_TABLE_HEIGHT][WALL_TABLE_WIDTH][3] =
{
// Rang 3 (le plus loin)
{
{{{0, 0}, {0, 0}}, {{0, 0}, {0, 0}}, {{0, 0}, {0, 0}} }, // 03
{{{0, 0}, {0, 0}}, {{ 8, 58}, {36, 48}}, {{0, 0}, {0, 0}} }, // 13
{{{0, 0}, {0, 0}}, {{78, 59}, {12, 48}}, {{134, 59}, {12, 48}}}, // 23
{{{0, 0}, {0, 0}}, {{0, 0}, {0, 0}}, {{180, 58}, {36, 48}}}, // 33
{{{0, 0}, {0, 0}}, {{0, 0}, {0, 0}}, {{0, 0}, {0, 0}} } // 43
},
// Rang 2
{
{{{-77, 58}, {70, 48}}, {{0, 0}, {0, 0}}, {{0, 0}, {0, 0}} }, // 02
{{{ 7, 58}, {70, 48}}, {{0, 0}, {0, 0}}, {{0, 0}, {0, 0}} }, // 12
{{{ 77, 58}, {70, 48}}, {{60, 52}, {18, 74}}, {{146, 52}, {18, 74}}}, // 22
{{{146, 58}, {70, 48}}, {{0, 0}, {0, 0}}, {{0, 0}, {0, 0}} }, // 32
{{{216, 58}, {70, 48}}, {{0, 0}, {0, 0}}, {{0, 0}, {0, 0}} } // 42
},
// Rang 1
{
{{{0, 0}, {0, 0}}, {{0, 0}, {0, 0}}, {{0, 0}, {0, 0}} }, // 01
{{{-46, 52}, {105, 74}}, {{0, 0}, {0, 0}}, {{0, 0}, {0, 0}} }, // 11
{{{ 59, 52}, {105, 74}}, {{33, 42}, {27, 111}}, {{164, 42}, {27, 111}}}, // 21
{{{164, 52}, {105, 74}}, {{0, 0}, {0, 0}}, {{0, 0}, {0, 0}} }, // 31
{{{0, 0}, {0, 0}}, {{0, 0}, {0, 0}}, {{0, 0}, {0, 0}} } // 41
},
// Rang 0 (le plus proche)
{
{{{0, 0}, {0, 0}}, {{0, 0}, {0, 0}}, {{0, 0}, {0, 0}}}, // 00
{{{-127, 42}, {159, 111}}, {{0, 0}, {0, 0}}, {{0, 0}, {0, 0}}}, // 10
{{{ 32, 42}, {159, 111}}, {{0, 0}, {0, 0}}, {{0, 0}, {0, 0}}}, // 20
{{{ 191, 42}, {159, 111}}, {{0, 0}, {0, 0}}, {{0, 0}, {0, 0}}}, // 30
{{{0, 0}, {0, 0}}, {{0, 0}, {0, 0}}, {{0, 0}, {0, 0}}} // 40
}
};
Maintenant vous pouvez vous demander pourquoi on a besoin d'une autre table alors que celle qui est dans "walls.cpp" nous
Mise en place des variables
CWalls::COrnateData& ornateData = walls.ornatesDatas[ornate];
const SWallInfos* ornateTabData = &gWallsInfos[tablePos.y][tablePos.x][tableSide];
const SWallInfos* ornate0 = NULL;
QString ornateFileName;
CVec2 ornatePos;
bool ornateFlip = false;
switch(side)
{
case eWallSideUp:
ornate0 = &gWallsInfos[3][2][tableSide];
ornateFileName = ornateData.imageFront;
ornatePos = ornateData.posFront;
break;
case eWallSideLeft:
ornate0 = &gWallsInfos[2][2][1];
ornateFileName = walls.ornatesDatas[ornate].imageSide;
ornatePos = ornateData.posSide;
break;
case eWallSideRight:
ornate0 = &gWallsInfos[2][2][1];
ornateFileName = walls.ornatesDatas[ornate].imageSide;
ornatePos = ornateData.posSide;
ornateFlip = true;
break;
default:
break;
}
Calculer la position et redimensionner l'image
// calcule la position et le facteur d'échelle et dessine le décor dans une image temporaire
float scale = (float)ornateTabData->size.y / 111.0f;
QImage ornateImage = fileCache.getImage(ornateFileName.toLocal8Bit().constData());
QSize ornateSize = ornateImage.size() * scale;
ornatePos = (ornatePos - ornate0->pos);
ornatePos.x = ornatePos.x * ornateTabData->size.x / ornate0->size.x;
ornatePos.y = ornatePos.y * ornateTabData->size.y / ornate0->size.y;
if (ornateFlip == true)
ornatePos.x = ornateTabData->size.x - ornatePos.x - ornateSize.width();
ornatePos += ornateTabData->pos;
QImage tempImage(ornateSize, QImage::Format_ARGB32);
tempImage.fill(QColor(0, 0, 0, 0));
graph2D.drawImageScaled(&tempImage, CVec2(), ornateImage, scale, ornateFlip);
Dans les 3 premières lignes, on calcule le facteur d'échelle de l'image et sa taille finale.
Assombrir l'image
// assombrit le décor en fonction de sa distance
static const float shadowLevels[] = {0.0f, 0.2f, 0.4f};
float shadow;
if (side == eWallSideUp)
shadow = shadowLevels[WALL_TABLE_HEIGHT - 1 - tablePos.y];
else
shadow = shadowLevels[WALL_TABLE_HEIGHT - 2 - tablePos.y];
QPainter painter(&tempImage);
painter.setOpacity(shadow);
painter.setCompositionMode(QPainter::CompositionMode_SourceAtop);
painter.drawImage(QPoint(0, 0), *shadowImage);
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
painter.setOpacity(1.0f);
painter.end();
// dessine les décors à l'écran.
graph2D.drawImage(image, ornatePos, tempImage, 0, false, QRect(0, 33, MAINVIEW_WIDTH, MAINVIEW_HEIGHT));
Pour réaliser ça, on change l'opacité de dessin et on dessine par dessus notre image temporaire une "image d'ombre".
De meilleurs graphismes