#include "entity.h" #include "game.h" BoundingBox entityBoxFromScale(float scale, float width, float height) { Vector2 size = (Vector2){width / height * scale, scale}; size = Vector2Scale(size, 0.5); return (BoundingBox){ .min = (Vector3){-size.x, -size.y, -size.x}, .max = (Vector3){size.x, size.y, size.x} }; } Entity createEntity(EntityId id, Vector3 position) { Entity entity; entity.id = id; // Bounding boxes. switch (id) { case OLD_MINT: case STICKY_NICKEL: entity.box = entityBoxFromScale(1.0, 32.0, 32.0); break; case TREE: entity.box = entityBoxFromScale(TREE_SCALE, 113.0, 250.0); break; case BUSH: entity.box = entityBoxFromScale(BUSH_SCALE, 87.0, 62.0); break; case FLOWER: entity.box = entityBoxFromScale(FLOWER_SCALE, 32.0, 54.0); break; case POND: entity.box = (BoundingBox){ .min = (Vector3){-POND_SIZE, -POND_HEIGHT, -POND_SIZE}, .max = (Vector3){POND_SIZE, POND_HEIGHT, POND_SIZE} }; break; case UTILITY_POLE: entity.box = (BoundingBox){ .min = (Vector3){-UTILITY_POLE_RADIUS, -UTILITY_POLE_HEIGHT, -UTILITY_POLE_RADIUS}, .max = (Vector3){UTILITY_POLE_RADIUS, UTILITY_POLE_HEIGHT, UTILITY_POLE_RADIUS}, }; break; case SAMANTHA: entity.box = (BoundingBox){ .min = (Vector3){-SAMANTHA_WIDTH, -SAMANTHA_HEIGHT, -SAMANTHA_THICKNESS}, .max = (Vector3){SAMANTHA_WIDTH, SAMANTHA_HEIGHT, SAMANTHA_THICKNESS} }; break; case SAMANTHAS_SPOT: entity.box = (BoundingBox){ .min = (Vector3){-SAMANTHAS_SPOT_SIZE, -SAMANTHAS_SPOT_HEIGHT, -SAMANTHAS_SPOT_SIZE}, .max = (Vector3){SAMANTHAS_SPOT_SIZE, SAMANTHAS_SPOT_HEIGHT, SAMANTHAS_SPOT_SIZE}, }; break; case TRASHCAN: entity.box = entityBoxFromScale(TRASHCAN_SCALE, TRASHCAN_WIDTH, TRASHCAN_HEIGHT); break; case TRASH: entity.box = entityBoxFromScale(TRASH_SCALE, 202.0, 122.0); break; case MEDICAL_TRASH: entity.box = entityBoxFromScale(MEDICAL_TRASH_SCALE, 200.0, 132.0); break; // TODO: do the thing case JOHN: entity.box = (BoundingBox){ .min = (Vector3){-1.0, -1.0, -1.0}, .max = (Vector3){1.0, 1.0, 1.0} }; break; case RON: entity.box = (BoundingBox){ .min = (Vector3){-1.0, -1.0, -1.0}, .max = (Vector3){1.0, 1.0, 1.0} }; break; default: break; } entity.position = Vector3Zero(); setEntityPosition(&entity, position); return entity; } void updateSamantha(Entity* entity, Game* game) { // silly tv static effect. game->assets.models[SAMANTHA_MODEL].materials[0] .maps[MATERIAL_MAP_DIFFUSE].texture = game->assets.textures[ SAMANTHA_1_TEXTURE + ((int)(GetTime() * SAMANTHA_STATIC_SPEED) % SAMANTHA_STATIC_FRAMES)]; DrawModel(game->assets.models[SAMANTHA_MODEL], entity->position, 1.0, WHITE); } void updateTrashcan(Entity* entity, Game* game) { int frame = (int)(GetTime() * TRASHCAN_ANIMATION_SPEED) % TRASHCAN_FRAMES; Rectangle rect = (Rectangle){ .x = frame * TRASHCAN_WIDTH, .y = 0.0, .width = TRASHCAN_WIDTH, .height = TRASHCAN_HEIGHT }; DrawBillboardRec( game->player.camera, game->assets.textures[TRASHCAN_TEXTURE], rect, entity->position, (Vector2){TRASHCAN_SCALE * (TRASHCAN_WIDTH / TRASHCAN_HEIGHT), TRASHCAN_SCALE}, WHITE); } void updateEntity(Entity* entity, Game* game) { DrawBoundingBox(entity->box, RED); switch (entity->id) { case OLD_MINT: DrawBillboard(game->player.camera, game->assets.textures[MINT_TEXTURE], entity->position, 1.0, WHITE); break; case STICKY_NICKEL: DrawBillboard(game->player.camera, game->assets.textures[NICKEL_TEXTURE], entity->position, 1.0, WHITE); break; case TREE: DrawBillboard(game->player.camera, game->assets.textures[TREE_TEXTURE], entity->position, TREE_SCALE, WHITE); break; case BUSH: DrawBillboard(game->player.camera, game->assets.textures[BUSH_TEXTURE], entity->position, BUSH_SCALE, WHITE); break; case FLOWER: DrawBillboard(game->player.camera, game->assets.textures[FLOWER_TEXTURE], entity->position, FLOWER_SCALE, WHITE); break; case POND: DrawPlane( Vector3Add(entity->position, (Vector3){0.0, POND_HEIGHT * 2.0, 0.0}), (Vector2){POND_SIZE * 2.5, POND_SIZE * 2.5}, BLUE); break; case SAMANTHA: updateSamantha(entity, game); break; case SAMANTHAS_SPOT: DrawModel(game->world.samanthasSpotFloor, Vector3Add(entity->position, (Vector3){0.0, -SAMANTHAS_SPOT_HEIGHT + 0.01, 0.0}), 1.0, WHITE); break; case TRASHCAN: updateTrashcan(entity, game); break; case TRASH: DrawBillboard(game->player.camera, game->assets.textures[TRASH_TEXTURE], entity->position, TRASH_SCALE, WHITE); break; case MEDICAL_TRASH: DrawBillboard(game->player.camera, game->assets.textures[MEDICAL_TRASH_TEXTURE], entity->position, MEDICAL_TRASH_SCALE, WHITE); break; case JOHN: DrawModel(game->assets.models[JOHN_MODEL], entity->position, 1.0, WHITE); break; case RON: DrawModel(game->assets.models[RON_MODEL], entity->position, 1.0, WHITE); break; default: break; } } void setEntityPosition(Entity* entity, Vector3 position) { Vector3 movedBy = Vector3Subtract(position, entity->position); entity->position = position; entity->box.min = Vector3Add(entity->box.min, movedBy); entity->box.max = Vector3Add(entity->box.max, movedBy); } void placeEntityOnGround(Entity* entity, const World* world) { Vector3 position = entity->position; position.y = getWorldHeightAtLocation( world, entity->position.x, entity->position.z); position.y += (entity->box.max.y - entity->box.min.y) / 2.0; setEntityPosition(entity, position); }