More cutscene stuff

This commit is contained in:
2026-07-02 12:54:12 -05:00
parent fdc4e056f9
commit 900b3f8558
11 changed files with 95 additions and 81 deletions
+19 -1
View File
@@ -33,4 +33,22 @@ typedef struct cutscene_s {
{ .type = CUTSCENE_ITEM_TYPE_WAIT, .wait = WAIT } { .type = CUTSCENE_ITEM_TYPE_WAIT, .wait = WAIT }
#define CUTSCENE_CUTSCENE(CUTSCENE) \ #define CUTSCENE_CUTSCENE(CUTSCENE) \
{ .type = CUTSCENE_ITEM_TYPE_CUTSCENE, .cutscene = CUTSCENE_REFERENCE(CUTSCENE) } { \
.type = CUTSCENE_ITEM_TYPE_CUTSCENE, \
.cutscene = CUTSCENE_REFERENCE(CUTSCENE) \
}
#define CUTSCENE_CALLBACK(CALLBACK) \
{ .type = CUTSCENE_ITEM_TYPE_CALLBACK, .callback = CALLBACK }
#define CUTSCENE_ENTITY_TELEPORT(ENTITY_INDEX, X, Y, Z) \
{ \
.type = CUTSCENE_ITEM_TYPE_ENTITY_TELEPORT, \
.entityTeleport = { .entityIndex = ENTITY_INDEX, .target = { X, Y, Z } } \
}
#define CUTSCENE_FADE(FROM, TO, DURATION, EASING) \
{ \
.type = CUTSCENE_ITEM_TYPE_FADE, \
.fade = { .from = FROM, .to = TO, .duration = DURATION, .easing = EASING } \
}
@@ -7,5 +7,4 @@
target_sources(${DUSK_LIBRARY_TARGET_NAME} target_sources(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC PUBLIC
cutsceneitem.c cutsceneitem.c
cutsceneentitymove.c
) )
@@ -1,39 +0,0 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "cutsceneentitymove.h"
#include "rpg/cutscene/cutscenesystem.h"
#include "rpg/entity/entity.h"
void cutsceneEntityMoveStart(const cutsceneitem_t *item) {
}
void cutsceneEntityMoveUpdate(const cutsceneitem_t *item) {
entity_t *entity = &ENTITIES[item->entityMove.entityIndex];
if(worldPosIsEqual(entity->position, item->entityMove.target)) {
cutsceneSystemNext();
return;
}
entitydir_t dir;
if(entity->position.x != item->entityMove.target.x) {
dir = entity->position.x < item->entityMove.target.x
? ENTITY_DIR_EAST : ENTITY_DIR_WEST;
} else {
dir = entity->position.y < item->entityMove.target.y
? ENTITY_DIR_SOUTH : ENTITY_DIR_NORTH;
}
if(entityCanTurn(entity)) entityTurn(entity, dir);
if(item->entityMove.run) {
if(entityCanRun(entity)) entityRun(entity, dir);
} else {
if(entityCanWalk(entity)) entityWalk(entity, dir);
}
}
@@ -1,24 +0,0 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "cutsceneitem.h"
/**
* Handles the start of an entity move cutscene item.
*
* @param item The cutscene item.
*/
void cutsceneEntityMoveStart(const cutsceneitem_t *item);
/**
* Updates an entity move cutscene item, steering the entity one step
* per frame toward the target and advancing the cutscene on arrival.
*
* @param item The cutscene item.
*/
void cutsceneEntityMoveUpdate(const cutsceneitem_t *item);
+17
View File
@@ -0,0 +1,17 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "display/color.h"
#include "animation/easing.h"
typedef struct {
color_t from;
color_t to;
float_t duration;
easingtype_t easing;
} cutscenefade_t;
+27 -5
View File
@@ -6,10 +6,11 @@
*/ */
#include "rpg/cutscene/cutscenesystem.h" #include "rpg/cutscene/cutscenesystem.h"
#include "cutsceneentitymove.h"
#include "input/input.h" #include "input/input.h"
#include "ui/overlay/uifullbox.h"
#include "time/time.h" #include "time/time.h"
#include "ui/rpg/uitextboxmain.h" #include "ui/rpg/uitextboxmain.h"
#include "rpg/entity/entity.h"
void cutsceneItemStart(const cutsceneitem_t *item, cutsceneitemdata_t *data) { void cutsceneItemStart(const cutsceneitem_t *item, cutsceneitemdata_t *data) {
switch(item->type) { switch(item->type) {
@@ -29,8 +30,21 @@ void cutsceneItemStart(const cutsceneitem_t *item, cutsceneitemdata_t *data) {
if(item->cutscene != NULL) cutsceneSystemStartCutscene(item->cutscene); if(item->cutscene != NULL) cutsceneSystemStartCutscene(item->cutscene);
break; break;
case CUTSCENE_ITEM_TYPE_ENTITY_MOVE: case CUTSCENE_ITEM_TYPE_ENTITY_TELEPORT:
cutsceneEntityMoveStart(item); entityPositionSet(
&ENTITIES[item->entityTeleport.entityIndex],
item->entityTeleport.target
);
break;
case CUTSCENE_ITEM_TYPE_FADE:
uiFullboxTransition(
&UI_FULLBOX_OVER,
item->fade.from,
item->fade.to,
item->fade.duration,
item->fade.easing
);
break; break;
default: default:
@@ -50,8 +64,16 @@ void cutsceneItemUpdate(const cutsceneitem_t *item, cutsceneitemdata_t *data) {
if(data->wait <= 0) cutsceneSystemNext(); if(data->wait <= 0) cutsceneSystemNext();
break; break;
case CUTSCENE_ITEM_TYPE_ENTITY_MOVE: case CUTSCENE_ITEM_TYPE_ENTITY_TELEPORT:
cutsceneEntityMoveUpdate(item); cutsceneSystemNext();
break;
case CUTSCENE_ITEM_TYPE_FADE:
if(
UI_FULLBOX_OVER.duration > 0.0f &&
UI_FULLBOX_OVER.time < UI_FULLBOX_OVER.duration
) return;
cutsceneSystemNext();
break; break;
default: default:
+5 -3
View File
@@ -9,6 +9,7 @@
#include "cutscenewait.h" #include "cutscenewait.h"
#include "cutscenecallback.h" #include "cutscenecallback.h"
#include "cutscenetext.h" #include "cutscenetext.h"
#include "cutscenefade.h"
#include "rpg/overworld/worldpos.h" #include "rpg/overworld/worldpos.h"
typedef struct cutscene_s cutscene_t; typedef struct cutscene_s cutscene_t;
@@ -19,7 +20,8 @@ typedef enum {
CUTSCENE_ITEM_TYPE_CALLBACK, CUTSCENE_ITEM_TYPE_CALLBACK,
CUTSCENE_ITEM_TYPE_WAIT, CUTSCENE_ITEM_TYPE_WAIT,
CUTSCENE_ITEM_TYPE_CUTSCENE, CUTSCENE_ITEM_TYPE_CUTSCENE,
CUTSCENE_ITEM_TYPE_ENTITY_MOVE CUTSCENE_ITEM_TYPE_ENTITY_TELEPORT,
CUTSCENE_ITEM_TYPE_FADE
} cutsceneitemtype_t; } cutsceneitemtype_t;
typedef struct cutsceneitem_s { typedef struct cutsceneitem_s {
@@ -34,8 +36,8 @@ typedef struct cutsceneitem_s {
struct { struct {
uint8_t entityIndex; uint8_t entityIndex;
worldpos_t target; worldpos_t target;
bool_t run; } entityTeleport;
} entityMove; cutscenefade_t fade;
}; };
} cutsceneitem_t; } cutsceneitem_t;
+7 -5
View File
@@ -7,14 +7,16 @@
#pragma once #pragma once
#include "rpg/cutscene/cutscene.h" #include "rpg/cutscene/cutscene.h"
#include "rpg/cutscene/cutscenesystem.h"
CUTSCENE(TEST_ONE, DEFAULT, CUTSCENE(TEST_ONE, DEFAULT,
CUTSCENE_TEXT("This is a test cutscene."), CUTSCENE_TEXT("Test One."),
CUTSCENE_WAIT(0.5f),
CUTSCENE_TEXT("It has multiple lines of text.\nAnd waits in between.")
); );
CUTSCENE(TEST_TWO, DEFAULT, CUTSCENE(TEST_TWO, DEFAULT,
CUTSCENE_WAIT(0.1f), CUTSCENE_TEXT("Test Two."),
CUTSCENE_CUTSCENE(TEST_ONE), CUTSCENE_FADE(COLOR_TRANSPARENT_BLACK, COLOR_BLACK, 1.0f, EASING_LINEAR),
CUTSCENE_ENTITY_TELEPORT(0, 20, 0, 0),
CUTSCENE_WAIT(1.0f),
CUTSCENE_FADE(COLOR_BLACK, COLOR_TRANSPARENT_BLACK, 1.0f, EASING_LINEAR),
); );
+9
View File
@@ -244,6 +244,15 @@ uint8_t entityGetAvailable() {
return 0xFF; return 0xFF;
} }
void entityPositionSet(entity_t *entity, const worldpos_t pos) {
assertNotNull(entity, "Entity pointer cannot be NULL");
entity->lastPosition = pos;
entity->position = pos;
entity->animation = ENTITY_ANIM_IDLE;
entity->animTime = 0;
entity->walkEndCooldown = 0;
}
void entitySetChunk(entity_t *entity, const uint8_t chunkIndex) { void entitySetChunk(entity_t *entity, const uint8_t chunkIndex) {
assertNotNull(entity, "Entity pointer cannot be NULL"); assertNotNull(entity, "Entity pointer cannot be NULL");
+8
View File
@@ -123,3 +123,11 @@ uint8_t entityGetAvailable();
* @param chunkIndex Index of the chunk to assign to, or 0xFF for none. * @param chunkIndex Index of the chunk to assign to, or 0xFF for none.
*/ */
void entitySetChunk(entity_t *entity, const uint8_t chunkIndex); void entitySetChunk(entity_t *entity, const uint8_t chunkIndex);
/**
* Instantly moves an entity to a world position, resetting movement state.
*
* @param entity Pointer to the entity to move.
* @param pos The world position to place the entity at.
*/
void entityPositionSet(entity_t *entity, const worldpos_t pos);
+2 -2
View File
@@ -33,7 +33,7 @@ errorret_t rpgInit(void) {
assertTrue(entIndex != 0xFF, "No available entity slots!."); assertTrue(entIndex != 0xFF, "No available entity slots!.");
entity_t *ent = &ENTITIES[entIndex]; entity_t *ent = &ENTITIES[entIndex];
entityInit(ent, ENTITY_TYPE_PLAYER); entityInit(ent, ENTITY_TYPE_PLAYER);
ent->position = (worldpos_t){ 10, 2, 0 }; entityPositionSet(ent, (worldpos_t){ 10, 2, 0 });
RPG_CAMERA.mode = RPG_CAMERA_MODE_FOLLOW_ENTITY; RPG_CAMERA.mode = RPG_CAMERA_MODE_FOLLOW_ENTITY;
RPG_CAMERA.followEntity.followEntityId = ent->id; RPG_CAMERA.followEntity.followEntityId = ent->id;
{ {
@@ -47,7 +47,7 @@ errorret_t rpgInit(void) {
entity_t *npc = &ENTITIES[npcIndex]; entity_t *npc = &ENTITIES[npcIndex];
entityInit(npc, ENTITY_TYPE_NPC); entityInit(npc, ENTITY_TYPE_NPC);
npcSetMoveType(npc, NPC_MOVE_TYPE_PATH); npcSetMoveType(npc, NPC_MOVE_TYPE_PATH);
npc->position = (worldpos_t){ 8, 8, 1 }; entityPositionSet(npc, (worldpos_t){ 8, 8, 1 });
npc->interact.type = ENTITY_INTERACT_CUTSCENE; npc->interact.type = ENTITY_INTERACT_CUTSCENE;
npc->interact.data.cutscene = CUTSCENE_REFERENCE(TEST_TWO); npc->interact.data.cutscene = CUTSCENE_REFERENCE(TEST_TWO);
{ {