CRM64Pro GDK v0.80.0
A free cross-platform game development kit built on top of SDL 3.0
Loading...
Searching...
No Matches
Tutorial 08: Animated sprites

Overview

This tutorial extends Tutorial 07 with an animated Sprite resource. It turns Base/sprite2.png into four directional animations, stores the sprite in the shared Tutorial.cdc archive and creates three child sprites with independent image appearance.

The main sprite follows the cursor keys. The other sprites move automatically with different animation speeds, scaling, color modulation and alpha.

Final result

CRM64Pro Tutorial 08 animated sprites

Runtime controls

  • Cursor keys: Move the main sprite.
  • I: Enable or disable interpolated positioning.
  • D: Show or hide the debug window.
  • Grave key: Show or hide the built-in console.
  • Any key or mouse click: Write the input event to the log.
  • Q or ESC: Exit the tutorial.

Prerequisites

  • CRM64Pro GDK installed and configured with a supported C++17 compiler.
  • Tutorial package downloaded and fully extracted, preserving its folder structure.
  • Run Tutorials 02 and 04 first so Tutorial.cdc contains the background and cursor resources.
  • Included assets available under bin/Base/: sprite2.png.
  • Write access to the platform output directory.

What you will learn

  • Create a Sprite from a sprite-sheet Image.
  • Split the sheet into animations and frames with Sprite::setOffset().
  • Map animation rows to directional sprite states.
  • Create child sprites that reuse the parent animation data.
  • Change animation speed, scale, color and alpha independently.
  • Select animations from movement direction.
  • Toggle interpolated sprite positioning.

Step by step

1. Verify the shared archive

The sprite must extend the archive created by the earlier tutorials. Checking the file first prevents an incomplete sprite-only archive.

// Tutorial 08 introduces one new resource. Earlier tutorials already added
// the background and cursor to the CDC.
mLog.msg(LL_INFO, " Find Tutorial 04 CDC: %s ... ", OUTPUT_CDC);
if(!mC64.tool().fileExists(OUTPUT_CDC))
{
logTaskFailed(mLog);
return false;
}
logTaskOk(mLog);

2. Create the sprite resource

Load the sheet, create an empty Sprite and transfer ownership of the Image to it. Closing the Sprite will then release its owned Image.

mLog.msg(LL_INFO, " Load sprite sheet: %s ... ", RESOURCE_SPRITE_IMAGE);
Sint32 idSpriteImage = mC64.imageMgr().loadFromFile(RESOURCE_SPRITE_IMAGE, "tutorialSpriteImageFile");
Image* pSpriteImage = mC64.imageMgr().get(idSpriteImage);
if(idSpriteImage < 0 || pSpriteImage == nullptr)
{
logTaskFailed(mLog, idSpriteImage);
return false;
}
logTaskOk(mLog);
mLog.msg(LL_INFO, " Create sprite from image ... ");
Sint32 idSpriteFile = mC64.spriteMgr().create(RESOURCE_SPRITE_CDC_NAME);
Sprite* pSpriteFile = mC64.spriteMgr().get(idSpriteFile);
if(idSpriteFile < 0 || pSpriteFile == nullptr)
{
logTaskFailed(mLog, idSpriteFile);
mC64.imageMgr().close(idSpriteImage);
return false;
}
if(pSpriteFile->assignImage(idSpriteImage, 1) < 0)
{
logTaskFailed(mLog);
mC64.spriteMgr().close(idSpriteFile);
mC64.imageMgr().close(idSpriteImage);
return false;
}

3. Define animations and frames

Each 32x32 row becomes an animation. The rows map to the four directional states, all frames use 75 milliseconds and the animation hotspot is centered.

// Configure the sprite animation and behaviour.
static bool configureSprite(Sprite* pSprite)
{
if(!pSprite || !pSprite->setOffset(iSpriteW, iSpriteH)) return false;
if(!pSprite->setAnimStateIndex(0, SPR_STATE_UP) ||
!pSprite->setAnimStateIndex(1, SPR_STATE_LEFT) ||
!pSprite->setAnimStateIndex(2, SPR_STATE_DOWN) ||
!pSprite->setAnimStateIndex(3, SPR_STATE_RIGHT)) return false;
for(Sint32 iAnim = 0; iAnim < 4; ++iAnim)
{
if(!pSprite->setFrameTimeIndex(iAnim, -1, 75) ||
!pSprite->setAnimHotSpotIndex(iAnim, PH_CENTER, PH_CENTER)) return false;
}
return pSprite->selectAnim(SPR_STATE_DOWN);
}
#define SPR_STATE_RIGHT
Definition CRM64Pro.h:4246
#define SPR_STATE_DOWN
Definition CRM64Pro.h:4242
#define SPR_STATE_UP
Definition CRM64Pro.h:4240
#define SPR_STATE_LEFT
Definition CRM64Pro.h:4244
if(!configureSprite(pSpriteFile))
{
logTaskFailed(mLog);
mC64.spriteMgr().close(idSpriteFile);
return false;
}
logTaskOk(mLog);

4. Save and reload the sprite

Save the configured Sprite by resource name, close the temporary object and load a fresh runtime instance from the CDC archive.

// Save appends or replaces the sprite resource in Tutorial.cdc.
mLog.msg(LL_INFO, " Save sprite to CDC ... ");
if(pSpriteFile->save(OUTPUT_CDC, RESOURCE_SPRITE_CDC_NAME) < 0)
{
logTaskFailed(mLog);
mC64.spriteMgr().close(idSpriteFile);
return false;
}
logTaskOk(mLog);
// Close the temporary sprite. The tutorial loads a fresh copy from CDC next.
mLog.msg(LL_INFO, " Close temporary sprite ... ");
mC64.spriteMgr().close(idSpriteFile);
logTaskOk(mLog);
mLog.msg(LL_INFO, " Load main sprite from CDC ... ");
state.idMainSprite = mC64.spriteMgr().load(OUTPUT_CDC, RESOURCE_SPRITE_CDC_NAME);
Sprite* pMainSprite = mC64.spriteMgr().get(state.idMainSprite);
if(state.idMainSprite < 0 || pMainSprite == nullptr)
{
logTaskFailed(mLog, state.idMainSprite);
Main::terminate();
return -1;
}
pMainSprite->setPosition(state.fMainX, state.fMainY);
logTaskOk(mLog);

