Part 22: Objects - Part 2: On the floor
Downloads
The objects database
<?xml version="1.0" encoding="utf-8"?>
<items>
<!-- ======================== Weapons ======================== -->
<!-- EYE OF TIME -->
<item name="ITEM001">
<category>Weapon</category>
<floor_image>00W_Ring.png</floor_image>
</item>
<!-- STORMRING -->
<item name="ITEM002">
<category>Weapon</category>
<floor_image>00W_Ring.png</floor_image>
</item>
[...]
</items>
First, each item will have a name. I added them to "texts.xml" as they will appear in the game, but we won't use them in this part.
<?xml version="1.0" encoding="ISO-8859-1"?>
<texts>
[...]
<text id="ITEM001">EYE OF TIME</text>
<text id="ITEM002">STORMRING</text>
<text id="ITEM003">TORCH</text>
<text id="ITEM004">FLAMITT</text>
[...]
</texts>
Then we find the "category" of the object. Each object belongs to one of the 6 following categories:
Positions of the objects
CVec2 CObjects::getObjectPos(CVec2 tablePos)
{
CVec2 pos;
pos.x = 250 * (tablePos.x - 4.5) / (8.5 - tablePos.y) + 112;
pos.y = 310 / (8.5 - 0.9 * tablePos.y) + 66;
return pos;
}
Anyways, this gives a result close enough from the original game. And this function will be useful later when we will
The front and back rows
void CObjects::drawBackRow(QImage* image, CVec2 mapPos, CVec2 tablePos)
{
CVec2 pos1, pos2;
switch (player.dir)
{
case 0: // up
pos1 = CVec2(0, 0);
pos2 = CVec2(1, 0);
break;
case 1: // left
pos1 = CVec2(0, 1);
pos2 = CVec2(0, 0);
break;
case 2: // down
pos1 = CVec2(1, 1);
pos2 = CVec2(0, 1);
break;
case 3: // right
pos1 = CVec2(1, 0);
pos2 = CVec2(1, 1);
break;
}
drawObjectsStack(image, mapPos * 2 + pos1, tablePos * 2 + CVec2(0, 0));
drawObjectsStack(image, mapPos * 2 + pos2, tablePos * 2 + CVec2(1, 0));
}
You can see that the coordinates of the tiles are multiplied by 2 because there are 4 places to put the objects stacks
Drawing the objects
void CObjects::drawObjectsStack(QImage* image, CVec2 mapPos, CVec2 tablePos)
{
if (tablePos.y < 1 ||
tablePos.y > (WALL_TABLE_HEIGHT - 1) * 2)
return;
CObjectStack* stack = map.findObjectsStack(mapPos);
if (stack != NULL)
{
for (size_t i = 0; i < stack->getSize(); ++i)
{
int type = stack->getObject(i).getType();
if (type != 0)
{
// get object image
CObjectInfo object = mObjectInfos[type - 1];
QImage objectImage = fileCache.getImage(object.floorImage.toLocal8Bit().constData());
// get object position and add a pseudo random value
CVec2 pos = getObjectPos(tablePos);
pos.x += ((mapPos.x - mapPos.y + i) * 53) % 7 - 3;
pos.y += (i < 4 ? i : 3);
// compute the scale based on the reference position (the nearest)
CVec2 pos0 = getObjectPos(CVec2(WALL_TABLE_WIDTH, (WALL_TABLE_HEIGHT - 1) * 2));
CVec2 pos1 = getObjectPos(CVec2(WALL_TABLE_WIDTH, tablePos.y));
float scale = (float)(pos1.x - 112) / (float)(pos0.x - 112);
// scale the object in a temporary image
QImage scaledObject(objectImage.size() * scale, QImage::Format_ARGB32);
scaledObject.fill(QColor(0, 0, 0, 0));
graph2D.drawImageScaled(&scaledObject, CVec2(), objectImage, scale);
// darken the object based on it's distance
float shadow = ((WALL_TABLE_HEIGHT - 1) * 2 - tablePos.y) * 0.13f;
graph2D.darken(&scaledObject, shadow);
// draw the object on screen
pos -= CVec2(scaledObject.size().width() / 2, scaledObject.size().height() - 1);
graph2D.drawImage(image, pos, scaledObject, 0, false, QRect(0, 33, MAINVIEW_WIDTH, MAINVIEW_HEIGHT));
}
}
}
}
We scale the image and darken it according to the distance of the object.