/* 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 . * */ /* * 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(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(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