CRM64Pro GDK v0.80.0
A free cross-platform game development kit built on top of SDL 3.0
Loading...
Searching...
No Matches
Tutorial 11: 2D lightmaps

Overview

This tutorial introduces the GFX 2D lighting pass. It first draws the scene, then builds and applies a lightmap from ambient color, three light types and optional rectangle, circle and segment occluders.

The lights demonstrate a candle animation, a mouse-controlled point light and a spotlight positioned above the segment so its shadow is visible.

Final result

CRM64Pro Tutorial 11 lightmap

Runtime controls

  • Mouse: Move the warm point light.
  • L: Enable or disable the lightmap pass.
  • O: Enable or disable occluders.
  • P: Cycle ambient presets.
  • A / Z: Increase or decrease ambient intensity.
  • I / K: Increase or decrease mouse-light intensity.
  • D: Show or hide the debug window.
  • Grave key: Show or hide the built-in console.
  • 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.
  • A renderer supported by the GFX lightmap implementation.

What you will learn

  • Start and finish a lightmap pass with GFX::beginLighting() and GFX::endLighting().
  • Convert an ambient color and intensity into lightmap bytes.
  • Add rectangle, circle and segment light occluders.
  • Configure point and spot lights with GFXLight.
  • Animate light color, intensity and radius with GLA_CANDLE.
  • Accumulate return values while always finishing an active lightmap pass.
  • Draw diagnostics and the HUD after lighting is applied.

Step by step

1. Define ambient presets

Each preset combines a base RGB color with its recommended starting intensity.

static const AmbientPreset vAmbientPresets[] =
{
{ "Daylight", 255, 255, 255, 1.00f },
{ "Neutral dim", 255, 255, 255, 0.25f },
{ "Dusk", 154, 168, 200, 0.45f },
{ "Moonlight", 113, 136, 184, 0.20f },
{ "Warm interior", 208, 144, 88, 0.20f },
{ "Torch", 58, 32, 8, 0.08f },
{ "Blackout", 0, 0, 0, 0.00f }
};

2. Convert ambient values safely

The ambient multiplication uses floats. Clamp and round each result before passing it to the byte-based beginLighting() interface.

// Convert a light value to a valid colour byte.
static Uint8 lightByte(float fValue)
{
if(fValue <= 0.0f) return 0;
if(fValue >= 255.0f) return 255;
return static_cast<Uint8>(fValue + 0.5f);
}

3. Draw the scene before lighting

The shapes are normal scene content. Lighting is accumulated only after these objects have been rendered.

// Draw the scene objects lit by the lightmap.
static void renderSceneProps(GFX& mGFX)
{
mGFX.rectFilled(260, 205, 390, 295, 62, 76, 88, 255);
mGFX.rect(260, 205, 390, 295, 210, 220, 230, 255);
mGFX.circleFilled(610, 350, 56, 56, 72, 74, 255);
mGFX.circle(610, 350, 56, 210, 220, 230, 255);
mGFX.line(485, 130, 760, 260, 210, 220, 230, 255);
}

4. Begin with ambient light

When lighting is disabled, leave the already-rendered scene unchanged. Otherwise begin a lightmap using the active ambient preset.

if(!rState.bLighting) return true;
const AmbientPreset& Ambient = vAmbientPresets[rState.iAmbientPreset];
bool bOk = mGFX.beginLighting(lightByte(Ambient.iR * rState.fAmbientIntensity),
lightByte(Ambient.iG * rState.fAmbientIntensity), lightByte(Ambient.iB * rState.fAmbientIntensity));
if(!bOk) return false;

5. Add matching occluders

The occluder geometry matches the visible scene shapes. Accumulating the result allows every operation, including endLighting(), to run after a successful begin.

if(rState.bOccluders)
{
bOk = mGFX.addLightOccluderRect(260, 205, 390, 295) && bOk;
bOk = mGFX.addLightOccluderCircle(610, 350, 56) && bOk;
bOk = mGFX.addLightOccluderSegment(485, 130, 760, 260) && bOk;
}

6. Configure an animated candle

GFXLight defaults let the tutorial set only relevant fields. GLA_CANDLE varies intensity, blends toward a secondary color and changes radius using a stable animation ID.

