Entity
This commit is contained in:
@@ -35,7 +35,6 @@ add_subdirectory(engine)
|
||||
add_subdirectory(error)
|
||||
add_subdirectory(input)
|
||||
# add_subdirectory(locale)
|
||||
add_subdirectory(physics)
|
||||
add_subdirectory(rpg)
|
||||
add_subdirectory(scene)
|
||||
add_subdirectory(thread)
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
target_sources(${DUSK_TARGET_NAME}
|
||||
PRIVATE
|
||||
entity.c
|
||||
entityanim.c
|
||||
npc.c
|
||||
player.c
|
||||
direction.c
|
||||
entitydir.c
|
||||
)
|
||||
@@ -1,48 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "direction.h"
|
||||
#include "assert/assert.h"
|
||||
|
||||
float_t directionToAngle(const direction_t dir) {
|
||||
switch(dir) {
|
||||
case DIRECTION_NORTH: return (M_PI_2);
|
||||
case DIRECTION_SOUTH: return -(M_PI_2);
|
||||
case DIRECTION_EAST: return 0;
|
||||
case DIRECTION_WEST: return (M_PI);
|
||||
default: return 0; // Should never happen
|
||||
}
|
||||
}
|
||||
|
||||
void directionGetVec2(const direction_t dir, vec2 out) {
|
||||
assertNotNull(out, "Output vector cannot be NULL");
|
||||
|
||||
switch(dir) {
|
||||
case DIRECTION_NORTH:
|
||||
out[0] = 0.0f;
|
||||
out[1] = 1.0f;
|
||||
break;
|
||||
|
||||
case DIRECTION_SOUTH:
|
||||
out[0] = 0.0f;
|
||||
out[1] = -1.0f;
|
||||
break;
|
||||
|
||||
case DIRECTION_EAST:
|
||||
out[0] = 1.0f;
|
||||
out[1] = 0.0f;
|
||||
break;
|
||||
|
||||
case DIRECTION_WEST:
|
||||
out[0] = -1.0f;
|
||||
out[1] = 0.0f;
|
||||
break;
|
||||
|
||||
default:
|
||||
assertUnreachable("Invalid direction");
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "dusk.h"
|
||||
|
||||
typedef enum {
|
||||
DIRECTION_SOUTH = 0,
|
||||
DIRECTION_EAST = 1,
|
||||
DIRECTION_WEST = 2,
|
||||
DIRECTION_NORTH = 3,
|
||||
|
||||
DIRECTION_UP = DIRECTION_NORTH,
|
||||
DIRECTION_DOWN = DIRECTION_SOUTH,
|
||||
DIRECTION_LEFT = DIRECTION_WEST,
|
||||
DIRECTION_RIGHT = DIRECTION_EAST,
|
||||
} direction_t;
|
||||
|
||||
/**
|
||||
* Converts a direction to an angle in float_t format.
|
||||
*
|
||||
* @param dir The direction to convert.
|
||||
* @return The angle corresponding to the direction.
|
||||
*/
|
||||
float_t directionToAngle(const direction_t dir);
|
||||
|
||||
/**
|
||||
* Converts a direction to a vec2 unit vector.
|
||||
*
|
||||
* @param dir The direction to convert.
|
||||
* @param out Pointer to the vec2 array to populate.
|
||||
*/
|
||||
void directionGetVec2(const direction_t dir, vec2 out);
|
||||
@@ -46,8 +46,66 @@ void entityUpdate(entity_t *entity) {
|
||||
assertTrue(entity->type < ENTITY_TYPE_COUNT, "Invalid entity type");
|
||||
assertTrue(entity->type != ENTITY_TYPE_NULL, "Cannot have NULL entity type");
|
||||
|
||||
// What state is the entity in?
|
||||
if(entity->animation != ENTITY_ANIM_IDLE) {
|
||||
// Entity is mid animation, tick it (down).
|
||||
entity->animFrame--;
|
||||
if(entity->animFrame == 0) entity->animation = ENTITY_ANIM_IDLE;
|
||||
return;
|
||||
}
|
||||
|
||||
// Movement code.
|
||||
if(entity->type == ENTITY_TYPE_PLAYER) {
|
||||
playerMovement(entity);
|
||||
}
|
||||
}
|
||||
|
||||
void entityTurn(entity_t *entity, const entitydir_t direction) {
|
||||
entity->direction = direction;
|
||||
entity->animation = ENTITY_ANIM_TURN;
|
||||
entity->animFrame = ENTITY_ANIM_TURN_DURATION;
|
||||
}
|
||||
|
||||
|
||||
void entityWalk(entity_t *entity, const entitydir_t direction) {
|
||||
// TODO: Animation, delay, etc.
|
||||
entity->direction = direction;
|
||||
|
||||
// Where are we moving?
|
||||
uint8_t newX, newY;
|
||||
newX = entity->position.x;
|
||||
newY = entity->position.y;
|
||||
{
|
||||
int8_t relX, relY;
|
||||
entityDirGetRelative(direction, &relX, &relY);
|
||||
newX += relX;
|
||||
newY += relY;
|
||||
}
|
||||
|
||||
// TODO: Tile in way?
|
||||
// TODO: Map bounds in way?
|
||||
|
||||
// Entity in way?
|
||||
// entity_t *start = GAME.overworld.map.entities;
|
||||
// entity_t *end = start + MAP_ENTITY_COUNT;
|
||||
// while(start < end) {
|
||||
// if(
|
||||
// start == entity ||
|
||||
// entity->type == ENTITY_TYPE_NULL ||
|
||||
// start->position.x != newX ||
|
||||
// start->position.y != newY
|
||||
// ) {
|
||||
// start++;
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// return;// Blocked
|
||||
// }
|
||||
|
||||
// Move.
|
||||
entity->position.x = newX;
|
||||
entity->position.y = newY;
|
||||
|
||||
entity->animation = ENTITY_ANIM_WALK;
|
||||
entity->animFrame = ENTITY_ANIM_WALK_DURATION;// TODO: Running vs walking
|
||||
}
|
||||
@@ -6,9 +6,11 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "direction.h"
|
||||
#include "entitydir.h"
|
||||
#include "entityanim.h"
|
||||
#include "rpg/entity/player.h"
|
||||
#include "npc.h"
|
||||
#include "rpg/world/worldpos.h"
|
||||
|
||||
#define ENTITY_COUNT 256
|
||||
|
||||
@@ -18,15 +20,19 @@ typedef enum {
|
||||
ENTITY_TYPE_NULL,
|
||||
ENTITY_TYPE_PLAYER,
|
||||
ENTITY_TYPE_NPC,
|
||||
|
||||
ENTITY_TYPE_COUNT
|
||||
} entitytype_t;
|
||||
|
||||
typedef struct entity_s {
|
||||
uint8_t id;
|
||||
entitytype_t type;
|
||||
direction_t direction;
|
||||
uint32_t position;// Tile index
|
||||
|
||||
// Movement
|
||||
entitydir_t direction;
|
||||
worldpos_t position;
|
||||
|
||||
entityanim_t animation;
|
||||
uint8_t animFrame;
|
||||
|
||||
union {
|
||||
player_t player;
|
||||
@@ -50,3 +56,19 @@ void entityInit(entity_t *entity, const entitytype_t type);
|
||||
* @param entity Pointer to the entity structure to update.
|
||||
*/
|
||||
void entityUpdate(entity_t *entity);
|
||||
|
||||
/**
|
||||
* Turn an entity to face a new direction.
|
||||
*
|
||||
* @param entity Pointer to the entity to turn.
|
||||
* @param direction The direction to face.
|
||||
*/
|
||||
void entityTurn(entity_t *entity, const entitydir_t direction);
|
||||
|
||||
/**
|
||||
* Make an entity walk in a direction.
|
||||
*
|
||||
* @param entity Pointer to the entity to make walk.
|
||||
* @param direction The direction to walk in.
|
||||
*/
|
||||
void entityWalk(entity_t *entity, const entitydir_t direction);
|
||||
|
||||
9
src/rpg/entity/entityanim.c
Normal file
9
src/rpg/entity/entityanim.c
Normal file
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "entityanim.h"
|
||||
|
||||
18
src/rpg/entity/entityanim.h
Normal file
18
src/rpg/entity/entityanim.h
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "dusk.h"
|
||||
|
||||
#define ENTITY_ANIM_TURN_DURATION 1
|
||||
#define ENTITY_ANIM_WALK_DURATION 10
|
||||
|
||||
typedef enum {
|
||||
ENTITY_ANIM_IDLE,
|
||||
ENTITY_ANIM_TURN,
|
||||
ENTITY_ANIM_WALK,
|
||||
} entityanim_t;
|
||||
37
src/rpg/entity/entitydir.c
Normal file
37
src/rpg/entity/entitydir.c
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "entitydir.h"
|
||||
#include "assert/assert.h"
|
||||
|
||||
void entityDirGetRelative(const entitydir_t from, int8_t *outX, int8_t *outY) {
|
||||
assertValidEntityDir(from, "Invalid direction provided");
|
||||
assertNotNull(outX, "Output X pointer cannot be NULL");
|
||||
assertNotNull(outY, "Output Y pointer cannot be NULL");
|
||||
|
||||
switch(from) {
|
||||
case ENTITY_DIR_NORTH:
|
||||
*outX = 0;
|
||||
*outY = -1;
|
||||
break;
|
||||
|
||||
case ENTITY_DIR_EAST:
|
||||
*outX = 1;
|
||||
*outY = 0;
|
||||
break;
|
||||
|
||||
case ENTITY_DIR_SOUTH:
|
||||
*outX = 0;
|
||||
*outY = 1;
|
||||
break;
|
||||
|
||||
case ENTITY_DIR_WEST:
|
||||
*outX = -1;
|
||||
*outY = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
45
src/rpg/entity/entitydir.h
Normal file
45
src/rpg/entity/entitydir.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "dusk.h"
|
||||
|
||||
typedef enum {
|
||||
ENTITY_DIR_SOUTH = 0,
|
||||
ENTITY_DIR_EAST = 1,
|
||||
ENTITY_DIR_WEST = 2,
|
||||
ENTITY_DIR_NORTH = 3,
|
||||
|
||||
ENTITY_DIR_UP = ENTITY_DIR_NORTH,
|
||||
ENTITY_DIR_DOWN = ENTITY_DIR_SOUTH,
|
||||
ENTITY_DIR_LEFT = ENTITY_DIR_WEST,
|
||||
ENTITY_DIR_RIGHT = ENTITY_DIR_EAST,
|
||||
} entitydir_t;
|
||||
|
||||
/**
|
||||
* Asserts a given direction is valid.
|
||||
*
|
||||
* @param dir The direction to validate.
|
||||
* @param msg The message to display if the assertion fails.
|
||||
*/
|
||||
#define assertValidEntityDir(dir, msg) \
|
||||
assertTrue( \
|
||||
(dir) == ENTITY_DIR_NORTH || \
|
||||
(dir) == ENTITY_DIR_EAST || \
|
||||
(dir) == ENTITY_DIR_SOUTH || \
|
||||
(dir) == ENTITY_DIR_WEST, \
|
||||
msg \
|
||||
)
|
||||
|
||||
/**
|
||||
* Gets the relative x and y offsets for a given direction.
|
||||
*
|
||||
* @param dir The direction to get offsets for.
|
||||
* @param relX Pointer to store the relative x offset.
|
||||
* @param relY Pointer to store the relative y offset.
|
||||
*/
|
||||
void entityDirGetRelative(const entitydir_t dir, int8_t *relX, int8_t *relY);
|
||||
@@ -12,6 +12,20 @@
|
||||
#include "util/memory.h"
|
||||
#include "time/time.h"
|
||||
|
||||
typedef struct {
|
||||
inputaction_t action;
|
||||
entitydir_t direction;
|
||||
} playerinputdirmap_t;
|
||||
|
||||
static const playerinputdirmap_t PLAYER_INPUT_DIR_MAP[] = {
|
||||
{ INPUT_ACTION_UP, ENTITY_DIR_NORTH },
|
||||
{ INPUT_ACTION_DOWN, ENTITY_DIR_SOUTH },
|
||||
{ INPUT_ACTION_LEFT, ENTITY_DIR_WEST },
|
||||
{ INPUT_ACTION_RIGHT, ENTITY_DIR_EAST },
|
||||
|
||||
{ 0xFF, 0xFF }
|
||||
};
|
||||
|
||||
void playerInit(entity_t *entity) {
|
||||
assertNotNull(entity, "Entity pointer cannot be NULL");
|
||||
}
|
||||
@@ -19,47 +33,23 @@ void playerInit(entity_t *entity) {
|
||||
void playerMovement(entity_t *entity) {
|
||||
assertNotNull(entity, "Entity pointer cannot be NULL");
|
||||
|
||||
// Get movement angle as 0-> normalized vector.
|
||||
vec2 dir = {
|
||||
inputAxis(INPUT_ACTION_LEFT, INPUT_ACTION_RIGHT),
|
||||
inputAxis(INPUT_ACTION_UP, INPUT_ACTION_DOWN)
|
||||
};
|
||||
if(dir[0] == 0 && dir[1] == 0) return;
|
||||
glm_vec2_normalize(dir);
|
||||
// Turn
|
||||
const playerinputdirmap_t *dirMap = PLAYER_INPUT_DIR_MAP;
|
||||
do {
|
||||
if(!inputPressed(dirMap->action)) continue;
|
||||
if(entity->direction == dirMap->direction) continue;
|
||||
return entityTurn(entity, dirMap->direction);
|
||||
} while((++dirMap)->action != 0xFF);
|
||||
|
||||
entity->velocity[0] += PLAYER_SPEED * dir[0] * TIME.fixedDelta;
|
||||
entity->velocity[1] += PLAYER_SPEED * dir[1] * TIME.fixedDelta;
|
||||
// Walk
|
||||
dirMap = PLAYER_INPUT_DIR_MAP;
|
||||
do {
|
||||
if(!inputIsDown(dirMap->action)) continue;
|
||||
if(entity->direction != dirMap->direction) continue;
|
||||
return entityWalk(entity, dirMap->direction);
|
||||
} while((++dirMap)->action != 0xFF);
|
||||
|
||||
// Update direction.
|
||||
if(dir[0] > 0) {
|
||||
if(entity->direction == DIRECTION_RIGHT) {
|
||||
entity->direction = DIRECTION_RIGHT;
|
||||
} else {
|
||||
if(dir[1] < 0) {
|
||||
entity->direction = DIRECTION_UP;
|
||||
} else if(dir[1] > 0) {
|
||||
entity->direction = DIRECTION_DOWN;
|
||||
} else {
|
||||
entity->direction = DIRECTION_RIGHT;
|
||||
}
|
||||
}
|
||||
} else if(dir[0] < 0) {
|
||||
if(entity->direction == DIRECTION_LEFT) {
|
||||
entity->direction = DIRECTION_LEFT;
|
||||
} else {
|
||||
if(dir[1] < 0) {
|
||||
entity->direction = DIRECTION_UP;
|
||||
} else if(dir[1] > 0) {
|
||||
entity->direction = DIRECTION_DOWN;
|
||||
} else {
|
||||
entity->direction = DIRECTION_LEFT;
|
||||
}
|
||||
}
|
||||
} else if(dir[1] < 0) {
|
||||
entity->direction = DIRECTION_UP;
|
||||
} else if(dir[1] > 0) {
|
||||
entity->direction = DIRECTION_DOWN;
|
||||
}
|
||||
// Interaction
|
||||
}
|
||||
|
||||
void playerInteraction(entity_t *entity) {
|
||||
@@ -67,50 +57,4 @@ void playerInteraction(entity_t *entity) {
|
||||
|
||||
if(!inputPressed(INPUT_ACTION_ACCEPT)) return;
|
||||
|
||||
physicsbox_t interactBox;
|
||||
|
||||
// Get direction vector
|
||||
directionGetVec2(entity->direction, interactBox.min);
|
||||
|
||||
// Scale by interact range
|
||||
glm_vec2_scale(interactBox.min, PLAYER_INTERACTION_RANGE, interactBox.min);
|
||||
|
||||
// Add entity position, this makes the center of the box.
|
||||
glm_vec2_add(interactBox.min, entity->position, interactBox.min);
|
||||
|
||||
// Copy to max
|
||||
glm_vec2_copy(interactBox.min, interactBox.max);
|
||||
|
||||
// // Size of the hitbox
|
||||
// vec2 halfSize = {
|
||||
// 1 * PLAYER_INTERACTION_SIZE * 0.5f,
|
||||
// 1 * PLAYER_INTERACTION_SIZE * 0.5f
|
||||
// };
|
||||
|
||||
// // Subtract from min, add to max.
|
||||
// glm_vec2_sub(interactBox.min, halfSize, interactBox.min);
|
||||
// glm_vec2_add(interactBox.max, halfSize, interactBox.max);
|
||||
|
||||
// // For each entity
|
||||
// entity_t *start = ENTITIES;
|
||||
// entity_t *end = &ENTITIES[ENTITY_COUNT];
|
||||
// vec2 otherSize = { 1, 1 };
|
||||
// physicsbox_t otherBox;
|
||||
// physicsboxboxresult_t result;
|
||||
|
||||
// do {
|
||||
// if(start->type != ENTITY_TYPE_NPC) continue;
|
||||
|
||||
// // Setup other box.
|
||||
// glm_vec2_copy(start->position, otherBox.min);
|
||||
// glm_vec2_copy(start->position, otherBox.max);
|
||||
// glm_vec2_sub(otherBox.min, otherSize, otherBox.min);
|
||||
// glm_vec2_add(otherBox.min, otherSize, otherBox.max);
|
||||
|
||||
// physicsBoxCheckBox(interactBox, otherBox, &result);
|
||||
// if(!result.hit) continue;
|
||||
|
||||
// printf("Interacted with entity at (%.2f, %.2f)\n", start->position[0], start->position[1]);
|
||||
// break;
|
||||
// } while(++start != end);
|
||||
}
|
||||
@@ -27,11 +27,11 @@ errorret_t rpgInit(void) {
|
||||
entityInit(ent, ENTITY_TYPE_PLAYER);
|
||||
RPG_CAMERA.mode = RPG_CAMERA_MODE_FOLLOW_ENTITY;
|
||||
RPG_CAMERA.followEntity.followEntityId = ent->id;
|
||||
ent->position[0] = 4, ent->position[1] = 4;
|
||||
ent->position.x = 4, ent->position.y = 4;
|
||||
|
||||
ent = &ENTITIES[1];
|
||||
entityInit(ent, ENTITY_TYPE_NPC);
|
||||
ent->position[0] = 6, ent->position[1] = 6;
|
||||
ent->position.x = 6, ent->position.y = 6;
|
||||
|
||||
// All Good!
|
||||
errorOk();
|
||||
@@ -51,9 +51,6 @@ void rpgUpdate(void) {
|
||||
if(ent->type == ENTITY_TYPE_NULL) continue;
|
||||
entityUpdate(ent);
|
||||
} while(++ent < &ENTITIES[ENTITY_COUNT]);
|
||||
|
||||
// Update the camera.
|
||||
rpgCameraUpdate();
|
||||
}
|
||||
|
||||
void rpgDispose(void) {
|
||||
|
||||
@@ -14,19 +14,3 @@ rpgcamera_t RPG_CAMERA;
|
||||
void rpgCameraInit(void) {
|
||||
memoryZero(&RPG_CAMERA, sizeof(rpgcamera_t));
|
||||
}
|
||||
|
||||
void rpgCameraUpdate(void) {
|
||||
switch(RPG_CAMERA.mode) {
|
||||
case RPG_CAMERA_MODE_FOLLOW_ENTITY:
|
||||
if(RPG_CAMERA.followEntity.followEntityId >= ENTITY_COUNT) break;
|
||||
entity_t *ent = &ENTITIES[RPG_CAMERA.followEntity.followEntityId];
|
||||
if(ent->type == ENTITY_TYPE_NULL) break;
|
||||
memoryCopy(
|
||||
&RPG_CAMERA.position, ent->position, sizeof(RPG_CAMERA.position)
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "dusk.h"
|
||||
#include "rpg/world/worldpos.h"
|
||||
|
||||
typedef enum {
|
||||
RPG_CAMERA_MODE_FREE,
|
||||
@@ -14,10 +14,10 @@ typedef enum {
|
||||
} rpgcameramode_t;
|
||||
|
||||
typedef struct {
|
||||
vec3 position;
|
||||
rpgcameramode_t mode;
|
||||
|
||||
union {
|
||||
worldpos_t free;
|
||||
struct {
|
||||
uint8_t followEntityId;
|
||||
} followEntity;
|
||||
@@ -30,8 +30,3 @@ extern rpgcamera_t RPG_CAMERA;
|
||||
* Initializes the RPG camera.
|
||||
*/
|
||||
void rpgCameraInit(void);
|
||||
|
||||
/**
|
||||
* Updates the RPG camera.
|
||||
*/
|
||||
void rpgCameraUpdate(void);
|
||||
13
src/rpg/world/worldpos.h
Normal file
13
src/rpg/world/worldpos.h
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "dusk.h"
|
||||
|
||||
typedef struct worldpos_s {
|
||||
uint32_t x, y, z;
|
||||
} worldpos_t;
|
||||
@@ -40,18 +40,68 @@ void sceneMapUpdate(scenedata_t *data) {
|
||||
|
||||
}
|
||||
|
||||
void sceneMapGetWorldPosition(const worldpos_t pos, vec3 outPosition) {
|
||||
assertNotNull(outPosition, "Output position cannot be NULL");
|
||||
|
||||
outPosition[0] = pos.x * TILE_SIZE;
|
||||
outPosition[1] = pos.y * TILE_SIZE;
|
||||
outPosition[2] = pos.z * TILE_SIZE;
|
||||
}
|
||||
|
||||
void sceneMapEntityGetPosition(const entity_t *entity, vec3 outPosition) {
|
||||
assertNotNull(entity, "Entity cannot be NULL");
|
||||
assertNotNull(outPosition, "Output position cannot be NULL");
|
||||
|
||||
sceneMapGetWorldPosition(entity->position, outPosition);
|
||||
|
||||
// Add animation offset(s)
|
||||
switch(entity->animation) {
|
||||
case ENTITY_ANIM_WALK:
|
||||
float_t animPercentage = (
|
||||
(float_t)entity->animFrame / (float_t)ENTITY_ANIM_WALK_DURATION
|
||||
);
|
||||
|
||||
// Get facing rel, we know we moved from the inverse direction.
|
||||
int8_t x, y;
|
||||
entityDirGetRelative(entity->direction, &x, &y);
|
||||
x = -x, y = -y;
|
||||
|
||||
// Add tile size times percentage to posMin/max
|
||||
vec3 offset = {
|
||||
x * TILE_SIZE * animPercentage,
|
||||
y * TILE_SIZE * animPercentage,
|
||||
0.0f
|
||||
};
|
||||
glm_vec3_add(outPosition, offset, outPosition);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void sceneMapRender(scenedata_t *data) {
|
||||
// Look at target.
|
||||
glm_vec3_scale(
|
||||
RPG_CAMERA.position,
|
||||
TILE_SIZE,
|
||||
data->sceneMap.camera.lookatPixelPerfect.target
|
||||
);
|
||||
vec3 cameraTarget;
|
||||
switch(RPG_CAMERA.mode) {
|
||||
case RPG_CAMERA_MODE_FREE:
|
||||
sceneMapGetWorldPosition(RPG_CAMERA.free, cameraTarget);
|
||||
break;
|
||||
|
||||
// Center within tile
|
||||
glm_vec3_add(
|
||||
data->sceneMap.camera.lookatPixelPerfect.target,
|
||||
(vec3){TILE_SIZE / 2.0f, TILE_SIZE / 2.0f, TILE_SIZE / 2.0f },
|
||||
case RPG_CAMERA_MODE_FOLLOW_ENTITY: {
|
||||
const entity_t *ent = &ENTITIES[RPG_CAMERA.followEntity.followEntityId];
|
||||
sceneMapEntityGetPosition(ent, cameraTarget);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
glm_vec3_zero(cameraTarget);
|
||||
break;
|
||||
}
|
||||
|
||||
glm_vec3_copy(
|
||||
cameraTarget,
|
||||
data->sceneMap.camera.lookatPixelPerfect.target
|
||||
);
|
||||
|
||||
@@ -74,14 +124,36 @@ void sceneMapRenderEntity(entity_t *entity) {
|
||||
|
||||
if(entity->type == ENTITY_TYPE_NULL) return;
|
||||
|
||||
vec3 posMin, posMax;
|
||||
glm_vec3_scale(entity->position, TILE_SIZE, posMin);
|
||||
glm_vec3_add(posMin, (vec3){TILE_SIZE, TILE_SIZE, TILE_SIZE }, posMax);
|
||||
vec3 posCenter, posMin, posMax;
|
||||
vec3 halfSize = { TILE_SIZE / 2.0f, TILE_SIZE / 2.0f, TILE_SIZE / 2.0f };
|
||||
sceneMapEntityGetPosition(entity, posCenter);
|
||||
glm_vec3_sub(posCenter, halfSize, posMin);
|
||||
glm_vec3_add(posCenter, halfSize, posMax);
|
||||
|
||||
// TEST: Change color depending on dir.
|
||||
color_t testColor;
|
||||
switch(entity->direction) {
|
||||
case ENTITY_DIR_NORTH:
|
||||
testColor = COLOR_BLUE;
|
||||
break;
|
||||
case ENTITY_DIR_EAST:
|
||||
testColor = COLOR_GREEN;
|
||||
break;
|
||||
case ENTITY_DIR_SOUTH:
|
||||
testColor = COLOR_CYAN;
|
||||
break;
|
||||
case ENTITY_DIR_WEST:
|
||||
testColor = COLOR_YELLOW;
|
||||
break;
|
||||
default:
|
||||
testColor = COLOR_WHITE;
|
||||
break;
|
||||
}
|
||||
|
||||
vec2 uv0 = { 0.0f, 0.0f };
|
||||
vec2 uv1 = { 1.0f, 1.0f };
|
||||
|
||||
spriteBatchPush3D(NULL, posMin, posMax, COLOR_RED, uv0, uv1);
|
||||
spriteBatchPush3D(NULL, posMin, posMax, testColor, uv0, uv1);
|
||||
}
|
||||
|
||||
void sceneMapDispose(scenedata_t *data) {
|
||||
|
||||
Reference in New Issue
Block a user