More cutscene stuff
This commit is contained in:
@@ -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);
|
|
||||||
@@ -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;
|
||||||
@@ -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:
|
||||||
|
|||||||
@@ -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,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),
|
||||||
);
|
);
|
||||||
@@ -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");
|
||||||
|
|
||||||
|
|||||||
@@ -122,4 +122,12 @@ uint8_t entityGetAvailable();
|
|||||||
* @param entity Pointer to the entity.
|
* @param entity Pointer to the entity.
|
||||||
* @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
@@ -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);
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user