Files
2026-02-02 04:50:13 +01:00

285 lines
9.0 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* Copyright (C) 2006-2010 - Frictional Games
*
* This file is part of HPL1 Engine.
*/
#include "hpl1/engine/scene/TileMap.h"
#include "hpl1/engine/graphics/GraphicsTypes.h"
#include "hpl1/engine/graphics/RenderObject2D.h"
#include "hpl1/engine/graphics/Renderer2D.h"
#include "hpl1/engine/math/Math.h"
#include "hpl1/engine/resources/ResourceImage.h"
#include "hpl1/engine/resources/Resources.h"
#include "hpl1/engine/resources/TileSetManager.h"
#include "hpl1/engine/scene/TileMapLineIt.h"
#include "hpl1/engine/scene/TileMapRectIt.h"
#include "hpl1/engine/system/low_level_system.h"
namespace hpl {
//////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cTileMap::cTileMap(cVector2l avSize, float afTileSize, cGraphics *apGraphics, cResources *apResources) {
mfTileSize = 1;
mvSize = avSize;
mfTileSize = afTileSize;
mpGraphics = apGraphics;
mpResources = apResources;
mlShadowLayer = 0;
}
//-----------------------------------------------------------------------
cTileMap::~cTileMap() {
Log(" Deleting tilemap.\n");
for (tTileLayerVecIt it = mvTileLayer.begin(); it != mvTileLayer.end(); it++)
hplDelete(*it);
for (tTileSetVecIt it = mvTileSet.begin(); it != mvTileSet.end(); it++)
mpResources->GetTileSetManager()->Destroy(*it);
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
void cTileMap::Render(cCamera2D *apCam) {
cRect2f Rect;
apCam->GetClipRect(Rect);
iTileMapIt *TileIt = GetRectIterator(Rect, -1);
while (TileIt->HasNext()) {
RenderTileData(TileIt->Next(), TileIt->GetCurrentLayer());
}
hplDelete(TileIt);
}
//-----------------------------------------------------------------------
iTileMapIt *cTileMap::GetRectIterator(const cRect2f &aRect, int alLayer) {
cVector2l vPos = cVector2l((int)floor(aRect.x / mfTileSize),
(int)floor(aRect.y / mfTileSize));
cVector2l vSize = cVector2l((int)(aRect.w / mfTileSize) + 1,
(int)(aRect.h / mfTileSize) + 1);
// Check if we need yet another grid for x and y
if (aRect.x + aRect.w >= (vPos.x + vSize.x) * mfTileSize)
vSize.x++;
if (aRect.y + aRect.h >= (vPos.y + vSize.y) * mfTileSize)
vSize.y++;
// Log("\nPos: %d:%d\n",vPos.x,vPos.y);
// Log("Size: %d:%d\n\n",vSize.x,vSize.y);
return hplNew(cTileMapRectIt, (vPos, vSize, this, alLayer));
}
//-----------------------------------------------------------------------
iTileMapIt *cTileMap::GetLineIterator(const cVector2f &avStart, const cVector2f &avEnd, int alLayer) {
return hplNew(cTileMapLineIt, (avStart, avEnd, this, alLayer));
}
//-----------------------------------------------------------------------
cVector2f cTileMap::GetWorldPos(cVector2f avScreenPos, cCamera2D *apCam) {
cVector2f vWorldPos;
cRect2f Rect;
apCam->GetClipRect(Rect);
cVector2f vVirtSize = mpGraphics->GetLowLevel()->GetVirtualSize();
vWorldPos.x = Rect.x + Rect.w * (avScreenPos.x / ((float)vVirtSize.x));
vWorldPos.y = Rect.y + Rect.h * (avScreenPos.y / ((float)vVirtSize.y));
return vWorldPos;
}
//-----------------------------------------------------------------------
cTile *cTileMap::GetScreenTile(cVector2f avPos, int alLayer, cCamera2D *apCam) {
return GetWorldTile(GetWorldPos(avPos, apCam), alLayer);
}
//-----------------------------------------------------------------------
void cTileMap::SetScreenTileData(cVector2f avPos, int alLayer, cCamera2D *apCam,
int alTileSet, int alTileNum) {
cVector2f vWorldPos = GetWorldPos(avPos, apCam);
cTile *pOldTile = GetWorldTile(vWorldPos, alLayer);
iTileData *pData = NULL;
if (alTileSet >= 0) {
cTileSet *pSet = GetTileSet(alTileSet);
if (pSet == NULL)
return;
pData = pSet->Get(alTileNum);
if (pData == NULL)
return;
}
cVector2l vTilePos = cVector2l((int)floor(vWorldPos.x / mfTileSize), (int)floor(vWorldPos.y / mfTileSize));
if (vTilePos.x < 0 || vTilePos.y < 0 || vTilePos.x >= mvSize.x || vTilePos.y >= mvSize.y)
return;
if (alLayer < 0 || alLayer >= (int)mvTileLayer.size())
return;
cVector3f vTileWorldPos(vTilePos.x * mfTileSize, vTilePos.y * mfTileSize, mvTileLayer[alLayer]->GetZ());
int lAngle = 0;
if (pOldTile)
lAngle = pOldTile->GetAngle();
cTile *pTile = NULL;
if (pData)
pTile = hplNew(cTile, (pData, (eTileRotation)lAngle, vTileWorldPos, mfTileSize, NULL));
mvTileLayer[alLayer]->SetTile(vTilePos.x, vTilePos.y, pTile);
}
//-----------------------------------------------------------------------
void cTileMap::SetScreenTileAngle(cVector2f avPos, int alLayer, cCamera2D *apCam, int alAngle) {
cVector2f vWorldPos = GetWorldPos(avPos, apCam);
cTile *pTile = GetWorldTile(vWorldPos, alLayer);
if (pTile == NULL)
return;
cVector2l vTilePos = cVector2l((int)floor(vWorldPos.x / mfTileSize), (int)floor(vWorldPos.y / mfTileSize));
if (vTilePos.x < 0 || vTilePos.y < 0 || vTilePos.x >= mvSize.x || vTilePos.y >= mvSize.y)
return;
cVector3f vTileWorldPos(vTilePos.x * mfTileSize, vTilePos.y * mfTileSize, mvTileLayer[alLayer]->GetZ());
pTile->SetAngle((eTileRotation)alAngle);
}
//-----------------------------------------------------------------------
cTile *cTileMap::GetWorldTile(cVector2f avPos, int alLayer) {
if (alLayer < 0 || alLayer >= (int)mvTileLayer.size())
return NULL;
return mvTileLayer[alLayer]->GetAt((int)floor(avPos.x / mfTileSize),
(int)floor(avPos.y / mfTileSize));
}
//-----------------------------------------------------------------------
/**
*
* \param alTileNum
* \param alLayer
* \param avDir 0=left, 1=right, 2=up, 3 = down
* \return num of neighbours
*/
int cTileMap::GetTileNeighbours4Dir(int alTileNum, int alLayer, bool *avDir) {
int lCount = 0;
cTileLayer *pLayer = mvTileLayer[alLayer];
int lX = alTileNum % mvSize.x;
int lY = alTileNum / mvSize.x;
/*avDir[0] = pLayer->GetAt(lX-1,lY)!=NULL?true:false;
avDir[1] = pLayer->GetAt(lX+1,lY)!=NULL?true:false;
avDir[2] = pLayer->GetAt(lX,lY-1)!=NULL?true:false;
avDir[3] = pLayer->GetAt(lX,lY+1)!=NULL?true:false;*/
cTile *pTile;
cTileDataNormal *pData;
cVector2l vAdd[4] = {cVector2l(-1, 0), cVector2l(+1, 0), cVector2l(0, -1), cVector2l(0, +1)};
for (int i = 0; i < 4; i++) {
pTile = pLayer->GetAt(lX + vAdd[i].x, lY + vAdd[i].y);
if (pTile != NULL) {
pData = static_cast<cTileDataNormal *>(pTile->GetTileData());
if (pData->IsSolid())
avDir[i] = true;
else
avDir[i] = false;
} else {
avDir[i] = false;
}
}
for (int i = 0; i < 4; i++)
if (avDir[i] == true)
lCount++;
return lCount;
}
//-----------------------------------------------------------------------
void cTileMap::AddTileLayerFront(cTileLayer *apLayer) {
if (mvTileLayer.size() < 1) {
mvTileLayer.push_back(apLayer);
} else {
mvTileLayer.push_back(NULL);
for (int i = (int)mvTileLayer.size() - 2; i >= 0; i--) {
mvTileLayer[i + 1] = mvTileLayer[i];
}
mvTileLayer[0] = apLayer;
}
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// PRIVATE METHODS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
void cTileMap::RenderTileData(cTile *apTile, int alLayer) {
cTileDataNormal *pData = static_cast<cTileDataNormal *>(apTile->GetTileData());
if (pData == NULL)
return;
cRect2f _obj = cRect2f(apTile->GetPosition().x - mfTileSize / 2,
apTile->GetPosition().y - mfTileSize / 2, mfTileSize, mfTileSize);
cRenderObject2D _obj2 = cRenderObject2D(pData->GetMaterial(),
pData->GetVertexVec(apTile->GetAngle()),
pData->GetIndexVec(apTile->GetAngle()),
ePrimitiveType_Quad, apTile->GetPosition().z,
_obj,
NULL, apTile->GetPositionPtr());
mpGraphics->GetRenderer2D()->AddObject(_obj2);
}
//-----------------------------------------------------------------------
} // namespace hpl