This tutorial builds a strategy map with weighted A* pathfinding, animated grid movement, manual camera scrolling, terrain diagnostics and fog of war.
The unit keeps its current cell, destination, in-cell pixel offset and current A* path.
The priority queue places the node with the lowest estimated total cost first.
Cost and predecessor grids cover the map. Eight directions allow cardinal and diagonal movement.
Blocked cells are skipped. Terrain weight and diagonal distance determine the accumulated cost.
Predecessors are followed from the destination to the start, then reversed for movement.
Each map cell samples the center of its source block. Red is blocked; grayscale becomes a movement weight.
Previously visible cells become explored, then a circular area around the unit becomes fully visible.
The logical cell plus pixel offset produces smooth world movement. The Scene context converts it to the viewport.
One generated image contains explored and opaque fog tiles; the Scene assigns their global IDs.
A right-button edge is converted through Scene coordinates and only starts movement when A* returns a route.
The final Scene and CDC are checked when saved. Cleanup also handles partial initialization.
The tutorial source is authoritative. The following listing is included directly from validation/source/Tutorial_16_Scene_WarGame.cpp.
#include "CRM64Pro.h"
#include "RunParameter.h"
#define BASEDIR "Base/"
#ifdef CRM64PRO_PLATFORM_WINDOWS
#define OUTPUTDIR "Win64/"
#elif defined(CRM64PRO_PLATFORM_LINUX)
#define OUTPUTDIR "Linux/"
#elif defined(CRM64PRO_PLATFORM_MACOS)
#define OUTPUTDIR "macOS/"
#endif
#define RESOURCE_BG_CDC_NAME "Tutorial_bg"
#define OUTPUT_CDC OUTPUTDIR"Tutorial.cdc"
static const Sint32 iScreenW = 960;
static const Sint32 iScreenH = 540;
static const Sint32 iViewW = 640;
static const Sint32 iViewH = 480;
static const Sint32 iViewX = (iScreenW - iViewW) / 2;
static const Sint32 iViewY = (iScreenH - iViewH) / 2;
static const Sint32 iLogicRate = 20;
static const float fLogicStep = 1.0f / static_cast<float>(iLogicRate);
static const float fScrollSpeed = 320.0f;
static const float fPlayerSpeed = 80.0f;
struct Player
{
Sint32 iIDSprite;
Sint32 iX, iY;
float fOffX, fOffY;
Sint32 iTargetX, iTargetY;
bool bIsMoving;
vector<SDL_Point> vPath;
Sint32 iCurrentPathIndex;
};
struct TutorialState
{
Player* pPlayer = nullptr;
Sint32 idBgImage = -1;
Sint32 idDebugFont = -1;
Sint32 iFogFirstGID = 0;
Sint32 iTileSize = 0;
};
static TutorialState* g_pState = nullptr;
Sint32 renderWrapper(Sint32)
{
if(!g_pState || !g_pState->pScene) return 0;
g_pState->pScene->render();
return 0;
}
{
public:
SceneLayerHeightMap(
const string& sName, Sint32 iH, Sint32 iW) :
SceneLayerTile(sName, iH, iW)
{
}
Sint32 render(Scene* pScene, SceneLayerContext& rContext) override
{
if(!g_pState) return 0;
Font* pFont = Main::instance().fontMgr().get(g_pState->idDebugFont);
if(!pFont) return 0;
for(Sint32 iLY = mVR.iCYStart; iLY < mVR.iCYEnd; iLY++)
{
Sint32 iCY = iLY;
if(iCY < 0 || iCY >= getHeight()) continue;
float fScreenY = rContext.
worldToScreen(0.0f,
static_cast<float>(iLY * mVR.iTileH),
true).y;
for(Sint32 iLX = mVR.iCXStart; iLX < mVR.iCXEnd; iLX++)
{
Sint32 iCX = iLX;
if(iCX < 0 || iCX >= getWidth()) continue;
Uint32 iWeight = iCellMap[iCY][iCX];
float fRawX = rContext.
worldToScreen(
static_cast<float>(iLX * mVR.iTileW), 0.0f,
true).x;
float fScreenX = floorf(fRawX);
char szBuf[16];
snprintf(szBuf, 16, "%d", iWeight);
pFont->
setPosition(fScreenX + (mVR.iTileW - iFW) / 2, fScreenY + (mVR.iTileH - iFH) / 2);
}
}
return 0;
}
};
struct Node
{
Sint32 iX, iY;
float fF, fG;
bool operator<(const Node& rOther) const
{
return fF > rOther.fF;
}
};
vector<SDL_Point> findPath(Sint32 iStartX, Sint32 iStartY, Sint32 iEndX, Sint32 iEndY)
{
vector<SDL_Point> vPath;
if(!g_pState || !g_pState->pScene) return vPath;
if(!pMap) return vPath;
if(iStartX < 0 || iStartX >= iWidth || iStartY < 0 || iStartY >= iHeight ||
iEndX < 0 || iEndX >= iWidth || iEndY < 0 || iEndY >= iHeight) return vPath;
if(pMap->
iCellMap[iEndY][iEndX] == 255)
return vPath;
priority_queue<Node> vOpenSet;
vector<vector<float>> vvfCostSoFar(iHeight, vector<float>(iWidth, -1.0f));
vector<vector<SDL_Point>> vvCameFrom(iHeight, vector<SDL_Point>(iWidth, { -1, -1 }));
vOpenSet.push({ iStartX, iStartY, 0.0f, 0.0f });
vvfCostSoFar[iStartY][iStartX] = 0.0f;
const Sint32 iDirs[8][2] = { {0,1}, {1,0}, {0,-1}, {-1,0}, {1,1}, {1,-1}, {-1,1}, {-1,-1} };
while(!vOpenSet.empty())
{
Node mCurrent = vOpenSet.top();
vOpenSet.pop();
if(mCurrent.iX == iEndX && mCurrent.iY == iEndY) break;
for(auto& rDir : iDirs)
{
Sint32 iNX = mCurrent.iX + rDir[0];
Sint32 iNY = mCurrent.iY + rDir[1];
if(iNX >= 0 && iNX < iWidth && iNY >= 0 && iNY < iHeight)
{
Uint32 iWeight = pMap->
iCellMap[iNY][iNX];
if(iWeight == 255) continue;
float fDist = (rDir[0] != 0 && rDir[1] != 0) ? 1.414f : 1.0f;
float fNewCost = vvfCostSoFar[mCurrent.iY][mCurrent.iX] + (fDist * (float)iWeight);
if(vvfCostSoFar[iNY][iNX] == -1.0f || fNewCost < vvfCostSoFar[iNY][iNX])
{
vvfCostSoFar[iNY][iNX] = fNewCost;
float fPriority = fNewCost + (abs(iEndX - iNX) + abs(iEndY - iNY));
vOpenSet.push({ iNX, iNY, fPriority, fNewCost });
vvCameFrom[iNY][iNX] = { mCurrent.iX, mCurrent.iY };
}
}
}
}
if(vvCameFrom[iEndY][iEndX].x != -1)
{
SDL_Point mCurr = { iEndX, iEndY };
while(mCurr.x != iStartX || mCurr.y != iStartY)
{
vPath.push_back(mCurr);
mCurr = vvCameFrom[mCurr.y][mCurr.x];
}
reverse(vPath.begin(), vPath.end());
}
return vPath;
}
void updateFog(int iGridX, int iGridY)
{
if(!g_pState || !g_pState->pScene) return;
if(!pFog) return;
for(Sint32 iY = 0; iY < iH; iY++)
{
for(Sint32 iX = 0; iX < iW; iX++)
{
{
pFog->
iCellMap[iY][iX] = g_pState->iFogFirstGID;
}
}
}
Sint32 iRadius = 3;
Sint32 iR2 = iRadius * iRadius;
for(Sint32 iY = -iRadius; iY <= iRadius; iY++)
{
for(Sint32 iX = -iRadius; iX <= iRadius; iX++)
{
if(iX * iX + iY * iY <= iR2)
{
Sint32 iGX = iGridX + iX;
Sint32 iGY = iGridY + iY;
if(iGX >= 0 && iGX < iW && iGY >= 0 && iGY < iH)
{
}
}
}
}
}
void updateSpriteMap(Sint32 iOldX, Sint32 iOldY, Sint32 iNewX, Sint32 iNewY)
{
if(!g_pState || !g_pState->pScene) return;
if(!pSprLayer) return;
if(iOldX >= 0 && iOldX < pSprLayer->getWidth() && iOldY >= 0 && iOldY < pSprLayer->getHeight())
if(iNewX >= 0 && iNewX < pSprLayer->getWidth() && iNewY >= 0 && iNewY < pSprLayer->getHeight())
}
{
if(!g_pState || !g_pState->pPlayer) return;
if(!pSpr) return;
float fWorldX = (static_cast<float>(g_pState->pPlayer->iX * g_pState->iTileSize)) + g_pState->pPlayer->fOffX;
float fWorldY = (static_cast<float>(g_pState->pPlayer->iY * g_pState->iTileSize)) + g_pState->pPlayer->fOffY;
SDL_FPoint pScreen = rContext.
worldToScreen(fWorldX, fWorldY,
true);
float fScreenX = pScreen.x;
float fScreenY = pScreen.y;
{
}
}
void setupSpriteAnimations(Sint32 iIDSpr)
{
if(!pSpr) return;
Sint32 iHX = 8;
Sint32 iHY = 8;
for(Sint32 i = 0; i <= 10; i++)
{
}
}
bool setupTutorial(const string& rMapName, Sint32 iTileSize)
{
if(!g_pState || !g_pState->pScene) return false;
string sMapFile = rMapName + ".png";
string sHeightMapFile = rMapName + "-heightmap.png";
mLog.msg(
LL_INFO,
"Setting up War Game Layers for map '%s' (TileSize: %d)...\n", rMapName.c_str(), iTileSize);
if(g_pState->pScene->importLayerFromFile(1, sMapFile, "Background", iTileSize, iTileSize) < 0)
{
mLog.msg(
LL_ERROR,
"Failed to load background map from '%s'.\n", sMapFile.c_str());
return false;
}
if(!pLayerBg) return false;
if(iMapW <= 0 || iMapH <= 0 || g_pState->iTileSize <= 0)
{
mLog.msg(
LL_ERROR,
"Background layer has invalid dimensions.\n");
return false;
}
mLog.msg(
LL_INFO,
"Layer 1 imported. Map Size: %dx%d tiles. Tile Size: %d.\n", iMapW, iMapH, g_pState->iTileSize);
SceneLayerHeightMap* pLayerH = new(std::nothrow) SceneLayerHeightMap("HeightMap", iMapH, iMapW);
if(!pLayerH)
{
mLog.msg(
LL_ERROR,
"Failed to allocate the heightmap layer.\n");
return false;
}
if(!pLayerH->setCellWidth(g_pState->iTileSize) ||
!pLayerH->setCellHeight(g_pState->iTileSize) ||
g_pState->pScene->addLayer(pLayerH, 2) < 0)
{
delete pLayerH;
mLog.msg(
LL_ERROR,
"Failed to add the heightmap layer.\n");
return false;
}
!g_pState->pScene->setLayerAlphaMod(2, 128))
{
mLog.msg(
LL_ERROR,
"Failed to configure the heightmap layer.\n");
return false;
}
if(idImgH <= 0)
{
mLog.msg(
LL_ERROR,
"Failed to load heightmap image: %s\n", sHeightMapFile.c_str());
return false;
}
Image* pHeightImage = mImageMgr.
get(idImgH);
SDL_Surface* sH = pHeightImage ? pHeightImage->
getSurface() :
nullptr;
if(!sH || sH->w <= 0 || sH->h <= 0)
{
mLog.msg(
LL_ERROR,
"Failed to access heightmap image pixels.\n");
return false;
}
for(Sint32 iY = 0; iY < iMapH; iY++)
{
for(Sint32 iX = 0; iX < iMapW; iX++)
{
Sint32 iPX = iX * g_pState->iTileSize + (g_pState->iTileSize / 2);
Sint32 iPY = iY * g_pState->iTileSize + (g_pState->iTileSize / 2);
if(iPX >= sH->w) iPX = sH->w - 1;
if(iPY >= sH->h) iPY = sH->h - 1;
Uint8 iR = 0, iG = 0, iB = 0, iA = 0;
if(!SDL_ReadSurfacePixel(sH, iPX, iPY, &iR, &iG, &iB, &iA))
{
mLog.msg(
LL_ERROR,
"Failed to read heightmap image pixels.\n");
return false;
}
Uint32 iWeight = 255;
if(iR <= 200 || iG >= 50 || iB >= 50)
{
const Sint32 iBrightness = (iR + iG + iB) / 3;
iWeight = 128 - static_cast<Uint32>(static_cast<float>(iBrightness) * 0.439f);
if(iWeight < 16) iWeight = 16;
}
pLayerH->setCellValue(iY, iX, iWeight);
}
}
if(g_pState->pScene->createLayer(
"Sprites",
SLT_TILE, 3, iMapW, iMapH) < 0)
{
mLog.msg(
LL_ERROR,
"Failed to create the sprite layer.\n");
return false;
}
if(!pLayerS || !pLayerS->
setCellWidth(g_pState->iTileSize) ||
!g_pState->pScene->setLayerOnRenderEnd(3, onRenderSprites) ||
!g_pState->pScene->setLayerFeatures(3,
SLF_RENDER,
true))
{
mLog.msg(
LL_ERROR,
"Failed to configure the sprite layer.\n");
return false;
}
Sint32 idFogImg = mImageMgr.
create(
"FogImage");
SDL_Surface* sFog = SDL_CreateSurface(g_pState->iTileSize * 2, g_pState->iTileSize, SDL_PIXELFORMAT_RGBA8888);
Image* pFogImage = mImageMgr.
get(idFogImg);
if(idFogImg <= 0 || !pFogImage || !sFog)
{
if(sFog) SDL_DestroySurface(sFog);
mLog.msg(
LL_ERROR,
"Failed to create the fog image.\n");
return false;
}
SDL_Rect r1 = { 0, 0, g_pState->iTileSize, g_pState->iTileSize };
if(!SDL_FillSurfaceRect(sFog, &r1, SDL_MapRGBA(SDL_GetPixelFormatDetails(sFog->format), NULL, 0, 0, 0, 128)))
{
SDL_DestroySurface(sFog);
mLog.msg(
LL_ERROR,
"Failed to draw the fog image.\n");
return false;
}
SDL_Rect r2 = { g_pState->iTileSize, 0, g_pState->iTileSize, g_pState->iTileSize };
if(!SDL_FillSurfaceRect(sFog, &r2, SDL_MapRGBA(SDL_GetPixelFormatDetails(sFog->format), NULL, 0, 0, 0, 255)) ||
{
SDL_DestroySurface(sFog);
mLog.msg(
LL_ERROR,
"Failed to finish the fog image.\n");
return false;
}
Sint32 idFogTile = mTileMgr.
create(
"FogTiles");
Tile* pFogTile = mTileMgr.
get(idFogTile);
if(idFogTile <= 0 || !pFogTile || pFogTile->assignImage(idFogImg, 1) < 0 ||
!pFogTile->
setOffset(1, g_pState->iTileSize, g_pState->iTileSize))
{
mLog.msg(
LL_ERROR,
"Failed to create the fog tiles.\n");
return false;
}
if(g_pState->pScene->createLayer(
"FogOfWar",
SLT_TILE, 4, iMapW, iMapH) < 0)
{
mLog.msg(
LL_ERROR,
"Failed to create the fog layer.\n");
return false;
}
g_pState->iFogFirstGID = g_pState->pScene->createTileSet(idFogTile);
if(g_pState->iFogFirstGID <= 0)
{
mLog.msg(
LL_ERROR,
"Failed to attach the fog tileset.\n");
return false;
}
if(!pLayerFog || !pLayerFog->
setCellWidth(g_pState->iTileSize) ||
{
mLog.msg(
LL_ERROR,
"Failed to configure the fog layer.\n");
return false;
}
for(Sint32 iY = 0; iY < iMapH; iY++)
for(Sint32 iX = 0; iX < iMapW; iX++)
pLayerFog->
setCellValue(iY, iX, g_pState->iFogFirstGID + 1);
{
mLog.msg(
LL_ERROR,
"Failed to enable the fog layer.\n");
return false;
}
return true;
}
static void closeTutorial()
{
}
int main(int argc, char* argv[])
{
if(!runParameterReadRender(argc, argv, eRenderer)) return 1;
TutorialState state;
g_pState = &state;
Player player = {};
g_pState->pPlayer = &player;
{
mLog.msg(
LL_ERROR,
"Failed to initialize tutorial timing.\n");
return -1;
}
pScreen->
setSize(iScreenW, iScreenH);
pScreen->
setTitle(
"Tutorial 16 Scene - WarGame");
{
return -1;
}
{
mLog.msg(
LL_ERROR,
"Failed to set the render callback.\n");
return -1;
}
g_pState->idBgImage = mC64.
imageMgr().
load(OUTPUT_CDC, RESOURCE_BG_CDC_NAME);
if(g_pState->idBgImage <= 0 || g_pState->idDebugFont <= 0)
{
mLog.msg(
LL_ERROR,
"Failed to load the tutorial interface resources.\n");
closeTutorial();
return -1;
}
if(idSprImg <= 0 || !pImSprite || pImSprite->setColorKey(255, 255, 255) < 0)
{
mLog.msg(
LL_ERROR,
"Failed to load the player sprite image.\n");
closeTutorial();
return -1;
}
if(!pPlayerSprite || pPlayerSprite->
assignImage(idSprImg, 1) < 0)
{
mLog.msg(
LL_ERROR,
"Failed to create the player sprite.\n");
closeTutorial();
return -1;
}
setupSpriteAnimations(g_pState->pPlayer->iIDSprite);
if(idScene < 0 || !g_pState->pScene)
{
mLog.msg(
LL_ERROR,
"Failed to create the War Game Scene.\n");
closeTutorial();
return -1;
}
if(!setupTutorial(BASEDIR"map-war1", 32))
{
mLog.msg(
LL_CRITICAL,
"Failed to setup War Game layers.\n");
closeTutorial();
return -1;
}
if(!pL1)
{
mLog.msg(
LL_ERROR,
"Failed to access the background layer.\n");
closeTutorial();
return -1;
}
g_pState->pPlayer->iX = (Sint32)((pL1->
getTotalWidth() / 2.0f) / g_pState->iTileSize);
g_pState->pPlayer->iY = (Sint32)((pL1->
getTotalHeight() / 2.0f) / g_pState->iTileSize);
g_pState->pPlayer->fOffX = 0.0f;
g_pState->pPlayer->fOffY = 0.0f;
g_pState->pPlayer->iTargetX = g_pState->pPlayer->iX;
g_pState->pPlayer->iTargetY = g_pState->pPlayer->iY;
g_pState->pPlayer->bIsMoving = false;
updateSpriteMap(-1, -1, g_pState->pPlayer->iX, g_pState->pPlayer->iY);
SDL_Rect rView = { iViewX, iViewY, iViewW, iViewH };
if(!g_pState->pScene->setViewport(&rView))
{
mLog.msg(
LL_ERROR,
"Failed to configure the Scene viewport.\n");
closeTutorial();
return -1;
}
{
mLog.msg(
LL_ERROR,
"Failed to center the Scene camera.\n");
closeTutorial();
return -1;
}
updateFog(g_pState->pPlayer->iX, g_pState->pPlayer->iY);
mLog.msg(
LL_INFO,
"Initialization complete. Starting loop.\n");
mLog.msg(
LL_INFO,
"\nCONTROLS:\n [Right-Click] Move\n [Cursors] Scroll\n [F1] Toggle heightmap\n [F2] Toggle fog of war\n [Q/Esc] Quit\n\n");
SDL_Event ev;
bool bDone = false;
bool bShowHeightMap = false;
bool bVisibleFog = true;
float fMoveAccum = 0.0f;
while(!bDone)
{
{
switch(ev.type)
{
case SDL_EVENT_QUIT:
bDone = true;
break;
case SDL_EVENT_KEY_DOWN:
if(ev.key.key == SDLK_ESCAPE || ev.key.key == SDLK_Q)
{
bDone = true;
}
else if(ev.key.key == SDLK_F1)
{
bShowHeightMap = !bShowHeightMap;
g_pState->pScene->setLayerFeatures(2,
SLF_RENDER, bShowHeightMap);
mLog.msg(
LL_INFO,
"Heightmap: %s\n", bShowHeightMap ?
"ON" :
"OFF");
}
else if(ev.key.key == SDLK_F2)
{
bVisibleFog = !bVisibleFog;
mLog.msg(
LL_INFO,
"Fog of War: %s\n", bVisibleFog ?
"ON" :
"OFF");
}
break;
}
}
if(bDone) break;
float fSpeed = fScrollSpeed * fLogicStep;
float fDX = 0, fDY = 0;
if(fDX != 0.0f || fDY != 0.0f)
{
float fX = 0.0f, fY = 0.0f;
if(g_pState->pScene->getLayerPosition(1, &fX, &fY) >= 0)
{
}
}
const bool bRightPressed =
((iMouseButtons & SDL_BUTTON_MASK(SDL_BUTTON_RIGHT)) != 0) &&
((iMouseButtonsPrev & SDL_BUTTON_MASK(SDL_BUTTON_RIGHT)) == 0);
if(bRightPressed)
{
Sint32 iTX = 0;
Sint32 iTY = 0;
if(g_pState->pScene->mouseToCell(&iTX, &iTY, 1))
{
if(iTX != g_pState->pPlayer->iTargetX || iTY != g_pState->pPlayer->iTargetY)
{
mLog.msg(
LL_INFO,
"Moving to grid cell: (%d, %d)\n", iTX, iTY);
}
if(iTX != g_pState->pPlayer->iX || iTY != g_pState->pPlayer->iY) {
g_pState->pPlayer->vPath = findPath(g_pState->pPlayer->iX, g_pState->pPlayer->iY, iTX, iTY);
if(!g_pState->pPlayer->vPath.empty()) {
g_pState->pPlayer->iCurrentPathIndex = 0;
g_pState->pPlayer->bIsMoving = true;
}
}
}
}
if(g_pState->pPlayer->bIsMoving)
{
if(g_pState->pPlayer->iCurrentPathIndex < (int)g_pState->pPlayer->vPath.size())
{
g_pState->pPlayer->iTargetX = g_pState->pPlayer->vPath[g_pState->pPlayer->iCurrentPathIndex].x;
g_pState->pPlayer->iTargetY = g_pState->pPlayer->vPath[g_pState->pPlayer->iCurrentPathIndex].y;
}
fMoveAccum += fPlayerSpeed * fLogicStep;
while(fMoveAccum >= 1.0f)
{
if(g_pState->pPlayer->iX == g_pState->pPlayer->iTargetX && g_pState->pPlayer->iY == g_pState->pPlayer->iTargetY && g_pState->pPlayer->fOffX == 0.0f && g_pState->pPlayer->fOffY == 0.0f)
{
if(g_pState->pPlayer->iCurrentPathIndex < (int)g_pState->pPlayer->vPath.size())
{
g_pState->pPlayer->iCurrentPathIndex++;
if(g_pState->pPlayer->iCurrentPathIndex >= (int)g_pState->pPlayer->vPath.size())
{
g_pState->pPlayer->bIsMoving = false;
g_pState->pPlayer->vPath.clear();
g_pState->pPlayer->iCurrentPathIndex = 0;
fMoveAccum = 0.0f;
break;
}
else
{
g_pState->pPlayer->iTargetX = g_pState->pPlayer->vPath[g_pState->pPlayer->iCurrentPathIndex].x;
g_pState->pPlayer->iTargetY = g_pState->pPlayer->vPath[g_pState->pPlayer->iCurrentPathIndex].y;
}
}
else
{
g_pState->pPlayer->bIsMoving = false;
fMoveAccum = 0.0f;
break;
}
}
float fDiffX = (float)(g_pState->pPlayer->iTargetX - g_pState->pPlayer->iX);
float fDiffY = (float)(g_pState->pPlayer->iTargetY - g_pState->pPlayer->iY);
float fMoveX = 0.0f;
float fMoveY = 0.0f;
if(fDiffX > 0) fMoveX = 1.0f;
else if(fDiffX < 0) fMoveX = -1.0f;
else if(g_pState->pPlayer->fOffX > 0) fMoveX = -1.0f;
else if(g_pState->pPlayer->fOffX < 0) fMoveX = 1.0f;
if(fDiffY > 0) fMoveY = 1.0f;
else if(fDiffY < 0) fMoveY = -1.0f;
else if(g_pState->pPlayer->fOffY > 0) fMoveY = -1.0f;
else if(g_pState->pPlayer->fOffY < 0) fMoveY = 1.0f;
g_pState->pPlayer->fOffX += fMoveX;
g_pState->pPlayer->fOffY += fMoveY;
Sint32 iHalfTile = (g_pState->iTileSize / 2) + 1;
Sint32 iOldX = g_pState->pPlayer->iX;
Sint32 iOldY = g_pState->pPlayer->iY;
bool bCellChanged = false;
if(g_pState->pPlayer->fOffX >= iHalfTile)
{
g_pState->pPlayer->iX++;
g_pState->pPlayer->fOffX -= g_pState->iTileSize;
bCellChanged = true;
}
else if(g_pState->pPlayer->fOffX <= -iHalfTile)
{
g_pState->pPlayer->iX--;
g_pState->pPlayer->fOffX += g_pState->iTileSize;
bCellChanged = true;
}
if(g_pState->pPlayer->fOffY >= iHalfTile)
{
g_pState->pPlayer->iY++;
g_pState->pPlayer->fOffY -= g_pState->iTileSize;
bCellChanged = true;
}
else if(g_pState->pPlayer->fOffY <= -iHalfTile)
{
g_pState->pPlayer->iY--;
g_pState->pPlayer->fOffY += g_pState->iTileSize;
bCellChanged = true;
}
if(g_pState->pPlayer->iX == g_pState->pPlayer->iTargetX && g_pState->pPlayer->iY == g_pState->pPlayer->iTargetY)
{
if(abs(g_pState->pPlayer->fOffX) < 1.0f) g_pState->pPlayer->fOffX = 0.0f;
if(abs(g_pState->pPlayer->fOffY) < 1.0f) g_pState->pPlayer->fOffY = 0.0f;
}
if(bCellChanged)
{
updateSpriteMap(iOldX, iOldY, g_pState->pPlayer->iX, g_pState->pPlayer->iY);
updateFog(g_pState->pPlayer->iX, g_pState->pPlayer->iY);
}
else if(fMoveX == 0 && fMoveY < 0) iNextState =
SPR_STATE_UP;
fMoveAccum -= 1.0f;
}
}
g_pState->pScene->update();
}
if(g_pState->pScene->save(OUTPUTDIR"wargame.tmx", "", "wargame.cdc", true) < 0)
{
mLog.msg(
LL_ERROR,
"Failed to save the War Game Scene.\n");
closeTutorial();
return -1;
}
closeTutorial();
return 0;
}
Screen * get(Sint32 idScreen=0)
Get a pointer to the screen using its handle.
Definition CoreConfig.cpp:1497
void setMTFriendly(Uint8 iDelayMS)
Set the multithread-friendly scheduler yield.
Definition CoreConfig.cpp:1183
Sint32 getButtonsPrev() const
Get the previous mouse buttons.
Definition GraphicsCursor.cpp:1053
Sint32 getButtons() const
Get the mouse buttons.
Definition GraphicsCursor.cpp:1047
Sint32 getHeight() const
Get the height of this font (in pixels).
Definition GraphicsFont.cpp:1025
Sint32 render(const string &sText, bool bShowCursor=false, Sint32 iCurPos=-1, Sint32 idRes=0)
Render a text using this font.
Definition GraphicsFont.cpp:1095
bool setPosition(const Position &rPosX, const Position &rPosY, bool bInterpolate=false)
Set the font position.
Definition GraphicsFont.cpp:1037
Sint32 getWidth(const string &sText, Sint32 iCurPos=-1) const
Get the width of the given string (in pixels).
Definition GraphicsFont.cpp:987
Sint32 getBuiltin(const string &sName)
Get a built-in embedded font id using its name.
Definition GraphicsFont.cpp:1436
Sint32 close(Sint32 idFont) override
Close and destroy a font.
Definition GraphicsFont.cpp:1363
Image Object class.
Definition CRM64Pro.h:3356
SDL_Surface * getSurface()
Get the raw source surface of this image.
Definition GraphicsImage.cpp:1827
Sint32 assignSurface(SDL_Surface *pSurface, Sint32 iOwnership=0)
Assign a SDL_Surface to this image.
Definition GraphicsImage.cpp:1360
Sint32 render(Sint32 idRes=0, SDL_FRect *pSrc=nullptr, SDL_FRect *pDst=nullptr)
Render the image.
Definition GraphicsImage.cpp:1575
Image Manager class.
Definition CRM64Pro.h:3570
Image * get(Sint32 idImg)
Get a pointer to the image using its handle.
Definition GraphicsImage.cpp:2279
Sint32 loadFromFile(const string &sFile, const string &sName="")
Load an image from an external file (BMP, PNG, JPG, PCX, TGA or WebP formats).
Definition GraphicsImage.cpp:2434
Sint32 load(const string &sCDCFile, const string &sName)
Load an image stored in a CDC file.
Definition GraphicsImage.cpp:2476
Sint32 create(const string &sName, Uint32 iVersion=10) override
Creates a new image.
Definition GraphicsImage.cpp:2136
Sint32 close(Sint32 idImg) override
Close and destroy an image.
Definition GraphicsImage.cpp:2178
Log Object class.
Definition CRM64Pro.h:771
CRM64Pro GDK Main class.
Definition CRM64Pro.h:502
Scene class.
Definition CRM64Pro.h:11200
TileLayer class for tile-based map layers.
Definition CRM64Pro.h:10368
Uint32 ** iCellMap
Direct mutable 2D cell map.
Definition CRM64Pro.h:10571
Screen Object class.
Definition CRM64Pro.h:1055
Sint32 show()
Show the screen.
Definition CoreConfig.cpp:362
Sint32 setDriver(eConfigRendererDriver eCRD)
Set the renderer driver.
Definition CoreConfig.cpp:454
bool setRenderCallback(RenderCallback fnCallback)
Set a callback function for rendering graphics at Render Frame Rate.
Definition CoreConfig.cpp:765
Sint32 setSize(Sint32 iWidth, Sint32 iHeight)
Set the size of the screen.
Definition CoreConfig.cpp:526
bool setTitle(const string &sName)
Set the title.
Definition CoreConfig.cpp:674
Sprite Object class.
Definition CRM64Pro.h:4262
Tile Object class.
Definition CRM64Pro.h:3998
Tile Manager class.
Definition CRM64Pro.h:4118
void setStatsLevel(eMemStatsLevel eMSL)
Set the memory stats gathering level.
Definition CMemoryManager.cpp:618
void destroy()
Releases the internal heap and displays final stats.
Definition CMemoryManager.cpp:954
@ MSL_HIGH
MSL_NORMAL plus deallocations and sizes logging for each module.
Definition CRM64Pro.h:387
eConfigRendererDriver
Screen renderer drivers.
Definition CRM64Pro.h:1013
@ CRD_SOFTWARE
Screen::setDriver(): software renderer driver. Slow but works on all platforms.
Definition CRM64Pro.h:1015
bool init(const string &sAppname, eLogLevel eLL, eLogMode eLM, const string &sFilename="", const string &sAuthor="", const string &sEmail="", const string &sWeb="")
Initialize the log object.
Definition CoreLog.cpp:338
@ LM_FILE
Log output mode for the 'lm' parameter in CRM64Pro::Log::init(). Output to a file and overwrite exist...
Definition CRM64Pro.h:748
@ LM_STDOUT
Log output mode for the 'lm' parameter in CRM64Pro::Log::init(). Output to standard output (stdout).
Definition CRM64Pro.h:750
@ LL_INFO
Runtime events (startup/shutdown). Messages without timestamp.
Definition CRM64Pro.h:764
@ LL_DEBUG
Detailed information for flow control.
Definition CRM64Pro.h:765
@ LL_CRITICAL
Fatal errors, application crash, or assertions.
Definition CRM64Pro.h:761
@ LL_ERROR
Runtime errors that do not require immediate termination.
Definition CRM64Pro.h:762
TileMgr & tileMgr()
Get reference to Tile Manager.
Definition CoreMain.cpp:766
SpriteMgr & spriteMgr()
Get reference to Sprite Manager.
Definition CoreMain.cpp:772
Timer & timer()
Get reference to Timer module.
Definition CoreMain.cpp:730
Sint32 update(SDL_Event *evUser=nullptr)
Manage the GDK update cycle with a fixed virtual logic frame rate.
Definition CoreMain.cpp:451
ImageMgr & imageMgr()
Get reference to Image Manager.
Definition CoreMain.cpp:754
CursorMgr & cursorMgr()
Get reference to Cursor Manager.
Definition CoreMain.cpp:760
SceneMgr & sceneMgr()
Get reference to Scene Manager.
Definition CoreMain.cpp:814
static void terminate()
Main explicit destructor.
Definition CoreMain.cpp:266
static Main & instance()
Access the Main singleton.
Definition CoreMain.cpp:252
bool getKeyState(SDL_Keycode keycode) const
Get the current state of a key.
Definition CoreMain.cpp:686
FontMgr & fontMgr()
Get reference to Font Manager.
Definition CoreMain.cpp:778
ConfigMgr & configMgr()
Get reference to Config Manager.
Definition CoreMain.cpp:712
@ PH_CENTER
Cursor::setHotSpot(): set hotspot to cursor_size/2. Sprite::setAnimHotSpot(): set hotspot to frame_si...
Definition CRM64Pro.h:336
@ SLF_RENDER
Enable the rendering feature. Enabling this flag also enables SLF_UPDATE. Disabling render does not d...
Definition CRM64Pro.h:10079
@ SLF_UPDATE
Enable the updating feature. Check update() for further details.
Definition CRM64Pro.h:10078
@ SDO_TILE_CELLGRID
Draw tile cell grid overlays for rendered tile layers.
Definition CRM64Pro.h:10097
@ SLT_TILE
Layer contains tile data (SceneLayerTile).
Definition CRM64Pro.h:10151
float getTotalHeight() const override
Get layer total height in pixels.
Definition SceneLayerTile.cpp:112
bool setCellHeight(Sint32 iSize)
Set cell height.
Definition SceneLayerTile.cpp:126
float getTotalWidth() const override
Get layer total width in pixels.
Definition SceneLayerTile.cpp:106
Sint32 getHeight() const
Get map height.
Definition SceneLayerTile.cpp:101
bool setCellWidth(Sint32 iSize)
Set cell width.
Definition SceneLayerTile.cpp:118
Sint32 getCellWidth() const
Get cell width.
Definition SceneLayerTile.cpp:92
bool setCellValue(Sint32 iY, Sint32 iX, Uint32 iValue)
Set arbitrary values on 2D array of cells.
Definition SceneLayerTile.cpp:160
Sint32 getWidth() const
Get map width.
Definition SceneLayerTile.cpp:98
Sint32 close(Sint32 idScene) override
Close and destroy a Scene.
Definition Scene.cpp:2298
bool info(Sint32 iMode=0) override
Request Scene Manager information.
Definition Scene.cpp:2215
Sint32 create(const string &sName, Uint32 iNumLayers=3) override
Create a new Scene.
Definition Scene.cpp:2256
Scene * get(Sint32 idScene)
Get a pointer to the Scene using its handle.
Definition Scene.cpp:2355
#define SPR_STATE_DOWNRIGHT
Definition CRM64Pro.h:4254
Sint32 assignImage(Sint32 idImage, Sint32 iOwnership=0)
Assign an Image to this sprite.
Definition GraphicsSprite.cpp:494
#define SPR_STATE_UPRIGHT
Definition CRM64Pro.h:4250
Sint32 render(Sint32 idRes=0)
Render the sprite.
Definition GraphicsSprite.cpp:1395
#define SPR_STATE_RIGHT
Definition CRM64Pro.h:4246
bool setAnimStateIndex(Sint32 iIndex, Uint16 iState)
Set the animation state by index.
Definition GraphicsSprite.cpp:927
bool selectAnim(Uint16 iState)
Select an animation by state.
Definition GraphicsSprite.cpp:794
#define SPR_STATE_UPLEFT
Definition CRM64Pro.h:4248
#define SPR_STATE_NORMAL
Definition CRM64Pro.h:4238
#define SPR_STATE_DOWN
Definition CRM64Pro.h:4242
bool setPosition(float fX, float fY, bool bInterpolate=false)
Set the sprite position.
Definition GraphicsSprite.cpp:1356
#define SPR_STATE_DOWNLEFT
Definition CRM64Pro.h:4252
Sint32 create(const string &sName, Uint32 iVersion=10) override
Create a new sprite.
Definition GraphicsSprite.cpp:1691
bool setOffset(Sint32 iX, Sint32 iY)
Set the sprite offsets for creating the animations and frames.
Definition GraphicsSprite.cpp:640
#define SPR_STATE_UP
Definition CRM64Pro.h:4240
Sprite * get(Sint32 idSprite)
Get a pointer to the sprite using its handle.
Definition GraphicsSprite.cpp:1843
#define SPR_STATE_LEFT
Definition CRM64Pro.h:4244
bool setFrameTimeIndex(Sint32 iIndex, Sint32 iFrame, Uint16 iTime)
Set the frame time duration by index.
Definition GraphicsSprite.cpp:1284
bool setAnimHotSpotIndex(Sint32 iIndex, Sint32 iHotX, Sint32 iHotY)
Set the animation hotspot by index.
Definition GraphicsSprite.cpp:1046
Sint32 close(Sint32 idSprite) override
Close and destroy a sprite.
Definition GraphicsSprite.cpp:1739
Tile * get(Sint32 idTile)
Get a pointer to the tile using its handle.
Definition GraphicsTile.cpp:850
bool setOffset(Sint32 iTSMode, Sint32 iX, Sint32 iY)
Set tileset mode and offset.
Definition GraphicsTile.cpp:351
Sint32 close(Sint32 idTile) override
Close and destroy a tile.
Definition GraphicsTile.cpp:785
Sint32 create(const string &sName, Uint32 iVersion=10) override
Create a new tile.
Definition GraphicsTile.cpp:744
bool init(eTimerState eState=TS_INIT)
Initialize the timer system.
Definition CoreTimer.cpp:543
bool setRate(Uint16 iR, Uint16 iL)
Set preferred Render and Logic Frame Rate.
Definition CoreTimer.cpp:556
CRM64Pro GDK.
Definition AudioTrack.cpp:36
Absolute coordinate or helper-relative position used by layout APIs.
Definition CRM64Pro.h:346
Layer Context structure.
Definition CRM64Pro.h:10223
float fScrollY
Current Logic/Render Y scroll position.
Definition CRM64Pro.h:10228
SDL_Rect rViewport
The effective viewport used for this frame.
Definition CRM64Pro.h:10226
SDL_FPoint worldToScreen(float fWorldX, float fWorldY, bool bQuantize=true) const
Convert world coordinates to screen coordinates using the canonical render camera.
Definition CRM64Pro.h:10273
float fScrollX
Current Logic/Render X scroll position.
Definition CRM64Pro.h:10227