interactions

This commit is contained in:
2025-06-20 22:10:09 -05:00
parent 56642774c4
commit 907d3234a9
8 changed files with 174 additions and 36 deletions

View File

@ -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) {

View File

@ -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];
@ -66,3 +67,11 @@ void entityInit(entity_t *entity, const entitytype_t type);
* @param entity Pointer to the entity to update.
*/
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);

View File

@ -14,3 +14,7 @@ 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");
}

View File

@ -21,3 +21,11 @@ void npcInit(entity_t *entity);
* @param entity The entity to update.
*/
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);

View File

@ -82,6 +82,7 @@ void playerNPCUpdate(entity_t *entity) {
} else {
entity->vx = 0;
entity->vy = 0;
}
// Interact
if(inputPressed(INPUT_BIND_ACTION)) {
@ -92,29 +93,53 @@ void playerNPCUpdate(entity_t *entity) {
continue;
}
// 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(
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;
}
// 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;
printf("Interacting with entity %u\n", other->id);
// 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
}
}

View File

@ -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.

View File

@ -199,3 +199,59 @@ fixed248_t fx248Clamp(
) {
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;
}

View File

@ -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.
@ -351,3 +355,25 @@ fixed248_t fx248Clamp(
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
);