Improved cutscene system.
This commit is contained in:
@@ -15,6 +15,7 @@ target_sources(microrpg PRIVATE
|
||||
)
|
||||
|
||||
# Subdirs
|
||||
add_subdirectory(cutscene)
|
||||
add_subdirectory(entity)
|
||||
add_subdirectory(scene)
|
||||
add_subdirectory(platform)
|
||||
|
||||
11
src/cutscene/CMakeLists.txt
Executable file
11
src/cutscene/CMakeLists.txt
Executable file
@@ -0,0 +1,11 @@
|
||||
# Copyright (c) 2025 Dominic Masters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
# Sources
|
||||
target_sources(microrpg PRIVATE
|
||||
cutscene.c
|
||||
cutsceneitem.c
|
||||
cutscenemode.c
|
||||
)
|
||||
49
src/cutscene/cutscene.c
Normal file
49
src/cutscene/cutscene.c
Normal file
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "cutscene.h"
|
||||
#include "game.h"
|
||||
|
||||
void cutsceneInit() {
|
||||
memset(&GAME.cutsceneSystem, 0, sizeof(GAME.cutsceneSystem));
|
||||
}
|
||||
|
||||
void cutsceneStart(const cutscene_t *cutscene) {
|
||||
GAME.cutsceneSystem.cutscene = cutscene;
|
||||
GAME.cutsceneSystem.mode = CUTSCENE_MODE_INITIAL;
|
||||
GAME.cutsceneSystem.currentItem = 0xFF;// Set to 0xFF so start wraps.
|
||||
cutsceneNext();
|
||||
}
|
||||
|
||||
void cutsceneTick() {
|
||||
if(GAME.cutsceneSystem.cutscene == NULL) return;
|
||||
|
||||
const cutsceneitem_t *item = (
|
||||
&GAME.cutsceneSystem.cutscene->items[GAME.cutsceneSystem.currentItem]
|
||||
);
|
||||
cutsceneItemTick(item, &GAME.cutsceneSystem.data);
|
||||
}
|
||||
|
||||
void cutsceneNext() {
|
||||
if(GAME.cutsceneSystem.cutscene == NULL) return;
|
||||
|
||||
GAME.cutsceneSystem.currentItem++;
|
||||
|
||||
// End of the cutscene?
|
||||
if(GAME.cutsceneSystem.currentItem >= GAME.cutsceneSystem.cutscene->itemCount) {
|
||||
GAME.cutsceneSystem.cutscene = NULL;
|
||||
GAME.cutsceneSystem.currentItem = 0;
|
||||
GAME.cutsceneSystem.mode = CUTSCENE_MODE_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
// Start item.
|
||||
const cutsceneitem_t *item = (
|
||||
&GAME.cutsceneSystem.cutscene->items[GAME.cutsceneSystem.currentItem]
|
||||
);
|
||||
cutsceneItemStart(item, &GAME.cutsceneSystem.data);
|
||||
}
|
||||
@@ -6,22 +6,41 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "microrpg.h"
|
||||
|
||||
#define CUTSCENE_ITEM_NULL 0
|
||||
#define CUTSCENE_ITEM_TEXTBOX 1
|
||||
#define CUTSCENE_ITEM_CALLBACK 2
|
||||
#include "cutsceneitem.h"
|
||||
#include "cutscenemode.h"
|
||||
|
||||
typedef struct {
|
||||
uint8_t type;
|
||||
|
||||
union {
|
||||
const char *textbox;
|
||||
void (*callback)(void);// TODO: Bring entity data across.
|
||||
};
|
||||
} cutsceneitem_t;
|
||||
|
||||
typedef struct {
|
||||
cutsceneitem_t *items;
|
||||
const cutsceneitem_t *items;
|
||||
uint8_t itemCount;
|
||||
} cutscene_t;
|
||||
} cutscene_t;
|
||||
|
||||
typedef struct {
|
||||
const cutscene_t *cutscene;
|
||||
uint8_t currentItem;
|
||||
|
||||
// Data (used by the current item).
|
||||
cutsceneitemdata_t data;
|
||||
cutscenemode_t mode;
|
||||
} cutscenesystem_t;
|
||||
|
||||
/**
|
||||
* Initialize the cutscene system.
|
||||
*/
|
||||
void cutsceneInit();
|
||||
|
||||
/**
|
||||
* Start a cutscene.
|
||||
*
|
||||
* @param cutscene Pointer to the cutscene to start.
|
||||
*/
|
||||
void cutsceneStart(const cutscene_t *cutscene);
|
||||
|
||||
/**
|
||||
* Advance to the next item in the cutscene.
|
||||
*/
|
||||
void cutsceneNext();
|
||||
|
||||
/**
|
||||
* Update the cutscene system for one tick.
|
||||
*/
|
||||
void cutsceneTick();
|
||||
11
src/cutscene/cutscenecallback.h
Normal file
11
src/cutscene/cutscenecallback.h
Normal file
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "microrpg.h"
|
||||
|
||||
typedef void (*cutscenecallback_t)(void);
|
||||
48
src/cutscene/cutsceneitem.c
Normal file
48
src/cutscene/cutsceneitem.c
Normal file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "cutsceneitem.h"
|
||||
#include "cutscene.h"
|
||||
|
||||
void cutsceneItemStart(const cutsceneitem_t *item, cutsceneitemdata_t *data) {
|
||||
switch(item->type) {
|
||||
case CUTSCENE_ITEM_TEXT:
|
||||
break;
|
||||
|
||||
case CUTSCENE_ITEM_WAIT:
|
||||
data->wait = item->wait;
|
||||
break;
|
||||
|
||||
case CUTSCENE_ITEM_CALLBACK:
|
||||
if(item->callback != NULL) item->callback();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void cutsceneItemTick(const cutsceneitem_t *item, cutsceneitemdata_t *data) {
|
||||
switch(item->type) {
|
||||
case CUTSCENE_ITEM_TEXT:
|
||||
break;
|
||||
|
||||
case CUTSCENE_ITEM_CALLBACK:
|
||||
break;
|
||||
|
||||
case CUTSCENE_ITEM_WAIT:
|
||||
data->wait--;
|
||||
if(data->wait <= 0) {
|
||||
// Wait is over, proceed to next item.
|
||||
cutsceneNext();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
47
src/cutscene/cutsceneitem.h
Normal file
47
src/cutscene/cutsceneitem.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "cutscenewait.h"
|
||||
#include "cutscenecallback.h"
|
||||
#include "cutscenetext.h"
|
||||
|
||||
#define CUTSCENE_ITEM_NULL 0
|
||||
#define CUTSCENE_ITEM_TEXT 1
|
||||
#define CUTSCENE_ITEM_CALLBACK 2
|
||||
#define CUTSCENE_ITEM_WAIT 3
|
||||
|
||||
typedef struct cutsceneitem_s {
|
||||
uint8_t type;
|
||||
|
||||
// Arguments/Data that will be used when this item is invoked.
|
||||
union {
|
||||
cutscenetext_t text;
|
||||
cutscenecallback_t callback;
|
||||
cutscenewait_t wait;
|
||||
};
|
||||
} cutsceneitem_t;
|
||||
|
||||
typedef union {
|
||||
cutscenewaitdata_t wait;
|
||||
} cutsceneitemdata_t;
|
||||
|
||||
/**
|
||||
* Start the given cutscene item.
|
||||
*
|
||||
* @param item The cutscene item to start.
|
||||
* @param data The cutscene item data storage.
|
||||
*/
|
||||
void cutsceneItemStart(const cutsceneitem_t *item, cutsceneitemdata_t *data);
|
||||
|
||||
/**
|
||||
* Tick the given cutscene item (one frame).
|
||||
*
|
||||
* @param item The cutscene item to tick.
|
||||
* @param data The cutscene item data storage.
|
||||
*/
|
||||
void cutsceneItemTick(const cutsceneitem_t *item, cutsceneitemdata_t *data);
|
||||
20
src/cutscene/cutscenemode.c
Normal file
20
src/cutscene/cutscenemode.c
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "cutscenemode.h"
|
||||
#include "game.h"
|
||||
|
||||
bool_t cutsceneModeIsInputAllowed() {
|
||||
switch(GAME.cutsceneSystem.mode) {
|
||||
case CUTSCENE_MODE_FULL_FREEZE:
|
||||
case CUTSCENE_MODE_INPUT_FREEZE:
|
||||
return false;
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
33
src/cutscene/cutscenemode.h
Normal file
33
src/cutscene/cutscenemode.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "microrpg.h"
|
||||
|
||||
// Mode 0, Assume no cutscene is active.
|
||||
#define CUTSCENE_MODE_NONE 0
|
||||
|
||||
// Mode 1, assume that the cutscene is controlling all gameplay (full freeze).
|
||||
#define CUTSCENE_MODE_FULL_FREEZE 1
|
||||
|
||||
// Mode 2, assume that the cutscene is simply stopping regular player input.
|
||||
#define CUTSCENE_MODE_INPUT_FREEZE 2
|
||||
|
||||
// Mode 3, assume that the cutscene is not affecting gameplay directly.
|
||||
#define CUTSCENE_MODE_GAMEPLAY 3
|
||||
|
||||
// Default mode for all cutscenes.
|
||||
#define CUTSCENE_MODE_INITIAL CUTSCENE_MODE_INPUT_FREEZE
|
||||
|
||||
typedef uint8_t cutscenemode_t;
|
||||
|
||||
/**
|
||||
* Check if input is allowed in the current cutscene mode.
|
||||
*
|
||||
* @return true if input is allowed, false otherwise.
|
||||
*/
|
||||
bool_t cutsceneModeIsInputAllowed();
|
||||
11
src/cutscene/cutscenetext.h
Normal file
11
src/cutscene/cutscenetext.h
Normal file
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "microrpg.h"
|
||||
|
||||
typedef const char *cutscenetext_t;
|
||||
12
src/cutscene/cutscenewait.h
Normal file
12
src/cutscene/cutscenewait.h
Normal file
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "microrpg.h"
|
||||
|
||||
typedef uint16_t cutscenewait_t;
|
||||
typedef uint16_t cutscenewaitdata_t;
|
||||
21
src/cutscene/scene/testcutscene.h
Executable file
21
src/cutscene/scene/testcutscene.h
Executable file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "cutscene/cutscene.h"
|
||||
|
||||
static void testCutsceneTest() {
|
||||
}
|
||||
|
||||
static const cutsceneitem_t TEST_CUTSCENE_ITEMS[] = {
|
||||
{ .type = CUTSCENE_ITEM_WAIT, .wait = 1 * GAME_TIME_TICKS_PER_SECOND }
|
||||
};
|
||||
|
||||
static const cutscene_t TEST_CUTSCENE = {
|
||||
.items = TEST_CUTSCENE_ITEMS,
|
||||
.itemCount = sizeof(TEST_CUTSCENE_ITEMS) / sizeof(cutsceneitem_t)
|
||||
};
|
||||
@@ -1,17 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "cutscene.h"
|
||||
|
||||
static void testCutsceneTest() {
|
||||
abort();
|
||||
}
|
||||
|
||||
cutsceneitem_t TEST_CUTSCENE_ITEMS[] = {
|
||||
{ .type = CUTSCENE_ITEM_CALLBACK, .callback = testCutsceneTest }
|
||||
};
|
||||
@@ -31,7 +31,7 @@ void entityTick(entity_t *entity) {
|
||||
}
|
||||
|
||||
// Let entities move (if they do)
|
||||
if(entity->type == ENTITY_TYPE_PLAYER) {
|
||||
if(entity->type == ENTITY_TYPE_PLAYER && cutsceneModeIsInputAllowed()) {
|
||||
playerTickInput(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,5 +9,6 @@
|
||||
#include "entity.h"
|
||||
|
||||
void signInteract(entity_t *entity) {
|
||||
abort();
|
||||
if(entity->sign.cutscene == NULL) return;
|
||||
cutsceneStart(entity->sign.cutscene);
|
||||
}
|
||||
@@ -6,12 +6,12 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "microrpg.h"
|
||||
#include "cutscene/cutscene.h"
|
||||
|
||||
typedef struct entity_s entity_t;
|
||||
|
||||
typedef struct sign_s {
|
||||
void *nothing;
|
||||
const cutscene_t *cutscene;
|
||||
} sign_t;
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,22 +6,28 @@
|
||||
*/
|
||||
|
||||
#include "game.h"
|
||||
#include "cutscene/cutscene.h"
|
||||
#include "cutscene/scene/testcutscene.h"
|
||||
|
||||
game_t GAME;
|
||||
|
||||
void gameInit() {
|
||||
memset(&GAME, 0, sizeof(GAME));
|
||||
|
||||
cutsceneInit();
|
||||
|
||||
entityInit(&GAME.player, ENTITY_TYPE_PLAYER);
|
||||
|
||||
entityInit(&GAME.overworld.map.entities[0], ENTITY_TYPE_SIGN);
|
||||
GAME.overworld.map.entities[0].position.x = 5;
|
||||
GAME.overworld.map.entities[0].position.y = 5;
|
||||
GAME.overworld.map.entities[0].sign.cutscene = &TEST_CUTSCENE;
|
||||
|
||||
GAME.scene = SCENE_OVERWORLD;
|
||||
}
|
||||
|
||||
void gameTick() {
|
||||
gameTimeTick(&GAME.time);
|
||||
cutsceneTick();
|
||||
sceneTick();
|
||||
}
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "entity/entity.h"
|
||||
#include "world/map.h"
|
||||
#include "scene/scene.h"
|
||||
#include "cutscene/cutscene.h"
|
||||
#include "gametime.h"
|
||||
|
||||
#define GAME_SCENE_INITIAL 0
|
||||
@@ -18,6 +19,7 @@ typedef struct game_s {
|
||||
scene_t scene;
|
||||
entity_t player;
|
||||
gametime_t time;
|
||||
cutscenesystem_t cutsceneSystem;
|
||||
|
||||
union {
|
||||
struct {
|
||||
|
||||
@@ -72,7 +72,7 @@ uint8_t platformUpdate() {
|
||||
// Update input state.
|
||||
PLATFORM_RAYLIB.inputPrevious = PLATFORM_RAYLIB.inputCurrent;
|
||||
PLATFORM_RAYLIB.inputCurrent = 0;
|
||||
rlkeyboardmap_t *map = RL_KEYBOARD_MAP;
|
||||
const rlkeyboardmap_t *map = RL_KEYBOARD_MAP;
|
||||
do {
|
||||
if(IsKeyDown(map->raylibKey)) {
|
||||
PLATFORM_RAYLIB.inputCurrent |= map->action;
|
||||
|
||||
Reference in New Issue
Block a user