test
This commit is contained in:
@@ -9,12 +9,18 @@
|
||||
#include "entity/entitymanager.h"
|
||||
#include "entity/component/physics/entityphysics.h"
|
||||
#include "entity/component/display/entitycamera.h"
|
||||
#include "entity/component/display/entityposition.h"
|
||||
#include "input/input.h"
|
||||
#include "util/memory.h"
|
||||
|
||||
#define ENTITY_PLAYER_MOVE_SPEED_DEFAULT 4.0f
|
||||
#define ENTITY_PLAYER_JUMP_IMPULSE_DEFAULT 6.0f
|
||||
|
||||
// Below this squared magnitude, movement input is treated as "not moving"
|
||||
// and the player keeps facing whichever way it last faced, rather than
|
||||
// snapping to some default orientation.
|
||||
#define ENTITY_PLAYER_MOVE_ROTATE_THRESHOLD_SQ 0.0001f
|
||||
|
||||
void entityPlayerInit(
|
||||
entitymanager_t *mgr,
|
||||
const entityid_t entityId,
|
||||
@@ -85,4 +91,58 @@ void entityPlayerUpdate(
|
||||
velocity[0] = moveDir[0] * player->moveSpeed;
|
||||
velocity[2] = moveDir[1] * player->moveSpeed;
|
||||
entityPhysicsSetVelocity(mgr, entityId, physComp, velocity);
|
||||
|
||||
// Face the direction of movement. Only updated while actually moving --
|
||||
// releasing input leaves the player facing whichever way it last moved.
|
||||
float_t moveDirMagSq = moveDir[0] * moveDir[0] + moveDir[1] * moveDir[1];
|
||||
if(moveDirMagSq < ENTITY_PLAYER_MOVE_ROTATE_THRESHOLD_SQ) return;
|
||||
|
||||
componentid_t posComp = entityGetComponent(
|
||||
mgr, entityId, COMPONENT_TYPE_POSITION
|
||||
);
|
||||
if(posComp == COMPONENT_ID_INVALID) return;
|
||||
|
||||
vec3 rotation;
|
||||
entityPositionGetLocalRotation(mgr, entityId, posComp, rotation);
|
||||
// The player's "front" is +local Z, not -Z (entityCameraGetForward's
|
||||
// convention is for cameras, which look down -Z -- the player model
|
||||
// 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]);
|
||||
entityPositionSetLocalRotation(mgr, entityId, posComp, rotation);
|
||||
}
|
||||
|
||||
errorret_t entityPlayerSerialize(
|
||||
entitymanager_t *mgr,
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *json
|
||||
) {
|
||||
entityplayer_t *player = entityPlayerGet(mgr, entityId, componentId);
|
||||
|
||||
yyjson_mut_obj_add_real(doc, json, "moveSpeed", player->moveSpeed);
|
||||
yyjson_mut_obj_add_real(doc, json, "jumpImpulse", player->jumpImpulse);
|
||||
|
||||
errorOk();
|
||||
}
|
||||
|
||||
errorret_t entityPlayerDeserialize(
|
||||
entitymanager_t *mgr,
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
yyjson_val *json
|
||||
) {
|
||||
entityplayer_t *player = entityPlayerGet(mgr, entityId, componentId);
|
||||
|
||||
yyjson_val *v;
|
||||
if((v = yyjson_obj_get(json, "moveSpeed"))) {
|
||||
player->moveSpeed = (float_t)yyjson_get_num(v);
|
||||
}
|
||||
if((v = yyjson_obj_get(json, "jumpImpulse"))) {
|
||||
player->jumpImpulse = (float_t)yyjson_get_num(v);
|
||||
}
|
||||
|
||||
errorOk();
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#pragma once
|
||||
#include "entity/entitybase.h"
|
||||
#include "error/error.h"
|
||||
#include "yyjson.h"
|
||||
|
||||
typedef struct {
|
||||
float_t moveSpeed;
|
||||
@@ -48,8 +50,14 @@ entityplayer_t *entityPlayerGet(
|
||||
* and drives the entity's physics velocity, relative to the current
|
||||
* camera's horizontal facing (so "up" always moves away from the camera
|
||||
* and "left"/"right" strafe relative to its view), rather than fixed world
|
||||
* axes. No-op if the entity has no physics component. Registered
|
||||
* automatically as an update callback by entityPlayerInit.
|
||||
* 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
|
||||
* movement input -- releasing input leaves the entity facing whichever
|
||||
* way it last moved, rather than snapping to a default orientation.
|
||||
*
|
||||
* Registered automatically as an update callback by entityPlayerInit.
|
||||
*
|
||||
* @param mgr The entity manager that owns the entity.
|
||||
* @param entityId The entity ID.
|
||||
@@ -62,3 +70,40 @@ void entityPlayerUpdate(
|
||||
const componentid_t componentId,
|
||||
void *user
|
||||
);
|
||||
|
||||
/**
|
||||
* Serializes the player's "moveSpeed" and "jumpImpulse" into the given
|
||||
* JSON object.
|
||||
*
|
||||
* @param mgr The entity manager that owns the entity.
|
||||
* @param entityId The entity ID.
|
||||
* @param componentId The component ID.
|
||||
* @param doc The mutable JSON document to allocate values from.
|
||||
* @param json The JSON object to write the component's fields into.
|
||||
* @return Error state.
|
||||
*/
|
||||
errorret_t entityPlayerSerialize(
|
||||
entitymanager_t *mgr,
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *json
|
||||
);
|
||||
|
||||
/**
|
||||
* Reads "moveSpeed" and "jumpImpulse" (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.
|
||||
* @param componentId The component ID.
|
||||
* @param json The JSON object to read the component's fields from.
|
||||
* @return Error state.
|
||||
*/
|
||||
errorret_t entityPlayerDeserialize(
|
||||
entitymanager_t *mgr,
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
yyjson_val *json
|
||||
);
|
||||
|
||||
@@ -15,5 +15,8 @@
|
||||
// Init function (optional)
|
||||
// Dispose function (optional)
|
||||
// Render function (optional)
|
||||
// Serialize function (optional)
|
||||
// Deserialize function (optional)
|
||||
|
||||
X(PLAYER, entityplayer_t, player, entityPlayerInit, NULL, NULL)
|
||||
X(PLAYER, entityplayer_t, player, entityPlayerInit, NULL, NULL,
|
||||
entityPlayerSerialize, entityPlayerDeserialize)
|
||||
|
||||
+25
-1
@@ -8,9 +8,33 @@
|
||||
#include "game/game.h"
|
||||
#include "scene/scene.h"
|
||||
#include "scene/overworldscene.h"
|
||||
#include "assert/assert.h"
|
||||
#include "asset/asset.h"
|
||||
#include "yyjson.h"
|
||||
|
||||
#define GAME_TEST_SCENE_ASSET "scenes/test.json"
|
||||
|
||||
errorret_t gameInit(void) {
|
||||
sceneSetActive(overworldSceneCreate());
|
||||
// overworldSceneCreate();
|
||||
|
||||
sceneid_t testSceneId = sceneCreate();
|
||||
|
||||
// Exercises sceneDeserialize() end-to-end: a camera looking at a
|
||||
// colored cube that falls under gravity onto a static ground plane,
|
||||
// described entirely as JSON rather than built with the entity API.
|
||||
assetentry_t *sceneEntry = assetLock(
|
||||
GAME_TEST_SCENE_ASSET, ASSET_LOADER_TYPE_JSON, NULL
|
||||
);
|
||||
errorret_t ret = assetRequireLoaded(sceneEntry);
|
||||
if(errorIsOk(ret)) {
|
||||
ret = sceneDeserialize(
|
||||
testSceneId, yyjson_doc_get_root(sceneEntry->data.json)
|
||||
);
|
||||
}
|
||||
assetUnlockEntry(sceneEntry);
|
||||
errorChain(ret);
|
||||
|
||||
sceneSetActive(testSceneId);
|
||||
errorOk();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user