Part 38: Breakable doors
Downloads
Door 22
<tile name="Door">
[...]
<param type="bool">isBroken</param>
</tile>
Now we will have to convert the map to the new format.
Converting maps
//#define CONVERT_MAP 1
If you search for it in the code, you will find that it is used in 2 functions.
void CBridge::load(QString fileName)
{
//trick to convert old map formats
#ifdef CONVERT_MAP
CMap::mTilesParams.clear();
editor.readTilesDB("databases/tiles-old.xml");
// CMap::mWallsParams.clear();
// editor.readWallsDB("databases/walls-old.xml");
// CMap::mObjectsParams.clear();
// editor.readObjectsDB("databases/items-old.xml");
#endif
// [8] to remove "file:///"
map.load(&fileName.toLocal8Bit().data()[8]);
updateQMLImage();
}
and the save() function:
void CBridge::save(QString fileName)
{
//trick to convert old map formats
#ifdef CONVERT_MAP
CMap::mTilesParams.clear();
editor.readTilesDB("databases/tiles.xml");
// CMap::mWallsParams.clear();
// editor.readWallsDB("databases/walls.xml");
// CMap::mObjectsParams.clear();
// editor.readObjectsDB("databases/items.xml");
#endif
// [8] to remove "file:///"
map.save(&fileName.toLocal8Bit().data()[8]);
}
As you can see, the load() function opens a file with an "-old" suffix. That is the file as it was in the previous
Drawing the broken door
void CGraphics2D::drawImageTransparent(QImage* destImage, const CVec2& pos, const QImage& srcImage)
{
QPainter painter(destImage);
painter.setCompositionMode(QPainter::CompositionMode_DestinationOut);
painter.drawImage(pos.x, pos.y, srcImage);
painter.end();
}
void CDoors::drawDoor(QImage* image, CVec2 tablePos, CTile* tile)
{
[...]
// breakable door
if (tile->getBoolParam("isBreakable") == true && tile->getBoolParam("isBroken") == true)
{
QImage holeImage = fileCache.getImage(std::string("gfx/3DView/doors/Bashed_Door.png"));
graph2D.drawImageTransparent(&doorImage, CVec2(), holeImage);
}
void CInterface::updateWeapons()
{
// attack highlight
if (attackHighlightTime.update() == true)
{
[...]
CVec2 frontPos = player.getPosFromLocal(CVec2(0, -1));
CTile* frontTile = map.getTile(frontPos);
if (frontTile != NULL)
{
// breakble door
if (frontTile->getType() == eTileDoor &&
frontTile->getBoolParam("isBreakable") == true &&
frontTile->getBoolParam("isBroken") == false &&
(attackType == ATTACK_CHOP ||
attackType == ATTACK_KICK ||
attackType == ATTACK_SWING ||
attackType == ATTACK_HACK ||
attackType == ATTACK_BERZERK ||
attackType == ATTACK_BASH)
)
{
frontTile->setBoolParam("isBroken", true);
weaponCoolDown[currentWeapon].set(60, true);
sound->play(frontPos, "sound/Wooden_Thud.wav");
}
else
{
// normal hit
[...]
}
}
In the original game, the doors had a "defense" value and could only be destroyed with an attack strong enough, but
bool CDoors::isOpened(CTile* tile)
{
bool isOpened = tile->getBoolParam("isOpened") || tile->getBoolParam("isBroken");
bool isMoving = tile->getBoolParam("isMoving");
if (isOpened == true && isMoving == false)
return true;
else
return false;
}
Finally all the doors mechanics are coded for level 2.