Scene prefabs
This commit is contained in:
@@ -11,10 +11,13 @@
|
||||
#include "entity/component/display/entitycamera.h"
|
||||
#include "entity/component/display/entityposition.h"
|
||||
#include "input/input.h"
|
||||
#include "time/time.h"
|
||||
#include "util/memory.h"
|
||||
#include "util/math.h"
|
||||
|
||||
#define ENTITY_PLAYER_MOVE_SPEED_DEFAULT 4.0f
|
||||
#define ENTITY_PLAYER_JUMP_IMPULSE_DEFAULT 6.0f
|
||||
#define ENTITY_PLAYER_TURN_SPEED_DEFAULT 10.0f
|
||||
|
||||
// Below this squared magnitude, movement input is treated as "not moving"
|
||||
// and the player keeps facing whichever way it last faced, rather than
|
||||
@@ -32,6 +35,7 @@ void entityPlayerInit(
|
||||
|
||||
player->moveSpeed = ENTITY_PLAYER_MOVE_SPEED_DEFAULT;
|
||||
player->jumpImpulse = ENTITY_PLAYER_JUMP_IMPULSE_DEFAULT;
|
||||
player->turnSpeed = ENTITY_PLAYER_TURN_SPEED_DEFAULT;
|
||||
|
||||
entityUpdateAdd(mgr, entityId, entityPlayerUpdate, componentId, NULL);
|
||||
}
|
||||
@@ -109,7 +113,16 @@ void entityPlayerUpdate(
|
||||
// faces the opposite way), which for a pure yaw rotation works out to
|
||||
// (sin(yaw), 0, cos(yaw)) -- invert that to solve for the yaw facing
|
||||
// moveDir.
|
||||
rotation[1] = atan2f(moveDir[0], moveDir[1]);
|
||||
float_t targetYaw = atan2f(moveDir[0], moveDir[1]);
|
||||
|
||||
// Turn towards targetYaw at turnSpeed rad/s instead of snapping to it:
|
||||
// wrap the shortest signed delta into [-PI, PI), then clamp the step.
|
||||
float_t yawDelta = mathModFloat(
|
||||
targetYaw - rotation[1] + (float_t)MATH_PI, 2.0f * (float_t)MATH_PI
|
||||
) - (float_t)MATH_PI;
|
||||
float_t maxStep = player->turnSpeed * TIME.delta;
|
||||
rotation[1] += mathClamp(yawDelta, -maxStep, maxStep);
|
||||
|
||||
entityPositionSetLocalRotation(mgr, entityId, posComp, rotation);
|
||||
}
|
||||
|
||||
@@ -124,6 +137,7 @@ errorret_t entityPlayerSerialize(
|
||||
|
||||
yyjson_mut_obj_add_real(doc, json, "moveSpeed", player->moveSpeed);
|
||||
yyjson_mut_obj_add_real(doc, json, "jumpImpulse", player->jumpImpulse);
|
||||
yyjson_mut_obj_add_real(doc, json, "turnSpeed", player->turnSpeed);
|
||||
|
||||
errorOk();
|
||||
}
|
||||
@@ -143,6 +157,9 @@ errorret_t entityPlayerDeserialize(
|
||||
if((v = yyjson_obj_get(json, "jumpImpulse"))) {
|
||||
player->jumpImpulse = (float_t)yyjson_get_num(v);
|
||||
}
|
||||
if((v = yyjson_obj_get(json, "turnSpeed"))) {
|
||||
player->turnSpeed = (float_t)yyjson_get_num(v);
|
||||
}
|
||||
|
||||
errorOk();
|
||||
}
|
||||
|
||||
@@ -13,11 +13,14 @@
|
||||
typedef struct {
|
||||
float_t moveSpeed;
|
||||
float_t jumpImpulse;
|
||||
|
||||
/** Yaw turn rate, in radians/second, when facing the movement direction. */
|
||||
float_t turnSpeed;
|
||||
} entityplayer_t;
|
||||
|
||||
/**
|
||||
* Initializes the player component: sets default move speed and jump
|
||||
* impulse.
|
||||
* Initializes the player component: sets default move speed, jump
|
||||
* impulse, and turn speed.
|
||||
*
|
||||
* @param mgr The entity manager that owns the entity.
|
||||
* @param entityId The entity ID.
|
||||
@@ -53,7 +56,8 @@ entityplayer_t *entityPlayerGet(
|
||||
* axes. No-op if the entity has no physics component.
|
||||
*
|
||||
* Also yaws the entity's position component (if any) to face the
|
||||
* direction of movement. Facing is only updated while there's actual
|
||||
* direction of movement, turning at most turnSpeed radians/second rather
|
||||
* than snapping instantly. Facing is only updated while there's actual
|
||||
* movement input -- releasing input leaves the entity facing whichever
|
||||
* way it last moved, rather than snapping to a default orientation.
|
||||
*
|
||||
@@ -72,8 +76,8 @@ void entityPlayerUpdate(
|
||||
);
|
||||
|
||||
/**
|
||||
* Serializes the player's "moveSpeed" and "jumpImpulse" into the given
|
||||
* JSON object.
|
||||
* Serializes the player's "moveSpeed", "jumpImpulse", and "turnSpeed"
|
||||
* into the given JSON object.
|
||||
*
|
||||
* @param mgr The entity manager that owns the entity.
|
||||
* @param entityId The entity ID.
|
||||
@@ -91,9 +95,9 @@ errorret_t entityPlayerSerialize(
|
||||
);
|
||||
|
||||
/**
|
||||
* Reads "moveSpeed" and "jumpImpulse" (see entityPlayerSerialize()) from
|
||||
* the given JSON object and applies whichever are present, leaving the
|
||||
* rest at their current values.
|
||||
* Reads "moveSpeed", "jumpImpulse", and "turnSpeed" (see
|
||||
* entityPlayerSerialize()) from the given JSON object and applies
|
||||
* whichever are present, leaving the rest at their current values.
|
||||
*
|
||||
* @param mgr The entity manager that owns the entity.
|
||||
* @param entityId The entity ID.
|
||||
|
||||
@@ -8,9 +8,11 @@
|
||||
// Game-specific prefabs, appended after the engine's inbuilt prefabs in
|
||||
// entity/entityprefablist.h.
|
||||
#include "entity/prefab/entityprefabplayer.h"
|
||||
#include "entity/prefab/entityprefaboverworldcamera.h"
|
||||
|
||||
// Name (Uppercase)
|
||||
// Extends (name of another prefab to apply first, or "" for none)
|
||||
// Apply function
|
||||
|
||||
X(PLAYER, "", entityPrefabPlayerApply)
|
||||
X(OVERWORLD_CAMERA, "", entityPrefabOverworldCameraApply)
|
||||
|
||||
@@ -6,4 +6,5 @@
|
||||
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||
PUBLIC
|
||||
entityprefabplayer.c
|
||||
entityprefaboverworldcamera.c
|
||||
)
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "entityprefaboverworldcamera.h"
|
||||
#include "entity/entitymanager.h"
|
||||
#include "entity/component/display/entityposition.h"
|
||||
#include "entity/component/display/entitycamera.h"
|
||||
|
||||
errorret_t entityPrefabOverworldCameraApply(
|
||||
entitymanager_t *mgr,
|
||||
const entityid_t entityId
|
||||
) {
|
||||
componentid_t posComp = entityAddComponent(
|
||||
mgr, entityId, COMPONENT_TYPE_POSITION
|
||||
);
|
||||
vec3 eye = { 10.0f, 10.0f, 10.0f };
|
||||
vec3 target = { 0.0f, 0.0f, 0.0f };
|
||||
vec3 up = { 0.0f, 1.0f, 0.0f };
|
||||
entityPositionLookAt(mgr, entityId, posComp, eye, target, up);
|
||||
|
||||
componentid_t camComp = entityAddComponent(
|
||||
mgr, entityId, COMPONENT_TYPE_CAMERA
|
||||
);
|
||||
entitycamera_t *cam = componentGetData(
|
||||
mgr, entityId, camComp, COMPONENT_TYPE_CAMERA
|
||||
);
|
||||
cam->projType = ENTITY_CAMERA_PROJECTION_TYPE_PERSPECTIVE;
|
||||
cam->nearClip = 0.1f;
|
||||
cam->farClip = 1000.0f;
|
||||
cam->perspective.fov = 0.9f;
|
||||
|
||||
errorOk();
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "entity/entitybase.h"
|
||||
#include "error/error.h"
|
||||
|
||||
/**
|
||||
* Applies the OVERWORLD_CAMERA prefab: a POSITION at (10, 10, 10) looking
|
||||
* at the world origin, and a perspective CAMERA (0.1/1000 near/far clip,
|
||||
* 0.9 fov). C-coded equivalent of the hand-authored "camera" entity
|
||||
* previously in assets/scenes/test.json.
|
||||
*
|
||||
* @param mgr The entity manager that owns the entity.
|
||||
* @param entityId The ID of the entity to apply the prefab to.
|
||||
* @return Error state.
|
||||
*/
|
||||
errorret_t entityPrefabOverworldCameraApply(
|
||||
entitymanager_t *mgr,
|
||||
const entityid_t entityId
|
||||
);
|
||||
@@ -7,3 +7,5 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||
PUBLIC
|
||||
overworldscene.c
|
||||
)
|
||||
|
||||
add_subdirectory(prefab)
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
// Game-specific scene prefabs, appended after the engine's inbuilt scene
|
||||
// prefabs in scene/sceneprefablist.h.
|
||||
#include "scene/prefab/sceneprefaboverworldscene.h"
|
||||
|
||||
// Name (Uppercase)
|
||||
// Extends (name of another prefab to apply first, or "" for none)
|
||||
// Apply function
|
||||
|
||||
X(OVERWORLDSCENE, "", scenePrefabOverworldSceneApply)
|
||||
@@ -0,0 +1,9 @@
|
||||
# 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
|
||||
sceneprefaboverworldscene.c
|
||||
)
|
||||
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "sceneprefaboverworldscene.h"
|
||||
#include "scene/scene.h"
|
||||
#include "entity/entityprefab.h"
|
||||
|
||||
errorret_t scenePrefabOverworldSceneApply(const sceneid_t sceneId) {
|
||||
entitymanager_t *mgr = sceneGetEntities(sceneId);
|
||||
|
||||
entityid_t cameraEntity = entityManagerAdd(mgr);
|
||||
entitySetName(mgr, cameraEntity, "camera");
|
||||
errorChain(
|
||||
entityPrefabResolveAndApply(mgr, cameraEntity, "OVERWORLD_CAMERA")
|
||||
);
|
||||
|
||||
entityid_t playerEntity = entityManagerAdd(mgr);
|
||||
entitySetName(mgr, playerEntity, "player");
|
||||
errorChain(entityPrefabResolveAndApply(mgr, playerEntity, "PLAYER"));
|
||||
|
||||
errorOk();
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "scene/scenebase.h"
|
||||
#include "error/error.h"
|
||||
|
||||
/**
|
||||
* Applies the OVERWORLDSCENE prefab: spawns a "camera" entity (see
|
||||
* entityPrefabOverworldCameraApply()) and a "player" entity (see
|
||||
* entityPrefabPlayerApply()) into the scene.
|
||||
*
|
||||
* @param sceneId The ID of the scene to apply the prefab to.
|
||||
* @return Error state.
|
||||
*/
|
||||
errorret_t scenePrefabOverworldSceneApply(const sceneid_t sceneId);
|
||||
Reference in New Issue
Block a user