diff --git a/CMakeLists.txt b/CMakeLists.txt index 02646a0..9b72d22 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,12 +15,14 @@ set(SOURCES src/draw.c src/input.c src/level.c + src/editor.c src/player.c src/polarity.c ) set(ASSETS res/tileset.png + res/editor_cursor.png res/test.kble res/burn.kble res/bounce.kble diff --git a/inc/editor.h b/inc/editor.h new file mode 100644 index 0000000..a37cfa5 --- /dev/null +++ b/inc/editor.h @@ -0,0 +1,3 @@ +#pragma once + +void editor(void); diff --git a/inc/input.h b/inc/input.h index 9cf7c81..e4676e7 100644 --- a/inc/input.h +++ b/inc/input.h @@ -1,6 +1,18 @@ #pragma once -enum Key { K_LEFT, K_RIGHT, K_UP, K_DOWN, K_JUMP, K_POLARITY, K_EXIT, K_COUNT }; +enum Key { + K_LEFT, + K_RIGHT, + K_UP, + K_DOWN, + K_JUMP, + K_POLARITY, + K_EXIT, + K_EDITOR, + K_SCROLL_UP, + K_SCROLL_DOWN, + K_COUNT +}; enum KeyState { KS_UP, KS_DOWN, KS_PRESS }; struct Input { diff --git a/inc/level.h b/inc/level.h index 8c1790d..1777a64 100644 --- a/inc/level.h +++ b/inc/level.h @@ -28,11 +28,14 @@ void level_deinit(void); void level_load(int id); void level_reload(void); -void level_regen_visual_data(void); +void level_regen_visual_data(int editing); void level_next(void); void level_draw(void); +void level_draw_name(void); int level_get(int x, int y); int level_get_px(int x, int y); +void level_set(int x, int y, int v); struct Vec level_find(enum Tile); +struct Vec level_dim(void); diff --git a/inc/tile.h b/inc/tile.h index 74862a6..82c77fa 100644 --- a/inc/tile.h +++ b/inc/tile.h @@ -13,5 +13,6 @@ enum Tile { TILE_GRAV_U, TILE_GRAV_R, TILE_GRAV_L, + TILE_COUNT, TILE_OOB, }; diff --git a/res/editor_cursor.png b/res/editor_cursor.png new file mode 100644 index 0000000..6ce82c7 Binary files /dev/null and b/res/editor_cursor.png differ diff --git a/src/editor.c b/src/editor.c new file mode 100644 index 0000000..598ec4b --- /dev/null +++ b/src/editor.c @@ -0,0 +1,100 @@ +#include "editor.h" +#include "conf.h" +#include "input.h" +#include "level.h" +#include "tile.h" +#include "vec.h" +#include + +static int cx, cy; +static int ctile = 1; + +static void editor_update(void); +static void editor_draw(void); +static void draw_grid(void); +static void draw_cursor(void); + +void +editor(void) +{ + extern volatile int has_ticked; + level_regen_visual_data(1); + do { + editor_draw(); + editor_update(); + } while (!input_pressed(K_EDITOR)); + has_ticked = 0; + level_regen_visual_data(0); +} + +static void +editor_update(void) +{ + const struct Vec dim = level_dim(); + + input_update(); + + /* move cursor */ + cx += input_pressed(K_RIGHT) - input_pressed(K_LEFT); + cy += input_pressed(K_DOWN) - input_pressed(K_UP); + cx %= dim.x; + cx += dim.x * (cx < 0); + cy %= dim.y; + cy += dim.y * (cy < 0); + + /* select tile */ + ctile += input_pressed(K_SCROLL_UP) - input_pressed(K_SCROLL_DOWN); + ctile += (TILE_COUNT - 1) * (ctile < 1); + ctile %= TILE_COUNT; + ctile += !ctile; + + /* change the world */ + if (input_down(K_JUMP)) { + level_set(cx, cy, ctile); + level_regen_visual_data(1); + } + if (input_down(K_POLARITY)) { + level_set(cx, cy, 0); + level_regen_visual_data(1); + } +} + +static void +editor_draw(void) +{ + dclear(C_BLACK); + level_draw(); + draw_cursor(); + draw_grid(); + dupdate(); +} + +static void +draw_grid(void) +{ + int i; + + /* hlines */ + i = 0; + while (i += TILE_SIZE, i < DHEIGHT) + dhline(i, C_BLUE); + + /* vlines */ + i = DRAW_OFF_X; + while (i += TILE_SIZE, i < DWIDTH) + dvline(i, C_BLUE); +} + +static void +draw_cursor(void) +{ + const int dx = cx * TILE_SIZE + DRAW_OFF_X; + const int dy = cy * TILE_SIZE; + extern bopti_image_t bimg_editor_cursor, bimg_tileset; + const int tileset_width = bimg_tileset.width / TILE_SIZE; + + dimage(dx - TILE_SIZE / 2, dy - TILE_SIZE / 2, &bimg_editor_cursor); + dsubimage(dx, dy, &bimg_tileset, ctile % tileset_width * TILE_SIZE, + (int)(ctile / tileset_width) * TILE_SIZE, TILE_SIZE, + TILE_SIZE, 0); +} diff --git a/src/input.c b/src/input.c index 72f05e6..1846a8c 100644 --- a/src/input.c +++ b/src/input.c @@ -3,7 +3,8 @@ static struct Input input; static const int default_map[K_COUNT] = { - KEY_LEFT, KEY_RIGHT, KEY_UP, KEY_DOWN, KEY_SHIFT, KEY_ALPHA, KEY_EXIT}; + KEY_LEFT, KEY_RIGHT, KEY_UP, KEY_DOWN, KEY_SHIFT, + KEY_ALPHA, KEY_EXIT, KEY_F3, KEY_F2, KEY_F1}; void input_init(void) diff --git a/src/level.c b/src/level.c index 2bc538c..866c3be 100644 --- a/src/level.c +++ b/src/level.c @@ -53,7 +53,7 @@ level_load(int id) while (i-- > 0) level.data[i] = b->data[i]; polarity_reset(); - level_regen_visual_data(); + level_regen_visual_data(0); player_spawn(level.player); } @@ -73,7 +73,7 @@ level_next(void) } void -level_regen_visual_data(void) +level_regen_visual_data(int editing) { const int tileset_width = bimg_tileset.width / TILE_SIZE; int y = level.height; @@ -88,6 +88,7 @@ level_regen_visual_data(void) vd->img_x = tile % tileset_width * TILE_SIZE; vd->img_y = (int)(tile / tileset_width) * TILE_SIZE; vd->visible = tile != 0; + if (editing) continue; switch (tile) { case TILE_RED: vd->img_y += polarity() ? TILE_SIZE : 0; @@ -114,8 +115,11 @@ level_draw(void) 0); } } +} - /* level name */ +void +level_draw_name(void) +{ dprint_opt(DWIDTH - 4, DHEIGHT - 2, C_BLACK, C_NONE, DTEXT_RIGHT, DTEXT_BOTTOM, "%s", levels[level.id].name); } @@ -134,6 +138,13 @@ level_get_px(int x, int y) return level_get(x / TILE_SIZE, y / TILE_SIZE); } +void +level_set(int x, int y, int v) +{ + if (x < 0 || y < 0 || x >= level.width || y >= level.height) return; + level.data[x + y * level.width] = v; +} + struct Vec level_find(enum Tile t) { @@ -143,6 +154,12 @@ level_find(enum Tile t) return (struct Vec){i % level.width, i / level.width}; } +struct Vec +level_dim(void) +{ + return (struct Vec){level.width, level.height}; +} + static void level_free(void) { diff --git a/src/main.c b/src/main.c index 1532b01..81f7588 100644 --- a/src/main.c +++ b/src/main.c @@ -1,4 +1,5 @@ #include "conf.h" +#include "editor.h" #include "input.h" #include "level.h" #include "player.h" @@ -8,7 +9,7 @@ static struct Player player; static int timer; -static volatile int has_ticked; +volatile int has_ticked; static void init(void); static void deinit(void); @@ -68,6 +69,8 @@ update(void) { input_update(); player_update(&player); + /* enter editor */ + if (input_pressed(K_EDITOR)) editor(); } static void @@ -76,6 +79,7 @@ draw(void) dclear(C_BLACK); level_draw(); player_draw(&player); + level_draw_name(); dupdate(); } diff --git a/src/polarity.c b/src/polarity.c index f24905e..37a2eaf 100644 --- a/src/polarity.c +++ b/src/polarity.c @@ -13,7 +13,7 @@ void polarity_invert(void) { pol = !pol; - level_regen_visual_data(); + level_regen_visual_data(0); } void