GFXLight CandleLight;
CandleLight.fX = 175.0f;
CandleLight.fY = 170.0f;
CandleLight.fRadius = 165.0f;
CandleLight.iColor = 0xFFF0B0FF;
CandleLight.fIntensity = 0.52f;
CandleLight.bUseOccluders = rState.bOccluders;
CandleLight.eAnimation = GLA_CANDLE;
CandleLight.fAnimationRate = 8.0f;
CandleLight.fAnimationAmount = 0.32f;
CandleLight.iSecondaryColor = 0xE85018FF;
CandleLight.fAnimationRadiusAmount = 0.10f;
CandleLight.iAnimationID = 1;
bOk = mGFX.drawLight(CandleLight) && bOk;

7. Add a mouse-controlled point light

The second GFXLight follows the cursor and exposes its intensity through the runtime controls.

GFXLight MouseLight;
MouseLight.fX = rState.fMouseX;
MouseLight.fY = rState.fMouseY;
MouseLight.fRadius = 180.0f;
MouseLight.iColor = 0xFFDCA0FF;
MouseLight.fIntensity = rState.fMouseIntensity;
MouseLight.bUseOccluders = rState.bOccluders;
bOk = mGFX.drawLight(MouseLight) && bOk;

8. Add a spotlight and finish

A direction of 90 degrees points downward. The 70-degree cone crosses the segment occluder, making its cast shadow easy to see. Always finish the active lightmap pass.

GFXLight SpotLight;
SpotLight.fX = 640.0f;
SpotLight.fY = 70.0f;
SpotLight.fRadius = 430.0f;
SpotLight.fDirection = 90.0f;
SpotLight.fAngle = 70.0f;
SpotLight.iColor = 0xB0D8FFFF;
SpotLight.fIntensity = 0.65f;
SpotLight.bUseOccluders = rState.bOccluders;
bOk = mGFX.drawLight(SpotLight) && bOk;
bOk = mGFX.endLighting() && bOk;
return bOk;

9. Keep diagnostics outside the pass

After the lightmap is applied, draw any failure notice, visible occluder outlines and the HUD so they are not darkened.

if(!renderLighting(mGFX, rState))
{
mGFX.rectFilled(10, 58, 330, 78, 160, 0, 0, 220);
renderText(pFont, 14, 60, "Lightmap pass failed");
}
if(rState.bOccluders)
{
mGFX.rect(260, 205, 390, 295, 255, 80, 80, 210);
mGFX.circle(610, 350, 56, 255, 80, 80, 210);
mGFX.line(485, 130, 760, 260, 255, 80, 80, 210);
}
renderHUD(pFont, rState);

10. Change ambient and light intensity

The controls cycle presets and clamp both adjustable intensity values to the 0.0-1.0 range.

else if(event.key.key == SDLK_P)
{
state.iAmbientPreset = (state.iAmbientPreset + 1) % iAmbientPresetCount;
state.fAmbientIntensity = vAmbientPresets[state.iAmbientPreset].fIntensity;
}
else if(event.key.key == SDLK_A)
{
state.fAmbientIntensity += 0.05f;
if(state.fAmbientIntensity > 1.0f) state.fAmbientIntensity = 1.0f;
}
else if(event.key.key == SDLK_Z)
{
state.fAmbientIntensity -= 0.05f;
if(state.fAmbientIntensity < 0.0f) state.fAmbientIntensity = 0.0f;
}

11. Select the cursor and finish cleanly

Use the cursor's existing hotspot. A quit request exits before another state update.

mLog.msg(LL_INFO, " Select cursor ... ");
if(mC64.cursorMgr().select(state.idCursor) < 0 || !mC64.cursorMgr().show())
{
logTaskFailed(mLog);
Main::terminate();
return -1;
}
logTaskOk(mLog);
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);

Complete source