5. Create visual variants

SpriteMgr::child() reuses the parent's animation data and creates a child Image whose rendering attributes can change independently. The variants demonstrate animation speed, scale, color modulation and alpha modulation.

if(!createSpriteClone(mC64, mLog, state.idMainSprite, state.idScaledSprite, "scaled") ||
!createSpriteClone(mC64, mLog, state.idMainSprite, state.idTintedSprite, "color mod") ||
!createSpriteClone(mC64, mLog, state.idMainSprite, state.idGhostSprite, "alpha mod"))
{
Main::terminate();
return -1;
}
Sprite* pScaledSprite = mC64.spriteMgr().get(state.idScaledSprite);
Sprite* pTintedSprite = mC64.spriteMgr().get(state.idTintedSprite);
Sprite* pGhostSprite = mC64.spriteMgr().get(state.idGhostSprite);
if(pScaledSprite)
{
pScaledSprite->setPosition(state.fScaledX, state.fScaledY);
pScaledSprite->setSpeed(0.8f);
}
if(pTintedSprite)
{
pTintedSprite->setPosition(state.fTintedX, state.fTintedY);
pTintedSprite->setSpeed(1.2f);
Image* pTintedImage = mC64.imageMgr().get(pTintedSprite->getImage());
if(pTintedImage) pTintedImage->setColorMod(255, 120, 120);
}
if(pGhostSprite)
{
pGhostSprite->setPosition(state.fGhostX, state.fGhostY);
pGhostSprite->setSpeed(1.6f);
Image* pGhostImage = mC64.imageMgr().get(pGhostSprite->getImage());
if(pGhostImage) pGhostImage->setAlphaMod(150);
}

6. Select direction animations

Movement selects the horizontal or vertical animation with the largest change. No selection is made while the sprite is stationary.

// Choose the sprite animation for its movement.
static void selectSpriteAnim(Sprite* pSprite, float fDX, float fDY)
{
if(!pSprite) return;
if(fDX == 0.0f && fDY == 0.0f) return;
if(fabsf(fDX) > fabsf(fDY))
{
pSprite->selectAnim(fDX < 0.0f ? SPR_STATE_LEFT : SPR_STATE_RIGHT);
}
else
{
pSprite->selectAnim(fDY < 0.0f ? SPR_STATE_UP : SPR_STATE_DOWN);
}
}

7. Move with optional interpolation

The fixed logic step updates positions. Bounds account for centered hotspots, and the interpolation flag is passed directly to Sprite::setPosition().

const float fSpriteHalfW = static_cast<float>(iSpriteW) * 0.5f;
const float fSpriteHalfH = static_cast<float>(iSpriteH) * 0.5f;
rState.fMainX = clampFloat(rState.fMainX + fDX, fSpriteHalfW, static_cast<float>(iScreenW) - fSpriteHalfW);
rState.fMainY = clampFloat(rState.fMainY + fDY, fSpriteHalfH, static_cast<float>(iScreenH) - fSpriteHalfH);
if(pMainSprite)
{
pMainSprite->setPosition(rState.fMainX, rState.fMainY, rState.iSmoothInterpolation != 0);
selectSpriteAnim(pMainSprite, fDX, fDY);
}
moveAutoSprite(mC64.spriteMgr().get(rState.idScaledSprite), rState.fScaledX, rState.fScaledY, rState.fScaledVX, rState.fScaledVY, fDeltaTime, fSpriteHalfW * fScaledSpriteScale, fSpriteHalfH * fScaledSpriteScale, rState.iSmoothInterpolation != 0);
moveAutoSprite(mC64.spriteMgr().get(rState.idTintedSprite), rState.fTintedX, rState.fTintedY, rState.fTintedVX, rState.fTintedVY, fDeltaTime, fSpriteHalfW, fSpriteHalfH, rState.iSmoothInterpolation != 0);
moveAutoSprite(mC64.spriteMgr().get(rState.idGhostSprite), rState.fGhostX, rState.fGhostY, rState.fGhostVX, rState.fGhostVY, fDeltaTime, fSpriteHalfW, fSpriteHalfH, rState.iSmoothInterpolation != 0);

8. Render the sprites

The scaled child uses Sprite::renderEx(); the remaining sprites use their own Image modulation through the normal Sprite::render() path.

Sprite* pScaledSprite = mC64.spriteMgr().get(rState.idScaledSprite);
Sprite* pTintedSprite = mC64.spriteMgr().get(rState.idTintedSprite);
Sprite* pGhostSprite = mC64.spriteMgr().get(rState.idGhostSprite);
Sprite* pMainSprite = mC64.spriteMgr().get(rState.idMainSprite);
if(pScaledSprite) pScaledSprite->renderEx(fScaledSpriteScale, fScaledSpriteScale);
if(pTintedSprite) pTintedSprite->render();
if(pGhostSprite) pGhostSprite->render();
if(pMainSprite) pMainSprite->render();

9. Handle movement and interpolation input

Key-down and key-up events maintain movement flags. Pressing I toggles whether future positions are interpolated.

