NPCs
This commit is contained in:
@ -10,29 +10,18 @@
|
||||
#include "display/render.h"
|
||||
|
||||
#include "rpg/entity/entity.h"
|
||||
#include "rpg/world/maps/testmap.h"
|
||||
|
||||
int32_t main(const int32_t argc, const char **argv) {
|
||||
inputInit();
|
||||
randomInit();
|
||||
renderInit();
|
||||
|
||||
entity_t *ent;
|
||||
|
||||
ent = &ENTITIES[0];
|
||||
entityInit(ent, ENTITY_TYPE_PLAYER);
|
||||
|
||||
mapSet(TEST_MAP);
|
||||
|
||||
while(1) {
|
||||
inputUpdate();
|
||||
|
||||
ent = ENTITIES;
|
||||
do {
|
||||
if(ent->type == ENTITY_TYPE_NULL) {
|
||||
ent++;
|
||||
continue;
|
||||
}
|
||||
entityUpdate(ent++);
|
||||
} while(ent < (ENTITIES + ENTITY_COUNT));
|
||||
|
||||
mapUpdate();
|
||||
if(!renderUpdate()) break;
|
||||
}
|
||||
|
||||
|
@ -8,4 +8,5 @@ target_sources(${DUSK_TARGET_NAME}
|
||||
PRIVATE
|
||||
entity.c
|
||||
player.c
|
||||
npc.c
|
||||
)
|
@ -8,20 +8,25 @@
|
||||
#include "assert/assert.h"
|
||||
#include "util/memory.h"
|
||||
#include "entity.h"
|
||||
|
||||
entity_t ENTITIES[ENTITY_COUNT];
|
||||
#include "rpg/world/map.h"
|
||||
#include "util/math.h"
|
||||
|
||||
entitycallbacks_t ENTITY_CALLBACKS[ENTITY_TYPE_COUNT] = {
|
||||
[ENTITY_TYPE_NULL] = { 0 },
|
||||
|
||||
[ENTITY_TYPE_PLAYER] = {
|
||||
.init = playerInit,
|
||||
.update = playerUpdate
|
||||
.update = playerUpdate,
|
||||
.interact = NULL,
|
||||
},
|
||||
|
||||
[ENTITY_TYPE_NPC] = {
|
||||
.init = npcInit,
|
||||
.update = npcUpdate,
|
||||
.interact = npcInteract,
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
void entityInit(entity_t *entity, const entitytype_t type) {
|
||||
assertNotNull(entity, "Entity is NULL");
|
||||
assertTrue(type < ENTITY_TYPE_COUNT, "Invalid entity type");
|
||||
@ -60,42 +65,128 @@ void entityTurn(entity_t *entity, const entitydir_t dir) {
|
||||
entity->dir = dir;
|
||||
}
|
||||
|
||||
void entityWalk(entity_t *entity) {
|
||||
assertNotNull(entity, "Entity cannot be NULL");
|
||||
assertFalse(entityIsWalking(entity), "Entity is already walking");
|
||||
void entityDirGetPosition(
|
||||
const entitydir_t dir,
|
||||
const uint8_t distance,
|
||||
int8_t *outX,
|
||||
int8_t *outY
|
||||
) {
|
||||
assertTrue(dir < ENTITY_DIR_COUNT, "Invalid entity direction");
|
||||
assertNotNull(outX, "Output X cannot be NULL");
|
||||
assertNotNull(outY, "Output Y cannot be NULL");
|
||||
|
||||
switch(entity->dir) {
|
||||
switch(dir) {
|
||||
case ENTITY_DIR_UP:
|
||||
entity->y--;
|
||||
entity->subY = ENTITY_MOVE_SUBPIXEL;
|
||||
*outX = 0;
|
||||
*outY = -distance;
|
||||
break;
|
||||
case ENTITY_DIR_DOWN:
|
||||
entity->y++;
|
||||
entity->subY = -ENTITY_MOVE_SUBPIXEL;
|
||||
*outX = 0;
|
||||
*outY = distance;
|
||||
break;
|
||||
case ENTITY_DIR_LEFT:
|
||||
entity->x--;
|
||||
entity->subX = ENTITY_MOVE_SUBPIXEL;
|
||||
*outX = -distance;
|
||||
*outY = 0;
|
||||
break;
|
||||
case ENTITY_DIR_RIGHT:
|
||||
entity->x++;
|
||||
entity->subX = -ENTITY_MOVE_SUBPIXEL;
|
||||
*outX = distance;
|
||||
*outY = 0;
|
||||
break;
|
||||
default:
|
||||
assertUnreachable("Invalid entity direction");
|
||||
}
|
||||
}
|
||||
|
||||
entitydir_t entityGetLookDirection(
|
||||
const entity_t *entity,
|
||||
const uint8_t x,
|
||||
const uint8_t y
|
||||
) {
|
||||
assertNotNull(entity, "Entity cannot be NULL");
|
||||
assertTrue(x < MAP.width, "X coordinate out of bounds");
|
||||
assertTrue(y < MAP.height, "Y coordinate out of bounds");
|
||||
|
||||
int8_t dX = x - entity->x;
|
||||
int8_t dY = y - entity->y;
|
||||
|
||||
// More horizontal movement or more vertical movement?
|
||||
if(mathAbsI8(dX) > mathAbsI8(dY)) {
|
||||
// More horizontal movement
|
||||
if(dX < 0) return ENTITY_DIR_LEFT;
|
||||
return ENTITY_DIR_RIGHT;
|
||||
}
|
||||
|
||||
if(dY < 0) {
|
||||
return ENTITY_DIR_UP;
|
||||
}
|
||||
return ENTITY_DIR_DOWN;
|
||||
}
|
||||
|
||||
void entityWalk(entity_t *entity) {
|
||||
assertNotNull(entity, "Entity cannot be NULL");
|
||||
assertFalse(entityIsWalking(entity), "Entity is already walking");
|
||||
assertTrue(entityCanWalk(entity, entity->dir, NULL), "Entity cannot walk");
|
||||
|
||||
int8_t tX, tY;
|
||||
entityDirGetPosition(entity->dir, 1, &tX, &tY);
|
||||
|
||||
entity->y += tY;
|
||||
entity->x += tX;
|
||||
entity->subX = ENTITY_MOVE_SUBPIXEL * -tX;
|
||||
entity->subY = ENTITY_MOVE_SUBPIXEL * -tY;
|
||||
}
|
||||
|
||||
bool_t entityIsWalking(const entity_t *entity) {
|
||||
assertNotNull(entity, "Entity cannot be NULL");
|
||||
return (entity->subX != 0 || entity->subY != 0);
|
||||
}
|
||||
|
||||
entity_t * entityGetAt(const uint8_t x, const uint8_t y) {
|
||||
entity_t *e = ENTITIES;
|
||||
do {
|
||||
if(e->type && e->x == x && e->y == y) return e;
|
||||
e++;
|
||||
} while(e < (ENTITIES + ENTITY_COUNT));
|
||||
return NULL;
|
||||
bool_t entityCanWalk(
|
||||
const entity_t *entity,
|
||||
const entitydir_t dir,
|
||||
entity_t **entityInWay
|
||||
) {
|
||||
assertNotNull(entity, "Entity cannot be NULL");
|
||||
assertTrue(dir < ENTITY_DIR_COUNT, "Invalid entity direction");
|
||||
|
||||
int8_t dX, dY;
|
||||
entityDirGetPosition(dir, 1, &dX, &dY);
|
||||
|
||||
uint8_t tX = entity->x + dX;
|
||||
if(tX < 0 || tX >= MAP.width) return false;
|
||||
|
||||
uint8_t tY = entity->y + dY;
|
||||
if(tY < 0 || tY >= MAP.height) return false;
|
||||
|
||||
if(entityInWay == NULL) {
|
||||
if(mapGetEntityAt(tX, tY) != NULL) return false;
|
||||
} else {
|
||||
*entityInWay = mapGetEntityAt(tX, tY);
|
||||
if(*entityInWay != NULL) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void entityPositionSet(entity_t *entity, const uint8_t x, const uint8_t y) {
|
||||
assertNotNull(entity, "Entity cannot be NULL");
|
||||
assertTrue(x < MAP.width, "X coordinate out of bounds");
|
||||
assertTrue(y < MAP.height, "Y coordinate out of bounds");
|
||||
entity->x = x;
|
||||
entity->y = y;
|
||||
entity->subX = 0;
|
||||
entity->subY = 0;
|
||||
}
|
||||
|
||||
bool_t entityInteract(entity_t *interacted, entity_t *player) {
|
||||
assertNotNull(interacted, "Interacted entity cannot be NULL");
|
||||
assertNotNull(player, "Player entity cannot be NULL");
|
||||
assertTrue(interacted->type != ENTITY_TYPE_NULL, "Interacted entity invalid");
|
||||
assertTrue(player->type == ENTITY_TYPE_PLAYER, "Entity is not a player");
|
||||
|
||||
if(ENTITY_CALLBACKS[interacted->type].interact != NULL) {
|
||||
return ENTITY_CALLBACKS[interacted->type].interact(interacted, player);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
@ -7,6 +7,7 @@
|
||||
|
||||
#pragma once
|
||||
#include "player.h"
|
||||
#include "npc.h"
|
||||
|
||||
#define ENTITY_WIDTH 16
|
||||
#define ENTITY_HEIGHT 16
|
||||
@ -24,11 +25,14 @@ typedef enum {
|
||||
ENTITY_DIR_EAST = ENTITY_DIR_RIGHT
|
||||
} entitydir_t;
|
||||
|
||||
#define ENTITY_DIR_COUNT (ENTITY_DIR_RIGHT + 1)
|
||||
|
||||
typedef enum {
|
||||
ENTITY_TYPE_NULL = 0,
|
||||
ENTITY_TYPE_PLAYER = 1,
|
||||
ENTITY_TYPE_NPC = 2,
|
||||
} entitytype_t;
|
||||
#define ENTITY_TYPE_COUNT (ENTITY_TYPE_PLAYER + 1)
|
||||
#define ENTITY_TYPE_COUNT (ENTITY_TYPE_NPC + 1)
|
||||
|
||||
typedef struct _entity_t {
|
||||
entitytype_t type;
|
||||
@ -39,15 +43,14 @@ typedef struct _entity_t {
|
||||
// Per type data
|
||||
union {
|
||||
player_t player;
|
||||
npc_t npc;
|
||||
};
|
||||
} entity_t;
|
||||
|
||||
#define ENTITY_COUNT 16
|
||||
extern entity_t ENTITIES[ENTITY_COUNT];
|
||||
|
||||
typedef struct {
|
||||
void (*init)(entity_t *entity);
|
||||
void (*update)(entity_t *entity);
|
||||
bool_t (*interact)(entity_t *self, entity_t *player);
|
||||
} entitycallbacks_t;
|
||||
extern entitycallbacks_t ENTITY_CALLBACKS[ENTITY_TYPE_COUNT];
|
||||
|
||||
@ -74,6 +77,36 @@ void entityUpdate(entity_t *entity);
|
||||
*/
|
||||
void entityTurn(entity_t *entity, const entitydir_t dir);
|
||||
|
||||
/**
|
||||
* Gets the position of a specific direction at a given distance.
|
||||
*
|
||||
* @param dir The direction to get the position in.
|
||||
* @param distance The distance to move in that direction.
|
||||
* @param outX Pointer to store the resulting x-coordinate.
|
||||
* @param outY Pointer to store the resulting y-coordinate.
|
||||
*/
|
||||
void entityDirGetPosition(
|
||||
const entitydir_t dir,
|
||||
const uint8_t distance,
|
||||
int8_t *outX,
|
||||
int8_t *outY
|
||||
);
|
||||
|
||||
/**
|
||||
* Gets the look direction for a given entity to be looking at the specified
|
||||
* coordinates.
|
||||
*
|
||||
* @param entity Pointer to the entity to get the look direction for.
|
||||
* @param x The x-coordinate to look at.
|
||||
* @param Y The y-coordinate to look at.
|
||||
* @return The direction the entity should look towards.
|
||||
*/
|
||||
entitydir_t entityGetLookDirection(
|
||||
const entity_t *entity,
|
||||
const uint8_t x,
|
||||
const uint8_t Y
|
||||
);
|
||||
|
||||
/**
|
||||
* Makes the entity walk in the current direction.
|
||||
*
|
||||
@ -90,10 +123,36 @@ void entityWalk(entity_t *entity);
|
||||
bool_t entityIsWalking(const entity_t *entity);
|
||||
|
||||
/**
|
||||
* Resets the entity at a given position.
|
||||
* Checks if the entity can walk in a specific direction.
|
||||
*
|
||||
* @param x The x-coordinate of the entity.
|
||||
* @param y The y-coordinate of the entity.
|
||||
* @return Pointer to the entity at the specified position, or NULL.
|
||||
* @param entity Pointer to the entity to check.
|
||||
* @param dir The direction to check for walking capability.
|
||||
* @param inWay Pointer to store any entity in the way, if applicable.
|
||||
* @return true if the entity can walk in the specified direction, false otherwise.
|
||||
*/
|
||||
entity_t * entityGetAt(const uint8_t x, const uint8_t y);
|
||||
bool_t entityCanWalk(
|
||||
const entity_t *entity,
|
||||
const entitydir_t dir,
|
||||
entity_t **inWay
|
||||
);
|
||||
|
||||
/**
|
||||
* Sets the position of the entity.
|
||||
*
|
||||
* @param entity Pointer to the entity to set the position for.
|
||||
* @param x The x-coordinate to set.
|
||||
* @param y The y-coordinate to set.
|
||||
*/
|
||||
void entityPositionSet(entity_t *entity, const uint8_t x, const uint8_t y);
|
||||
|
||||
/**
|
||||
* Handles interaction between an entity and a player.
|
||||
*
|
||||
* @param self Pointer to the entity that is being interacted with.
|
||||
* @param player Pointer to the player entity interacting with the entity.
|
||||
* @return true if interaction happened.
|
||||
*/
|
||||
bool_t entityInteract(
|
||||
entity_t *self,
|
||||
entity_t *player
|
||||
);
|
31
src/dusk/rpg/entity/npc.c
Normal file
31
src/dusk/rpg/entity/npc.c
Normal file
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "entity.h"
|
||||
#include "assert/assert.h"
|
||||
|
||||
void npcInit(entity_t *ent) {
|
||||
assertNotNull(ent, "NPC entity is NULL");
|
||||
assertTrue(ent->type == ENTITY_TYPE_NPC, "Entity is not an NPC");
|
||||
}
|
||||
|
||||
void npcUpdate(entity_t *ent) {
|
||||
assertNotNull(ent, "Entity is NULL");
|
||||
assertTrue(ent->type == ENTITY_TYPE_NPC, "Entity is not an NPC");
|
||||
}
|
||||
|
||||
bool_t npcInteract(entity_t *self, entity_t *player) {
|
||||
assertNotNull(self, "NPC entity cannot be NULL");
|
||||
assertNotNull(player, "Player entity cannot be NULL");
|
||||
assertTrue(self->type == ENTITY_TYPE_NPC, "Entity is not an NPC");
|
||||
assertTrue(player->type == ENTITY_TYPE_PLAYER, "Entity is not a player");
|
||||
|
||||
// Look at the player
|
||||
entityTurn(self, entityGetLookDirection(self, player->x, player->y));
|
||||
|
||||
return true;
|
||||
}
|
37
src/dusk/rpg/entity/npc.h
Normal file
37
src/dusk/rpg/entity/npc.h
Normal file
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* 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 _entity_t entity_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t nothing; // Placeholder for NPC-specific data
|
||||
} npc_t;
|
||||
|
||||
/**
|
||||
* Initializes an NPC entity.
|
||||
*
|
||||
* @param ent Pointer to the NPC entity to initialize.
|
||||
*/
|
||||
void npcInit(entity_t *ent);
|
||||
|
||||
/**
|
||||
* Updates an NPC entity.
|
||||
*
|
||||
* @param ent Entity to update.
|
||||
*/
|
||||
void npcUpdate(entity_t *ent);
|
||||
|
||||
/**
|
||||
* Handles interaction between an NPC and a player.
|
||||
*
|
||||
* @param self Pointer to the NPC entity.
|
||||
* @param player Pointer to the player entity interacting with the NPC.
|
||||
*/
|
||||
bool_t npcInteract(entity_t *self, entity_t *player);
|
@ -8,6 +8,7 @@
|
||||
#include "entity.h"
|
||||
#include "assert/assert.h"
|
||||
#include "input.h"
|
||||
#include "rpg/world/map.h"
|
||||
|
||||
void playerInit(entity_t *player) {
|
||||
assertNotNull(player, "Player entity is NULL");
|
||||
@ -15,28 +16,43 @@ void playerInit(entity_t *player) {
|
||||
}
|
||||
|
||||
void playerUpdate(entity_t *entity) {
|
||||
entity_t *other;
|
||||
assertNotNull(entity, "Entity is NULL");
|
||||
assertTrue(entity->type == ENTITY_TYPE_PLAYER, "Entity is not a player");
|
||||
|
||||
if(!entityIsWalking(entity)) {
|
||||
entitydir_t dir = 0xFF;
|
||||
if(inputIsDown(INPUT_UP)) {
|
||||
dir = ENTITY_DIR_UP;
|
||||
} else if(inputIsDown(INPUT_DOWN)) {
|
||||
dir = ENTITY_DIR_DOWN;
|
||||
} else if(inputIsDown(INPUT_LEFT)) {
|
||||
dir = ENTITY_DIR_LEFT;
|
||||
} else if(inputIsDown(INPUT_RIGHT)) {
|
||||
dir = ENTITY_DIR_RIGHT;
|
||||
}
|
||||
|
||||
if(dir != 0xFF) {
|
||||
if(dir != entity->dir) {
|
||||
entityTurn(entity, dir);
|
||||
} else {
|
||||
entityWalk(entity);
|
||||
}
|
||||
}
|
||||
// Handle movement
|
||||
if(entityIsWalking(entity)) {
|
||||
return;
|
||||
}
|
||||
|
||||
entitydir_t dir = 0xFF;
|
||||
if(inputIsDown(INPUT_UP)) {
|
||||
dir = ENTITY_DIR_UP;
|
||||
} else if(inputIsDown(INPUT_DOWN)) {
|
||||
dir = ENTITY_DIR_DOWN;
|
||||
} else if(inputIsDown(INPUT_LEFT)) {
|
||||
dir = ENTITY_DIR_LEFT;
|
||||
} else if(inputIsDown(INPUT_RIGHT)) {
|
||||
dir = ENTITY_DIR_RIGHT;
|
||||
}
|
||||
|
||||
if(dir != 0xFF) {
|
||||
if(dir != entity->dir) {
|
||||
entityTurn(entity, dir);
|
||||
} else {
|
||||
if(!entityCanWalk(entity, dir, &other)) return;
|
||||
entityWalk(entity);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle interaction
|
||||
if(inputWasPressed(INPUT_ACTION)) {
|
||||
int8_t dX, dY;
|
||||
entityDirGetPosition(entity->dir, 1, &dX, &dY);
|
||||
other = mapGetEntityAt(entity->x + dX, entity->y + dY);
|
||||
|
||||
assertTrue(other != entity, "Player trying to interact with itself?");
|
||||
if(other != NULL && entityInteract(other, entity)) return;
|
||||
}
|
||||
}
|
@ -7,4 +7,7 @@
|
||||
target_sources(${DUSK_TARGET_NAME}
|
||||
PRIVATE
|
||||
map.c
|
||||
)
|
||||
)
|
||||
|
||||
# Subdirs
|
||||
add_subdirectory(maps)
|
@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "map.h"
|
||||
#include "util/memory.h"
|
||||
#include "assert/assert.h"
|
||||
|
||||
map_t MAP;
|
||||
|
||||
void mapSet(const mapinfo_t mapInfo) {
|
||||
assertTrue(mapInfo.init != NULL, "Map initialization function cannot be NULL");
|
||||
mapInfo.init();
|
||||
}
|
||||
|
||||
void mapInit(const uint8_t width, const uint8_t height) {
|
||||
memoryZero(&MAP, sizeof(map_t));
|
||||
|
||||
MAP.width = width;
|
||||
MAP.height = height;
|
||||
}
|
||||
|
||||
void mapUpdate() {
|
||||
entity_t *ent = MAP.entities;
|
||||
do {
|
||||
if(ent->type != ENTITY_TYPE_NULL) {
|
||||
entityUpdate(ent);
|
||||
}
|
||||
ent++;
|
||||
} while(ent < MAP.entities + MAP_ENTITY_COUNT);
|
||||
}
|
||||
|
||||
entity_t * mapGetEntityAt(const uint8_t x, const uint8_t y) {
|
||||
if(x >= MAP.width || y >= MAP.height) return NULL;
|
||||
entity_t *ent = MAP.entities;
|
||||
do {
|
||||
if(ent->type != ENTITY_TYPE_NULL && ent->x == x && ent->y == y) return ent;
|
||||
ent++;
|
||||
} while(ent < MAP.entities + MAP_ENTITY_COUNT);
|
||||
|
||||
return NULL;
|
||||
}
|
@ -6,11 +6,54 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "dusk.h"
|
||||
#include "rpg/entity/entity.h"
|
||||
|
||||
#define MAP_ENTITY_COUNT 16
|
||||
|
||||
typedef struct {
|
||||
uint8_t width;
|
||||
uint8_t height;
|
||||
entity_t entities[MAP_ENTITY_COUNT];
|
||||
} map_t;
|
||||
|
||||
extern map_t MAP;
|
||||
typedef struct {
|
||||
const char *name;
|
||||
void (*init)(void);
|
||||
} mapinfo_t;
|
||||
|
||||
extern map_t MAP;
|
||||
|
||||
/**
|
||||
* Sets the current map to the specified map information.
|
||||
*
|
||||
* This function initializes the map with the provided map information,
|
||||
* including its name and initialization function.
|
||||
*
|
||||
* @param mapInfo Map information containing the name and initialization function.
|
||||
*/
|
||||
void mapSet(const mapinfo_t mapInfo);
|
||||
|
||||
/**
|
||||
* Initializes the map with the given width and height.
|
||||
*
|
||||
* @param width Width of the map.
|
||||
* @param height Height of the map.
|
||||
*/
|
||||
void mapInit(const uint8_t width, const uint8_t height);
|
||||
|
||||
/**
|
||||
* Updates the map, processing all entities.
|
||||
*
|
||||
* This function should be called every frame to update the state of the map
|
||||
* and its entities.
|
||||
*/
|
||||
void mapUpdate();
|
||||
|
||||
/**
|
||||
* Gets the entity at the specified coordinates.
|
||||
*
|
||||
* @param x X coordinate of the entity.
|
||||
* @param y Y coordinate of the entity.
|
||||
* @return Pointer to the entity at the specified coordinates or NULL.
|
||||
*/
|
||||
entity_t * mapGetEntityAt(const uint8_t x, const uint8_t y);
|
9
src/dusk/rpg/world/maps/CMakeLists.txt
Normal file
9
src/dusk/rpg/world/maps/CMakeLists.txt
Normal file
@ -0,0 +1,9 @@
|
||||
# Copyright (c) 2025 Dominic Masters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
# Sources
|
||||
target_sources(${DUSK_TARGET_NAME}
|
||||
PRIVATE
|
||||
)
|
31
src/dusk/rpg/world/maps/testmap.h
Normal file
31
src/dusk/rpg/world/maps/testmap.h
Normal file
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "rpg/entity/entity.h"
|
||||
#include "rpg/world/map.h"
|
||||
|
||||
/**
|
||||
* Initializes the test map.
|
||||
*
|
||||
* This function sets up a test map with predefined dimensions.
|
||||
*/
|
||||
void testMapInit() {
|
||||
mapInit(10, 10);
|
||||
|
||||
entity_t *ent = MAP.entities;
|
||||
entityInit(ent, ENTITY_TYPE_PLAYER);
|
||||
|
||||
ent++;
|
||||
entityInit(ent, ENTITY_TYPE_NPC);
|
||||
entityPositionSet(ent, 5, 5);
|
||||
}
|
||||
|
||||
mapinfo_t TEST_MAP = {
|
||||
.name = "Test Map",
|
||||
.init = testMapInit
|
||||
};
|
@ -9,4 +9,5 @@ target_sources(${DUSK_TARGET_NAME}
|
||||
memory.c
|
||||
string.c
|
||||
random.c
|
||||
math.c
|
||||
)
|
12
src/dusk/util/math.c
Normal file
12
src/dusk/util/math.c
Normal file
@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
|
||||
int8_t mathAbsI8(const int8_t val) {
|
||||
return (val > 0) ? val : -val;
|
||||
}
|
17
src/dusk/util/math.h
Normal file
17
src/dusk/util/math.h
Normal file
@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "dusk.h"
|
||||
|
||||
/**
|
||||
* Returns the absolute (ignoring sign) value of an 8-bit integer.
|
||||
*
|
||||
* @param val The 8-bit integer value to get the absolute value of.
|
||||
* @return The absolute value of the input integer.
|
||||
*/
|
||||
int8_t mathAbsI8(const int8_t val);
|
@ -8,7 +8,7 @@
|
||||
#include "assert/assert.h"
|
||||
#include "display/render.h"
|
||||
#include "raylib.h"
|
||||
#include "rpg/entity/entity.h"
|
||||
#include "rpg/world/map.h"
|
||||
|
||||
const uint16_t RENDER_WIDTH = 480;
|
||||
const uint16_t RENDER_HEIGHT = 270;
|
||||
@ -29,7 +29,7 @@ bool_t renderUpdate() {
|
||||
ClearBackground(RAYWHITE);
|
||||
DrawText("Hello, Dusk!", 10, 10, 20, BLACK);
|
||||
|
||||
entity_t *ent = ENTITIES;
|
||||
entity_t *ent = MAP.entities;
|
||||
do {
|
||||
if(ent->type == ENTITY_TYPE_NULL) {
|
||||
ent++;
|
||||
@ -83,7 +83,7 @@ bool_t renderUpdate() {
|
||||
}
|
||||
|
||||
ent++;
|
||||
} while(ent < (ENTITIES + ENTITY_COUNT));
|
||||
} while(ent < (MAP.entities + MAP_ENTITY_COUNT));
|
||||
|
||||
EndDrawing();
|
||||
|
||||
|
Reference in New Issue
Block a user