Restored some stuff

This commit is contained in:
2026-06-25 11:53:15 -05:00
parent a162002af2
commit 26fcaf6e75
20 changed files with 273 additions and 62 deletions
+1 -3
View File
@@ -41,9 +41,7 @@ errorret_t rpgInit(void) {
errorret_t rpgUpdate(void) {
#if TIME_FIXED == 0
if(TIME.dynamicUpdate) {
errorOk();
}
if(TIME.dynamicUpdate) errorOk();
#endif
// TODO: Do not update if the scene is not the map scene?
+32
View File
@@ -53,6 +53,10 @@ errorret_t screenBind() {
SCREEN.width = frameBufferGetWidth(FRAMEBUFFER_BOUND);
SCREEN.height = frameBufferGetHeight(FRAMEBUFFER_BOUND);
SCREEN.aspect = frameBufferGetAspect(FRAMEBUFFER_BOUND);
SCREEN.scanX = 0;
SCREEN.scanY = 0;
SCREEN.scanWidth = SCREEN.width;
SCREEN.scanHeight = SCREEN.height;
// No needd for a framebuffer.
#ifdef DUSK_DISPLAY_SIZE_DYNAMIC
@@ -69,6 +73,10 @@ errorret_t screenBind() {
SCREEN.width = SCREEN.fixedSize.width;
SCREEN.height = SCREEN.fixedSize.height;
SCREEN.aspect = (float_t)SCREEN.width / (float_t)SCREEN.height;
SCREEN.scanX = 0;
SCREEN.scanY = 0;
SCREEN.scanWidth = SCREEN.width;
SCREEN.scanHeight = SCREEN.height;
if(SCREEN.framebufferReady) {
// Is current framebuffer the correct size?
@@ -106,6 +114,10 @@ errorret_t screenBind() {
SCREEN.width = fbWidth;
SCREEN.height = fbHeight;
SCREEN.aspect = (float_t)SCREEN.width / (float_t)SCREEN.height;
SCREEN.scanX = 0;
SCREEN.scanY = 0;
SCREEN.scanWidth = SCREEN.width;
SCREEN.scanHeight = SCREEN.height;
if(SCREEN.framebufferReady) {
errorChain(frameBufferDispose(&SCREEN.framebuffer));
@@ -136,6 +148,10 @@ errorret_t screenBind() {
SCREEN.width = newFbWidth;
SCREEN.height = newFbHeight;
SCREEN.aspect = curFbAspect;
SCREEN.scanX = 0;
SCREEN.scanY = 0;
SCREEN.scanWidth = SCREEN.width;
SCREEN.scanHeight = SCREEN.height;
errorChain(frameBufferBind(&SCREEN.framebuffer));
errorOk();
}
@@ -152,6 +168,10 @@ errorret_t screenBind() {
SCREEN.width = newFbWidth;
SCREEN.height = newFbHeight;
SCREEN.aspect = (float_t)SCREEN.width / (float_t)SCREEN.height;
SCREEN.scanX = 0;
SCREEN.scanY = 0;
SCREEN.scanWidth = SCREEN.width;
SCREEN.scanHeight = SCREEN.height;
SCREEN.framebufferReady = true;
// Bind FB
@@ -171,6 +191,10 @@ errorret_t screenBind() {
SCREEN.width = newFbWidth;
SCREEN.height = newFbHeight;
SCREEN.aspect = (float_t)SCREEN.width / (float_t)SCREEN.height;
SCREEN.scanX = 0;
SCREEN.scanY = 0;
SCREEN.scanWidth = SCREEN.width;
SCREEN.scanHeight = SCREEN.height;
if(fbWidth == newFbWidth && fbHeight == newFbHeight) {
// No need to use framebuffer.
@@ -217,6 +241,10 @@ errorret_t screenBind() {
SCREEN.width = newFbWidth;
SCREEN.height = newFbHeight;
SCREEN.aspect = (float_t)SCREEN.width / (float_t)SCREEN.height;
SCREEN.scanX = 0;
SCREEN.scanY = 0;
SCREEN.scanWidth = SCREEN.width;
SCREEN.scanHeight = SCREEN.height;
if(fbWidth == newFbWidth && fbHeight == newFbHeight) {
// No need to use framebuffer.
@@ -258,6 +286,10 @@ errorret_t screenBind() {
float_t fbAspect = fbWidth / fbHeight;
SCREEN.width = (int32_t)floorf(SCREEN.height * fbAspect);
SCREEN.aspect = (float_t)SCREEN.width / (float_t)SCREEN.height;
SCREEN.scanX = 0;
SCREEN.scanY = 0;
SCREEN.scanWidth = SCREEN.width;
SCREEN.scanHeight = SCREEN.height;
break;
}
+8
View File
@@ -44,6 +44,14 @@ typedef struct {
int32_t width;
int32_t height;
float_t aspect;
// Overscan-safe area; defaults to full viewport each frame.
// Platforms with TV overscan set these after screenBind().
int32_t scanX;
int32_t scanY;
int32_t scanWidth;
int32_t scanHeight;
color_t background;
#ifdef DUSK_DISPLAY_SIZE_DYNAMIC
+2 -1
View File
@@ -8,7 +8,8 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
entity.c
entityanim.c
entitydir.c
entityinteract.c
npc.c
player.c
entitydir.c
)
+23
View File
@@ -49,13 +49,27 @@ void entityUpdate(entity_t *entity) {
}
}
bool_t entityCanTurn(entity_t *entity) {
return entity->animation == ENTITY_ANIM_IDLE;
}
bool_t entityCanWalk(entity_t *entity) {
return entity->animation == ENTITY_ANIM_IDLE;
}
bool_t entityCanRun(entity_t *entity) {
return entity->animation == ENTITY_ANIM_IDLE;
}
void entityTurn(entity_t *entity, const entitydir_t direction) {
if(!entityCanTurn(entity)) return;
entity->direction = direction;
entity->animation = ENTITY_ANIM_TURN;
entity->animTime = ENTITY_ANIM_TURN_DURATION;
}
void entityWalk(entity_t *entity, const entitydir_t direction) {
if(!entityCanWalk(entity)) return;
// TODO: Animation, delay, etc.
entity->direction = direction;
@@ -172,6 +186,15 @@ void entityWalk(entity_t *entity, const entitydir_t direction) {
}
}
void entityRun(entity_t *entity, const entitydir_t direction) {
if(!entityCanRun(entity)) return;
entityWalk(entity, direction);
if(entity->animation == ENTITY_ANIM_WALK) {
entity->animation = ENTITY_ANIM_RUN;
entity->animTime = ENTITY_ANIM_RUN_DURATION;
}
}
entity_t * entityGetAt(const worldpos_t position) {
entity_t *ent = ENTITIES;
do {
+36 -1
View File
@@ -8,6 +8,7 @@
#pragma once
#include "entitydir.h"
#include "entityanim.h"
#include "entityinteract.h"
#include "entitytype.h"
#include "npc.h"
@@ -21,11 +22,13 @@ typedef struct entity_s {
// Movement
entitydir_t direction;
worldpos_t position;
tilepos_t subPosition;
worldpos_t lastPosition;
vec3 renderPosition;
entityanim_t animation;
float_t animTime;
entityinteract_t interact;
} entity_t;
extern entity_t ENTITIES[ENTITY_COUNT];
@@ -45,6 +48,30 @@ void entityInit(entity_t *entity, const entitytype_t type);
*/
void entityUpdate(entity_t *entity);
/**
* Returns true if the entity is in a state where it can turn.
*
* @param entity Pointer to the entity to check.
* @returns True if the entity can turn.
*/
bool_t entityCanTurn(entity_t *entity);
/**
* Returns true if the entity is in a state where it can walk.
*
* @param entity Pointer to the entity to check.
* @returns True if the entity can walk.
*/
bool_t entityCanWalk(entity_t *entity);
/**
* Returns true if the entity is in a state where it can run.
*
* @param entity Pointer to the entity to check.
* @returns True if the entity can run.
*/
bool_t entityCanRun(entity_t *entity);
/**
* Turn an entity to face a new direction.
*
@@ -61,6 +88,14 @@ void entityTurn(entity_t *entity, const entitydir_t direction);
*/
void entityWalk(entity_t *entity, const entitydir_t direction);
/**
* Make an entity run in a direction.
*
* @param entity Pointer to the entity to make run.
* @param direction The direction to run in.
*/
void entityRun(entity_t *entity, const entitydir_t direction);
/**
* Gets the entity at a specific world position.
*
+27 -5
View File
@@ -9,11 +9,33 @@
#include "time/time.h"
void entityAnimUpdate(entity_t *entity) {
if(entity->animation == ENTITY_ANIM_IDLE) return;
if(entity->animation != ENTITY_ANIM_IDLE) {
entity->animTime -= TIME.delta;
if(entity->animTime <= 0) {
entity->animation = ENTITY_ANIM_IDLE;
entity->animTime = 0;
}
}
entity->animTime -= TIME.delta;
if(entity->animTime <= 0) {
entity->animation = ENTITY_ANIM_IDLE;
entity->animTime = 0;
if(
entity->animation == ENTITY_ANIM_WALK ||
entity->animation == ENTITY_ANIM_RUN
) {
float_t duration = entity->animation == ENTITY_ANIM_WALK ?
ENTITY_ANIM_WALK_DURATION : ENTITY_ANIM_RUN_DURATION;
float_t t = 1.0f - (entity->animTime / duration);
entity->renderPosition[0] = (float_t)entity->lastPosition.x + t * (
(float_t)entity->position.x - (float_t)entity->lastPosition.x
);
entity->renderPosition[1] = (float_t)entity->lastPosition.y + t * (
(float_t)entity->position.y - (float_t)entity->lastPosition.y
);
entity->renderPosition[2] = (float_t)entity->lastPosition.z + t * (
(float_t)entity->position.z - (float_t)entity->lastPosition.z
);
} else {
entity->renderPosition[0] = (float_t)entity->position.x;
entity->renderPosition[1] = (float_t)entity->position.y;
entity->renderPosition[2] = (float_t)entity->position.z;
}
}
+2
View File
@@ -10,6 +10,7 @@
#define ENTITY_ANIM_TURN_DURATION 0.06f
#define ENTITY_ANIM_WALK_DURATION 0.1f
#define ENTITY_ANIM_RUN_DURATION 0.05f
typedef struct entity_s entity_t;
@@ -17,6 +18,7 @@ typedef enum {
ENTITY_ANIM_IDLE,
ENTITY_ANIM_TURN,
ENTITY_ANIM_WALK,
ENTITY_ANIM_RUN,
} entityanim_t;
/**
+40
View File
@@ -0,0 +1,40 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "entity.h"
#include "assert/assert.h"
#include "console/console.h"
#include "rpg/cutscene/cutscenesystem.h"
void entityInteractWith(entity_t *player, entity_t *target) {
assertNotNull(player, "Player entity pointer cannot be NULL");
assertNotNull(target, "Target entity pointer cannot be NULL");
switch(target->interact.type) {
case ENTITY_INTERACT_CUTSCENE:
assertNotNull(
target->interact.data.cutscene,
"Interact cutscene pointer cannot be NULL"
);
cutsceneSystemStartCutscene(target->interact.data.cutscene);
return;
case ENTITY_INTERACT_PRINT:
consolePrint(target->interact.data.message);
return;
case ENTITY_INTERACT_NULL:
break;
default:
assertUnreachable("Unknown entity interact type");
break;
}
if(ENTITY_CALLBACKS[target->type].interact == NULL) return;
ENTITY_CALLBACKS[target->type].interact(player, target);
}
+49
View File
@@ -0,0 +1,49 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "dusk.h"
#include "rpg/cutscene/cutscene.h"
typedef struct entity_s entity_t;
/**
* Describes the type of interaction an entity supports.
*/
typedef enum {
ENTITY_INTERACT_NULL = 0,
ENTITY_INTERACT_CUTSCENE,
ENTITY_INTERACT_PRINT,
ENTITY_INTERACT_COUNT
} entityinteracttype_t;
/**
* Per-type data for an entity's interact component.
*/
typedef union {
const cutscene_t *cutscene;
char_t message[32];
} entityinteractdata_t;
/**
* Interact component attached to any entity that can be interacted with.
* Set type to ENTITY_INTERACT_NULL to mark the entity as non-interactable.
*/
typedef struct {
entityinteracttype_t type;
entityinteractdata_t data;
} entityinteract_t;
/**
* Attempts to interact with the target entity on behalf of the player.
* Dispatches via the interact component; falls back to the entity type
* callback if no component is set.
*
* @param player Pointer to the player entity.
* @param target Pointer to the entity to interact with.
*/
void entityInteractWith(entity_t *player, entity_t *target);
+6 -5
View File
@@ -26,11 +26,13 @@ void playerInput(entity_t *entity) {
return entityTurn(entity, dirMap->direction);
} while((++dirMap)->action != 0xFF);
// Walk
// Walk / Run
bool_t running = inputIsDown(INPUT_ACTION_CANCEL);
dirMap = PLAYER_INPUT_DIR_MAP;
do {
if(!inputIsDown(dirMap->action)) continue;
if(entity->direction != dirMap->direction) continue;
if(running) return entityRun(entity, dirMap->direction);
return entityWalk(entity, dirMap->direction);
} while((++dirMap)->action != 0xFF);
@@ -45,10 +47,9 @@ void playerInput(entity_t *entity) {
z = entity->position.z;
}
entity_t *interact = entityGetAt((worldpos_t){ x, y, z });
if(interact != NULL && ENTITY_CALLBACKS[interact->type].interact != NULL) {
if(ENTITY_CALLBACKS[interact->type].interact(entity, interact)) return;
}
entity_t *target = entityGetAt((worldpos_t){ x, y, z });
if(target == NULL) return;
entityInteractWith(entity, target);
}
}
-9
View File
@@ -8,9 +8,6 @@
#pragma once
#include "dusk.h"
#define TILE_POS_MIN -128
#define TILE_POS_MAX 127
#define CHUNK_WIDTH 16
#define CHUNK_HEIGHT CHUNK_WIDTH
#define CHUNK_DEPTH 8
@@ -32,8 +29,6 @@ typedef uint32_t chunktileindex_t;
typedef int32_t worldunits_t;
typedef int32_t chunkunits_t;
typedef int8_t tileunit_t;
typedef struct worldpos_s {
worldunit_t x, y, z;
} worldpos_t;
@@ -42,10 +37,6 @@ typedef struct chunkpos_t {
chunkunit_t x, y, z;
} chunkpos_t;
typedef struct tilepos_s {
tileunit_t x, y, z;
} tilepos_t;
/**
* Compares two world positions for equality.
*
+8
View File
@@ -13,6 +13,7 @@
#include "rpgcamera.h"
#include "rpgtextbox.h"
#include "util/memory.h"
#include "util/string.h"
#include "assert/assert.h"
errorret_t rpgInit(void) {
@@ -37,6 +38,13 @@ errorret_t rpgInit(void) {
RPG_CAMERA.mode = RPG_CAMERA_MODE_FOLLOW_ENTITY;
RPG_CAMERA.followEntity.followEntityId = ent->id;
uint8_t npcIndex = entityGetAvailable();
entity_t *npc = &ENTITIES[npcIndex];
entityInit(npc, ENTITY_TYPE_NPC);
npc->position = (worldpos_t){ 3, 3, 0 };
npc->interact.type = ENTITY_INTERACT_PRINT;
stringCopy(npc->interact.data.message, "hello world", 32);
// All Good!
errorOk();
}
+14 -5
View File
@@ -19,17 +19,20 @@ void rpgCameraInit(void) {
memoryZero(&RPG_CAMERA, sizeof(rpgcamera_t));
}
worldpos_t rpgCameraGetPosition(void) {
void rpgCameraGetPosition(vec3 out) {
switch(RPG_CAMERA.mode) {
case RPG_CAMERA_MODE_FREE:
return RPG_CAMERA.free;
glm_vec3_copy(RPG_CAMERA.free, out);
return;
case RPG_CAMERA_MODE_FOLLOW_ENTITY: {
entity_t *entity = &ENTITIES[RPG_CAMERA.followEntity.followEntityId];
if(entity->type == ENTITY_TYPE_NULL) {
return (worldpos_t){ 0, 0, 0 };
glm_vec3_zero(out);
return;
}
return entity->position;
glm_vec3_copy(entity->renderPosition, out);
return;
}
default:
@@ -40,8 +43,14 @@ worldpos_t rpgCameraGetPosition(void) {
errorret_t rpgCameraUpdate(void) {
if(!mapIsLoaded()) errorOk();
vec3 pos;
rpgCameraGetPosition(pos);
worldpos_t worldPos = {
(worldunit_t)pos[0],
(worldunit_t)pos[1],
(worldunit_t)pos[2]
};
chunkpos_t chunkPos;
worldpos_t worldPos = rpgCameraGetPosition();
worldPosToChunkPos(&worldPos, &chunkPos);
errorChain(mapPositionSet((chunkpos_t){
+3 -3
View File
@@ -18,7 +18,7 @@ typedef struct {
rpgcameramode_t mode;
union {
worldpos_t free;
vec3 free;
struct {
uint8_t followEntityId;
@@ -38,9 +38,9 @@ void rpgCameraInit(void);
/**
* Gets the RPG camera's position.
*
* @return The RPG camera's position.
* @param out Output vec3 filled with the camera world position.
*/
worldpos_t rpgCameraGetPosition(void);
void rpgCameraGetPosition(vec3 out);
/**
* Updates the RPG camera.
+4 -14
View File
@@ -61,14 +61,10 @@ errorret_t sceneOverworldRender(scenedata_t *sceneData) {
float_t pixelsPerUnit = 16.0f;
float_t worldH = (float)SCREEN.height / pixelsPerUnit;
float_t z = (worldH * 0.5f) / tanf(fov * 0.5f);
worldpos_t worldPos = rpgCameraGetPosition();
vec3 worldPosVec;
rpgCameraGetPosition(worldPosVec);
float_t offset = -16.0f;
vec3 worldPosVec = {
worldPos.x,
worldPos.y,
worldPos.z
};
glm_vec3_add(worldPosVec, (vec3){ 0.5f, 0.5f, 0.5f }, worldPosVec);
glm_lookat(
@@ -119,14 +115,8 @@ errorret_t sceneOverworldRender(scenedata_t *sceneData) {
entity_t *ent = &ENTITIES[i];
if(ent->type == ENTITY_TYPE_NULL) continue;
vec3 position = {
ent->position.x + ((float_t)ent->subPosition.x / TILE_POS_MAX),
ent->position.y + ((float_t)ent->subPosition.y / TILE_POS_MAX),
ent->position.z + ((float_t)ent->subPosition.z / TILE_POS_MAX) + 0.01f
};
glm_vec3_copy(position, sprites[spriteCount].min);
glm_vec3_copy(position, sprites[spriteCount].max);
glm_vec3_copy(ent->renderPosition, sprites[spriteCount].min);
glm_vec3_copy(ent->renderPosition, sprites[spriteCount].max);
glm_vec3_add(
sprites[spriteCount].max,
(vec3){ 1, 1, 0 },
+1 -3
View File
@@ -44,9 +44,7 @@ errorret_t sceneUpdate(void) {
}
#if DUSK_TIME_DYNAMIC
if(TIME.dynamicUpdate) {
errorOk();
}
if(TIME.dynamicUpdate) errorOk();
#endif
if(
+4 -3
View File
@@ -51,7 +51,8 @@ errorret_t uiFPSDraw() {
}
errorChain(textDraw(
0, 0,
(float_t)SCREEN.scanX,
(float_t)SCREEN.scanY,
fpsText, textColor,
&FONT_DEFAULT
));
@@ -60,8 +61,8 @@ errorret_t uiFPSDraw() {
int32_t versionWidth, versionHeight;
textMeasure(ENGINE.version, &FONT_DEFAULT, &versionWidth, &versionHeight);
errorChain(textDraw(
(float_t)(SCREEN.width - versionWidth),
(float_t)(SCREEN.height - versionHeight),
(float_t)(SCREEN.scanX + SCREEN.scanWidth - versionWidth),
(float_t)(SCREEN.scanY + SCREEN.scanHeight - versionHeight),
ENGINE.version,
color(255, 255, 255, 128),
&FONT_DEFAULT
+4 -2
View File
@@ -52,8 +52,10 @@ errorret_t uiLoadingDraw(void) {
int32_t textW, textH;
textMeasure(UI_LOADING_TEXT, &FONT_DEFAULT, &textW, &textH);
float_t x = (float_t)SCREEN.width - (float_t)textW - UI_LOADING_MARGIN;
float_t y = (float_t)SCREEN.height - (float_t)textH - UI_LOADING_MARGIN;
float_t x = (float_t)(SCREEN.scanX + SCREEN.scanWidth) -
(float_t)textW - UI_LOADING_MARGIN;
float_t y = (float_t)(SCREEN.scanY + SCREEN.scanHeight) -
(float_t)textH - UI_LOADING_MARGIN;
color_t color = COLOR_WHITE;
color.a = (uint8_t)(alpha * 255.0f);
+4 -3
View File
@@ -32,9 +32,10 @@ errorret_t uiTextboxInit(void) {
(float_t)(UI_TEXTBOX_LINES_PER_PAGE_MAX - 1) * UI_TEXTBOX_LINE_SPACING +
2.0f * fontH
);
UI_TEXTBOX.x = 10.0f;
UI_TEXTBOX.y = (float_t)SCREEN.height - tbHeight - 10.0f;
UI_TEXTBOX.width = (float_t)SCREEN.width - 20.0f;
UI_TEXTBOX.x = (float_t)SCREEN.scanX + 10.0f;
UI_TEXTBOX.y = (float_t)(SCREEN.scanY + SCREEN.scanHeight) -
tbHeight - 10.0f;
UI_TEXTBOX.width = (float_t)SCREEN.scanWidth - 20.0f;
UI_TEXTBOX.height = tbHeight;
UI_TEXTBOX.frame.tileset.columns = 3;