else if(event.key.key == SDLK_LEFT)
{
state.bMoveLeft = true;
}
else if(event.key.key == SDLK_RIGHT)
{
state.bMoveRight = true;
}
else if(event.key.key == SDLK_UP)
{
state.bMoveUp = true;
}
else if(event.key.key == SDLK_DOWN)
{
state.bMoveDown = true;
}
else if(event.key.key == SDLK_I)
{
state.iSmoothInterpolation = state.iSmoothInterpolation ? 0 : 1;
mLog.msg(LL_INFO, " Smooth interpolation: %s\n", state.iSmoothInterpolation ? "enabled" : "disabled");
}
else if(event.type == SDL_EVENT_KEY_UP)
{
if(event.key.key == SDLK_LEFT) state.bMoveLeft = false;
else if(event.key.key == SDLK_RIGHT) state.bMoveRight = false;
else if(event.key.key == SDLK_UP) state.bMoveUp = false;
else if(event.key.key == SDLK_DOWN) state.bMoveDown = false;
}

10. Finish the loop cleanly

A quit request exits before another state update. The fixed logic delta comes from the configured logic rate.

if(!bRunning) break;
state.fMouseX = mC64.cursorMgr().getX();
state.fMouseY = mC64.cursorMgr().getY();
state.iCurrentRenderRate = static_cast<Sint32>(mC64.timer().getCurrentRFR());
state.iCurrentLogicRate = static_cast<Sint32>(mC64.timer().getCurrentLFR());
updateLogic(state, 1.0f / static_cast<float>(iLogicRate));

11. Release dependent resources first

Sprites and cursors can own Images, so they close before ImageMgr and the CDC archives.

mLog.msg(LL_INFO, " Close sprites ... ");
mC64.spriteMgr().close(0);
logTaskOk(mLog);
mLog.msg(LL_INFO, " Close cursors ... ");
mC64.cursorMgr().close(0);
logTaskOk(mLog);
mLog.msg(LL_INFO, " Close images ... ");
mC64.imageMgr().close(0);
logTaskOk(mLog);
mLog.msg(LL_INFO, " Close CDC archives ... ");
mC64.archiveMgr().close(0);
logTaskOk(mLog);
Main::terminate();

Complete source

The tutorial source is authoritative. The following listing is included directly from validation/source/Tutorial_08_Sprite.cpp.

