| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- // enemy.c
- #include <game/enemy.h>
- // Allocation function
- static EnemyContext *enemy_generic_alloc(const char *id, int index, float x, float y, float width, float height)
- {
- EnemyContext *context = malloc(sizeof(EnemyContext));
- if (!context)
- {
- FURI_LOG_E("Game", "Failed to allocate EnemyContext");
- return NULL;
- }
- snprintf(context->id, sizeof(context->id), "%s", id);
- context->index = index;
- context->x = x;
- context->y = y;
- context->width = width;
- context->height = height;
- // Initialize other fields as needed
- context->trajectory = (Vector){0, 0}; // Default trajectory
- context->sprite_right = NULL; // Assign appropriate sprite
- context->sprite_left = NULL; // Assign appropriate sprite
- context->is_looking_left = false;
- context->radius = 3.0f; // Default collision radius
- return context;
- }
- // Free function
- static void enemy_generic_free(void *context)
- {
- if (context != NULL)
- {
- EnemyContext *enemy_context = (EnemyContext *)context;
- // Free sprites if they were dynamically loaded
- if (enemy_context->sprite_right)
- {
- sprite_free(enemy_context->sprite_right);
- }
- if (enemy_context->sprite_left)
- {
- sprite_free(enemy_context->sprite_left);
- }
- free(context);
- }
- }
- // Enemy start function
- static void enemy_start(Entity *self, GameManager *manager, void *context)
- {
- UNUSED(manager);
- if (!self || !context)
- return;
- EnemyContext *enemy_context = (EnemyContext *)context;
- // Set enemy's initial position based on context
- entity_pos_set(self, (Vector){enemy_context->x, enemy_context->y});
- // Add collision circle based on the enemy's radius
- entity_collider_add_circle(self, enemy_context->radius);
- }
- // Enemy render function
- static void enemy_render(Entity *self, GameManager *manager, Canvas *canvas, void *context)
- {
- UNUSED(manager);
- if (!self || !context || !canvas)
- return;
- EnemyContext *enemy_context = (EnemyContext *)context;
- // Get the position of the enemy
- Vector pos = entity_pos_get(self);
- // Draw the enemy sprite based on their direction
- if (enemy_context->is_looking_left && enemy_context->sprite_left)
- {
- canvas_draw_sprite(canvas, enemy_context->sprite_left, pos.x, pos.y);
- }
- else if (enemy_context->sprite_right)
- {
- canvas_draw_sprite(canvas, enemy_context->sprite_right, pos.x, pos.y);
- }
- else
- {
- // Fallback if no sprite is set
- canvas_draw_disc(canvas, pos.x, pos.y, enemy_context->radius);
- }
- }
- // Enemy collision function
- static void enemy_collision(Entity *self, Entity *other, GameManager *manager, void *context)
- {
- UNUSED(self);
- UNUSED(context);
- // Check if the enemy collided with the player
- if (entity_description_get(other) == &player_desc)
- {
- // Increase score
- GameContext *game_context = game_manager_game_context_get(manager);
- if (game_context)
- {
- game_context->xp++;
- }
- // Move enemy to original position or handle respawn logic
- EnemyContext *enemy_context = (EnemyContext *)context;
- if (enemy_context)
- {
- entity_pos_set(self, (Vector){enemy_context->x, enemy_context->y});
- }
- }
- }
- // Enemy update function (optional)
- static void enemy_update(Entity *self, GameManager *manager, void *context)
- {
- if (!self || !context)
- return;
- UNUSED(manager);
- EnemyContext *enemy_context = (EnemyContext *)context;
- // Update position based on trajectory
- Vector pos = entity_pos_get(self);
- pos.x += enemy_context->trajectory.x;
- pos.y += enemy_context->trajectory.y;
- entity_pos_set(self, pos);
- // Example: Change direction if hitting boundaries
- if (pos.x < 0 || pos.x > WORLD_WIDTH)
- {
- enemy_context->trajectory.x *= -1;
- enemy_context->is_looking_left = !enemy_context->is_looking_left;
- }
- if (pos.y < 0 || pos.y > WORLD_HEIGHT)
- {
- enemy_context->trajectory.y *= -1;
- }
- }
- // Free function for the entity
- static void enemy_free(Entity *self, GameManager *manager, void *context)
- {
- UNUSED(self);
- UNUSED(manager);
- enemy_generic_free(context);
- }
- // Enemy behavior structure
- static const EntityDescription _generic_enemy = {
- .start = enemy_start,
- .stop = enemy_free,
- .update = enemy_update,
- .render = enemy_render,
- .collision = enemy_collision,
- .event = NULL,
- .context_size = sizeof(EnemyContext),
- };
- // Enemy function to return the entity description
- const EntityDescription *enemy(GameManager *manager, const char *id, int index, float x, float y, float width, float height, bool moving_left)
- {
- // Allocate a new EnemyContext with provided parameters
- EnemyContext *context = enemy_generic_alloc(id, index, x, y, width, height);
- if (!context)
- {
- return NULL;
- }
- char right_edited[64];
- char left_edited[64];
- snprintf(right_edited, sizeof(right_edited), "%s_right.fxbm", id);
- snprintf(left_edited, sizeof(left_edited), "%s_left.fxbm", id);
- context->sprite_right = game_manager_sprite_load(manager, right_edited);
- context->sprite_left = game_manager_sprite_load(manager, left_edited);
- // Set initial direction
- context->is_looking_left = moving_left; // Default direction
- // set trajectory
- context->trajectory = !moving_left ? (Vector){1.0f, 0.0f} : (Vector){-1.0f, 0.0f}; // Default trajectory
- return &_generic_enemy;
- }
|