add a sandbox level to test enemy behaviors
This commit is contained in:
parent
de57441d24
commit
0b0a667ce0
|
@ -47,6 +47,8 @@ set(ASSETS
|
|||
assets-cg/levels/lv1.txt
|
||||
assets-cg/levels/lv2.tmx
|
||||
assets-cg/levels/lv2.txt
|
||||
assets-cg/levels/lvsandbox.tmx
|
||||
assets-cg/levels/lvsandbox.txt
|
||||
# Menu
|
||||
assets-cg/menu_title.png
|
||||
assets-cg/menu_arrows.png
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.5" tiledversion="1.7.2" orientation="orthogonal" renderorder="right-down" width="24" height="11" tilewidth="16" tileheight="16" infinite="0" nextlayerid="3" nextobjectid="1">
|
||||
<map version="1.8" tiledversion="1.8.4" orientation="orthogonal" renderorder="right-down" width="24" height="11" tilewidth="16" tileheight="16" infinite="0" nextlayerid="3" nextobjectid="1">
|
||||
<tileset firstgid="1" source="../tilesets/lab.tsx"/>
|
||||
<layer id="1" name="Ground" width="24" height="11">
|
||||
<data encoding="csv">
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.8" tiledversion="1.8.4" orientation="orthogonal" renderorder="right-down" width="24" height="11" tilewidth="16" tileheight="16" infinite="0" nextlayerid="3" nextobjectid="1">
|
||||
<tileset firstgid="1" source="../tilesets/cavern.tsx"/>
|
||||
<layer id="1" name="Ground" width="24" height="11">
|
||||
<data encoding="csv">
|
||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||
2,2,2,2,2,7,15,8,7,8,7,16,8,7,15,7,7,16,8,2,2,2,2,2,
|
||||
2,2,2,2,2,4,4,14,14,6,3,3,3,3,6,4,4,14,4,2,2,2,2,2,
|
||||
2,2,2,2,2,14,14,5,3,3,3,5,5,3,3,3,5,4,4,2,2,2,2,2,
|
||||
2,2,2,2,2,3,5,3,3,3,4,5,5,4,3,3,3,5,3,2,2,2,2,2,
|
||||
2,2,2,2,2,5,3,3,6,5,5,6,6,5,5,6,3,3,5,2,2,2,2,2,
|
||||
2,2,2,2,2,3,5,3,3,3,4,5,5,4,3,3,3,5,3,2,2,2,2,2,
|
||||
2,2,2,2,2,14,4,5,3,3,3,5,5,3,3,3,5,4,14,2,2,2,2,2,
|
||||
2,2,2,2,2,4,14,4,4,6,3,3,3,3,6,14,14,4,4,2,2,2,2,2,
|
||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="2" name="Decorations" width="24" height="11">
|
||||
<data encoding="csv">
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,10,0,0,0,0,0,10,0,0,9,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
</data>
|
||||
</layer>
|
||||
</map>
|
|
@ -0,0 +1,8 @@
|
|||
name: Sandbox
|
||||
map: lvsandbox
|
||||
|
||||
player_spawn: 6,5
|
||||
|
||||
spawner: 17,5
|
||||
|
||||
wave: 1s 1*slime/1
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<tileset version="1.8" tiledversion="1.8.4" name="heaven" tilewidth="16" tileheight="16" tilecount="16" columns="8">
|
||||
<image source="heaven.png" width="128" height="32"/>
|
||||
</tileset>
|
|
@ -118,6 +118,9 @@ static enemy_t const * const enemies[] = {
|
|||
|
||||
enemy_t const *enemy_data(int enemy_id)
|
||||
{
|
||||
if(enemy_id < 1 || (size_t)enemy_id >= sizeof enemies / sizeof *enemies)
|
||||
return NULL;
|
||||
|
||||
return enemies[enemy_id];
|
||||
}
|
||||
|
||||
|
|
33
src/game.c
33
src/game.c
|
@ -350,9 +350,27 @@ int game_sort_entities(game_t const *g, entity_measure_t *measure,
|
|||
// Per-frame update functions
|
||||
//---
|
||||
|
||||
void game_spawn_enemies(game_t *g)
|
||||
void game_spawn_enemy(game_t *g, int identity, int spawner)
|
||||
{
|
||||
level_t const *level = g->level;
|
||||
|
||||
/* Select a random spawner if none is specified */
|
||||
if(spawner < 0)
|
||||
spawner = rand() % level->spawner_count;
|
||||
|
||||
entity_t *e = enemy_make(identity);
|
||||
g->wave_spawned++;
|
||||
if(!e) return;
|
||||
|
||||
physical_t *p = getcomp(e, physical);
|
||||
p->x = fix(level->spawner_x[spawner]) + fix(0.5);
|
||||
p->y = fix(level->spawner_y[spawner]) + fix(0.5);
|
||||
|
||||
game_spawn_entity(g, e);
|
||||
}
|
||||
|
||||
void game_spawn_enemies(game_t *g)
|
||||
{
|
||||
level_event_t const *event = game_current_event(g);
|
||||
level_wave_t const *wave = game_current_wave(g);
|
||||
if(!wave || !g->wave_left) return;
|
||||
|
@ -379,18 +397,7 @@ void game_spawn_enemies(game_t *g)
|
|||
return; /* just in case */
|
||||
g->wave_left[entry]--;
|
||||
|
||||
/* Select a random spawner */
|
||||
int s = rand() % level->spawner_count;
|
||||
|
||||
entity_t *e = enemy_make(wave->entries[entry].identity);
|
||||
g->wave_spawned++;
|
||||
if(!e) continue;
|
||||
|
||||
physical_t *p = getcomp(e, physical);
|
||||
p->x = fix(level->spawner_x[s]) + fix(0.5);
|
||||
p->y = fix(level->spawner_y[s]) + fix(0.5);
|
||||
|
||||
game_spawn_entity(g, e);
|
||||
game_spawn_enemy(g, wave->entries[entry].identity, -1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -96,6 +96,9 @@ void game_add_entity(game_t *g, entity_t *e);
|
|||
/* Like game_add_entity(), but with a visual effect */
|
||||
void game_spawn_entity(game_t *g, entity_t *e);
|
||||
|
||||
/* Spawn a new enemy into the arena. Spawner is selected randomly if -1. */
|
||||
void game_spawn_enemy(game_t *g, int identity, int spawner_id);
|
||||
|
||||
/* Remove dead entities. */
|
||||
void game_remove_dead_entities(game_t *g);
|
||||
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
#include "level.h"
|
||||
|
||||
level_t const *level_all[LEVEL_COUNT] = {
|
||||
&level_lv1,
|
||||
&level_lv2,
|
||||
&level_lvsandbox,
|
||||
};
|
||||
|
||||
int level_wave_count(level_t const *lv)
|
||||
{
|
||||
int wave_count = 0;
|
||||
|
|
|
@ -80,3 +80,7 @@ int level_wave_count(level_t const *lv);
|
|||
/* List of levels */
|
||||
extern level_t level_lv1;
|
||||
extern level_t level_lv2;
|
||||
extern level_t level_lvsandbox;
|
||||
|
||||
#define LEVEL_COUNT 3
|
||||
extern level_t const *level_all[LEVEL_COUNT];
|
||||
|
|
120
src/main.c
120
src/main.c
|
@ -53,18 +53,19 @@ int main(void)
|
|||
usb_open(interfaces, GINT_CALL_NULL);
|
||||
|
||||
int lv = menu_level_select(0);
|
||||
level_t const *level = NULL;
|
||||
if(lv == -1) return 1;
|
||||
|
||||
if(lv == 0) level = &level_lv1;
|
||||
if(lv == 1) level = &level_lv2;
|
||||
|
||||
game_t game = { 0 };
|
||||
camera_t *c = &game.camera;
|
||||
|
||||
game_load(&game, level);
|
||||
game_load(&game, level_all[lv]);
|
||||
|
||||
struct {
|
||||
/* Developer menu is open */
|
||||
bool dev_menu;
|
||||
/* Show developer submenus */
|
||||
bool dev_menu_view;
|
||||
bool dev_menu_spawn;
|
||||
/* Show variables */
|
||||
bool show_vars;
|
||||
/* Show hitboxes */
|
||||
|
@ -175,7 +176,7 @@ int main(void)
|
|||
fixed_t dt_rt = dt;
|
||||
if(bullet_time)
|
||||
dt >>= 2;
|
||||
if(debug.paused)
|
||||
if(debug.paused || debug.dev_menu)
|
||||
dt = dt_rt = 0;
|
||||
|
||||
perf_render = prof_make();
|
||||
|
@ -215,6 +216,42 @@ int main(void)
|
|||
dprint(15, 160, gray, "[)] -/+ [sin]");
|
||||
}
|
||||
|
||||
if(debug.dev_menu_view) {
|
||||
uint32_t *vram = (void *)gint_vram;
|
||||
for(int i = 0; i < DWIDTH * DHEIGHT / 2; i++)
|
||||
vram[i] = (vram[i] & 0xf7def7de) >> 1;
|
||||
|
||||
int fg = C_RGB(31, 31, 0);
|
||||
dprint(3, 25, debug.show_hitboxes ? fg : C_WHITE,
|
||||
"[1] Show hitboxes");
|
||||
dprint(3, 40, debug.show_bfs_field ? fg : C_WHITE,
|
||||
"[2] Show BFS field");
|
||||
dprint(3, 55, debug.show_path ? fg : C_WHITE,
|
||||
"[3] Show pathfinding to spawner");
|
||||
}
|
||||
|
||||
if(debug.dev_menu_spawn) {
|
||||
uint32_t *vram = (void *)gint_vram;
|
||||
for(int i = 0; i < DWIDTH * DHEIGHT / 2; i++)
|
||||
vram[i] = (vram[i] & 0xf7def7de) >> 1;
|
||||
|
||||
dprint(3, 25, C_WHITE, "Spawn an enemy");
|
||||
|
||||
for(int i = 0; i < 15; i++) {
|
||||
int x=12+124*(i/5), y=40+15*(i%5);
|
||||
enemy_t const *enemy = enemy_data(i+1);
|
||||
if(!enemy)
|
||||
continue;
|
||||
|
||||
anim_frame_t *frame = enemy->anim_idle->start[0];
|
||||
dprint(x, y, C_WHITE, "[%d]", i+1);
|
||||
dsubimage(x+20, y+4 - frame->h / 2, frame->sheet,
|
||||
frame->x, frame->y, frame->w, frame->h, DIMAGE_NONE);
|
||||
dprint(x+40, y, C_WHITE, "%s (lv. %d)", enemy->name,
|
||||
enemy->level);
|
||||
}
|
||||
}
|
||||
|
||||
if(debug.show_path) {
|
||||
if(debug.grid_path.points)
|
||||
for(int i = 0; i < debug.grid_path.length; i++) {
|
||||
|
@ -258,17 +295,17 @@ int main(void)
|
|||
dprint(1, 29, C_WHITE, "Simul: %.3D ms", time_simul);
|
||||
}
|
||||
|
||||
if(keydown(KEY_VARS)) {
|
||||
if(debug.dev_menu) {
|
||||
int fg = C_RGB(31, 31, 0);
|
||||
fkey_button(1, "PARAMS", debug.show_vars ? fg : C_WHITE);
|
||||
fkey_button(2, "HITBOX", debug.show_hitboxes ? fg : C_WHITE);
|
||||
fkey_button(3, "BFS", debug.show_bfs_field ? fg : C_WHITE);
|
||||
fkey_button(4, "PATHS", debug.show_path ? fg : C_WHITE);
|
||||
fkey_button(2, "VIEW", debug.dev_menu_view ? fg : C_WHITE);
|
||||
fkey_button(3, "SPAWN", debug.dev_menu_spawn ? fg : C_WHITE);
|
||||
fkey_button(4, "GOD", C_WHITE);
|
||||
fkey_button(5, "PERF", debug.show_perf ? fg : C_WHITE);
|
||||
fkey_button(6, "PAUSE", debug.paused ? fg : C_WHITE);
|
||||
}
|
||||
|
||||
if(keydown(KEY_F6) && keydown(KEY_ALPHA) && !keydown(KEY_VARS)
|
||||
if(keydown(KEY_F6) && keydown(KEY_ALPHA) && debug.dev_menu
|
||||
&& usb_is_open()) {
|
||||
rogue_life_video_capture = !rogue_life_video_capture;
|
||||
}
|
||||
|
@ -301,18 +338,52 @@ int main(void)
|
|||
stop = true;
|
||||
|
||||
/* Debug settings */
|
||||
// if(ev.key == KEY_F1 && keydown(KEY_VARS))
|
||||
// debug.show_vars ^= 1;
|
||||
if(ev.key == KEY_F2 && keydown(KEY_VARS))
|
||||
debug.show_hitboxes ^= 1;
|
||||
if(ev.key == KEY_F3 && keydown(KEY_VARS))
|
||||
debug.show_bfs_field ^= 1;
|
||||
if(ev.key == KEY_F4 && keydown(KEY_VARS))
|
||||
debug.show_path ^= 1;
|
||||
if(ev.key == KEY_F5 && keydown(KEY_VARS))
|
||||
if(ev.key == KEY_OPTN) {
|
||||
debug.dev_menu ^= 1;
|
||||
if(!debug.dev_menu) {
|
||||
debug.dev_menu_view = 0;
|
||||
debug.dev_menu_spawn = 0;
|
||||
}
|
||||
}
|
||||
/* Main debug menu entries */
|
||||
if(ev.key == KEY_F1 && debug.dev_menu)
|
||||
debug.show_vars ^= 1;
|
||||
if(ev.key == KEY_F2 && debug.dev_menu) {
|
||||
debug.dev_menu_view ^= 1;
|
||||
if(debug.dev_menu_view)
|
||||
debug.dev_menu_spawn = 0;
|
||||
}
|
||||
if(ev.key == KEY_F3 && debug.dev_menu) {
|
||||
debug.dev_menu_spawn ^= 1;
|
||||
if(debug.dev_menu_spawn)
|
||||
debug.dev_menu_view = 0;
|
||||
}
|
||||
if(ev.key == KEY_F4 && debug.dev_menu) {
|
||||
player_add_xp(game.player, 1000);
|
||||
fighter_invulnerability(game.player, fix(999.0));
|
||||
player_f->skills[1] = AOE_SHOCK;
|
||||
player_f->skills[2] = AOE_JUDGEMENT;
|
||||
player_f->skills[3] = SKILL_DASH;
|
||||
player_f->skills[4] = AOE_BULLET;
|
||||
}
|
||||
if(ev.key == KEY_F5 && debug.dev_menu)
|
||||
debug.show_perf ^= 1;
|
||||
if(ev.key == KEY_F6 && keydown(KEY_VARS))
|
||||
if(ev.key == KEY_F6 && debug.dev_menu)
|
||||
debug.paused ^= 1;
|
||||
if(ev.key == KEY_F2 && debug.dev_menu) {
|
||||
}
|
||||
/* Debug menu: View */
|
||||
if(ev.key == KEY_1 && debug.dev_menu_view)
|
||||
debug.show_hitboxes ^= 1;
|
||||
if(ev.key == KEY_2 && debug.dev_menu_view)
|
||||
debug.show_bfs_field ^= 1;
|
||||
if(ev.key == KEY_3 && debug.dev_menu_view)
|
||||
debug.show_path ^= 1;
|
||||
/* Debug menu: Spawn */
|
||||
if(keycode_digit(ev.key) >= 0 && debug.dev_menu_spawn) {
|
||||
int id = keycode_digit(ev.key);
|
||||
game_spawn_enemy(&game, id, -1);
|
||||
}
|
||||
|
||||
#if 0
|
||||
if(ev.key == KEY_XOT)
|
||||
|
@ -356,11 +427,12 @@ int main(void)
|
|||
camera_zoom(c, c->zoom - 1);
|
||||
#endif
|
||||
|
||||
if(!debug.paused && !game.menu_open && ev.key == KEY_SHIFT)
|
||||
if(!debug.paused && !game.menu_open && ev.key == KEY_SHIFT
|
||||
&& !debug.dev_menu)
|
||||
attack = true;
|
||||
|
||||
/* Menus */
|
||||
if(!debug.paused && ev.key == KEY_F6 && !keydown(KEY_VARS)
|
||||
if(!debug.paused && ev.key == KEY_F6 && !debug.dev_menu
|
||||
&& !keydown(KEY_ALPHA))
|
||||
game.menu_open = !game.menu_open;
|
||||
|
||||
|
@ -423,7 +495,7 @@ int main(void)
|
|||
|
||||
/* Player skills (including movement skills) */
|
||||
bool can_use_skill = !debug.paused && !game.menu_open
|
||||
&& player_f->HP > 0 && !keydown(KEY_VARS);
|
||||
&& player_f->HP > 0 && !debug.dev_menu;
|
||||
|
||||
if(can_use_skill && keydown(KEY_F1))
|
||||
skill_use(&game, player, 1, fdir(next_dir));
|
||||
|
|
|
@ -60,11 +60,11 @@ int menu_level_select(int start)
|
|||
{
|
||||
extern bopti_image_t img_menu_title, img_menu_arrows;
|
||||
|
||||
menu_game_t *options[2];
|
||||
#define OPTION_COUNT ((int)(sizeof options / sizeof options[0]))
|
||||
menu_game_t *options[LEVEL_COUNT];
|
||||
#define OPTION_COUNT LEVEL_COUNT
|
||||
|
||||
options[0] = menu_load_game(&level_lv1);
|
||||
options[1] = menu_load_game(&level_lv2);
|
||||
for(int i = 0; i < LEVEL_COUNT; i++)
|
||||
options[i] = menu_load_game(level_all[i]);
|
||||
|
||||
int selection = (start >= 0 && start < OPTION_COUNT) ? start : 0;
|
||||
int target_x=0, x=0;
|
||||
|
|
Loading…
Reference in New Issue