From 7b98e40ccf7368888a60c221d83d3f91993b5cb4 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Thu, 2 Jul 2026 11:18:36 -0500 Subject: [PATCH] Cutscene tests --- assets/init.js | 21 -------- assets/player.js | 63 ---------------------- assets/testscene.js | 42 --------------- assets/ui/test.js | 6 --- src/dusk/rpg/CMakeLists.txt | 1 - src/dusk/rpg/cutscene/cutscene.h | 2 + src/dusk/rpg/cutscene/cutscenepause.h | 20 +++++++ src/dusk/rpg/cutscene/item/cutsceneitem.c | 11 ++-- src/dusk/rpg/cutscene/item/cutscenetext.h | 7 +-- src/dusk/rpg/cutscene/scene/testcutscene.h | 9 ++-- src/dusk/rpg/entity/npc/npc.c | 8 ++- src/dusk/rpg/entity/player.c | 5 ++ src/dusk/rpg/rpg.c | 8 ++- src/dusk/rpg/rpgtextbox.c | 39 -------------- src/dusk/rpg/rpgtextbox.h | 52 ------------------ 15 files changed, 49 insertions(+), 245 deletions(-) delete mode 100644 assets/init.js delete mode 100644 assets/player.js delete mode 100644 assets/testscene.js delete mode 100644 assets/ui/test.js create mode 100644 src/dusk/rpg/cutscene/cutscenepause.h delete mode 100644 src/dusk/rpg/rpgtextbox.c delete mode 100644 src/dusk/rpg/rpgtextbox.h diff --git a/assets/init.js b/assets/init.js deleted file mode 100644 index 210ad6ff..00000000 --- a/assets/init.js +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2026 Dominic Masters -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT - -const platformNames = { - [System.PLATFORM_LINUX]: 'Linux', - [System.PLATFORM_KNULLI]: 'Knulli', - [System.PLATFORM_PSP]: 'PSP', - [System.PLATFORM_GAMECUBE]: 'GameCube', - [System.PLATFORM_WII]: 'Wii', -}; - -Console.print('Platform: ' + (platformNames[System.platform] || 'Unknown')); - -UIFullboxOver.setColor(Color.BLACK); - -requireAsync('testscene.js').then(Scene.set).catch(err => { - Console.print('Error loading scene: ' + err); - Engine.exit(); -}); \ No newline at end of file diff --git a/assets/player.js b/assets/player.js deleted file mode 100644 index 3582b60c..00000000 --- a/assets/player.js +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 2026 Dominic Masters -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT - -const PLAYER_SPEED = 5.0; -// 1 world unit = 16 pixels. -const PIXEL_SCALE = 1.0 / 16.0; -// Player sprite is 32x32 px (test.png dimensions). -const PLAYER_W = 32 * PIXEL_SCALE; -const PLAYER_H = 32 * PIXEL_SCALE; - -var player = {}; - -player.getAssets = () => { - return [ - { path: 'test.png', type: Asset.TYPE_TEXTURE, format: Texture.FORMAT_RGBA } - ]; -} - -player.init = function(scene) { - var texture = scene.assets.getAssetByPath('test.png'); - Console.print('Player init: got texture ' + texture); - - _entity = Entity.create(); - _position = _entity.add(Component.POSITION); - _physics = _entity.add(Component.PHYSICS); - - _physics.bodyType = Physics.DYNAMIC; - _physics.shape = Physics.SHAPE_CUBE; - _physics.gravityScale = 1.0; - - var r = _entity.add(Component.RENDERABLE); - r.texture = texture.texture; - r.type = Renderable.SPRITEBATCH; - r.color = new Color(220, 80, 80); - // Upright quad centered on X, bottom-aligned on Y. - r.sprites = [[-PLAYER_W/2, 0, 0, PLAYER_W/2, PLAYER_H, 0, 0, 1, 1, 0]]; - - _position.localPosition = new Vec3(0, PLAYER_H, 0); -}; - -player.getPosition = function() { - return _position; -}; - -player.update = function() { - if(!_physics) return; - var vx = Input.axis(INPUT_ACTION_LEFT, INPUT_ACTION_RIGHT) * PLAYER_SPEED; - var vz = Input.axis(INPUT_ACTION_DOWN, INPUT_ACTION_UP) * PLAYER_SPEED; - // Preserve vertical velocity so gravity and landing work correctly. - var vy = _physics.velocity.y; - _physics.velocity = new Vec3(vx, vy, vz); -}; - -player.dispose = function() { - Entity.dispose(_entity); - _entity = null; - _position = null; - _physics = null; -}; - -module.exports = player; diff --git a/assets/testscene.js b/assets/testscene.js deleted file mode 100644 index 87696156..00000000 --- a/assets/testscene.js +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2026 Dominic Masters -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT - -var scene = {}; - -// Pokemon DS-style camera: ~34 degrees elevation (atan(6/9)). -// CAM_HEIGHT / CAM_DIST ratio controls the tilt - keep it under 0.7 for -// the characteristically shallow DS angle. -const CAM_HEIGHT = 6; -const CAM_DIST = 9; - -scene.init = async function() { - // Camera - scene.cam = Entity.create(); - var camPos = scene.cam.add(Component.POSITION); - var cam = scene.cam.add(Component.CAMERA); - camPos.localPosition = new Vec3(3, 3, 3); - camPos.lookAt(new Vec3(0, 0, 0)); - - // Floor - large flat slab, no texture needed. - scene.floor = Entity.create(); - var floorPos = scene.floor.add(Component.POSITION); - var floorR = scene.floor.add(Component.RENDERABLE); - floorR.type = Renderable.SHADER_MATERIAL; - floorR.color = Color.BLUE; - // floorPos.localScale = new Vec3(16, 0.2, 16); - // floorPos.localPosition = new Vec3(0, -0.1, 0); - - await UIFullboxOver.transition(Color.BLACK, Color.TRANSPARENT, 1.0); -}; - -scene.update = function() { -}; - -scene.dispose = function() { - Entity.dispose(scene.floor); - Entity.dispose(scene.cam); -}; - -module.exports = scene; \ No newline at end of file diff --git a/assets/ui/test.js b/assets/ui/test.js deleted file mode 100644 index e202801c..00000000 --- a/assets/ui/test.js +++ /dev/null @@ -1,6 +0,0 @@ -module = { - render() { - Text.draw(0, 0, "Hello World"); - SpriteBatch.flush(); - } -}; diff --git a/src/dusk/rpg/CMakeLists.txt b/src/dusk/rpg/CMakeLists.txt index 5af4c304..0652db73 100644 --- a/src/dusk/rpg/CMakeLists.txt +++ b/src/dusk/rpg/CMakeLists.txt @@ -8,7 +8,6 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME} PUBLIC rpg.c rpgcamera.c - rpgtextbox.c ) # Subdirs diff --git a/src/dusk/rpg/cutscene/cutscene.h b/src/dusk/rpg/cutscene/cutscene.h index 7df18ad6..d4c9cde8 100644 --- a/src/dusk/rpg/cutscene/cutscene.h +++ b/src/dusk/rpg/cutscene/cutscene.h @@ -7,8 +7,10 @@ #pragma once #include "rpg/cutscene/item/cutsceneitem.h" +#include "cutscenepause.h" typedef struct cutscene_s { const cutsceneitem_t *items; uint8_t itemCount; + cutscenepause_t pause; } cutscene_t; \ No newline at end of file diff --git a/src/dusk/rpg/cutscene/cutscenepause.h b/src/dusk/rpg/cutscene/cutscenepause.h new file mode 100644 index 00000000..735ae3e6 --- /dev/null +++ b/src/dusk/rpg/cutscene/cutscenepause.h @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" + +typedef uint8_t cutscenepause_t; + +#define CUTSCENE_PAUSE_NPC ((cutscenepause_t)(1 << 0)) +#define CUTSCENE_PAUSE_PLAYER ((cutscenepause_t)(1 << 1)) +#define CUTSCENE_PAUSE_WORLD ((cutscenepause_t)(1 << 2)) + +#define CUTSCENE_PAUSE_DEFAULT \ + ((cutscenepause_t)(CUTSCENE_PAUSE_NPC | CUTSCENE_PAUSE_PLAYER)) +#define CUTSCENE_PAUSE_ALL \ + ((cutscenepause_t)(CUTSCENE_PAUSE_NPC | CUTSCENE_PAUSE_PLAYER | CUTSCENE_PAUSE_WORLD)) diff --git a/src/dusk/rpg/cutscene/item/cutsceneitem.c b/src/dusk/rpg/cutscene/item/cutsceneitem.c index 8c41a4f3..263ebf7d 100644 --- a/src/dusk/rpg/cutscene/item/cutsceneitem.c +++ b/src/dusk/rpg/cutscene/item/cutsceneitem.c @@ -9,16 +9,13 @@ #include "cutsceneentitymove.h" #include "input/input.h" #include "time/time.h" +#include "ui/rpg/uitextboxmain.h" void cutsceneItemStart(const cutsceneitem_t *item, cutsceneitemdata_t *data) { switch(item->type) { - case CUTSCENE_ITEM_TYPE_TEXT: { - rpgTextboxShow( - item->text.position, - item->text.text - ); + case CUTSCENE_ITEM_TYPE_TEXT: + uiTextboxMainSetText(item->text.text); break; - } case CUTSCENE_ITEM_TYPE_WAIT: data->wait = item->wait; @@ -44,7 +41,7 @@ void cutsceneItemStart(const cutsceneitem_t *item, cutsceneitemdata_t *data) { void cutsceneItemUpdate(const cutsceneitem_t *item, cutsceneitemdata_t *data) { switch(item->type) { case CUTSCENE_ITEM_TYPE_TEXT: - if(rpgTextboxIsVisible()) return; + if(uiTextboxMainIsActive()) return; cutsceneSystemNext(); break; diff --git a/src/dusk/rpg/cutscene/item/cutscenetext.h b/src/dusk/rpg/cutscene/item/cutscenetext.h index 3ad07f29..76fb6026 100644 --- a/src/dusk/rpg/cutscene/item/cutscenetext.h +++ b/src/dusk/rpg/cutscene/item/cutscenetext.h @@ -6,9 +6,10 @@ */ #pragma once -#include "rpg/rpgtextbox.h" +#include "dusk.h" + +#define CUTSCENE_TEXT_MAX_CHARS 256 typedef struct { - char_t text[RPG_TEXTBOX_MAX_CHARS]; - rpgtextboxpos_t position; + char_t text[CUTSCENE_TEXT_MAX_CHARS]; } cutscenetext_t; \ No newline at end of file diff --git a/src/dusk/rpg/cutscene/scene/testcutscene.h b/src/dusk/rpg/cutscene/scene/testcutscene.h index bcdffb21..c50b47a5 100755 --- a/src/dusk/rpg/cutscene/scene/testcutscene.h +++ b/src/dusk/rpg/cutscene/scene/testcutscene.h @@ -9,9 +9,9 @@ #include "rpg/cutscene/cutscenesystem.h" static const cutsceneitem_t TEST_CUTSCENE_ONE_ITEMS[] = { - { .type = CUTSCENE_ITEM_TYPE_TEXT, .text = { .text = "This is a test cutscene.", .position = RPG_TEXTBOX_POS_BOTTOM } }, - { .type = CUTSCENE_ITEM_TYPE_WAIT, .wait = 2.0f }, - { .type = CUTSCENE_ITEM_TYPE_TEXT, .text = { .text = "It has multiple lines of text.\nAnd waits in between.", .position = RPG_TEXTBOX_POS_TOP } }, + { .type = CUTSCENE_ITEM_TYPE_TEXT, .text = { .text = "This is a test cutscene." } }, + { .type = CUTSCENE_ITEM_TYPE_WAIT, .wait = 0.5f }, + { .type = CUTSCENE_ITEM_TYPE_TEXT, .text = { .text = "It has multiple lines of text.\nAnd waits in between." } }, }; static const cutscene_t TEST_CUTSCENE_ONE = { @@ -20,11 +20,12 @@ static const cutscene_t TEST_CUTSCENE_ONE = { }; static const cutsceneitem_t TEST_CUTSCENE_TWO_ITEMS[] = { - { .type = CUTSCENE_ITEM_TYPE_WAIT, .wait = 1.0f }, + { .type = CUTSCENE_ITEM_TYPE_WAIT, .wait = 0.1f }, { .type = CUTSCENE_ITEM_TYPE_CUTSCENE, .cutscene = &TEST_CUTSCENE_ONE }, }; static const cutscene_t TEST_CUTSCENE = { .items = TEST_CUTSCENE_TWO_ITEMS, + .pause = CUTSCENE_PAUSE_NPC, .itemCount = sizeof(TEST_CUTSCENE_TWO_ITEMS) / sizeof(cutsceneitem_t) }; \ No newline at end of file diff --git a/src/dusk/rpg/entity/npc/npc.c b/src/dusk/rpg/entity/npc/npc.c index d8ccf55b..eebd80a2 100644 --- a/src/dusk/rpg/entity/npc/npc.c +++ b/src/dusk/rpg/entity/npc/npc.c @@ -7,9 +7,9 @@ #include "rpg/entity/entity.h" #include "assert/assert.h" +#include "rpg/cutscene/cutscenesystem.h" #include "rpg/cutscene/scene/testcutscene.h" -#include "rpg/rpgtextbox.h" const npcmovecallback_t NPC_MOVE_CALLBACKS[NPC_MOVE_TYPE_COUNT] = { [NPC_MOVE_TYPE_NULL] = { 0 }, @@ -50,7 +50,11 @@ void npcSetMoveType(entity_t *entity, const npcmovetype_t moveType) { void npcMovement(entity_t *entity) { assertNotNull(entity, "Entity pointer cannot be NULL"); - + if( + CUTSCENE_SYSTEM.scene != NULL && + (CUTSCENE_SYSTEM.scene->pause & CUTSCENE_PAUSE_NPC) + ) return; + npc_t *npc = &entity->data.npc; if(npc->interactState != NPC_INTERACT_STATE_NONE) return; diff --git a/src/dusk/rpg/entity/player.c b/src/dusk/rpg/entity/player.c index a041377b..91516226 100644 --- a/src/dusk/rpg/entity/player.c +++ b/src/dusk/rpg/entity/player.c @@ -12,6 +12,7 @@ #include "time/time.h" #include "ui/focus/uifocus.h" #include "ui/frame/uisettings.h" +#include "rpg/cutscene/cutscenesystem.h" void playerInit(entity_t *entity) { assertNotNull(entity, "Entity pointer cannot be NULL"); @@ -23,6 +24,10 @@ bool_t playerCanInteract(entity_t *entity) { void playerInput(entity_t *entity) { assertNotNull(entity, "Entity pointer cannot be NULL"); + if( + CUTSCENE_SYSTEM.scene != NULL && + (CUTSCENE_SYSTEM.scene->pause & CUTSCENE_PAUSE_PLAYER) + ) return; // Toggle settings on pause if(uiSettingsIsOpen() && inputPressed(INPUT_ACTION_PAUSE)) { diff --git a/src/dusk/rpg/rpg.c b/src/dusk/rpg/rpg.c index 5f33467b..ea250e3a 100644 --- a/src/dusk/rpg/rpg.c +++ b/src/dusk/rpg/rpg.c @@ -9,9 +9,9 @@ #include "entity/entity.h" #include "rpg/overworld/map.h" #include "rpg/cutscene/cutscenesystem.h" +#include "rpg/cutscene/scene/testcutscene.h" #include "time/time.h" #include "rpgcamera.h" -#include "rpgtextbox.h" #include "util/memory.h" #include "util/string.h" #include "assert/assert.h" @@ -25,8 +25,6 @@ errorret_t rpgInit(void) { errorChain(mapInit()); rpgCameraInit(); - rpgTextboxInit(); - // Init world errorChain(mapPositionSet((chunkpos_t){ 0, 0, 0 })); @@ -50,8 +48,8 @@ errorret_t rpgInit(void) { entityInit(npc, ENTITY_TYPE_NPC); npcSetMoveType(npc, NPC_MOVE_TYPE_PATH); npc->position = (worldpos_t){ 8, 8, 1 }; - npc->interact.type = ENTITY_INTERACT_PRINT; - npc->interact.data.message = "hello world"; + npc->interact.type = ENTITY_INTERACT_CUTSCENE; + npc->interact.data.cutscene = &TEST_CUTSCENE; { chunkpos_t cp; worldPosToChunkPos(&npc->position, &cp); diff --git a/src/dusk/rpg/rpgtextbox.c b/src/dusk/rpg/rpgtextbox.c deleted file mode 100644 index 6fba985c..00000000 --- a/src/dusk/rpg/rpgtextbox.c +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "rpgtextbox.h" -#include "util/memory.h" -#include "util/string.h" -#include "assert/assert.h" - -rpgtextbox_t RPG_TEXTBOX; - -void rpgTextboxInit() { - memoryZero(&RPG_TEXTBOX, sizeof(rpgtextbox_t)); -} - -void rpgTextboxShow( - const rpgtextboxpos_t position, - const char_t *text -) { - RPG_TEXTBOX.position = position; - RPG_TEXTBOX.visible = true; - - stringCopy( - RPG_TEXTBOX.text, - text, - RPG_TEXTBOX_MAX_CHARS - ); -} - -void rpgTextboxHide() { - RPG_TEXTBOX.visible = false; -} - -bool_t rpgTextboxIsVisible() { - return RPG_TEXTBOX.visible; -} \ No newline at end of file diff --git a/src/dusk/rpg/rpgtextbox.h b/src/dusk/rpg/rpgtextbox.h deleted file mode 100644 index 02e8cd98..00000000 --- a/src/dusk/rpg/rpgtextbox.h +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" - -#define RPG_TEXTBOX_MAX_CHARS 256 - -typedef enum { - RPG_TEXTBOX_POS_TOP, - RPG_TEXTBOX_POS_BOTTOM, -} rpgtextboxpos_t; - -typedef struct { - rpgtextboxpos_t position; - bool_t visible; - char_t text[RPG_TEXTBOX_MAX_CHARS]; -} rpgtextbox_t; - -extern rpgtextbox_t RPG_TEXTBOX; - -/** - * Initializes the RPG textbox. - */ -void rpgTextboxInit(); - -/** - * Shows the RPG textbox at a specified position. - * - * @param position The position to show the textbox at. - * @param text The text to display in the textbox (copied). - */ -void rpgTextboxShow( - const rpgtextboxpos_t position, - const char_t *text -); - -/** - * Hides the RPG textbox. - */ -void rpgTextboxHide(); - -/** - * Checks if the RPG textbox is currently visible. - * - * @return true if the textbox is visible, false otherwise. - */ -bool_t rpgTextboxIsVisible(); \ No newline at end of file