/* ----------------------------------------------------------------------
CRM64Pro GDK - Roberto Prieto
Copyright (C) 2013-2026 MegaStorm Systems
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
------------------------------------------------------------------------
Tutorial 08: Sprite
------------------------------------------------------------------------
Overview:
This tutorial extends Tutorial 07 Tileset with sprites.
It removes the tile map and ship image, adds sprite2.png to Tutorial.cdc,
loads it as a Sprite, and renders a few cloned sprites.
Key concepts:
- Create a Sprite from a sprite sheet Image.
- Split a sprite sheet into animations and frames.
- Assign animation states to each row.
- Move a sprite with the keyboard.
- Toggle interpolated positioning for smoother movement.
- Clone sprites and render them with different visual options.
Controls:
- Cursor Keys: Move the main sprite.
- I: Toggle smooth interpolation.
- D: Toggle debug window.
- Grave: Toggle console.
- Any Key/Mouse: Logs events.
- Q / ESC: Quit.
Loop order:
- Process input events.
- Run one fixed logic update.
- Let Main::update() call the screen render callback.
------------------------------------------------------------------------ */
#include "CRM64Pro.h"
#include "RunParameter.h"
using namespace CRM64Pro;
#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_SPRITE_IMAGE BASEDIR"sprite2.png"
#define RESOURCE_BG_CDC_NAME "Tutorial_bg"
#define RESOURCE_CURSOR_CDC_NAME "Tutorial_cursor"
#define RESOURCE_SPRITE_CDC_NAME "Tutorial_sprite"
#define OUTPUT_CDC OUTPUTDIR"Tutorial.cdc"
// Fixed-rate timing.
// Render rate 0 lets the screen render as often as possible. Logic rate controls movement.
static const Sint32 iLogicRate = 20;
static const Sint32 iRenderRate = 0;
// Window, sprite sheet and movement settings.
static const Sint32 iScreenW = 960;
static const Sint32 iScreenH = 540;
static const Sint32 iSpriteW = 32;
static const Sint32 iSpriteH = 32;
static const float fScaledSpriteScale = 1.5f;
static const float fMoveSpeed = 180.0f;
// Values changed while the tutorial runs.
struct TutorialState
{
Sint32 idBgImage = -1;
Sint32 idCursor = -1;
Sint32 idMainSprite = -1;
Sint32 idScaledSprite = -1;
Sint32 idTintedSprite = -1;
Sint32 idGhostSprite = -1;
Sint32 idBuiltInFont = -1;
Sint32 idDebugWindow = -1;
float fMainX = 434.0f;
float fMainY = 234.0f;
float fScaledX = 130.0f;
float fScaledY = 120.0f;
float fScaledVX = 70.0f;
float fScaledVY = 45.0f;
float fTintedX = 680.0f;
float fTintedY = 130.0f;
float fTintedVX = -80.0f;
float fTintedVY = 60.0f;
float fGhostX = 380.0f;
float fGhostY = 360.0f;
float fGhostVX = 95.0f;
float fGhostVY = -55.0f;
float fMouseX = 0.0f;
float fMouseY = 0.0f;
Sint32 iCurrentRenderRate = 0;
Sint32 iCurrentLogicRate = 0;
Sint32 iLogicFrames = 0;
Sint32 iSmoothInterpolation = 0;
bool bMoveLeft = false;
bool bMoveRight = false;
bool bMoveUp = false;
bool bMoveDown = false;
};
// Keep a value inside the given range.
static float clampFloat(float fValue, float fMin, float fMax)
{
if(fValue < fMin) return fMin;
if(fValue > fMax) return fMax;
return fValue;
}
// Helper functions used by the setup log messages.
static void logTaskOk(Log& mLog)
{
mLog.msg(LL_DEBUG, "OK\n");
}
// Record a failed tutorial task.
static void logTaskFailed(Log& mLog, Sint32 iCode)
{
mLog.msg(LL_ERROR, "FAILED (Code %d)\n", iCode);
}
// Record a failed tutorial task.
static void logTaskFailed(Log& mLog)
{
mLog.msg(LL_ERROR, "FAILED\n");
}
// Configure the sprite animation and behaviour.
static bool configureSprite(Sprite* pSprite)
{
if(!pSprite || !pSprite->setOffset(iSpriteW, iSpriteH)) return false;
if(!pSprite->setAnimStateIndex(0, SPR_STATE_UP) ||
!pSprite->setAnimStateIndex(3, SPR_STATE_RIGHT)) return false;
for(Sint32 iAnim = 0; iAnim < 4; ++iAnim)
{
if(!pSprite->setFrameTimeIndex(iAnim, -1, 75) ||
!pSprite->setAnimHotSpotIndex(iAnim, PH_CENTER, PH_CENTER)) return false;
}
return pSprite->selectAnim(SPR_STATE_DOWN);
}
// Choose the sprite animation for its movement.
static void selectSpriteAnim(Sprite* pSprite, float fDX, float fDY)
{
if(!pSprite) return;
if(fDX == 0.0f && fDY == 0.0f) return;
if(fabsf(fDX) > fabsf(fDY))
{
pSprite->selectAnim(fDX < 0.0f ? SPR_STATE_LEFT : SPR_STATE_RIGHT);
}
else
{
pSprite->selectAnim(fDY < 0.0f ? SPR_STATE_UP : SPR_STATE_DOWN);
}
}
// Move one automatically controlled sprite.
static void moveAutoSprite(Sprite* pSprite, float& rX, float& rY, float& rVX, float& rVY, float fDeltaTime, float fHalfW, float fHalfH, bool bInterpolate)
{
const float fMaxX = static_cast<float>(iScreenW) - fHalfW;
const float fMaxY = static_cast<float>(iScreenH) - fHalfH;
rX += rVX * fDeltaTime;
rY += rVY * fDeltaTime;
if(rX < fHalfW || rX > fMaxX)
{
rVX = -rVX;
rX = clampFloat(rX, fHalfW, fMaxX);
}
if(rY < fHalfH || rY > fMaxY)
{
rVY = -rVY;
rY = clampFloat(rY, fHalfH, fMaxY);
}
if(pSprite)
{
pSprite->setPosition(rX, rY, bInterpolate);
selectSpriteAnim(pSprite, rVX, rVY);
}
}
// Move sprites one fixed logic step.
static void updateLogic(TutorialState& rState, float fDeltaTime)
{
Main& mC64 = Main::instance();
Sprite* pMainSprite = mC64.spriteMgr().get(rState.idMainSprite);
float fDX = 0.0f;
float fDY = 0.0f;
if(rState.bMoveLeft) fDX -= fMoveSpeed * fDeltaTime;
if(rState.bMoveRight) fDX += fMoveSpeed * fDeltaTime;
if(rState.bMoveUp) fDY -= fMoveSpeed * fDeltaTime;
if(rState.bMoveDown) fDY += fMoveSpeed * fDeltaTime;
const float fSpriteHalfW = static_cast<float>(iSpriteW) * 0.5f;
const float fSpriteHalfH = static_cast<float>(iSpriteH) * 0.5f;
rState.fMainX = clampFloat(rState.fMainX + fDX, fSpriteHalfW, static_cast<float>(iScreenW) - fSpriteHalfW);
rState.fMainY = clampFloat(rState.fMainY + fDY, fSpriteHalfH, static_cast<float>(iScreenH) - fSpriteHalfH);
if(pMainSprite)
{
pMainSprite->setPosition(rState.fMainX, rState.fMainY, rState.iSmoothInterpolation != 0);
selectSpriteAnim(pMainSprite, fDX, fDY);
}
moveAutoSprite(mC64.spriteMgr().get(rState.idScaledSprite), rState.fScaledX, rState.fScaledY, rState.fScaledVX, rState.fScaledVY, fDeltaTime, fSpriteHalfW * fScaledSpriteScale, fSpriteHalfH * fScaledSpriteScale, rState.iSmoothInterpolation != 0);
moveAutoSprite(mC64.spriteMgr().get(rState.idTintedSprite), rState.fTintedX, rState.fTintedY, rState.fTintedVX, rState.fTintedVY, fDeltaTime, fSpriteHalfW, fSpriteHalfH, rState.iSmoothInterpolation != 0);
moveAutoSprite(mC64.spriteMgr().get(rState.idGhostSprite), rState.fGhostX, rState.fGhostY, rState.fGhostVX, rState.fGhostVY, fDeltaTime, fSpriteHalfW, fSpriteHalfH, rState.iSmoothInterpolation != 0);
rState.iLogicFrames++;
}
// Draw the current timing information.
static void renderRates(Font* pBuiltInFont, const TutorialState& rState)
{
if(!pBuiltInFont) return;
char szRates[96];
snprintf(szRates, sizeof(szRates), "Render: %d fps Logic: %d fps", rState.iCurrentRenderRate, rState.iCurrentLogicRate);
pBuiltInFont->setPosition(10, 10);
pBuiltInFont->render(szRates);
}
// Draw the current frame. CursorMgr draws the selected cursor automatically.
static void renderFrame(Image* pBgImage, Font* pBuiltInFont, const TutorialState& rState)
{
Main& mC64 = Main::instance();
if(pBgImage) pBgImage->render();
Sprite* pScaledSprite = mC64.spriteMgr().get(rState.idScaledSprite);
Sprite* pTintedSprite = mC64.spriteMgr().get(rState.idTintedSprite);
Sprite* pGhostSprite = mC64.spriteMgr().get(rState.idGhostSprite);
Sprite* pMainSprite = mC64.spriteMgr().get(rState.idMainSprite);
if(pScaledSprite) pScaledSprite->renderEx(fScaledSpriteScale, fScaledSpriteScale);
if(pTintedSprite) pTintedSprite->render();
if(pGhostSprite) pGhostSprite->render();
if(pMainSprite) pMainSprite->render();
renderRates(pBuiltInFont, rState);
}
// Screen render callback.
// Main::update() calls this when the screen is ready to render.
static Sint32 renderWrapper(Sint32, void* pObj)
{
TutorialState* pState = static_cast<TutorialState*>(pObj);
if(!pState) return 0;
Main& mC64 = Main::instance();
Image* pBgImage = mC64.imageMgr().get(pState->idBgImage);
Font* pBuiltInFont = mC64.fontMgr().get(pState->idBuiltInFont);
renderFrame(pBgImage, pBuiltInFont, *pState);
return 0;
}
// Show or hide the debug window.
static void toggleDebugWindow(DebugWindow* pDebug)
{
if(!pDebug) return;
if(pDebug->baseWidget().status() == GS_SHOWN) pDebug->baseWidget().hide();
else pDebug->baseWidget().show();
}
// Add the sprite resource to the tutorial archive.
static bool addSpriteToCDC(Main& mC64, Log& mLog)
{
// Tutorial 08 introduces one new resource. Earlier tutorials already added
// the background and cursor to the CDC.
mLog.msg(LL_INFO, " Find Tutorial 04 CDC: %s ... ", OUTPUT_CDC);
if(!mC64.tool().fileExists(OUTPUT_CDC))
{
logTaskFailed(mLog);
return false;
}
logTaskOk(mLog);
mLog.msg(LL_INFO, " Load sprite sheet: %s ... ", RESOURCE_SPRITE_IMAGE);
Sint32 idSpriteImage = mC64.imageMgr().loadFromFile(RESOURCE_SPRITE_IMAGE, "tutorialSpriteImageFile");
Image* pSpriteImage = mC64.imageMgr().get(idSpriteImage);
if(idSpriteImage < 0 || pSpriteImage == nullptr)
{
logTaskFailed(mLog, idSpriteImage);
return false;
}
logTaskOk(mLog);
mLog.msg(LL_INFO, " Create sprite from image ... ");
Sint32 idSpriteFile = mC64.spriteMgr().create(RESOURCE_SPRITE_CDC_NAME);
Sprite* pSpriteFile = mC64.spriteMgr().get(idSpriteFile);
if(idSpriteFile < 0 || pSpriteFile == nullptr)
{
logTaskFailed(mLog, idSpriteFile);
mC64.imageMgr().close(idSpriteImage);
return false;
}
if(pSpriteFile->assignImage(idSpriteImage, 1) < 0)
{
logTaskFailed(mLog);
mC64.spriteMgr().close(idSpriteFile);
mC64.imageMgr().close(idSpriteImage);
return false;
}
if(!configureSprite(pSpriteFile))
{
logTaskFailed(mLog);
mC64.spriteMgr().close(idSpriteFile);
return false;
}
logTaskOk(mLog);
// Save appends or replaces the sprite resource in Tutorial.cdc.
mLog.msg(LL_INFO, " Save sprite to CDC ... ");
if(pSpriteFile->save(OUTPUT_CDC, RESOURCE_SPRITE_CDC_NAME) < 0)
{
logTaskFailed(mLog);
mC64.spriteMgr().close(idSpriteFile);
return false;
}
logTaskOk(mLog);
// Close the temporary sprite. The tutorial loads a fresh copy from CDC next.
mLog.msg(LL_INFO, " Close temporary sprite ... ");
mC64.spriteMgr().close(idSpriteFile);
logTaskOk(mLog);
return true;
}
// Create a sprite resource from an existing sprite.
static bool createSpriteClone(Main& mC64, Log& mLog, Sint32 idParentSprite, Sint32& rIDClone, const char* szName)
{
mLog.msg(LL_INFO, " Clone sprite: %s ... ", szName);
rIDClone = mC64.spriteMgr().child(idParentSprite);
if(rIDClone < 0 || mC64.spriteMgr().get(rIDClone) == nullptr)
{
logTaskFailed(mLog, rIDClone);
return false;
}
logTaskOk(mLog);
return true;
}
// Run the tutorial application and release its resources.
int main(int argc, char* argv[])
{
if(!runParameterReadRender(argc, argv, eRenderer)) return 1;
// Start CRM64Pro memory tracking before creating engine resources.
// atexit() releases memory tracking data when the program exits.
atexit(CMem::destroy);
// Main gives access to the CRM64Pro managers.
Main& mC64 = Main::instance();
Log& mLog = *mC64.logMgr().get();
TutorialState state;
// Write log output to stdout and to a file under validation/bin.
mLog.init("Tutorial_08_Sprite", LL_DEBUG, LM_FILE | LM_STDOUT, OUTPUTDIR"Tutorial_08_Sprite.log");
mLog.msg(LL_INFO, "\nSETUP: screen and timing\n");
// Initialize the timer before calling Main::update().
// setRate() receives render frames per second, then logic frames per second.
mLog.msg(LL_INFO, " Initialize timer ... ");
if(!mC64.timer().init())
{
logTaskFailed(mLog);
return -1;
}
logTaskOk(mLog);
mLog.msg(LL_INFO, " Set frame rates (render=%d, logic=%d) ... ", iRenderRate, iLogicRate);
if(!mC64.timer().setRate(iRenderRate, iLogicRate))
{
logTaskFailed(mLog);
return -1;
}
logTaskOk(mLog);
// Add a 1 ms idle delay inside Main::update().
// Configure and show the default screen.
Screen* pScreen = mC64.configMgr().get();
pScreen->setSize(iScreenW, iScreenH);
pScreen->setDriver(eRenderer);
pScreen->setTitle("CRM64Pro - Tutorial 08: Sprite");
mLog.msg(LL_INFO, " Create screen (%dx%d) ... ", iScreenW, iScreenH);
if(pScreen->show() < 0)
{
mLog.msg(LL_CRITICAL, "FAILED\n");
return -1;
}
logTaskOk(mLog);
mLog.msg(LL_INFO, " Set render callback ... ");
if(!pScreen->setRenderCallback([&state](Sint32 iMode) { return renderWrapper(iMode, &state); }))
{
logTaskFailed(mLog);
return -1;
}
logTaskOk(mLog);
mLog.msg(LL_INFO, "\nRESOURCES: add sprite and load from CDC\n");
if(!addSpriteToCDC(mC64, mLog))
{
return -1;
}
mLog.msg(LL_INFO, " Load background image from CDC ... ");
state.idBgImage = mC64.imageMgr().load(OUTPUT_CDC, RESOURCE_BG_CDC_NAME);
if(state.idBgImage < 0)
{
logTaskFailed(mLog, state.idBgImage);
return -1;
}
logTaskOk(mLog);
mLog.msg(LL_INFO, " Load main sprite from CDC ... ");
state.idMainSprite = mC64.spriteMgr().load(OUTPUT_CDC, RESOURCE_SPRITE_CDC_NAME);
Sprite* pMainSprite = mC64.spriteMgr().get(state.idMainSprite);
if(state.idMainSprite < 0 || pMainSprite == nullptr)
{
logTaskFailed(mLog, state.idMainSprite);
return -1;
}
pMainSprite->setPosition(state.fMainX, state.fMainY);
logTaskOk(mLog);
if(!createSpriteClone(mC64, mLog, state.idMainSprite, state.idScaledSprite, "scaled") ||
!createSpriteClone(mC64, mLog, state.idMainSprite, state.idTintedSprite, "color mod") ||
!createSpriteClone(mC64, mLog, state.idMainSprite, state.idGhostSprite, "alpha mod"))
{
return -1;
}
Sprite* pScaledSprite = mC64.spriteMgr().get(state.idScaledSprite);
Sprite* pTintedSprite = mC64.spriteMgr().get(state.idTintedSprite);
Sprite* pGhostSprite = mC64.spriteMgr().get(state.idGhostSprite);
if(pScaledSprite)
{
pScaledSprite->setPosition(state.fScaledX, state.fScaledY);
pScaledSprite->setSpeed(0.8f);
}
if(pTintedSprite)
{
pTintedSprite->setPosition(state.fTintedX, state.fTintedY);
pTintedSprite->setSpeed(1.2f);
Image* pTintedImage = mC64.imageMgr().get(pTintedSprite->getImage());
if(pTintedImage) pTintedImage->setColorMod(255, 120, 120);
}
if(pGhostSprite)
{
pGhostSprite->setPosition(state.fGhostX, state.fGhostY);
pGhostSprite->setSpeed(1.6f);
Image* pGhostImage = mC64.imageMgr().get(pGhostSprite->getImage());
if(pGhostImage) pGhostImage->setAlphaMod(150);
}
mLog.msg(LL_INFO, " Load cursor from CDC ... ");
state.idCursor = mC64.cursorMgr().load(OUTPUT_CDC, RESOURCE_CURSOR_CDC_NAME);
Cursor* pCursor = mC64.cursorMgr().get(state.idCursor);
if(state.idCursor < 0 || pCursor == nullptr)
{
logTaskFailed(mLog, state.idCursor);
return -1;
}
logTaskOk(mLog);
mLog.msg(LL_INFO, " Select cursor ... ");
if(mC64.cursorMgr().select(state.idCursor) < 0 || !mC64.cursorMgr().show())
{
logTaskFailed(mLog);
return -1;
}
logTaskOk(mLog);
mLog.msg(LL_INFO, " Load built-in font ... ");
state.idBuiltInFont = mC64.fontMgr().getBuiltin("CourierNew10White");
Font* pBuiltInFont = mC64.fontMgr().get(state.idBuiltInFont);
if(state.idBuiltInFont < 0 || pBuiltInFont == nullptr)
{
logTaskFailed(mLog, state.idBuiltInFont);
return -1;
}
logTaskOk(mLog);
mLog.msg(LL_INFO, "\nTOOLS: debug window and console\n");
// The DebugWindow is available, but this tutorial starts with it hidden.
mLog.msg(LL_INFO, " Create debug window ... ");
state.idDebugWindow = mC64.guiMgr().create("Debug", CRM64PRO_GUI_DEBUGWINDOW);
DebugWindow* pDebug = mC64.guiMgr().getDebugWindow(state.idDebugWindow);
if(!pDebug)
{
logTaskFailed(mLog, state.idDebugWindow);
return -1;
}
pDebug->addWatch("Main X", nullptr, &state.fMainX);
pDebug->addWatch("Main Y", nullptr, &state.fMainY);
pDebug->addWatch("Mouse X", nullptr, &state.fMouseX);
pDebug->addWatch("Mouse Y", nullptr, &state.fMouseY);
pDebug->addWatch("Render fps", &state.iCurrentRenderRate);
pDebug->addWatch("Logic fps", &state.iCurrentLogicRate);
pDebug->addWatch("Logic frames", &state.iLogicFrames);
pDebug->addWatch("Interpolation", &state.iSmoothInterpolation);
pDebug->baseWidget().hide();
logTaskOk(mLog);
// Main creates the default Console. Log output is also sent there.
Console* pConsole = mC64.guiMgr().getConsole();
if(pConsole) pConsole->print("Tutorial 08: Sprite ready. Press ` to toggle the console.\n");
mLog.msg(LL_INFO, "\nCONTROLS\n");
mLog.msg(LL_INFO, " [Q] / [ESC] Quit\n");
mLog.msg(LL_INFO, " [Arrow Keys] Move the main sprite\n");
mLog.msg(LL_INFO, " [I] Toggle smooth interpolation\n");
mLog.msg(LL_INFO, " [D] Toggle debug window\n");
mLog.msg(LL_INFO, " [`] Toggle console\n");
mLog.msg(LL_INFO, " Any key or mouse button logs the input event\n");
mLog.msg(LL_INFO, "\nRUNNING\n");
SDL_Event event;
bool bRunning = true;
while(bRunning)
{
// Main::update() processes input, runs internal GUI logic and calls the
// screen render callback when a render frame is ready.
while(mC64.update(&event))
{
if(event.type == SDL_EVENT_QUIT)
{
bRunning = false;
}
else if(event.type == SDL_EVENT_KEY_DOWN)
{
// SDL3 stores the key value in event.key.key.
mLog.msg(LL_INFO, " Key pressed: %s (%d)\n", SDL_GetKeyName(event.key.key), event.key.key);
if(event.key.key == SDLK_Q || event.key.key == SDLK_ESCAPE)
{
bRunning = false;
}
else if(event.key.key == SDLK_LEFT)
{
state.bMoveLeft = true;
}
else if(event.key.key == SDLK_RIGHT)
{
state.bMoveRight = true;
}
else if(event.key.key == SDLK_UP)
{
state.bMoveUp = true;
}
else if(event.key.key == SDLK_DOWN)
{
state.bMoveDown = true;
}
else if(event.key.key == SDLK_I)
{
state.iSmoothInterpolation = state.iSmoothInterpolation ? 0 : 1;
mLog.msg(LL_INFO, " Smooth interpolation: %s\n", state.iSmoothInterpolation ? "enabled" : "disabled");
}
else if(event.key.key == SDLK_D)
{
toggleDebugWindow(pDebug);
}
}
else if(event.type == SDL_EVENT_KEY_UP)
{
if(event.key.key == SDLK_LEFT) state.bMoveLeft = false;
else if(event.key.key == SDLK_RIGHT) state.bMoveRight = false;
else if(event.key.key == SDLK_UP) state.bMoveUp = false;
else if(event.key.key == SDLK_DOWN) state.bMoveDown = false;
}
else if(event.type == SDL_EVENT_MOUSE_BUTTON_DOWN)
{
mLog.msg(LL_INFO, " Mouse clicked: button %d at %d, %d\n", event.button.button, (Sint32)event.button.x, (Sint32)event.button.y);
}
}
if(!bRunning) break;
state.fMouseX = mC64.cursorMgr().getX();
state.fMouseY = mC64.cursorMgr().getY();
state.iCurrentRenderRate = static_cast<Sint32>(mC64.timer().getCurrentRFR());
state.iCurrentLogicRate = static_cast<Sint32>(mC64.timer().getCurrentLFR());
updateLogic(state, 1.0f / static_cast<float>(iLogicRate));
}
// Close resources owned by this tutorial.
mC64.spriteMgr().info();
mLog.msg(LL_INFO, "\nCLEANUP\n");
mLog.msg(LL_INFO, " Close debug window ... ");
mC64.guiMgr().close(state.idDebugWindow);
logTaskOk(mLog);
mLog.msg(LL_INFO, " Close fonts ... ");
mC64.fontMgr().close(0);
logTaskOk(mLog);
mLog.msg(LL_INFO, " Close sprites ... ");
mC64.spriteMgr().close(0);
logTaskOk(mLog);
mLog.msg(LL_INFO, " Close cursors ... ");
mC64.cursorMgr().close(0);
logTaskOk(mLog);
mLog.msg(LL_INFO, " Close images ... ");
mC64.imageMgr().close(0);
logTaskOk(mLog);
mLog.msg(LL_INFO, " Close CDC archives ... ");
mC64.archiveMgr().close(0);
logTaskOk(mLog);
return 0;
}
Sint32 close(Sint32 idCDC) override
Close and destroy a CDC object.
Definition CoreArchive.cpp:2476
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
Console Object class.
Definition CRM64Pro.h:9678
Cursor Object class.
Definition CRM64Pro.h:3734
float getY() const
Get the mouse cursor Y position.
Definition GraphicsCursor.cpp:1041
Sint32 select(Sint32 idCursor)
Select a mouse cursor.
Definition GraphicsCursor.cpp:968
bool show()
Make visible the selected mouse cursor.
Definition GraphicsCursor.cpp:1001
Sint32 load(const string &sCDCFile, const string &sName)
Load a cursor stored in a CDC file.
Definition GraphicsCursor.cpp:1115
Sint32 close(Sint32 idCursor) override
Close and destroy a cursor.
Definition GraphicsCursor.cpp:897
Cursor * get(Sint32 idCursor)
Get a pointer to the cursor using its handle.
Definition GraphicsCursor.cpp:962
float getX() const
Get the mouse cursor X position.
Definition GraphicsCursor.cpp:1035
DebugWindow Object class.
Definition CRM64Pro.h:9810
Font Object class.
Definition CRM64Pro.h:4741
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 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
Font * get(const string &sName)
Get a pointer to the font using its name.
Definition GraphicsFont.cpp:1235
Image Object class.
Definition CRM64Pro.h:3356
bool setColorMod(Uint8 iR, Uint8 iG, Uint8 iB)
Set the color modulation value.
Definition GraphicsImage.cpp:1736
Sint32 render(Sint32 idRes=0, SDL_FRect *pSrc=nullptr, SDL_FRect *pDst=nullptr)
Render the image.
Definition GraphicsImage.cpp:1575
bool setAlphaMod(Sint32 iAlpha)
Set the alpha modulation value.
Definition GraphicsImage.cpp:1706
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 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
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
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_NORMAL
Collect allocations per module (CRM64Pro and user). Default for debug builds.
Definition CRM64Pro.h:386
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
Sint32 create(const string &sName, Uint32 iType=CRM64PRO_GUI_PANEL) override
Creates a new GUI object.
Definition GUI.cpp:1051
Sint32 addWatch(const string &sName, Sint32 *iIntegerVar, float *fFloatVar=nullptr)
Add a watch.
Definition GUIDebugWindow.cpp:275
#define CRM64PRO_GUI_DEBUGWINDOW
Definition CRM64Pro.h:9195
Widget & baseWidget()
Get the reference to base Widget for this object.
Definition GUIDebugWindow.cpp:269
Sint32 print(const char *format,...)
Print a formatted message to the console.
Definition GUIConsole.cpp:403
Console * getConsole(Sint32 idGUI=CRM64PRO_GUI_CONSOLE)
Get a pointer to a Console using its handle.
Definition GUI.cpp:1366
DebugWindow * getDebugWindow(Sint32 idGUI)
Get a pointer to a DebugWindow using its handle.
Definition GUI.cpp:1375
Sint32 close(Sint32 idGUI) override
Close and destroy a GUI object.
Definition GUI.cpp:1168
eGeneralStatus status() const
Get the widget status.
Definition GUIWidget.cpp:1772
bool hide()
Hide a widget.
Definition GUIWidget.cpp:1729
bool show()
Show a widget.
Definition GUIWidget.cpp:1671
Sint32 setPosition(const Position &rPosX=Position(PH_CENTER), const Position &rPosY=Position(PH_CENTER))
Set the position.
Definition GUIWidget.cpp:1923
Log * get(Sint32 idLog=0)
Get a pointer to the log object.
Definition CoreLog.cpp:921
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
SpriteMgr & spriteMgr()
Get reference to Sprite Manager.
Definition CoreMain.cpp:772
GUIMgr & guiMgr()
Get reference to GUI Manager.
Definition CoreMain.cpp:808
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
static void terminate()
Main explicit destructor.
Definition CoreMain.cpp:266
static Main & instance()
Access the Main singleton.
Definition CoreMain.cpp:252
LogMgr & logMgr()
Get reference to Log Manager.
Definition CoreMain.cpp:724
Tool & tool()
Get reference to Tool module.
Definition CoreMain.cpp:718
ArchiveMgr & archiveMgr()
Get reference to Archive Manager.
Definition CoreMain.cpp:736
FontMgr & fontMgr()
Get reference to Font Manager.
Definition CoreMain.cpp:778
ConfigMgr & configMgr()
Get reference to Config Manager.
Definition CoreMain.cpp:712
@ GS_SHOWN
General status: enabled and shown.
Definition CRM64Pro.h:300
@ PH_CENTER
Cursor::setHotSpot(): set hotspot to cursor_size/2. Sprite::setAnimHotSpot(): set hotspot to frame_si...
Definition CRM64Pro.h:336
@ PH_RIGHT
Widget/Font: right with optional offset. Scene: align to map right/end (MapWidth - ViewportWidth)....
Definition CRM64Pro.h:340
@ PH_TOP
Widget/Font: top with optional offset. Scene: align to map top/begin (0.0). Valid for Y axis.
Definition CRM64Pro.h:337
Sint32 assignImage(Sint32 idImage, Sint32 iOwnership=0)
Assign an Image to this sprite.
Definition GraphicsSprite.cpp:494
Sint32 getImage() const
Get the assigned Image of this sprite.
Definition GraphicsSprite.cpp:634
Sint32 render(Sint32 idRes=0)
Render the sprite.
Definition GraphicsSprite.cpp:1395
bool setAnimStateIndex(Sint32 iIndex, Uint16 iState)
Set the animation state by index.
Definition GraphicsSprite.cpp:927
Sint32 child(Sint32 idSprite)
Create a child sprite dependent on the provided one (the parent).
Definition GraphicsSprite.cpp:1849
Sint32 load(const string &sCDCFile, const string &sName)
Load a sprite stored in a CDC file.
Definition GraphicsSprite.cpp:1907
bool selectAnim(Uint16 iState)
Select an animation by state.
Definition GraphicsSprite.cpp:794
Sint32 save(const string &sCDCFile, const string &sResourceName="")
Save the sprite to a CDC file.
Definition GraphicsSprite.cpp:1452
bool setPosition(float fX, float fY, bool bInterpolate=false)
Set the sprite position.
Definition GraphicsSprite.cpp:1356
Sint32 renderEx(float fScaleX=1.0f, float fScaleY=1.0f, double dAngle=0.0, const SDL_FPoint *pCenter=nullptr, SDL_FlipMode rf=SDL_FLIP_NONE, Sint32 idRes=0)
Render the sprite with extended options.
Definition GraphicsSprite.cpp:1402
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
bool setSpeed(float fSpeed)
Set the sprite speed.
Definition GraphicsSprite.cpp:765
Sprite * get(Sint32 idSprite)
Get a pointer to the sprite using its handle.
Definition GraphicsSprite.cpp:1843
bool setFrameTimeIndex(Sint32 iIndex, Sint32 iFrame, Uint16 iTime)
Set the frame time duration by index.
Definition GraphicsSprite.cpp:1284
bool info(Sint32 iMode=0) override
Request Sprite Manager information.
Definition GraphicsSprite.cpp:1610
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
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
bool fileExists(const string &sPath)
Check if a file exists.
Definition CoreTool.cpp:750
CRM64Pro GDK.
Definition AudioTrack.cpp:36
Absolute coordinate or helper-relative position used by layout APIs.
Definition CRM64Pro.h:346

Navigation

Previous: Tutorial 07 - Tileset maps

Back to the tutorials index

Continue with Tutorial 09: Audio tracks