From 907d3234a91ba87948b6fe6c7ed4b14fe063be3b Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Fri, 20 Jun 2025 22:10:09 -0500 Subject: [PATCH] interactions --- src/dusk/entity/entity.c | 11 ++++- src/dusk/entity/entity.h | 11 ++++- src/dusk/entity/npc.c | 4 ++ src/dusk/entity/npc.h | 10 ++++- src/dusk/entity/player.c | 87 ++++++++++++++++++++++++++-------------- src/dusk/entity/player.h | 5 ++- src/dusk/util/fixed.c | 56 ++++++++++++++++++++++++++ src/dusk/util/fixed.h | 26 ++++++++++++ 8 files changed, 174 insertions(+), 36 deletions(-) diff --git a/src/dusk/entity/entity.c b/src/dusk/entity/entity.c index 18c8703..f4eed01 100644 --- a/src/dusk/entity/entity.c +++ b/src/dusk/entity/entity.c @@ -16,8 +16,15 @@ entity_t ENTITIES[ENTITY_COUNT_MAX] = {0}; entitycallback_t ENTITY_CALLBACKS[ENTITY_TYPE_COUNT] = { {NULL}, // ENTITY_TYPE_NULL - {playerNPCInit, playerNPCUpdate}, // ENTITY_TYPE_PLAYER - {npcInit, npcUpdate} // ENTITY_TYPE_NPC + { + .init = playerNPCInit, + .update = playerNPCUpdate, + }, + { + .init = npcInit, + .update = npcUpdate, + .interact = npcInteract, + }, }; void entityInit(entity_t *entity, const entitytype_t type) { diff --git a/src/dusk/entity/entity.h b/src/dusk/entity/entity.h index 2ce559d..28ba757 100644 --- a/src/dusk/entity/entity.h +++ b/src/dusk/entity/entity.h @@ -47,6 +47,7 @@ typedef struct _entity_t { typedef struct { void (*init) (entity_t *entity); void (*update) (entity_t *entity); + void (*interact)(entity_t *player, entity_t *self); } entitycallback_t; extern entity_t ENTITIES[ENTITY_COUNT_MAX]; @@ -65,4 +66,12 @@ void entityInit(entity_t *entity, const entitytype_t type); * * @param entity Pointer to the entity to update. */ -void entityUpdate(entity_t *entity); \ No newline at end of file +void entityUpdate(entity_t *entity); + +/** + * Converts an entity direction to an angle in fixed248_t format. + * + * @param dir The entity direction to convert. + * @return The angle corresponding to the entity direction. + */ +fixed248_t entityDirToAngle(const entitydir_t dir); \ No newline at end of file diff --git a/src/dusk/entity/npc.c b/src/dusk/entity/npc.c index 768db5c..c192a7f 100644 --- a/src/dusk/entity/npc.c +++ b/src/dusk/entity/npc.c @@ -13,4 +13,8 @@ void npcInit(entity_t *entity) { void npcUpdate(entity_t *entity) { +} + +void npcInteract(entity_t *player, entity_t *self) { + printf("I am being interacted with!\n"); } \ No newline at end of file diff --git a/src/dusk/entity/npc.h b/src/dusk/entity/npc.h index ed77799..27c1717 100644 --- a/src/dusk/entity/npc.h +++ b/src/dusk/entity/npc.h @@ -20,4 +20,12 @@ void npcInit(entity_t *entity); * * @param entity The entity to update. */ -void npcUpdate(entity_t *entity); \ No newline at end of file +void npcUpdate(entity_t *entity); + +/** + * Handles interaction between the player and the NPC. + * + * @param player The player entity interacting with the NPC. + * @param self The NPC entity being interacted with. + */ +void npcInteract(entity_t *player, entity_t *self); \ No newline at end of file diff --git a/src/dusk/entity/player.c b/src/dusk/entity/player.c index 0375b8e..3154c7d 100644 --- a/src/dusk/entity/player.c +++ b/src/dusk/entity/player.c @@ -82,39 +82,64 @@ void playerNPCUpdate(entity_t *entity) { } else { entity->vx = 0; entity->vy = 0; + } - // Interact - if(inputPressed(INPUT_BIND_ACTION)) { - entity_t *other = ENTITIES; - do { - if(other == entity || other->type == ENTITY_TYPE_NULL) { - other++; - continue; - } - - fixed248_t distanceX = fx248Subfx248(other->x, entity->x); - fixed248_t distanceY = fx248Subfx248(other->y, entity->y); - fixed248_t distance = fx248Sqrt( - fx248Addfx248( - fx248Mulfx248(distanceX, distanceX), - fx248Mulfx248(distanceY, distanceY) - ) - ); - - if(other->id == 102) { - printf("Distance to entity %u: %f\n", other->id, fx248Tof32(distance)); - } - - if(distance > PLAYER_INTERACT_RANGE) { - other++; - continue; - } - - - printf("Interacting with entity %u\n", other->id); + // Interact + if(inputPressed(INPUT_BIND_ACTION)) { + entity_t *other = ENTITIES; + do { + if(other == entity || other->type == ENTITY_TYPE_NULL) { other++; + continue; + } - } while(other != ENTITIES + ENTITY_COUNT_MAX); - } + // Is the other entity interactable? + if(ENTITY_CALLBACKS[other->type].interact == NULL) { + other++; + continue; + } + + fixed248_t distanceX = fx248Subfx248(other->x, entity->x); + fixed248_t distanceY = fx248Subfx248(other->y, entity->y); + fixed248_t distance = fx248Sqrt(fx248Addfx248( + fx248Mulfx248(distanceX, distanceX), + fx248Mulfx248(distanceY, distanceY) + )); + + if(distance > PLAYER_INTERACT_RANGE) { + other++; + continue; + } + + // Get angle + fixed248_t angle = fx248Atan2(distanceY, distanceX); + while(angle < 0) angle += FX248_PI; + fixed248_t selfAngle = entityDirToAngle(entity->dir); + while(selfAngle < 0) selfAngle += FX248_PI; + + // Check if angle is within range + fixed248_t angleDiff = fx248Subfx248(angle, selfAngle); + if(angleDiff > FX248_HALF_PI) angleDiff -= FX248_PI; + if(angleDiff < -FX248_HALF_PI) angleDiff += FX248_PI; + if(fx248Abs(angleDiff) > PLAYER_INTERACT_ANGLE) { + other++; + continue; + } + + ENTITY_CALLBACKS[other->type].interact(entity, other); + entity->vx = 0; + entity->vy = 0; + other++; + } while(other != ENTITIES + ENTITY_COUNT_MAX); + } +} + +fixed248_t entityDirToAngle(const entitydir_t dir) { + switch(dir) { + case ENTITY_DIR_NORTH: return FX248_HALF_PI; + case ENTITY_DIR_SOUTH: return -FX248_HALF_PI; + case ENTITY_DIR_EAST: return 0; + case ENTITY_DIR_WEST: return FX248_PI; + default: return 0; // Should never happen } } \ No newline at end of file diff --git a/src/dusk/entity/player.h b/src/dusk/entity/player.h index d4f0f73..564bcfa 100644 --- a/src/dusk/entity/player.h +++ b/src/dusk/entity/player.h @@ -18,7 +18,10 @@ typedef struct { #define PLAYER_ENTITY_ID (UINT32_MAX-1) #define PLAYER_MOVE_SPEED FIXED248(1, 0) #define PLAYER_MOVE_SPEED_XY FIXED248(0, 80) -#define PLAYER_INTERACT_RANGE FIXED248((TILE_WIDTH_HEIGHT + (TILE_WIDTH_HEIGHT / 3)), 0) +#define PLAYER_INTERACT_RANGE FIXED248( \ + (TILE_WIDTH_HEIGHT + (TILE_WIDTH_HEIGHT / 3)), 0 \ +) +#define PLAYER_INTERACT_ANGLE ((fixed248_t)175) /** * Initializes the player and all player-related entities. diff --git a/src/dusk/util/fixed.c b/src/dusk/util/fixed.c index 3612116..f664f80 100644 --- a/src/dusk/util/fixed.c +++ b/src/dusk/util/fixed.c @@ -198,4 +198,60 @@ fixed248_t fx248Clamp( const fixed248_t max ) { return (a < min) ? min : (a > max) ? max : a; +} + +fixed248_t fx248Abs(const fixed248_t a) { + return (a < 0) ? -a : a; +} + + + +fixed248_t fx248Atan2( + const fixed248_t y, + const fixed248_t x +) { + // Handle special cases + if (x == 0) { + if (y > 0) return FX248_HALF_PI; + if (y < 0) return -FX248_HALF_PI; + return 0; + } + + // Use absolute values for quadrant correction + fixed248_t abs_y = y; + if (abs_y < 0) abs_y = -abs_y; + + fixed248_t angle; + if (abs_y < fx248Abs(x)) { + fixed248_t z = fx248Divfx248(y, x); + fixed248_t z2 = fx248Mulfx248(z, z); + fixed248_t z3 = fx248Mulfx248(z2, z); + fixed248_t z5 = fx248Mulfx248(z3, z2); + angle = fx248Subfx248( + fx248Addfx248(z, fx248Divfx248(z5, fx248Fromi32(5))), + fx248Divfx248(z3, fx248Fromi32(3)) + ); + if (x < 0) { + if (y < 0) { + angle -= FX248_PI; + } else { + angle += FX248_PI; + } + } + } else { + fixed248_t z = fx248Divfx248(x, y); + fixed248_t z2 = fx248Mulfx248(z, z); + fixed248_t z3 = fx248Mulfx248(z2, z); + fixed248_t z5 = fx248Mulfx248(z3, z2); + angle = fx248Subfx248( + fx248Addfx248(z, fx248Divfx248(z5, fx248Fromi32(5))), + fx248Divfx248(z3, fx248Fromi32(3)) + ); + if (y > 0) { + angle = FX248_HALF_PI - angle; + } else { + angle = -FX248_HALF_PI - angle; + } + } + return angle; } \ No newline at end of file diff --git a/src/dusk/util/fixed.h b/src/dusk/util/fixed.h index 956e047..6e2ae2b 100644 --- a/src/dusk/util/fixed.h +++ b/src/dusk/util/fixed.h @@ -20,6 +20,10 @@ typedef int32_t fixed248_t; )) #define FIXED248_ONE (FIXED248(1, 0)) #define FIXED248_ZERO (FIXED248(0, 0)) +#define FX248_PI 804 +#define FX248_HALF_PI 402 +#define FX248_3PI_4 603 +#define FX248_NEG_PI -804 /** * Convert an int32_t value to a fixed248_t value. @@ -350,4 +354,26 @@ fixed248_t fx248Clamp( const fixed248_t a, const fixed248_t min, const fixed248_t max +); + +/** + * Returns the absolute value of a fixed248_t value. + * + * @param a The fixed248_t value to calculate the absolute value of. + * @return The absolute value as a fixed248_t value. + */ +fixed248_t fx248Abs(const fixed248_t a); + + + +/** + * Calculate the arctangent of a fixed248_t value. + * + * @param y Y coordinate value. + * @param x X coordinate value. + * @return The arctangent of the value as a fixed248_t value. + */ +fixed248_t fx248Atan2( + const fixed248_t y, + const fixed248_t x ); \ No newline at end of file