The tutorial source is authoritative. The following listing is included directly from validation/source/Tutorial_11_Lightmap.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 11: Lightmap
------------------------------------------------------------------------
Overview:
This tutorial introduces the GFX 2D lightmap pass. It draws a scene first,
accumulates lights and occluders into a lightmap, then applies the result
over the rendered scene.
Key concepts:
- Start a lightmap pass with GFX::beginLighting().
- Add rectangle, circle and segment occluders.
- Draw point lights and spot lights.
- Use GFXLight for candle animation and color/radius changes.
- Finish the pass with GFX::endLighting().
- Keep HUD rendering outside the lighting pass.
Controls:
- Mouse: Move the warm point light.
- L: Toggle lightmap pass.
- O: Toggle occluders.
- P: Cycle ambient presets.
- A / Z: Change ambient intensity.
- I / K: Change mouse-light intensity.
- D: Toggle debug window.
- Grave: Toggle console.
- Q / ESC: Quit.
Loop order:
- Process input events.
- Run one fixed logic update.
- Render the scene.
- Render and apply the lightmap.
- Render the HUD.
------------------------------------------------------------------------ */
#include "CRM64Pro.h"
#include "RunParameter.h"
using namespace CRM64Pro;
#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 RESOURCE_CURSOR_CDC_NAME "Tutorial_cursor"
#define OUTPUT_CDC OUTPUTDIR"Tutorial.cdc"
static const Sint32 iLogicRate = 20;
static const Sint32 iRenderRate = 0;
static const Sint32 iScreenW = 960;
static const Sint32 iScreenH = 540;
struct AmbientPreset
{
const char* szName;
Uint8 iR, iG, iB;
float fIntensity;
};
static const AmbientPreset vAmbientPresets[] =
{
{ "Daylight", 255, 255, 255, 1.00f },
{ "Neutral dim", 255, 255, 255, 0.25f },
{ "Dusk", 154, 168, 200, 0.45f },
{ "Moonlight", 113, 136, 184, 0.20f },
{ "Warm interior", 208, 144, 88, 0.20f },
{ "Torch", 58, 32, 8, 0.08f },
{ "Blackout", 0, 0, 0, 0.00f }
};
static const Sint32 iAmbientPresetCount = static_cast<Sint32>(sizeof(vAmbientPresets) / sizeof(vAmbientPresets[0]));
struct TutorialState
{
Sint32 idBgImage = -1;
Sint32 idCursor = -1;
Sint32 idBuiltInFont = -1;
Sint32 idDebugWindow = -1;
float fMouseX = iScreenW * 0.5f;
float fMouseY = iScreenH * 0.5f;
Sint32 iAmbientPreset = 1;
float fAmbientIntensity = 0.25f;
float fMouseIntensity = 1.0f;
Sint32 iCurrentRenderRate = 0;
Sint32 iCurrentLogicRate = 0;
Sint32 iLogicFrames = 0;
bool bLighting = true;
bool bOccluders = true;
};
// Record a successful tutorial task.
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");
}
// Convert a light value to a valid colour byte.
static Uint8 lightByte(float fValue)
{
if(fValue <= 0.0f) return 0;
if(fValue >= 255.0f) return 255;
return static_cast<Uint8>(fValue + 0.5f);
}
// Update the tutorial state for the current frame.
static void updateLogic(TutorialState& rState)
{
rState.iLogicFrames++;
}
// Draw text at the requested screen position.
static void renderText(Font* pFont, Sint32 iX, Sint32 iY, const char* szText)
{
if(!pFont) return;
pFont->setPosition(iX, iY);
pFont->render(szText);
}
// Draw the scene objects lit by the lightmap.
static void renderSceneProps(GFX& mGFX)
{
mGFX.rectFilled(260, 205, 390, 295, 62, 76, 88, 255);
mGFX.rect(260, 205, 390, 295, 210, 220, 230, 255);
mGFX.circleFilled(610, 350, 56, 56, 72, 74, 255);
mGFX.circle(610, 350, 56, 210, 220, 230, 255);
mGFX.line(485, 130, 760, 260, 210, 220, 230, 255);
}
// Draw and apply the lightmap.
static bool renderLighting(GFX& mGFX, TutorialState& rState)
{
if(!rState.bLighting) return true;
const AmbientPreset& Ambient = vAmbientPresets[rState.iAmbientPreset];
bool bOk = mGFX.beginLighting(lightByte(Ambient.iR * rState.fAmbientIntensity),
lightByte(Ambient.iG * rState.fAmbientIntensity), lightByte(Ambient.iB * rState.fAmbientIntensity));
if(!bOk) return false;
if(rState.bOccluders)
{
bOk = mGFX.addLightOccluderRect(260, 205, 390, 295) && bOk;
bOk = mGFX.addLightOccluderCircle(610, 350, 56) && bOk;
bOk = mGFX.addLightOccluderSegment(485, 130, 760, 260) && bOk;
}
GFXLight CandleLight;
CandleLight.fX = 175.0f;
CandleLight.fY = 170.0f;
CandleLight.fRadius = 165.0f;
CandleLight.iColor = 0xFFF0B0FF;
CandleLight.fIntensity = 0.52f;
CandleLight.bUseOccluders = rState.bOccluders;
CandleLight.eAnimation = GLA_CANDLE;
CandleLight.fAnimationRate = 8.0f;
CandleLight.fAnimationAmount = 0.32f;
CandleLight.iSecondaryColor = 0xE85018FF;
CandleLight.fAnimationRadiusAmount = 0.10f;
CandleLight.iAnimationID = 1;
bOk = mGFX.drawLight(CandleLight) && bOk;
GFXLight MouseLight;
MouseLight.fX = rState.fMouseX;
MouseLight.fY = rState.fMouseY;
MouseLight.fRadius = 180.0f;
MouseLight.iColor = 0xFFDCA0FF;
MouseLight.fIntensity = rState.fMouseIntensity;
MouseLight.bUseOccluders = rState.bOccluders;
bOk = mGFX.drawLight(MouseLight) && bOk;
GFXLight SpotLight;
SpotLight.fX = 640.0f;
SpotLight.fY = 70.0f;
SpotLight.fRadius = 430.0f;
SpotLight.fDirection = 90.0f;
SpotLight.fAngle = 70.0f;
SpotLight.iColor = 0xB0D8FFFF;
SpotLight.fIntensity = 0.65f;
SpotLight.bUseOccluders = rState.bOccluders;
bOk = mGFX.drawLight(SpotLight) && bOk;
bOk = mGFX.endLighting() && bOk;
return bOk;
}
// Draw the tutorial status information.
static void renderHUD(Font* pFont, TutorialState& rState)
{
if(!pFont) return;
char szLine[180];
snprintf(szLine, sizeof(szLine), "Tutorial 11: Lightmap Render: %d fps Logic: %d fps",
rState.iCurrentRenderRate, rState.iCurrentLogicRate);
renderText(pFont, 10, 10, szLine);
const AmbientPreset& Ambient = vAmbientPresets[rState.iAmbientPreset];
snprintf(szLine, sizeof(szLine), "Lighting: %s Occluders: %s Ambient: %s #%02X%02X%02X x %.2f -> %d,%d,%d",
rState.bLighting ? "ON" : "OFF", rState.bOccluders ? "ON" : "OFF", Ambient.szName,
Ambient.iR, Ambient.iG, Ambient.iB, rState.fAmbientIntensity,
lightByte(Ambient.iR * rState.fAmbientIntensity), lightByte(Ambient.iG * rState.fAmbientIntensity), lightByte(Ambient.iB * rState.fAmbientIntensity));
renderText(pFont, 10, 32, szLine);
snprintf(szLine, sizeof(szLine), "Mouse light %.2f P preset A/Z ambient I/K light L lighting O occluders D debug", rState.fMouseIntensity);
renderText(pFont, 10, 510, szLine);
renderText(pFont, 10, 488, "Animated light: GLA_CANDLE; spotlight: above the segment, pointing down with shadow");
}
// Draw the tutorial frame for the current state.
static void renderFrame(Image* pBgImage, Font* pFont, TutorialState& rState)
{
Main& mC64 = Main::instance();
GFX& mGFX = mC64.gfx();
if(pBgImage) pBgImage->render();
renderSceneProps(mGFX);
if(!renderLighting(mGFX, rState))
{
mGFX.rectFilled(10, 58, 330, 78, 160, 0, 0, 220);
renderText(pFont, 14, 60, "Lightmap pass failed");
}
if(rState.bOccluders)
{
mGFX.rect(260, 205, 390, 295, 255, 80, 80, 210);
mGFX.circle(610, 350, 56, 255, 80, 80, 210);
mGFX.line(485, 130, 760, 260, 255, 80, 80, 210);
}
renderHUD(pFont, rState);
}
// Adapt the renderer to the engine callback signature.
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* pFont = mC64.fontMgr().get(pState->idBuiltInFont);
renderFrame(pBgImage, pFont, *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();
}
// Run the tutorial application and release its resources.
int main(int argc, char* argv[])
{
if(!runParameterReadRender(argc, argv, eRenderer)) return 1;
atexit(CMem::destroy);
Main& mC64 = Main::instance();
Log& mLog = *mC64.logMgr().get();
TutorialState state;
mLog.init("Tutorial_11_Lightmap", LL_DEBUG, LM_FILE | LM_STDOUT, OUTPUTDIR"Tutorial_11_Lightmap.log");
mLog.msg(LL_INFO, "\nSETUP: screen and timing\n");
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);
Screen* pScreen = mC64.configMgr().get();
pScreen->setSize(iScreenW, iScreenH);
pScreen->setDriver(eRenderer);
pScreen->setTitle("CRM64Pro - Tutorial 11: Lightmap");
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: load from CDC\n");
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 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");
if(state.idBuiltInFont < 0 || mC64.fontMgr().get(state.idBuiltInFont) == nullptr)
{
logTaskFailed(mLog, state.idBuiltInFont);
return -1;
}
logTaskOk(mLog);
mLog.msg(LL_INFO, "\nTOOLS: debug window and console\n");
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("Mouse X", nullptr, &state.fMouseX);
pDebug->addWatch("Mouse Y", nullptr, &state.fMouseY);
pDebug->addWatch("Ambient preset", &state.iAmbientPreset);
pDebug->addWatch("Ambient intensity", nullptr, &state.fAmbientIntensity);
pDebug->addWatch("Mouse light intensity", nullptr, &state.fMouseIntensity);
pDebug->addWatch("Render fps", &state.iCurrentRenderRate);
pDebug->addWatch("Logic fps", &state.iCurrentLogicRate);
pDebug->addWatch("Logic frames", &state.iLogicFrames);
pDebug->baseWidget().hide();
logTaskOk(mLog);
Console* pConsole = mC64.guiMgr().getConsole();
if(pConsole) pConsole->print("Tutorial 11: Lightmap 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, " [Mouse] Move warm point light\n");
mLog.msg(LL_INFO, " [L] Toggle lighting\n");
mLog.msg(LL_INFO, " [O] Toggle occluders\n");
mLog.msg(LL_INFO, " [P] Cycle ambient presets\n");
mLog.msg(LL_INFO, " [A] / [Z] Change ambient intensity\n");
mLog.msg(LL_INFO, " [I] / [K] Change mouse-light intensity\n");
mLog.msg(LL_INFO, " [D] Toggle debug window\n");
mLog.msg(LL_INFO, " [`] Toggle console\n");
mLog.msg(LL_INFO, "\nRUNNING\n");
SDL_Event event;
bool bRunning = true;
while(bRunning)
{
while(mC64.update(&event))
{
if(event.type == SDL_EVENT_QUIT)
{
bRunning = false;
}
else if(event.type == SDL_EVENT_KEY_DOWN)
{
if(event.key.key == SDLK_Q || event.key.key == SDLK_ESCAPE) bRunning = false;
else if(event.key.key == SDLK_L) state.bLighting = !state.bLighting;
else if(event.key.key == SDLK_O) state.bOccluders = !state.bOccluders;
else if(event.key.key == SDLK_P)
{
state.iAmbientPreset = (state.iAmbientPreset + 1) % iAmbientPresetCount;
state.fAmbientIntensity = vAmbientPresets[state.iAmbientPreset].fIntensity;
}
else if(event.key.key == SDLK_A)
{
state.fAmbientIntensity += 0.05f;
if(state.fAmbientIntensity > 1.0f) state.fAmbientIntensity = 1.0f;
}
else if(event.key.key == SDLK_Z)
{
state.fAmbientIntensity -= 0.05f;
if(state.fAmbientIntensity < 0.0f) state.fAmbientIntensity = 0.0f;
}
else if(event.key.key == SDLK_I)
{
state.fMouseIntensity += 0.05f;
if(state.fMouseIntensity > 1.0f) state.fMouseIntensity = 1.0f;
}
else if(event.key.key == SDLK_K)
{
state.fMouseIntensity -= 0.05f;
if(state.fMouseIntensity < 0.0f) state.fMouseIntensity = 0.0f;
}
else if(event.key.key == SDLK_D)
{
toggleDebugWindow(pDebug);
}
}
}
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);
}
mC64.gfx().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 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
GFX class.
Definition CRM64Pro.h:5083
Image Object class.
Definition CRM64Pro.h:3356
Sint32 render(Sint32 idRes=0, SDL_FRect *pSrc=nullptr, SDL_FRect *pDst=nullptr)
Render the image.
Definition GraphicsImage.cpp:1575
Image * get(Sint32 idImg)
Get a pointer to the image using its handle.
Definition GraphicsImage.cpp:2279
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
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
bool rect(float fX1, float fY1, float fX2, float fY2, Uint32 iColor, Sint32 idRes=0)
Draw an outlined rectangle.
Definition GraphicsGFX.cpp:2287
bool beginLighting(Uint8 iR, Uint8 iG, Uint8 iB, Uint8 iA=255, Sint32 idRes=0, const SDL_Rect *pViewport=nullptr)
Start a 2D lightmap rendering pass.
Definition GraphicsGFX.cpp:1968
bool addLightOccluderSegment(float fX1, float fY1, float fX2, float fY2)
Add a segment light occluder to the active lighting pass.
Definition GraphicsGFX.cpp:1980
bool endLighting()
Finish the active 2D lightmap rendering pass.
Definition GraphicsGFX.cpp:2004
bool line(float fX1, float fY1, float fX2, float fY2, Uint32 iColor, Sint32 idRes=0)
Draw a line.
Definition GraphicsGFX.cpp:2245
bool addLightOccluderRect(float fX1, float fY1, float fX2, float fY2)
Add a rectangular light occluder to the active lighting pass.
Definition GraphicsGFX.cpp:1974
bool rectFilled(float fX1, float fY1, float fX2, float fY2, Uint32 iColor, Sint32 idRes=0)
Draw a filled rectangle.
Definition GraphicsGFX.cpp:2349
bool addLightOccluderCircle(float fX, float fY, float fRadius)
Add a circular light occluder to the active lighting pass.
Definition GraphicsGFX.cpp:1986
bool circleFilled(float fX, float fY, float fRad, Uint32 iColor, Sint32 idRes=0)
Draw a filled circle.
Definition GraphicsGFX.cpp:2729
bool circle(float fX, float fY, float fRad, Uint32 iColor, Sint32 idRes=0)
Draw an outlined circle.
Definition GraphicsGFX.cpp:2716
bool info(Sint32 iMode=0) override
Request GFX module information.
Definition GraphicsGFX.cpp:1952
bool drawLight(const GFXLight &rLight)
Draw a point or spot light into the active lighting pass.
Definition GraphicsGFX.cpp:1998
@ GLA_CANDLE
Animate the light with slow breathing and deterministic flicker.
Definition CRM64Pro.h:5052
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
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
GFX & gfx()
Get reference to GFX module.
Definition CoreMain.cpp:784
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
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_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
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
Point or spot light submitted to a GFX lightmap pass.
Definition CRM64Pro.h:5064
eGFXLightAnimation eAnimation
Light animation applied during rendering.
Definition CRM64Pro.h:5073
float fAnimationRate
Animation rate. Pulse uses cycles per second; flicker and candle use noise samples per second....
Definition CRM64Pro.h:5074
float fRadius
Maximum radius in pixels. Must be greater than 0.
Definition CRM64Pro.h:5067
float fAnimationAmount
Maximum proportional intensity reduction, clamped to [0.0, 1.0].
Definition CRM64Pro.h:5075
Uint32 iAnimationID
Stable identifier used to vary animation phase and noise.
Definition CRM64Pro.h:5078
float fDirection
Spot direction in degrees. 0 points right and 90 points down.
Definition CRM64Pro.h:5068
Uint32 iSecondaryColor
Color at the animation low point, or zero to reuse iColor.
Definition CRM64Pro.h:5076
float fY
Light center or spot origin Y coordinate in screen space.
Definition CRM64Pro.h:5066
Uint32 iColor
Primary light color in 0xRRGGBBAA format.
Definition CRM64Pro.h:5070
float fIntensity
Maximum intensity. Must be nonnegative; values above 1.0 are clamped.
Definition CRM64Pro.h:5071
bool bUseOccluders
true to clip the light against active occluders.
Definition CRM64Pro.h:5072
float fX
Light center or spot origin X coordinate in screen space.
Definition CRM64Pro.h:5065
float fAnimationRadiusAmount
Maximum proportional radius reduction, clamped to [0.0, 1.0].
Definition CRM64Pro.h:5077
float fAngle
Spot cone angle in degrees. Values of 360 or greater produce a point light.
Definition CRM64Pro.h:5069
Absolute coordinate or helper-relative position used by layout APIs.
Definition CRM64Pro.h:346

Navigation

Previous: Tutorial 10 - Particle effects

Back to the tutorials index

Next: Tutorial 12 - GUI