diff --git a/game.c b/game.c index f3fab79..907681d 100644 --- a/game.c +++ b/game.c @@ -50,6 +50,9 @@ struct enemy { struct enemy enemies[20] = {0}; size_t enemy_count = 0; +size_t player_health = 10; +char player_health_s[4] = " "; + void key_callback(int key, int scancode, int action, int mods) { (void) scancode; @@ -83,7 +86,25 @@ void cursor_position_callback(int xpos, int ypos) { mouse.y = ypos; } -void preview_closest(const struct bricks preview, struct brick *closest, size_t *min_dist) { +void enemy_closest_get(const struct enemy *enemies, const size_t enemy_count, size_t *closest_i, size_t *min_dist) { + *closest_i = -1; + *min_dist = (size_t)-1; + for (size_t i = 0; i < enemy_count; i++) { + if (!enemies[i].is_reachable) continue; + int active_x = active.front.x + mouse.x + DOMINO_WIDTH / 2; + int active_y = active.front.y + mouse.y + DOMINO_HEIGHT / 2; + int preview_x = camera.x + enemies[i].x * EYE_SIZE + EYE_SIZE / 2; + int preview_y = camera.y + enemies[i].y * EYE_SIZE + EYE_SIZE / 2; + size_t dist = (active_x - preview_x) * (active_x - preview_x) + (active_y - preview_y) * (active_y - preview_y); + if (*closest_i == (size_t)-1) *closest_i = i; + if (dist < *min_dist) { + *closest_i = i; + *min_dist = dist; + } + } +} + +void brick_preview_closest_get(const struct bricks preview, struct brick *closest, size_t *min_dist) { size_t min_dist_i = -1; *min_dist = (size_t)-1; for (size_t i = 0; i < preview.count; i++) { @@ -137,25 +158,60 @@ void mouse_button_callback(int button, int action, int mods) { has_active = 0; // get preview with minimal distance from active brick - size_t min_dist = -1; - struct brick closest = {0}; - preview_closest(preview, &closest, &min_dist); + size_t brick_preview_min_dist = -1; + struct brick brick_preview_closest = {0}; + brick_preview_closest_get(preview, &brick_preview_closest, &brick_preview_min_dist); - if (min_dist < EYE_SIZE * EYE_SIZE && preview.count) { - bricks_append(&bricks, closest); - for (size_t i = 0; i < enemy_count; i++) { - enemies[i].is_reachable |= VEC2_EQ(closest.front, enemies[i]) || VEC2_EQ(closest.back, enemies[i]); + size_t enemy_min_dist = -1; + size_t enemy_closest_i = -1; + if (active.front.vertical) enemy_closest_get(enemies, enemy_count, &enemy_closest_i, &enemy_min_dist); + + if (enemy_min_dist < brick_preview_min_dist && enemy_min_dist < EYE_SIZE * EYE_SIZE && enemy_count) { + enemies[enemy_closest_i].health -= active.front.val + 1; + if (enemies[enemy_closest_i].health <= 0) { + enemies[enemy_closest_i].health = 0; + for (size_t i = enemy_closest_i + 1; i < enemy_count; i++) { + enemies[i - 1] = enemies[i]; + } + enemy_count--; + enemies[enemy_count++] = (struct enemy) { + .attack = rand() % 6 + 1, + .health = rand() % 6 + 1, + .x = bricks.items.brick[bricks.count - 1].front.x + rand() % 8 - 4, + .y = bricks.items.brick[bricks.count - 1].front.y + rand() % 8 - 4, + .is_reachable = 0, + }; + for (size_t i = 0; i < bricks.count * 2; i++) { + if (VEC2_EQ(bricks.items.eye[i], enemies[enemy_count - 1])) { + enemies[enemy_count - 1].is_reachable = 1; + break; + } + } + for (size_t i = 0; i < 3; i++) { + hand[hand_count = MIN(hand_count + 1, 4)] = (struct brick) { + .front = {.val = rand() % 6}, + .back = {.val = rand() % 6}, + }; + } + } else { + player_health -= enemies[enemy_closest_i].attack - (active.back.val + 1); + sprintf(player_health_s, "%zu", player_health); } - hand[hand_count++] = (struct brick) { - .front = {.val = rand() % 6}, - .back = {.val = rand() % 6}, - }; - is_goal_reached |= VEC2_EQ(closest.front, goal) || VEC2_EQ(closest.back, goal); + } else if (brick_preview_min_dist < EYE_SIZE * EYE_SIZE && preview.count) { + bricks_append(&bricks, brick_preview_closest); + for (size_t i = 0; i < enemy_count; i++) { + enemies[i].is_reachable |= VEC2_EQ(brick_preview_closest.front, enemies[i]) || VEC2_EQ(brick_preview_closest.back, enemies[i]); + } + // hand[hand_count++] = (struct brick) { + // .front = {.val = rand() % 6}, + // .back = {.val = rand() % 6}, + // }; + is_goal_reached |= VEC2_EQ(brick_preview_closest.front, goal) || VEC2_EQ(brick_preview_closest.back, goal); for (size_t i = 0; i < bricks.count; i++) brick_print(bricks.items.brick[i]); } else { hand[hand_count++] = active; } - printf("dist: %d\n", closest.front.val); + printf("dist: %d\n", brick_preview_closest.front.val); preview.count = 0; } } @@ -176,6 +232,8 @@ void init(struct image canvas) { camera.x = canvas.width / 2; camera.y = canvas.height / 2; + sprintf(player_health_s, "%zu", player_health); + bricks_append( &bricks, (struct brick) { @@ -201,7 +259,7 @@ void init(struct image canvas) { } void render(struct image canvas) { - for (size_t i = 0; i < canvas.bufsize; i++) canvas.buf[i] = 0; + for (size_t i = 0; i < canvas.bufsize; i++) canvas.color[i] = (struct color) {0x12, 0x0b, 0x10, 0xFF}; // domino playground for (size_t i = 0; i < bricks.count; i++) { @@ -217,9 +275,13 @@ void render(struct image canvas) { draw_glyph(canvas, glyph_flag, camera.x + goal.x * EYE_SIZE + 3, camera.y + goal.y * EYE_SIZE + 3, (struct color) {255, 255, 0, 255}); for (size_t i = 0; i < enemy_count; i++) { - struct color color = {100, 0, 0, 255}; - if (enemies[i].is_reachable && has_active) { + // struct color color = {100, 0, 0, 255}; + struct color color = {0xFF, 0x00, 0x55, 0xFF}; + if (enemies[i].is_reachable) { color = (struct color) {255, 0, 0, 255}; + if (has_active) { + color = (struct color) {0, 0, 255, 255}; + } } draw_enemy(canvas, enemies[i], color); } @@ -252,7 +314,7 @@ void render(struct image canvas) { draw_text(canvas, "Drag Dominos from your inventory onto the chain to", 3, 2, (struct color) {255, 255, 255, 255}); draw_text(canvas, "reach the goal. Press [R] to rotate", 3, 9, (struct color) {255, 255, 255, 255}); draw_glyph(canvas, glyph_heart, 3, 20, (struct color) {255, 0, 0, 255}); - draw_text(canvas, "10", 10, 20, (struct color) {255, 255, 255, 255}); + draw_text(canvas, player_health_s, 10, 20, (struct color) {255, 255, 255, 255}); if (is_goal_reached) { draw_text(canvas, game_over, (canvas.width - (sizeof(game_over)-1) * 5) / 2, 20, (struct color) {255, 255, 255, 255});