more test waves, preparing skills, better HUD
This commit is contained in:
parent
fec8e3cab4
commit
8bca321d0f
|
@ -36,10 +36,10 @@ set(ASSETS
|
|||
assets-cg/levels/demo.txt
|
||||
assets-cg/levels/1.txt
|
||||
# HUD
|
||||
assets-cg/hud.png
|
||||
assets-cg/hud_life.png
|
||||
assets-cg/hud_wave.png
|
||||
assets-cg/hud_wave2.png
|
||||
assets-cg/hud_life.png
|
||||
assets-cg/hud_life2.png
|
||||
assets-cg/skillicons.png
|
||||
# Player animations
|
||||
assets-cg/player/player_up.aseprite
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
Before Width: | Height: | Size: 265 B After Width: | Height: | Size: 311 B |
Binary file not shown.
Before Width: | Height: | Size: 267 B |
Binary file not shown.
Before Width: | Height: | Size: 845 B After Width: | Height: | Size: 540 B |
|
@ -49,6 +49,10 @@ typedef struct {
|
|||
uint8_t combo_next;
|
||||
/* Delay until ideal time to start next hit */
|
||||
fixed_t combo_delay;
|
||||
/* Skill and item cooldowns (F2..F5).The "total" field is updated when
|
||||
switching skills/items. The base field is the dynamic value. */
|
||||
fixed_t actions_cooldown_total[5];
|
||||
fixed_t actions_cooldown[5];
|
||||
|
||||
} entity_player_t;
|
||||
|
||||
|
|
|
@ -79,6 +79,7 @@ void game_next_wave(game_t *g)
|
|||
g->wave++;
|
||||
g->wave_spawned = 0;
|
||||
g->time_wave = fix(0);
|
||||
g->time_victory = fix(0);
|
||||
}
|
||||
|
||||
//---
|
||||
|
|
45
src/level.c
45
src/level.c
|
@ -9,9 +9,23 @@ level_t lv_demo = {
|
|||
.map = &lv_map_demo,
|
||||
};
|
||||
|
||||
/* Notation that would be very cool:
|
||||
|
||||
- slime/1 ;
|
||||
| slime/1 ;
|
||||
slime/1 ;
|
||||
| slime/1 ;
|
||||
slime/2 ;
|
||||
| slime/2 ;
|
||||
- slime/2 | slime/2 ;
|
||||
bat/1 | bat/1 ;
|
||||
|
||||
Each - bullet is a wave, with ';' separating "instants". Default is
|
||||
increments of 0.5 unless specified otherwise or @<time> */
|
||||
|
||||
level_t lv_1 = {
|
||||
.map = &lv_map_1,
|
||||
.wave_count = 2,
|
||||
.wave_count = 5,
|
||||
.waves = (level_wave_t []){
|
||||
/* Wave 1: Just some slimes */
|
||||
{ .enemy_count = 6,
|
||||
|
@ -31,5 +45,34 @@ level_t lv_1 = {
|
|||
{ ENEMY_BAT, 1, 2,1, fix(1.0) },
|
||||
{ ENEMY_BAT, 1, 19,9, fix(1.0) },
|
||||
}},
|
||||
/* Wave 3: Strong, fast bats */
|
||||
{ .enemy_count = 4,
|
||||
.enemies = (level_wave_spawn_t []) {
|
||||
{ ENEMY_BAT, 2, 2,1, fix(0.0) },
|
||||
{ ENEMY_BAT, 2, 19,9, fix(0.5) },
|
||||
{ ENEMY_BAT, 2, 2,1, fix(1.0) },
|
||||
{ ENEMY_BAT, 2, 19,9, fix(1.5) },
|
||||
}},
|
||||
/* Wave 4: A hurl of slimes, with bats to harass you */
|
||||
{ .enemy_count = 12,
|
||||
.enemies = (level_wave_spawn_t []) {
|
||||
{ ENEMY_SLIME, 2, 2,1, fix(0.00) },
|
||||
{ ENEMY_SLIME, 2, 19,9, fix(0.00) },
|
||||
{ ENEMY_SLIME, 2, 2,1, fix(0.25) },
|
||||
{ ENEMY_SLIME, 2, 19,9, fix(0.25) },
|
||||
{ ENEMY_SLIME, 2, 2,1, fix(0.50) },
|
||||
{ ENEMY_SLIME, 2, 19,9, fix(0.50) },
|
||||
{ ENEMY_SLIME, 2, 2,1, fix(0.75) },
|
||||
{ ENEMY_SLIME, 2, 19,9, fix(0.75) },
|
||||
{ ENEMY_SLIME, 2, 2,1, fix(1.00) },
|
||||
{ ENEMY_SLIME, 2, 19,9, fix(1.00) },
|
||||
{ ENEMY_BAT, 3, 2,1, fix(2.00) },
|
||||
{ ENEMY_BAT, 3, 19,9, fix(2.00) },
|
||||
}},
|
||||
/* Wave 5: Stronger first boss */
|
||||
{ .enemy_count = 1,
|
||||
.enemies = (level_wave_spawn_t []) {
|
||||
{ ENEMY_BAT, 5, 2,1, fix(0.0) },
|
||||
}},
|
||||
},
|
||||
};
|
||||
|
|
11
src/main.c
11
src/main.c
|
@ -477,6 +477,17 @@ int main(void)
|
|||
player->current_attack = area;
|
||||
player->attack_follows_movement = false;
|
||||
}
|
||||
/* Ideas for additional skills:
|
||||
- Freeze enemies
|
||||
- Barrier around player
|
||||
- Teleport
|
||||
- Time manipulation
|
||||
- Player buuffs (short but strong) or wide area debuggs
|
||||
Ideas for items:
|
||||
- Healing potion
|
||||
- Equipment
|
||||
- XP boosts
|
||||
- Weaker but longer-lasting buffs */
|
||||
|
||||
/* Remove dead entities first as it will kill their attack areas */
|
||||
game_remove_dead_entities(&game);
|
||||
|
|
44
src/render.c
44
src/render.c
|
@ -29,8 +29,8 @@ void camera_init(camera_t *c, map_t const *m)
|
|||
c->x = (c->limits.x_min + c->limits.x_max) / 2;
|
||||
c->y = (c->limits.y_min + c->limits.y_max) / 2;
|
||||
|
||||
/* Slightly off-center to add space for the HUD */
|
||||
c->y -= fix(0.375);
|
||||
/* Vertical adjustment to add space for the HUD */
|
||||
c->y -= fix(0);
|
||||
}
|
||||
|
||||
ipoint_t camera_map2screen(camera_t const *c, fpoint_t p)
|
||||
|
@ -226,32 +226,27 @@ void render_game(game_t const *g, bool show_hitboxes)
|
|||
for(int i = 0; i < g->entity_count; i++)
|
||||
enemies_left += (g->entities[i]->identity != 0);
|
||||
|
||||
extern bopti_image_t img_hud_wave, img_hud_wave2;
|
||||
dimage(DWIDTH - img_hud_wave.width, 17, &img_hud_wave);
|
||||
int fill_length = (img_hud_wave2.width * enemies_left) /
|
||||
g->level->waves[g->wave-1].enemy_count;
|
||||
dsubimage(DWIDTH - fill_length, 17, &img_hud_wave2,
|
||||
img_hud_wave2.width - fill_length, 0, fill_length,
|
||||
img_hud_wave2.height, DIMAGE_NONE);
|
||||
|
||||
if(g->wave_spawned < game_current_wave(g)->enemy_count)
|
||||
dprint_opt(DWIDTH - 4, 2, C_WHITE, C_NONE, DTEXT_RIGHT, DTEXT_TOP,
|
||||
dprint_opt(DWIDTH/2, 2, C_WHITE, C_NONE, DTEXT_CENTER, DTEXT_TOP,
|
||||
"Wave %d is preppin' up...", g->wave,
|
||||
game_current_wave(g)->enemy_count - g->wave_spawned);
|
||||
else if(enemies_left > 0)
|
||||
dprint_opt(DWIDTH - 4, 2, C_WHITE, C_NONE, DTEXT_RIGHT, DTEXT_TOP,
|
||||
dprint_opt(DWIDTH/2, 2, C_WHITE, C_NONE, DTEXT_CENTER, DTEXT_TOP,
|
||||
"Wave %d is here for you!", g->wave, enemies_left);
|
||||
else
|
||||
dprint_opt(DWIDTH - 4, 2, C_WHITE, C_NONE, DTEXT_RIGHT, DTEXT_TOP,
|
||||
dprint_opt(DWIDTH/2, 2, C_WHITE, C_NONE, DTEXT_CENTER, DTEXT_TOP,
|
||||
"Victory! For now...", g->wave);
|
||||
|
||||
entity_t const *player = g->player;
|
||||
dprint(2, 2, C_WHITE, "HP: %d/%d", player->HP, player->HP_max);
|
||||
/* Render HUD */
|
||||
extern bopti_image_t img_hud;
|
||||
dimage(0, DHEIGHT - img_hud.height, &img_hud);
|
||||
|
||||
extern bopti_image_t img_hud_life, img_hud_life2;
|
||||
dimage(0, 17, &img_hud_life);
|
||||
fill_length = (img_hud_life2.width * player->HP) / player->HP_max;
|
||||
dsubimage(0, 17, &img_hud_life2, 0, 0, fill_length, img_hud_life2.height,
|
||||
/* Render life bar */
|
||||
extern bopti_image_t img_hud_life;
|
||||
entity_t const *player = g->player;
|
||||
int fill_height = (img_hud_life.height * player->HP) / player->HP_max;
|
||||
dsubimage(184, DHEIGHT - 5 - fill_height, &img_hud_life,
|
||||
0, img_hud_life.height - fill_height, img_hud_life.width, fill_height,
|
||||
DIMAGE_NONE);
|
||||
|
||||
/* Render skill icons */
|
||||
|
@ -264,12 +259,15 @@ void render_game(game_t const *g, bool show_hitboxes)
|
|||
cooldown_remaining = -player->movement.dash;
|
||||
}
|
||||
else if(i > 0) {
|
||||
cooldown_remaining=fix(1);
|
||||
cooldown_total = player->player->actions_cooldown_total[i-1];
|
||||
cooldown_remaining = player->player->actions_cooldown[i-1];
|
||||
}
|
||||
|
||||
int x=15+68*i, y=DHEIGHT-27, bg=(cooldown_remaining!=0);
|
||||
dsubimage(x, y, &img_skillicons, 23*bg, 0, 23, 23, DIMAGE_NONE);
|
||||
dsubimage(x, y, &img_skillicons, 23*(i+2), 0, 23, 23, DIMAGE_NONE);
|
||||
int x = 33 + 44*i + 84*(i>=3);
|
||||
int y = DHEIGHT - 29;
|
||||
int bg = (cooldown_remaining != 0);
|
||||
dsubimage(x+2, y+2, &img_skillicons, 19*bg, 0, 19, 19, DIMAGE_NONE);
|
||||
dsubimage(x+2, y+2, &img_skillicons, 19*(i+2), 0, 19, 19, DIMAGE_NONE);
|
||||
|
||||
/* Darken the area representing remaining cooldown */
|
||||
if(cooldown_total != 0) {
|
||||
|
|
Loading…
Reference in New Issue