Entity refactoring
This commit is contained in:
@@ -72,14 +72,10 @@ errorret_t engineUpdate(void) {
|
||||
errorChain(uiTextboxUpdate());
|
||||
physicsManagerUpdate();
|
||||
errorChain(displayUpdate());
|
||||
|
||||
if(inputPressed(INPUT_ACTION_RAGEQUIT)) ENGINE.running = false;
|
||||
|
||||
// Scene update occurs last because only after rendering would we want to do
|
||||
// scene switching, refer to sceneSet() for information.
|
||||
errorChain(cutsceneUpdate());
|
||||
errorChain(sceneUpdate());
|
||||
|
||||
if(inputPressed(INPUT_ACTION_RAGEQUIT)) ENGINE.running = false;
|
||||
errorOk();
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
add_subdirectory(display)
|
||||
add_subdirectory(overworld)
|
||||
add_subdirectory(physics)
|
||||
add_subdirectory(script)
|
||||
add_subdirectory(trigger)
|
||||
@@ -11,7 +11,14 @@
|
||||
#include "display/mesh/cube.h"
|
||||
#include "display/spritebatch/spritebatch.h"
|
||||
|
||||
errorret_t entityRenderableDrawDefault() {
|
||||
errorret_t entityRenderableDrawDefault(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
void *user
|
||||
) {
|
||||
(void)entityId;
|
||||
(void)componentId;
|
||||
(void)user;
|
||||
errorChain(shaderSetColor(&SHADER_UNLIT, SHADER_UNLIT_COLOR, COLOR_WHITE));
|
||||
errorChain(shaderSetTexture(&SHADER_UNLIT, SHADER_UNLIT_TEXTURE, NULL));
|
||||
return meshDraw(&CUBE_MESH_SIMPLE, 0, -1);
|
||||
@@ -25,6 +32,7 @@ void entityRenderableInit(
|
||||
entityId, componentId, COMPONENT_TYPE_RENDERABLE
|
||||
);
|
||||
r->draw = entityRenderableDrawDefault;
|
||||
r->drawUser = NULL;
|
||||
}
|
||||
|
||||
void entityRenderableDispose(
|
||||
@@ -37,12 +45,18 @@ void entityRenderableDispose(
|
||||
void entityRenderableSetDraw(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
errorret_t (*draw)(void)
|
||||
errorret_t (*draw)(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
void *user
|
||||
),
|
||||
void *user
|
||||
) {
|
||||
entityrenderable_t *r = componentGetData(
|
||||
entityId, componentId, COMPONENT_TYPE_RENDERABLE
|
||||
);
|
||||
r->draw = draw;
|
||||
r->drawUser = user;
|
||||
}
|
||||
|
||||
errorret_t entityRenderableDraw(
|
||||
@@ -52,5 +66,5 @@ errorret_t entityRenderableDraw(
|
||||
entityrenderable_t *r = componentGetData(
|
||||
entityId, componentId, COMPONENT_TYPE_RENDERABLE
|
||||
);
|
||||
return r->draw();
|
||||
}
|
||||
return r->draw(entityId, componentId, r->drawUser);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,12 @@
|
||||
#include "display/spritebatch/spritebatch.h"
|
||||
|
||||
typedef struct {
|
||||
errorret_t (*draw)(void);
|
||||
errorret_t (*draw)(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
void *user
|
||||
);
|
||||
void *drawUser;
|
||||
} entityrenderable_t;
|
||||
|
||||
/**
|
||||
@@ -48,7 +53,12 @@ void entityRenderableDispose(
|
||||
void entityRenderableSetDraw(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
errorret_t (*draw)(void)
|
||||
errorret_t (*draw)(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
void *user
|
||||
),
|
||||
void *user
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
# Copyright (c) 2026 Dominic Masters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||
PUBLIC
|
||||
entityinteractable.c
|
||||
entityoverworld.c
|
||||
entityoverworldcamera.c
|
||||
entityplayer.c
|
||||
)
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "entityinteractable.h"
|
||||
#include "entity/entitymanager.h"
|
||||
|
||||
void entityInteractableInit(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId
|
||||
) {
|
||||
entityinteractable_t *inter = entityInteractableGet(entityId, componentId);
|
||||
inter->onInteract = NULL;
|
||||
inter->user = NULL;
|
||||
}
|
||||
|
||||
entityinteractable_t * entityInteractableGet(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId
|
||||
) {
|
||||
return componentGetData(entityId, componentId, COMPONENT_TYPE_INTERACTABLE);
|
||||
}
|
||||
|
||||
void entityInteractableSetCallback(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
void (*onInteract)(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
void *user
|
||||
),
|
||||
void *user
|
||||
) {
|
||||
entityinteractable_t *inter = entityInteractableGet(entityId, componentId);
|
||||
inter->onInteract = onInteract;
|
||||
inter->user = user;
|
||||
}
|
||||
|
||||
void entityInteractableTrigger(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId
|
||||
) {
|
||||
entityinteractable_t *inter = entityInteractableGet(entityId, componentId);
|
||||
if(inter->onInteract == NULL) return;
|
||||
inter->onInteract(entityId, componentId, inter->user);
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "entity/entitybase.h"
|
||||
|
||||
typedef struct {
|
||||
void (*onInteract)(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
void *user
|
||||
);
|
||||
void *user;
|
||||
} entityinteractable_t;
|
||||
|
||||
/**
|
||||
* Initializes the interactable component, clearing the callback and user pointer.
|
||||
*
|
||||
* @param entityId The owning entity.
|
||||
* @param componentId This component's ID.
|
||||
*/
|
||||
void entityInteractableInit(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId
|
||||
);
|
||||
|
||||
/**
|
||||
* Returns a pointer to the interactable component data.
|
||||
*
|
||||
* @param entityId The owning entity.
|
||||
* @param componentId This component's ID.
|
||||
* @return Pointer to the entityinteractable_t data.
|
||||
*/
|
||||
entityinteractable_t * entityInteractableGet(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId
|
||||
);
|
||||
|
||||
/**
|
||||
* Sets the callback invoked when this interactable is triggered.
|
||||
*
|
||||
* @param entityId The owning entity.
|
||||
* @param componentId This component's ID.
|
||||
* @param onInteract Function called on interaction, or NULL to clear.
|
||||
* @param user Arbitrary pointer forwarded to the callback.
|
||||
*/
|
||||
void entityInteractableSetCallback(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
void (*onInteract)(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
void *user
|
||||
),
|
||||
void *user
|
||||
);
|
||||
|
||||
/**
|
||||
* Fires the interactable's callback if one is set.
|
||||
*
|
||||
* @param entityId The owning entity.
|
||||
* @param componentId This component's ID.
|
||||
*/
|
||||
void entityInteractableTrigger(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId
|
||||
);
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "entityoverworld.h"
|
||||
#include "entity/entitymanager.h"
|
||||
#include "entity/component/display/entityrenderable.h"
|
||||
#include "display/shader/shaderunlit.h"
|
||||
#include "display/mesh/cube.h"
|
||||
|
||||
void entityOverworldInit(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId
|
||||
) {
|
||||
entityoverworld_t *ow = entityOverworldGet(entityId, componentId);
|
||||
ow->type = OVERWORLD_ENTITY_TYPE_NPC;
|
||||
ow->facing = FACING_DIR_DOWN;
|
||||
ow->renderCompId = entityGetComponent(entityId, COMPONENT_TYPE_RENDERABLE);
|
||||
if(ow->renderCompId != COMPONENT_ID_INVALID) {
|
||||
entityRenderableSetDraw(entityId, ow->renderCompId, entityOverworldDraw, NULL);
|
||||
}
|
||||
ow->physCompId = entityGetComponent(entityId, COMPONENT_TYPE_PHYSICS);
|
||||
}
|
||||
|
||||
entityoverworld_t * entityOverworldGet(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId
|
||||
) {
|
||||
return componentGetData(entityId, componentId, COMPONENT_TYPE_OVERWORLD);
|
||||
}
|
||||
|
||||
void entityOverworldSetType(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
const entityoverworldtype_t type
|
||||
) {
|
||||
entityOverworldGet(entityId, componentId)->type = type;
|
||||
}
|
||||
|
||||
errorret_t entityOverworldDraw(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
void *user
|
||||
) {
|
||||
(void)componentId; (void)user;
|
||||
|
||||
componentid_t owCompId = entityGetComponent(entityId, COMPONENT_TYPE_OVERWORLD);
|
||||
entityoverworld_t *ow = entityOverworldGet(entityId, owCompId);
|
||||
|
||||
color_t col = ow->type == OVERWORLD_ENTITY_TYPE_PLAYER ? COLOR_WHITE : COLOR_BLUE;
|
||||
errorChain(shaderSetColor(&SHADER_UNLIT, SHADER_UNLIT_COLOR, col));
|
||||
errorChain(shaderSetTexture(&SHADER_UNLIT, SHADER_UNLIT_TEXTURE, NULL));
|
||||
return meshDraw(&CUBE_MESH_SIMPLE, 0, -1);
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "error/error.h"
|
||||
#include "entity/entitybase.h"
|
||||
#include "overworld/facingdir.h"
|
||||
|
||||
typedef enum {
|
||||
OVERWORLD_ENTITY_TYPE_PLAYER = 0,
|
||||
OVERWORLD_ENTITY_TYPE_NPC = 1,
|
||||
} entityoverworldtype_t;
|
||||
|
||||
typedef struct {
|
||||
entityoverworldtype_t type;
|
||||
facingdir_t facing;
|
||||
componentid_t renderCompId;
|
||||
componentid_t physCompId;
|
||||
} entityoverworld_t;
|
||||
|
||||
/**
|
||||
* Initializes the overworld component, wiring up the draw callback if a
|
||||
* renderable component is already present on the entity.
|
||||
*
|
||||
* @param entityId The owning entity.
|
||||
* @param componentId This component's ID.
|
||||
*/
|
||||
void entityOverworldInit(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId
|
||||
);
|
||||
|
||||
/**
|
||||
* Returns a pointer to the overworld component data.
|
||||
*
|
||||
* @param entityId The owning entity.
|
||||
* @param componentId This component's ID.
|
||||
* @return Pointer to the entityoverworld_t data.
|
||||
*/
|
||||
entityoverworld_t * entityOverworldGet(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId
|
||||
);
|
||||
|
||||
/**
|
||||
* Sets the overworld entity type.
|
||||
*
|
||||
* @param entityId The owning entity.
|
||||
* @param componentId This component's ID.
|
||||
* @param type The type to assign.
|
||||
*/
|
||||
void entityOverworldSetType(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
const entityoverworldtype_t type
|
||||
);
|
||||
|
||||
/**
|
||||
* Draw callback registered on the renderable component.
|
||||
*
|
||||
* @param entityId The owning entity.
|
||||
* @param componentId The renderable component's ID.
|
||||
* @param user Unused.
|
||||
* @return Error result.
|
||||
*/
|
||||
errorret_t entityOverworldDraw(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
void *user
|
||||
);
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "entityoverworldcamera.h"
|
||||
#include "entity/entitymanager.h"
|
||||
#include "entity/component/display/entityposition.h"
|
||||
#include "entity/component/display/entitycamera.h"
|
||||
|
||||
void entityOverworldCameraInit(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId
|
||||
) {
|
||||
entityoverworldcamera_t *cam = entityOverworldCameraGet(entityId, componentId);
|
||||
cam->targetEntityId = ENTITY_ID_INVALID;
|
||||
cam->targetPosCompId = COMPONENT_ID_INVALID;
|
||||
glm_vec3_zero(cam->targetOffset);
|
||||
glm_vec3_zero(cam->eyeOffset);
|
||||
cam->scale = 1.0f;
|
||||
}
|
||||
|
||||
entityoverworldcamera_t * entityOverworldCameraGet(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId
|
||||
) {
|
||||
return componentGetData(entityId, componentId, COMPONENT_TYPE_OVERWORLD_CAMERA);
|
||||
}
|
||||
|
||||
void entityOverworldCameraSetTarget(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
const entityid_t targetEntityId,
|
||||
const componentid_t targetPosCompId
|
||||
) {
|
||||
entityoverworldcamera_t *cam = entityOverworldCameraGet(entityId, componentId);
|
||||
cam->targetEntityId = targetEntityId;
|
||||
cam->targetPosCompId = targetPosCompId;
|
||||
}
|
||||
|
||||
void entityOverworldCameraUpdate(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId
|
||||
) {
|
||||
entityoverworldcamera_t *cam = entityOverworldCameraGet(entityId, componentId);
|
||||
|
||||
vec3 targetPos;
|
||||
entityPositionGetWorldPosition(
|
||||
cam->targetEntityId, cam->targetPosCompId, targetPos
|
||||
);
|
||||
|
||||
vec3 center = {
|
||||
targetPos[0] + cam->targetOffset[0],
|
||||
targetPos[1] + cam->targetOffset[1],
|
||||
targetPos[2] + cam->targetOffset[2]
|
||||
};
|
||||
|
||||
componentid_t posComp = entityGetComponent(entityId, COMPONENT_TYPE_POSITION);
|
||||
componentid_t camComp = entityGetComponent(entityId, COMPONENT_TYPE_CAMERA);
|
||||
entityCameraLookAtPixelPerfect(
|
||||
entityId, posComp, camComp, center, cam->eyeOffset, cam->scale
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "entity/entitybase.h"
|
||||
|
||||
typedef struct {
|
||||
entityid_t targetEntityId;
|
||||
componentid_t targetPosCompId;
|
||||
vec3 targetOffset;
|
||||
vec3 eyeOffset;
|
||||
float_t scale;
|
||||
} entityoverworldcamera_t;
|
||||
|
||||
/**
|
||||
* Initializes the overworld camera component.
|
||||
*
|
||||
* @param entityId The owning entity.
|
||||
* @param componentId This component's ID.
|
||||
*/
|
||||
void entityOverworldCameraInit(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId
|
||||
);
|
||||
|
||||
/**
|
||||
* Returns a pointer to the overworld camera component data.
|
||||
*
|
||||
* @param entityId The owning entity.
|
||||
* @param componentId This component's ID.
|
||||
* @return Pointer to the entityoverworldcamera_t data.
|
||||
*/
|
||||
entityoverworldcamera_t * entityOverworldCameraGet(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId
|
||||
);
|
||||
|
||||
/**
|
||||
* Sets the entity and position component the camera will follow.
|
||||
*
|
||||
* @param entityId The owning entity.
|
||||
* @param componentId This component's ID.
|
||||
* @param targetEntityId Entity to follow.
|
||||
* @param targetPosCompId Position component on the target entity.
|
||||
*/
|
||||
void entityOverworldCameraSetTarget(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
const entityid_t targetEntityId,
|
||||
const componentid_t targetPosCompId
|
||||
);
|
||||
|
||||
/**
|
||||
* Updates the camera position to track the target entity.
|
||||
*
|
||||
* @param entityId The owning entity.
|
||||
* @param componentId This component's ID.
|
||||
*/
|
||||
void entityOverworldCameraUpdate(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId
|
||||
);
|
||||
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "entityplayer.h"
|
||||
#include "entity/entitymanager.h"
|
||||
#include "entity/component/display/entityposition.h"
|
||||
#include "entity/component/physics/entityphysics.h"
|
||||
#include "entity/component/overworld/entityoverworld.h"
|
||||
#include "entity/component/overworld/entityinteractable.h"
|
||||
#include "input/input.h"
|
||||
|
||||
void entityPlayerInit(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId
|
||||
) {
|
||||
entityplayer_t *player = entityPlayerGet(entityId, componentId);
|
||||
player->speed = ENTITY_PLAYER_SPEED;
|
||||
player->runSpeed = ENTITY_PLAYER_RUN_SPEED;
|
||||
}
|
||||
|
||||
entityplayer_t * entityPlayerGet(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId
|
||||
) {
|
||||
return componentGetData(entityId, componentId, COMPONENT_TYPE_PLAYER);
|
||||
}
|
||||
|
||||
void entityPlayerUpdate(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId
|
||||
) {
|
||||
entityplayer_t *player = entityPlayerGet(entityId, componentId);
|
||||
|
||||
vec2 dir;
|
||||
inputAngle2D(
|
||||
INPUT_ACTION_LEFT, INPUT_ACTION_RIGHT,
|
||||
INPUT_ACTION_UP, INPUT_ACTION_DOWN,
|
||||
dir
|
||||
);
|
||||
|
||||
float_t speed = (
|
||||
inputIsDown(INPUT_ACTION_CANCEL) ? player->runSpeed : player->speed
|
||||
);
|
||||
|
||||
componentid_t owCompId = entityGetComponent(entityId, COMPONENT_TYPE_OVERWORLD);
|
||||
entityoverworld_t *ow = entityOverworldGet(entityId, owCompId);
|
||||
|
||||
if(ow && glm_vec2_norm(dir) > 0.0f) {
|
||||
if(fabsf(dir[0]) >= fabsf(dir[1])) {
|
||||
ow->facing = dir[0] > 0.0f ? FACING_DIR_RIGHT : FACING_DIR_LEFT;
|
||||
} else {
|
||||
ow->facing = dir[1] > 0.0f ? FACING_DIR_DOWN : FACING_DIR_UP;
|
||||
}
|
||||
}
|
||||
|
||||
vec3 vel;
|
||||
entityPhysicsGetVelocity(entityId, ow->physCompId, vel);
|
||||
vel[0] = dir[0] * speed;
|
||||
vel[2] = dir[1] * speed;
|
||||
entityPhysicsSetVelocity(entityId, ow->physCompId, vel);
|
||||
|
||||
if(!inputPressed(INPUT_ACTION_ACCEPT)) return;
|
||||
|
||||
vec3 playerPos;
|
||||
componentid_t playerPosCompId = entityGetComponent(entityId, COMPONENT_TYPE_POSITION);
|
||||
if(playerPosCompId == COMPONENT_ID_INVALID) return;
|
||||
entityPositionGetWorldPosition(entityId, playerPosCompId, playerPos);
|
||||
|
||||
vec2 facingDir;
|
||||
facingDirToVec2(ow ? ow->facing : FACING_DIR_DOWN, facingDir);
|
||||
|
||||
for(entityid_t i = 0; i < ENTITY_COUNT_MAX; i++) {
|
||||
if((ENTITY_MANAGER.entities[i].state & ENTITY_STATE_ACTIVE) == 0) continue;
|
||||
if(i == entityId) continue;
|
||||
|
||||
componentid_t interComp = entityGetComponent(i, COMPONENT_TYPE_INTERACTABLE);
|
||||
if(interComp == COMPONENT_ID_INVALID) continue;
|
||||
|
||||
componentid_t posComp = entityGetComponent(i, COMPONENT_TYPE_POSITION);
|
||||
if(posComp == COMPONENT_ID_INVALID) continue;
|
||||
|
||||
vec3 targetPos;
|
||||
entityPositionGetWorldPosition(i, posComp, targetPos);
|
||||
|
||||
vec2 toTarget = {
|
||||
targetPos[0] - playerPos[0],
|
||||
targetPos[2] - playerPos[2],
|
||||
};
|
||||
float_t forward = glm_vec2_dot(facingDir, toTarget);
|
||||
if(forward <= 0.0f || forward > ENTITY_PLAYER_INTERACT_RANGE) continue;
|
||||
|
||||
float_t lateral = fabsf(
|
||||
facingDir[0] * toTarget[1] - facingDir[1] * toTarget[0]
|
||||
);
|
||||
if(lateral > ENTITY_PLAYER_INTERACT_LATERAL) continue;
|
||||
|
||||
entityInteractableTrigger(i, interComp);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "error/error.h"
|
||||
#include "entity/entitybase.h"
|
||||
|
||||
#define ENTITY_PLAYER_SPEED 4.0f
|
||||
#define ENTITY_PLAYER_RUN_SPEED 8.0f
|
||||
#define ENTITY_PLAYER_INTERACT_RANGE 1.5f
|
||||
#define ENTITY_PLAYER_INTERACT_LATERAL 0.6f
|
||||
|
||||
typedef struct {
|
||||
float_t speed;
|
||||
float_t runSpeed;
|
||||
} entityplayer_t;
|
||||
|
||||
/**
|
||||
* Initializes the player component.
|
||||
*
|
||||
* @param entityId The owning entity.
|
||||
* @param componentId This component's ID.
|
||||
*/
|
||||
void entityPlayerInit(const entityid_t entityId, const componentid_t componentId);
|
||||
|
||||
/**
|
||||
* Returns a pointer to the player component data.
|
||||
*
|
||||
* @param entityId The owning entity.
|
||||
* @param componentId This component's ID.
|
||||
* @return Pointer to the entityplayer_t data.
|
||||
*/
|
||||
entityplayer_t * entityPlayerGet(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId
|
||||
);
|
||||
|
||||
/**
|
||||
* Reads input, moves the player, updates facing direction, and checks for
|
||||
* interactable entities in front of the player when accept is pressed.
|
||||
*
|
||||
* @param entityId The owning entity.
|
||||
* @param componentId This component's ID.
|
||||
*/
|
||||
void entityPlayerUpdate(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId
|
||||
);
|
||||
@@ -10,6 +10,10 @@
|
||||
#include "entity/component/display/entityrenderable.h"
|
||||
#include "entity/component/physics/entityphysics.h"
|
||||
#include "entity/component/trigger/entitytrigger.h"
|
||||
#include "entity/component/overworld/entityoverworld.h"
|
||||
#include "entity/component/overworld/entityplayer.h"
|
||||
#include "entity/component/overworld/entityinteractable.h"
|
||||
#include "entity/component/overworld/entityoverworldcamera.h"
|
||||
|
||||
// Name (Uppercase)
|
||||
// Structure
|
||||
@@ -22,3 +26,7 @@ X(CAMERA, entitycamera_t, camera, entityCameraInit, NULL)
|
||||
X(RENDERABLE, entityrenderable_t, renderable, entityRenderableInit, entityRenderableDispose)
|
||||
X(PHYSICS, entityphysics_t, physics, entityPhysicsInit, entityPhysicsDispose)
|
||||
X(TRIGGER, entitytrigger_t, trigger, entityTriggerInit, NULL)
|
||||
X(OVERWORLD, entityoverworld_t, overworld, entityOverworldInit, NULL)
|
||||
X(PLAYER, entityplayer_t, player, entityPlayerInit, NULL)
|
||||
X(INTERACTABLE, entityinteractable_t, interactable, entityInteractableInit, NULL)
|
||||
X(OVERWORLD_CAMERA, entityoverworldcamera_t, overworldCamera, entityOverworldCameraInit, NULL)
|
||||
|
||||
@@ -83,7 +83,7 @@ void entityDisposeDeep(const entityid_t entityId) {
|
||||
void entityUpdate(const entityid_t entityId) {
|
||||
entity_t *ent = &ENTITY_MANAGER.entities[entityId];
|
||||
for(uint8_t i = 0; i < ent->updateCount; i++) {
|
||||
ent->onUpdate[i](entityId);
|
||||
ent->onUpdate[i](entityId, ent->updateComponentId[i], ent->updateUser[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ void entityDispose(const entityid_t entityId) {
|
||||
entity_t *ent = &ENTITY_MANAGER.entities[entityId];
|
||||
|
||||
for(uint8_t i = 0; i < ent->disposeCount; i++) {
|
||||
ent->onDispose[i](entityId);
|
||||
ent->onDispose[i](entityId, ent->disposeComponentId[i], ent->disposeUser[i]);
|
||||
}
|
||||
|
||||
for(componentid_t i = 0; i < ENTITY_COMPONENT_COUNT_MAX; i++) {
|
||||
@@ -108,13 +108,21 @@ void entityDispose(const entityid_t entityId) {
|
||||
ent->state = 0;
|
||||
}
|
||||
|
||||
void entityUpdateAdd(const entityid_t entityId, const entitycallback_t callback) {
|
||||
void entityUpdateAdd(
|
||||
const entityid_t entityId,
|
||||
const entitycallback_t callback,
|
||||
const componentid_t componentId,
|
||||
void *user
|
||||
) {
|
||||
entity_t *ent = &ENTITY_MANAGER.entities[entityId];
|
||||
assertTrue(
|
||||
ent->updateCount < ENTITY_UPDATE_CALLBACK_COUNT_MAX,
|
||||
"Entity update callback slots full"
|
||||
);
|
||||
ent->onUpdate[ent->updateCount++] = callback;
|
||||
ent->onUpdate[ent->updateCount] = callback;
|
||||
ent->updateComponentId[ent->updateCount] = componentId;
|
||||
ent->updateUser[ent->updateCount] = user;
|
||||
ent->updateCount++;
|
||||
}
|
||||
|
||||
void entityUpdateRemove(const entityid_t entityId, const entitycallback_t callback) {
|
||||
@@ -123,19 +131,29 @@ void entityUpdateRemove(const entityid_t entityId, const entitycallback_t callba
|
||||
if(ent->onUpdate[i] != callback) continue;
|
||||
ent->updateCount--;
|
||||
for(uint8_t j = i; j < ent->updateCount; j++) {
|
||||
ent->onUpdate[j] = ent->onUpdate[j + 1];
|
||||
ent->onUpdate[j] = ent->onUpdate[j + 1];
|
||||
ent->updateComponentId[j] = ent->updateComponentId[j + 1];
|
||||
ent->updateUser[j] = ent->updateUser[j + 1];
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void entityDisposeAdd(const entityid_t entityId, const entitycallback_t callback) {
|
||||
void entityDisposeAdd(
|
||||
const entityid_t entityId,
|
||||
const entitycallback_t callback,
|
||||
const componentid_t componentId,
|
||||
void *user
|
||||
) {
|
||||
entity_t *ent = &ENTITY_MANAGER.entities[entityId];
|
||||
assertTrue(
|
||||
ent->disposeCount < ENTITY_DISPOSE_CALLBACK_COUNT_MAX,
|
||||
"Entity dispose callback slots full"
|
||||
);
|
||||
ent->onDispose[ent->disposeCount++] = callback;
|
||||
ent->onDispose[ent->disposeCount] = callback;
|
||||
ent->disposeComponentId[ent->disposeCount] = componentId;
|
||||
ent->disposeUser[ent->disposeCount] = user;
|
||||
ent->disposeCount++;
|
||||
}
|
||||
|
||||
void entityDisposeRemove(const entityid_t entityId, const entitycallback_t callback) {
|
||||
@@ -144,7 +162,9 @@ void entityDisposeRemove(const entityid_t entityId, const entitycallback_t callb
|
||||
if(ent->onDispose[i] != callback) continue;
|
||||
ent->disposeCount--;
|
||||
for(uint8_t j = i; j < ent->disposeCount; j++) {
|
||||
ent->onDispose[j] = ent->onDispose[j + 1];
|
||||
ent->onDispose[j] = ent->onDispose[j + 1];
|
||||
ent->disposeComponentId[j] = ent->disposeComponentId[j + 1];
|
||||
ent->disposeUser[j] = ent->disposeUser[j + 1];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -13,14 +13,22 @@
|
||||
#define ENTITY_UPDATE_CALLBACK_COUNT_MAX 5
|
||||
#define ENTITY_DISPOSE_CALLBACK_COUNT_MAX 5
|
||||
|
||||
typedef void (*entitycallback_t)(const entityid_t entityId);
|
||||
typedef void (*entitycallback_t)(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
void *user
|
||||
);
|
||||
|
||||
typedef struct {
|
||||
uint8_t state;
|
||||
uint8_t updateCount;
|
||||
uint8_t disposeCount;
|
||||
entitycallback_t onUpdate[ENTITY_UPDATE_CALLBACK_COUNT_MAX];
|
||||
componentid_t updateComponentId[ENTITY_UPDATE_CALLBACK_COUNT_MAX];
|
||||
void *updateUser[ENTITY_UPDATE_CALLBACK_COUNT_MAX];
|
||||
entitycallback_t onDispose[ENTITY_DISPOSE_CALLBACK_COUNT_MAX];
|
||||
componentid_t disposeComponentId[ENTITY_DISPOSE_CALLBACK_COUNT_MAX];
|
||||
void *disposeUser[ENTITY_DISPOSE_CALLBACK_COUNT_MAX];
|
||||
} entity_t;
|
||||
|
||||
/**
|
||||
@@ -85,7 +93,12 @@ void entityDisposeDeep(const entityid_t entityId);
|
||||
* @param entityId The entity to register on.
|
||||
* @param callback The function to call.
|
||||
*/
|
||||
void entityUpdateAdd(const entityid_t entityId, const entitycallback_t callback);
|
||||
void entityUpdateAdd(
|
||||
const entityid_t entityId,
|
||||
const entitycallback_t callback,
|
||||
const componentid_t componentId,
|
||||
void *user
|
||||
);
|
||||
|
||||
/**
|
||||
* Removes a previously registered update callback.
|
||||
@@ -102,7 +115,12 @@ void entityUpdateRemove(const entityid_t entityId, const entitycallback_t callba
|
||||
* @param entityId The entity to register on.
|
||||
* @param callback The function to call.
|
||||
*/
|
||||
void entityDisposeAdd(const entityid_t entityId, const entitycallback_t callback);
|
||||
void entityDisposeAdd(
|
||||
const entityid_t entityId,
|
||||
const entitycallback_t callback,
|
||||
const componentid_t componentId,
|
||||
void *user
|
||||
);
|
||||
|
||||
/**
|
||||
* Removes a previously registered dispose callback.
|
||||
|
||||
@@ -8,11 +8,11 @@
|
||||
#pragma once
|
||||
#include "dusk.h"
|
||||
|
||||
#define ENTITY_COUNT_MAX 100
|
||||
#define ENTITY_COMPONENT_COUNT_MAX 24
|
||||
#define ENTITY_COUNT_MAX 64
|
||||
#define ENTITY_COMPONENT_COUNT_MAX 16
|
||||
|
||||
#define ENTITY_ID_INVALID 0xFF
|
||||
#define COMPONENT_ID_INVALID 0xFF
|
||||
#define ENTITY_ID_INVALID 0xFF
|
||||
#define COMPONENT_ID_INVALID 0xFF
|
||||
|
||||
typedef uint8_t entityid_t;
|
||||
typedef uint8_t componentid_t;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||
PUBLIC
|
||||
facingdir.c
|
||||
maptypes.c
|
||||
map.c
|
||||
mapchunk.c
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "facingdir.h"
|
||||
|
||||
void facingDirToVec2(facingdir_t facing, vec2 dest) {
|
||||
switch(facing) {
|
||||
case FACING_DIR_UP: dest[0] = 0.0f; dest[1] = -1.0f; return;
|
||||
case FACING_DIR_LEFT: dest[0] = -1.0f; dest[1] = 0.0f; return;
|
||||
case FACING_DIR_RIGHT: dest[0] = 1.0f; dest[1] = 0.0f; return;
|
||||
default: dest[0] = 0.0f; dest[1] = 1.0f; return;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "dusk.h"
|
||||
|
||||
typedef enum {
|
||||
FACING_DIR_DOWN = 0,
|
||||
FACING_DIR_UP = 1,
|
||||
FACING_DIR_LEFT = 2,
|
||||
FACING_DIR_RIGHT = 3,
|
||||
FACING_DIR_SOUTH = FACING_DIR_DOWN,
|
||||
FACING_DIR_NORTH = FACING_DIR_UP,
|
||||
FACING_DIR_WEST = FACING_DIR_LEFT,
|
||||
FACING_DIR_EAST = FACING_DIR_RIGHT,
|
||||
} facingdir_t;
|
||||
|
||||
/**
|
||||
* Converts a facing direction to a normalized XZ vec2.
|
||||
*
|
||||
* @param facing The facing direction.
|
||||
* @param dest Output vec2 — [0] is X, [1] is Z.
|
||||
*/
|
||||
void facingDirToVec2(facingdir_t facing, vec2 dest);
|
||||
@@ -6,6 +6,7 @@
|
||||
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||
PUBLIC
|
||||
overworldground.c
|
||||
overworldnpc.c
|
||||
overworldplayer.c
|
||||
overworldscene.c
|
||||
)
|
||||
|
||||
@@ -14,7 +14,14 @@
|
||||
|
||||
#define OVERWORLD_GROUND_SIZE 20.0f
|
||||
|
||||
static errorret_t overworldGroundDraw(void) {
|
||||
static errorret_t overworldGroundDraw(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
void *user
|
||||
) {
|
||||
(void)entityId;
|
||||
(void)componentId;
|
||||
(void)user;
|
||||
errorChain(shaderSetColor(&SHADER_UNLIT, SHADER_UNLIT_COLOR, COLOR_MAGENTA));
|
||||
errorChain(shaderSetTexture(&SHADER_UNLIT, SHADER_UNLIT_TEXTURE, NULL));
|
||||
return meshDraw(&PLANE_MESH_SIMPLE, 0, -1);
|
||||
@@ -33,7 +40,7 @@ void overworldGroundAdd(overworldground_t *ground) {
|
||||
vec3 scale = { OVERWORLD_GROUND_SIZE * 2.0f, 1.0f, OVERWORLD_GROUND_SIZE * 2.0f };
|
||||
entityPositionSetLocalPosition(ground->entityId, ground->posCompId, pos);
|
||||
entityPositionSetLocalScale(ground->entityId, ground->posCompId, scale);
|
||||
entityRenderableSetDraw(ground->entityId, renderComp, overworldGroundDraw);
|
||||
entityRenderableSetDraw(ground->entityId, renderComp, overworldGroundDraw, NULL);
|
||||
|
||||
// Separate physics entity centered on the finite ground area.
|
||||
// The visual entity's position is its corner {-size, 0, -size}, not its
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "overworldnpc.h"
|
||||
#include "entity/entitymanager.h"
|
||||
#include "entity/component/physics/entityphysics.h"
|
||||
#include "entity/component/trigger/entitytrigger.h"
|
||||
#include "entity/component/overworld/entityoverworld.h"
|
||||
#include "entity/component/overworld/entityinteractable.h"
|
||||
|
||||
void overworldNpcAdd(overworldnpc_t *npc, vec3 position) {
|
||||
npc->entityId = entityManagerAdd();
|
||||
npc->posCompId = entityAddComponent(npc->entityId, COMPONENT_TYPE_POSITION);
|
||||
(void)entityAddComponent(npc->entityId, COMPONENT_TYPE_RENDERABLE);
|
||||
(void)entityAddComponent(npc->entityId, COMPONENT_TYPE_PHYSICS);
|
||||
npc->overworldCompId = entityAddComponent(npc->entityId, COMPONENT_TYPE_OVERWORLD);
|
||||
npc->triggerCompId = entityAddComponent(npc->entityId, COMPONENT_TYPE_TRIGGER);
|
||||
npc->interactableCompId = entityAddComponent(
|
||||
npc->entityId, COMPONENT_TYPE_INTERACTABLE
|
||||
);
|
||||
|
||||
entityPositionSetLocalPosition(npc->entityId, npc->posCompId, position);
|
||||
|
||||
componentid_t physCompId = entityOverworldGet(npc->entityId, npc->overworldCompId)->physCompId;
|
||||
entityPhysicsSetBodyType(npc->entityId, physCompId, PHYSICS_BODY_STATIC);
|
||||
physicsshape_t shape = {
|
||||
.type = PHYSICS_SHAPE_CAPSULE,
|
||||
.data.capsule = { .radius = 0.4f, .halfHeight = 0.1f }
|
||||
};
|
||||
entityPhysicsSetShape(npc->entityId, physCompId, shape);
|
||||
|
||||
vec3 min = {
|
||||
position[0] - OVERWORLD_NPC_INTERACT_RANGE,
|
||||
position[1] - OVERWORLD_NPC_INTERACT_RANGE,
|
||||
position[2] - OVERWORLD_NPC_INTERACT_RANGE
|
||||
};
|
||||
vec3 max = {
|
||||
position[0] + OVERWORLD_NPC_INTERACT_RANGE,
|
||||
position[1] + OVERWORLD_NPC_INTERACT_RANGE,
|
||||
position[2] + OVERWORLD_NPC_INTERACT_RANGE
|
||||
};
|
||||
entityTriggerSetBounds(npc->entityId, npc->triggerCompId, min, max);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "entity/entitybase.h"
|
||||
|
||||
#define OVERWORLD_NPC_INTERACT_RANGE 1.5f
|
||||
|
||||
typedef struct {
|
||||
entityid_t entityId;
|
||||
componentid_t posCompId;
|
||||
componentid_t overworldCompId;
|
||||
componentid_t triggerCompId;
|
||||
componentid_t interactableCompId;
|
||||
} overworldnpc_t;
|
||||
|
||||
/**
|
||||
* Creates the NPC entity at the given world position.
|
||||
*
|
||||
* @param npc The NPC state to initialize.
|
||||
* @param position World-space position to spawn the NPC at.
|
||||
*/
|
||||
void overworldNpcAdd(overworldnpc_t *npc, vec3 position);
|
||||
@@ -8,43 +8,31 @@
|
||||
#include "overworldplayer.h"
|
||||
#include "entity/entitymanager.h"
|
||||
#include "entity/component/physics/entityphysics.h"
|
||||
#include "input/input.h"
|
||||
|
||||
#define OVERWORLD_PLAYER_SPEED 4.0f
|
||||
#define OVERWORLD_PLAYER_RUN_SPEED 8.0f
|
||||
#include "entity/component/overworld/entityoverworld.h"
|
||||
#include "entity/component/overworld/entityplayer.h"
|
||||
|
||||
void overworldPlayerAdd(overworldplayer_t *player) {
|
||||
player->entityId = entityManagerAdd();
|
||||
player->posCompId = entityAddComponent(player->entityId, COMPONENT_TYPE_POSITION);
|
||||
(void)entityAddComponent(player->entityId, COMPONENT_TYPE_RENDERABLE);
|
||||
player->physCompId = entityAddComponent(player->entityId, COMPONENT_TYPE_PHYSICS);
|
||||
(void)entityAddComponent(player->entityId, COMPONENT_TYPE_PHYSICS);
|
||||
componentid_t owCompId = entityAddComponent(player->entityId, COMPONENT_TYPE_OVERWORLD);
|
||||
entityOverworldSetType(player->entityId, owCompId, OVERWORLD_ENTITY_TYPE_PLAYER);
|
||||
player->playerCompId = entityAddComponent(player->entityId, COMPONENT_TYPE_PLAYER);
|
||||
|
||||
vec3 pos = { 0.0f, 0.5f, 0.0f };
|
||||
entityPositionSetLocalPosition(player->entityId, player->posCompId, pos);
|
||||
|
||||
entityPhysicsSetBodyType(player->entityId, player->physCompId, PHYSICS_BODY_DYNAMIC);
|
||||
componentid_t physCompId = entityOverworldGet(player->entityId, owCompId)->physCompId;
|
||||
entityPhysicsSetBodyType(player->entityId, physCompId, PHYSICS_BODY_DYNAMIC);
|
||||
physicsshape_t shape = {
|
||||
.type = PHYSICS_SHAPE_CAPSULE,
|
||||
.data.capsule = { .radius = 0.4f, .halfHeight = 0.1f }
|
||||
};
|
||||
entityPhysicsSetShape(player->entityId, player->physCompId, shape);
|
||||
entityPhysicsSetShape(player->entityId, physCompId, shape);
|
||||
entityPhysicsGet(player->entityId, physCompId)->gravityScale = 1.0f;
|
||||
}
|
||||
|
||||
void overworldPlayerUpdate(overworldplayer_t *player) {
|
||||
vec2 dir;
|
||||
inputAngle2D(
|
||||
INPUT_ACTION_LEFT, INPUT_ACTION_RIGHT,
|
||||
INPUT_ACTION_UP, INPUT_ACTION_DOWN,
|
||||
dir
|
||||
);
|
||||
|
||||
float_t speed = inputIsDown(INPUT_ACTION_CANCEL)
|
||||
? OVERWORLD_PLAYER_RUN_SPEED
|
||||
: OVERWORLD_PLAYER_SPEED;
|
||||
|
||||
vec3 vel;
|
||||
entityPhysicsGetVelocity(player->entityId, player->physCompId, vel);
|
||||
vel[0] = dir[0] * speed;
|
||||
vel[2] = dir[1] * speed;
|
||||
entityPhysicsSetVelocity(player->entityId, player->physCompId, vel);
|
||||
entityPlayerUpdate(player->entityId, player->playerCompId);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
typedef struct {
|
||||
entityid_t entityId;
|
||||
componentid_t posCompId;
|
||||
componentid_t physCompId;
|
||||
componentid_t playerCompId;
|
||||
} overworldplayer_t;
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,60 +8,60 @@
|
||||
#include "overworldscene.h"
|
||||
#include "overworldplayer.h"
|
||||
#include "overworldground.h"
|
||||
#include "overworldnpc.h"
|
||||
#include "console/console.h"
|
||||
#include "entity/entitymanager.h"
|
||||
#include "entity/component/physics/entityphysics.h"
|
||||
#include "entity/component/overworld/entityinteractable.h"
|
||||
#include "entity/component/overworld/entityoverworldcamera.h"
|
||||
#include "scene/scene.h"
|
||||
|
||||
#define OVERWORLD (SCENE.data.overworld)
|
||||
|
||||
static void overworldSceneNpcInteract(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
void *user
|
||||
) {
|
||||
(void)entityId; (void)componentId; (void)user;
|
||||
consolePrint("NPC interacted with!");
|
||||
}
|
||||
|
||||
void overworldSceneInit(void) {
|
||||
consolePrint("Overworld scene initialized");
|
||||
|
||||
OVERWORLD.cameraEntityId = entityManagerAdd();
|
||||
OVERWORLD.cameraPosCompId = entityAddComponent(
|
||||
OVERWORLD.cameraEntityId, COMPONENT_TYPE_POSITION
|
||||
);
|
||||
OVERWORLD.cameraCamCompId = entityAddComponent(
|
||||
OVERWORLD.cameraEntityId, COMPONENT_TYPE_CAMERA
|
||||
);
|
||||
|
||||
overworldGroundAdd(&OVERWORLD.ground);
|
||||
overworldPlayerAdd(&OVERWORLD.player);
|
||||
|
||||
OVERWORLD.refCubeEntityId = entityManagerAdd();
|
||||
componentid_t refPosComp = entityAddComponent(
|
||||
OVERWORLD.refCubeEntityId, COMPONENT_TYPE_POSITION
|
||||
);
|
||||
(void)entityAddComponent(OVERWORLD.refCubeEntityId, COMPONENT_TYPE_RENDERABLE);
|
||||
vec3 refPos = { 3.0f, 0.5f, 3.0f };
|
||||
entityPositionSetLocalPosition(OVERWORLD.refCubeEntityId, refPosComp, refPos);
|
||||
vec3 npcPos = { 3.0f, 0.5f, 3.0f };
|
||||
overworldNpcAdd(&OVERWORLD.npc, npcPos);
|
||||
|
||||
componentid_t refPhysComp = entityAddComponent(
|
||||
OVERWORLD.refCubeEntityId, COMPONENT_TYPE_PHYSICS
|
||||
OVERWORLD.cameraEntityId = entityManagerAdd();
|
||||
(void)entityAddComponent(OVERWORLD.cameraEntityId, COMPONENT_TYPE_POSITION);
|
||||
(void)entityAddComponent(OVERWORLD.cameraEntityId, COMPONENT_TYPE_CAMERA);
|
||||
OVERWORLD.cameraOverworldCompId = entityAddComponent(
|
||||
OVERWORLD.cameraEntityId, COMPONENT_TYPE_OVERWORLD_CAMERA
|
||||
);
|
||||
entityOverworldCameraSetTarget(
|
||||
OVERWORLD.cameraEntityId, OVERWORLD.cameraOverworldCompId,
|
||||
OVERWORLD.player.entityId, OVERWORLD.player.posCompId
|
||||
);
|
||||
entityoverworldcamera_t *camData = entityOverworldCameraGet(
|
||||
OVERWORLD.cameraEntityId, OVERWORLD.cameraOverworldCompId
|
||||
);
|
||||
glm_vec3_copy((vec3){ 0.5f, 0.5f, 0.5f }, camData->targetOffset);
|
||||
glm_vec3_copy((vec3){ 0.0f, 0.0f, 5.0f }, camData->eyeOffset);
|
||||
camData->scale = 32.0f;
|
||||
entityInteractableSetCallback(
|
||||
OVERWORLD.npc.entityId, OVERWORLD.npc.interactableCompId,
|
||||
overworldSceneNpcInteract, NULL
|
||||
);
|
||||
entityPhysicsSetBodyType(OVERWORLD.refCubeEntityId, refPhysComp, PHYSICS_BODY_STATIC);
|
||||
physicsshape_t refShape = {
|
||||
.type = PHYSICS_SHAPE_CAPSULE,
|
||||
.data.capsule = { .radius = 0.4f, .halfHeight = 0.1f }
|
||||
};
|
||||
entityPhysicsSetShape(OVERWORLD.refCubeEntityId, refPhysComp, refShape);
|
||||
}
|
||||
|
||||
errorret_t overworldSceneUpdate(void) {
|
||||
overworldPlayerUpdate(&OVERWORLD.player);
|
||||
|
||||
vec3 pos;
|
||||
entityPositionGetLocalPosition(
|
||||
OVERWORLD.player.entityId, OVERWORLD.player.posCompId, pos
|
||||
);
|
||||
vec3 center = { pos[0] + 0.5f, pos[1] + 0.5f, pos[2] + 0.5f };
|
||||
vec3 eyeOffset = { 0.0f, 0.0f, 5.0f };
|
||||
entityCameraLookAtPixelPerfect(
|
||||
OVERWORLD.cameraEntityId,
|
||||
OVERWORLD.cameraPosCompId,
|
||||
OVERWORLD.cameraCamCompId,
|
||||
center, eyeOffset, 32.0f
|
||||
entityOverworldCameraUpdate(
|
||||
OVERWORLD.cameraEntityId, OVERWORLD.cameraOverworldCompId
|
||||
);
|
||||
|
||||
errorOk();
|
||||
@@ -69,12 +69,15 @@ errorret_t overworldSceneUpdate(void) {
|
||||
|
||||
void overworldSceneDispose(void) {
|
||||
OVERWORLD.cameraEntityId = ENTITY_ID_INVALID;
|
||||
OVERWORLD.cameraPosCompId = COMPONENT_ID_INVALID;
|
||||
OVERWORLD.cameraCamCompId = COMPONENT_ID_INVALID;
|
||||
OVERWORLD.cameraOverworldCompId = COMPONENT_ID_INVALID;
|
||||
OVERWORLD.ground.entityId = ENTITY_ID_INVALID;
|
||||
OVERWORLD.ground.posCompId = COMPONENT_ID_INVALID;
|
||||
OVERWORLD.ground.floorEntityId = ENTITY_ID_INVALID;
|
||||
OVERWORLD.player.entityId = ENTITY_ID_INVALID;
|
||||
OVERWORLD.player.posCompId = COMPONENT_ID_INVALID;
|
||||
OVERWORLD.refCubeEntityId = ENTITY_ID_INVALID;
|
||||
OVERWORLD.npc.entityId = ENTITY_ID_INVALID;
|
||||
OVERWORLD.npc.posCompId = COMPONENT_ID_INVALID;
|
||||
OVERWORLD.npc.overworldCompId = COMPONENT_ID_INVALID;
|
||||
OVERWORLD.npc.triggerCompId = COMPONENT_ID_INVALID;
|
||||
OVERWORLD.npc.interactableCompId = COMPONENT_ID_INVALID;
|
||||
}
|
||||
|
||||
@@ -10,14 +10,14 @@
|
||||
#include "entity/entitybase.h"
|
||||
#include "scene/overworld/overworldplayer.h"
|
||||
#include "scene/overworld/overworldground.h"
|
||||
#include "scene/overworld/overworldnpc.h"
|
||||
|
||||
typedef struct {
|
||||
entityid_t cameraEntityId;
|
||||
componentid_t cameraPosCompId;
|
||||
componentid_t cameraCamCompId;
|
||||
componentid_t cameraOverworldCompId;
|
||||
overworldplayer_t player;
|
||||
overworldground_t ground;
|
||||
entityid_t refCubeEntityId;
|
||||
overworldnpc_t npc;
|
||||
} overworldscene_t;
|
||||
|
||||
void overworldSceneInit(void);
|
||||
|
||||
Reference in New Issue
Block a user