commit 34267decfdf74e85e5b74df2d07cfaf43c531275
parent daadafd033e5442fbd78ef33c5c3f96f52b36767
Author: Sophie <info@soophie.de>
Date: Mon, 16 Dec 2024 13:16:44 +0100
feat: Added doors & updated levels
Diffstat:
9 files changed, 175 insertions(+), 36 deletions(-)
diff --git a/assets/background.png b/assets/background.png
Binary files differ.
diff --git a/assets/tiles.png b/assets/tiles.png
Binary files differ.
diff --git a/include/door.h b/include/door.h
@@ -0,0 +1,21 @@
+#pragma once
+
+typedef struct Door door_t;
+
+#include "game.h"
+#include "util.h"
+
+#define DOOR_COUNTDOWN 20
+
+struct Door {
+ pos_t pos;
+ bool is_locked;
+ int countdown;
+};
+
+door_t *door_create(pos_t pos);
+void door_update(door_t *door, game_t *game);
+void door_draw(door_t *door, game_t *game);
+void door_free(door_t *door);
+
+bool door_unlock(door_t *door, game_t *game);
diff --git a/include/entity.h b/include/entity.h
@@ -5,10 +5,12 @@ typedef struct Entity entity_t;
#include "enemy.h"
#include "gate.h"
#include "game.h"
+#include "door.h"
typedef enum {
ENTITY_ENEMY,
ENTITY_GATE,
+ ENTITY_DOOR,
} entity_e;
struct Entity {
@@ -16,7 +18,9 @@ struct Entity {
union {
enemy_t *enemy;
gate_t *gate;
+ door_t *door;
};
+ bool is_bad;
};
entity_t *entity_create(entity_e type);
diff --git a/src/door.c b/src/door.c
@@ -0,0 +1,65 @@
+#include <stdlib.h>
+
+#include "../include/door.h"
+#include "../include/const.h"
+
+door_t *door_create(pos_t pos) {
+ door_t *door = malloc(sizeof(door_t));
+ door->pos = pos;
+ door->is_locked = true;
+ door->countdown = 0;
+ return door;
+}
+
+void door_update(door_t *door, game_t *game) {
+ (void) game;
+ if (door->countdown > 0) {
+ door->countdown--;
+ }
+}
+
+void door_draw(door_t *door, game_t *game) {
+ if (door->is_locked) {
+ DrawTextureRec(game->assets.tiles, texture_rect(1, 2, TILE_WIDTH, TILE_HEIGHT), (pos_t) { door->pos.x, door->pos.y - TILE_HEIGHT }, WHITE);
+ DrawTextureRec(game->assets.tiles, texture_rect(1, 3, TILE_WIDTH, TILE_HEIGHT), door->pos, WHITE);
+ if (door->countdown > 0) {
+ pos_t lock_pos = {
+ .x = door->pos.x,
+ .y = door->pos.y - 2 * TILE_HEIGHT,
+ };
+ DrawTextureRec(game->assets.tiles, texture_rect(3, 1, TILE_WIDTH, TILE_HEIGHT), lock_pos, WHITE);
+ }
+ }
+ else {
+ DrawTextureRec(game->assets.tiles, texture_rect(2, 2, TILE_WIDTH, TILE_HEIGHT), (pos_t) { door->pos.x, door->pos.y - TILE_HEIGHT }, WHITE);
+ DrawTextureRec(game->assets.tiles, texture_rect(2, 3, TILE_WIDTH, TILE_HEIGHT), door->pos, WHITE);
+ }
+}
+
+void door_free(door_t *door) {
+ free(door);
+}
+
+bool door_unlock(door_t *door, game_t *game) {
+ if (!door->is_locked) {
+ return true;
+ }
+ int enemies_len = 0;
+ bool gates_frozen = true;
+ for (int i = 0; i < game->entities_len; i++) {
+ if(game->entities[i].type == ENTITY_ENEMY) {
+ enemies_len++;
+ }
+ if(game->entities[i].type == ENTITY_GATE) {
+ if (!game->entities[i].gate->frozen) {
+ gates_frozen = false;
+ }
+ }
+ }
+ if (enemies_len == 0 && gates_frozen) {
+ door->is_locked = false;
+ return true;
+ }
+ door->countdown = DOOR_COUNTDOWN;
+ return false;
+}
diff --git a/src/entity.c b/src/entity.c
@@ -3,10 +3,22 @@
#include "../include/entity.h"
#include "../include/enemy.h"
#include "../include/gate.h"
+#include "../include/door.h"
entity_t *entity_create(entity_e type) {
entity_t *entity = malloc(sizeof(entity_t));
entity->type = type;
+ switch (entity->type) {
+ case ENTITY_ENEMY:
+ entity->is_bad = true;
+ break;
+ case ENTITY_GATE:
+ entity->is_bad = true;
+ break;
+ case ENTITY_DOOR:
+ entity->is_bad = false;
+ break;
+ }
return entity;
}
@@ -18,6 +30,9 @@ void entity_update(entity_t *entity, game_t *game) {
case ENTITY_GATE:
gate_update(entity->gate, game);
break;
+ case ENTITY_DOOR:
+ door_update(entity->door, game);
+ break;
}
}
@@ -29,6 +44,9 @@ void entity_draw(entity_t *entity, game_t *game) {
case ENTITY_GATE:
gate_draw(entity->gate, game);
break;
+ case ENTITY_DOOR:
+ door_draw(entity->door, game);
+ break;
}
}
@@ -40,6 +58,9 @@ void entity_detach(entity_t *entity) {
case ENTITY_GATE:
gate_free(entity->gate);
break;
+ case ENTITY_DOOR:
+ door_free(entity->door);
+ break;
}
}
diff --git a/src/game.c b/src/game.c
@@ -58,8 +58,9 @@ void game_update(game_t *game) {
// defeat
if (game->defeat) {
if (game->sceen_timer == 100) {
+ level_e level = game->level->type;
level_unload(game);
- level_load(game, LEVEL_1);
+ level_load(game, level);
game->defeat = false;
game->xp = 0;
game->sceen_timer = 0;
@@ -69,34 +70,19 @@ void game_update(game_t *game) {
}
}
// victory
- int enemies_len = 0;
- bool gates_frozen = true;
- for (int i = 0; i < game->entities_len; i++) {
- if(game->entities[i].type == ENTITY_ENEMY) {
- enemies_len++;
- }
- if(game->entities[i].type == ENTITY_GATE) {
- if (!game->entities[i].gate->frozen) {
- gates_frozen = false;
+ if (game->victory) {
+ if (game->sceen_timer == 100) {
+ if (game->level->type < LEVELS) {
+ level_e level = game->level->type;
+ level++;
+ level_unload(game);
+ level_load(game, level);
}
+ game->victory = false;
+ game->sceen_timer = 0;
}
- }
- if (enemies_len == 0 && gates_frozen) {
- game->victory = true;
- if (game->victory) {
- if (game->sceen_timer == 100) {
- if (game->level->type < LEVELS) {
- level_e level = game->level->type;
- level++;
- level_unload(game);
- level_load(game, level);
- }
- game->victory = false;
- game->sceen_timer = 0;
- }
- else {
- game->sceen_timer++;
- }
+ else {
+ game->sceen_timer++;
}
}
if (!game->victory && !game->defeat) {
diff --git a/src/level.c b/src/level.c
@@ -14,12 +14,12 @@ const char *LEVEL_MAP_1 = {
"........................"
"........................"
"......e......3.........."
- "....xxxx................"
+ "....xxxxx..............."
".....b.................."
"...........--...xxx....."
"................e......."
"...........2...--xxxxx.."
- "....p..................."
+ "....p....u.............."
"..xxxxxxxxx---xxxxxxxx.."
"........................"
"........................"
@@ -30,7 +30,7 @@ const char *LEVEL_MAP_2 = {
"........................"
"......3....b............"
"........................"
- "........................"
+ "................u......."
"...............xxxx....."
"..o......s.e............"
".......xxxxxxtxxx--xx..."
@@ -51,8 +51,8 @@ const char *LEVEL_MAP_3 = {
"............-txx-......."
".............w.........."
"............-w..-......."
- "........s....w.........."
- "..x---xxxxxxxtxxx--xx..."
+ "........s....w......u..."
+ "..x---xxxxxxxtxxx--xxx.."
"....e........w....e....."
"...---....2..w--txxx...."
"....3........w..w......."
@@ -176,6 +176,7 @@ void level_generate(game_t *game, const char *map, int width, int height) {
game->entities[game->entities_len] = (entity_t) {
.type = ENTITY_ENEMY,
.enemy = enemy,
+ .is_bad = true,
};
game->entities_len++;
break;
@@ -189,6 +190,21 @@ void level_generate(game_t *game, const char *map, int width, int height) {
game->entities[game->entities_len] = (entity_t) {
.type = ENTITY_GATE,
.gate = gate,
+ .is_bad = true,
+ };
+ game->entities_len++;
+ break;
+ }
+ case 'u': {
+ game->entities = realloc(game->entities, sizeof(enemy_t) * (game->entities_len + 1));
+ door_t *door = door_create((pos_t) {
+ .x = x * TILE_WIDTH + (TILE_WIDTH - ENEMY_WIDTH) / 2.0,
+ .y = y * TILE_HEIGHT,
+ });
+ game->entities[game->entities_len] = (entity_t) {
+ .type = ENTITY_DOOR,
+ .door = door,
+ .is_bad = false,
};
game->entities_len++;
break;
diff --git a/src/player.c b/src/player.c
@@ -248,6 +248,10 @@ void player_update(player_t *player, game_t *game) {
if (entity->type == ENTITY_GATE && entity->gate->frozen) {
continue;
}
+ // ignore non-bad entities
+ if (!entity->is_bad) {
+ continue;
+ }
rect_t entity_rect;
switch (entity->type) {
case ENTITY_ENEMY:
@@ -256,6 +260,9 @@ void player_update(player_t *player, game_t *game) {
case ENTITY_GATE:
entity_rect = rect_from_pos((pos_t) { entity->gate->pos.x, entity->gate->pos.y - TILE_HEIGHT }, ENEMY_WIDTH, ENEMY_HEIGHT);
break;
+ case ENTITY_DOOR:
+ entity_rect = rect_from_pos((pos_t) { entity->gate->pos.x, entity->gate->pos.y - TILE_HEIGHT }, ENEMY_WIDTH, ENEMY_HEIGHT);
+ break;
}
if (rect_collide(shooting_rect, entity_rect)) {
float entity_x = entity_rect.x + entity_rect.width / 2.0;
@@ -314,8 +321,8 @@ void player_update(player_t *player, game_t *game) {
float tolerance = 0.0;
if (
player->pos.x <= enemy->pos.x + ENEMY_WIDTH - tolerance &&
- player->pos.x + PLAYER_WIDTH >= enemy->pos.x + tolerance &&
- player->pos.y <= enemy->pos.y + ENEMY_HEIGHT - tolerance &&
+ player->pos.x + PLAYER_WIDTH >= enemy->pos.x + tolerance &&
+ player->pos.y <= enemy->pos.y + ENEMY_HEIGHT - tolerance &&
player->pos.y + PLAYER_HEIGHT >= enemy->pos.y + tolerance
) {
if (player->held_enemy == NULL) {
@@ -336,6 +343,25 @@ void player_update(player_t *player, game_t *game) {
.y = player->pos.y - (player->sneaking ? 0.3 : 0.5) * TILE_HEIGHT,
};
}
+ // detect door entering
+ if (holding) {
+ for (int i = 0; i < game->entities_len; i++) {
+ if (game->entities[i].type == ENTITY_DOOR) {
+ door_t *door = game->entities[i].door;
+ float tolerance = 0.0;
+ if (
+ player->pos.x <= door->pos.x + ENEMY_WIDTH - tolerance &&
+ player->pos.x + PLAYER_WIDTH >= door->pos.x + tolerance &&
+ player->pos.y <= door->pos.y + ENEMY_HEIGHT - tolerance &&
+ player->pos.y + PLAYER_HEIGHT >= door->pos.y + tolerance
+ ) {
+ if (door_unlock(door, game)) {
+ game->victory = true;
+ }
+ }
+ }
+ }
+ }
// detect damage
for (int i = 0; i < game->entities_len; i++) {
if (game->entities[i].type == ENTITY_ENEMY) {
@@ -344,8 +370,8 @@ void player_update(player_t *player, game_t *game) {
float tolerance = TILE_WIDTH / 5.0;
if (
player->pos.x <= enemy->pos.x + ENEMY_WIDTH - tolerance &&
- player->pos.x + PLAYER_WIDTH >= enemy->pos.x + tolerance &&
- player->pos.y <= enemy->pos.y + ENEMY_HEIGHT - tolerance &&
+ player->pos.x + PLAYER_WIDTH >= enemy->pos.x + tolerance &&
+ player->pos.y <= enemy->pos.y + ENEMY_HEIGHT - tolerance &&
player->pos.y + PLAYER_HEIGHT >= enemy->pos.y + tolerance
) {
if (player->damage_timer == 0) {