From: Lukas Krickl Date: Tue, 3 Mar 2026 04:13:32 +0000 (+0100) Subject: camera: started work on camera scrolling. X-Git-Url: https://git.krickl.dev/?a=commitdiff_plain;h=8b6498fa39b3f2621c54c643d74ccc8ebe2cf87c;p=lrts%2F.git camera: started work on camera scrolling. The input scroll system currently is hard coded in i_input. This is likely not where it should remain but for now it works just fine. Changed docs for commands to explicitly mention commands should *only* affect gameplay and not contain anything related to menus or camera movement. --- diff --git a/src/i_input.c b/src/i_input.c index 441b3e6..a7cd748 100644 --- a/src/i_input.c +++ b/src/i_input.c @@ -42,13 +42,13 @@ void i_input_cursor_set(i32 x, i32 y) { } lrts_bool i_input_just_pressed(enum i_input_actions action) { - LRTS_UNUSED(action); - return LRTS_FALSE; + struct i_input_map_ent *e = &i_input_map.inputs[action]; + return e->pressed == 1 && !i_input_is_delayed(action); } lrts_bool i_input_held(enum i_input_actions action) { - LRTS_UNUSED(action); - return LRTS_FALSE; + struct i_input_map_ent *e = &i_input_map.inputs[action]; + return (e->pressed & 1) > 0 && !i_input_is_delayed(action); } lrts_bool i_input_double_press(enum i_input_actions action) { @@ -56,23 +56,62 @@ lrts_bool i_input_double_press(enum i_input_actions action) { return LRTS_FALSE; } +void i_input_delay_ticks(enum i_input_actions action, u32 tick_count) { + struct i_input_map_ent *e = &i_input_map.inputs[action]; + struct lrts_state *s = lrts_state(); + + e->delay_until_tick = s->tick_count + tick_count; +} + +lrts_bool i_input_is_delayed(enum i_input_actions action) { + struct lrts_state *s = lrts_state(); + struct i_input_map_ent *e = &i_input_map.inputs[action]; + + if (s->tick_count >= e->delay_until_tick) { + return LRTS_FALSE; + } + return LRTS_TRUE; +} + void i_input_poll(void) { u32 i; struct i_input_map_ent *e; p_poll_events(); i_input_update(); - /* translate inputs - * to command queue + /* + * handle inputs + * either directly or + * by translating to a commnad */ for (i = 0; i < I_INPUT_ACTION_LEN; i++) { e = &i_input_map.inputs[i]; LRTS_UNUSED(e); switch (i) { case I_INPUT_ACTION_CAMERA_UP: + if (i_input_held(i)) { + t_camera_scroll(&t_main_camera, 0, -10); + i_input_delay_ticks(i, 1); + } + break; case I_INPUT_ACTION_CAMERA_DOWN: + if (i_input_held(i)) { + t_camera_scroll(&t_main_camera, 0, 10); + i_input_delay_ticks(i, 1); + } + break; case I_INPUT_ACTION_CAMERA_LEFT: + if (i_input_held(i)) { + t_camera_scroll(&t_main_camera, -10, 0); + i_input_delay_ticks(i, 1); + } + break; case I_INPUT_ACTION_CAMERA_RIGHT: + if (i_input_held(i)) { + t_camera_scroll(&t_main_camera, 10, 0); + i_input_delay_ticks(i, 1); + } + break; case I_INPUT_ACTION_CURSOR_CLICK: case I_INPUT_ACTION_CURSOR_ACTION: case I_INPUT_ACTION_CURSOR_DRAG: diff --git a/src/i_input.h b/src/i_input.h index afa574a..bb8d975 100644 --- a/src/i_input.h +++ b/src/i_input.h @@ -50,6 +50,10 @@ struct i_input_map_ent { * the most recent state is in the rightmost bit */ u16 pressed; + + /* do not run again until the tick counter + * has reached this number */ + u32 delay_until_tick; }; /* map of all input actions to scanscodes */ @@ -90,6 +94,11 @@ lrts_bool i_input_double_press(enum i_input_actions action); */ void i_input_poll(void); +/* delays this action from beign treated as pressed for n ticks */ +void i_input_delay_ticks(enum i_input_actions action, u32 tick_count); + +/* tests if the input is delayed */ +lrts_bool i_input_is_delayed(enum i_input_actions action); /* inits the default for a keybind */ void i_input_map_init_default(enum i_input_actions action, diff --git a/src/p_r_sdl/p_draw.c b/src/p_r_sdl/p_draw.c index 468b1bd..2cb6750 100644 --- a/src/p_r_sdl/p_draw.c +++ b/src/p_r_sdl/p_draw.c @@ -18,7 +18,7 @@ u64 p_ticks_per_second(void) { } void p_draw_begin(void) { - SDL_FillSurfaceRect(r_target, NULL, 0x000000); + SDL_FillSurfaceRect(r_target, NULL, 0x0000FF); } void p_draw_end(void) { diff --git a/src/r_assets.c b/src/r_assets.c index f805170..b68499e 100644 --- a/src/r_assets.c +++ b/src/r_assets.c @@ -47,10 +47,12 @@ void r_asset_init_fallback_tile(void) { } void r_draw_solid_isometric_tile(i32 x, i32 y, r_color color) { + struct lrts_state *s = lrts_state(); u32 i = 0; u32 j = 0; r_color final_color; struct u_vec2 t = u_tile_to_screen(x, y); + t = u_screen_to_camera(&t_main_camera, t); /* converted origin point in isometric space */ @@ -61,9 +63,14 @@ void r_draw_solid_isometric_tile(i32 x, i32 y, r_color color) { r_draw_pixel(&r_framebuffer, t.x + i, t.y + j, final_color); } } + + if (s->debug) { + u_debug_draw_text(t.x, t.y, "%d/%d", x, y); + } } void r_draw_tile(struct t_tile *t, i32 x, i32 y) { + switch (t->type) { case T_TILE_TYPE_NONE: break; diff --git a/src/t_camera.c b/src/t_camera.c index e8e0b1c..bb60a64 100644 --- a/src/t_camera.c +++ b/src/t_camera.c @@ -15,7 +15,16 @@ struct t_camera t_camera_init(i32 viewport_x, i32 viewport_y) { void t_camera_scroll(struct t_camera *c, i32 by_x, i32 by_y) { c->x += by_x; c->y += by_y; - U_CLAMP(c->x, 0, c->viewport_x); - U_CLAMP(c->y, 0, c->viewport_y); + + /* TODO: calculate max viewport based on map */ + U_CLAMP(c->x, -4096, 4096); + U_CLAMP(c->y, -4096, 4096); } + +struct u_vec2 u_screen_to_camera(struct t_camera *c, struct u_vec2 v) { + v.x -= c->x; + v.y -= c->y; + + return v; +} diff --git a/src/t_camera.h b/src/t_camera.h index 73af3c7..347d349 100644 --- a/src/t_camera.h +++ b/src/t_camera.h @@ -17,4 +17,7 @@ struct t_camera t_camera_init(i32 viewport_x, i32 viewport_y); void t_camera_scroll(struct t_camera *c, i32 by_x, i32 by_y); +/* adjusts a screen coodrinate by the camera offset */ +struct u_vec2 u_screen_to_camera(struct t_camera *c, struct u_vec2 v); + #endif diff --git a/src/t_command.c b/src/t_command.c index 29dd1b9..5a84377 100644 --- a/src/t_command.c +++ b/src/t_command.c @@ -5,6 +5,7 @@ struct t_command_queue t_command_queue; u32 t_command_queue_process(void) { u32 i = 0; + u32 n_exec = 0; struct t_command *c; struct lrts_state *state = lrts_state(); @@ -17,16 +18,18 @@ u32 t_command_queue_process(void) { if (c->type == T_COMMAND_NONE || c->run_at_tick > state->tick_count) { break; } - t_command_exec(c); + if (t_command_exec(c)) { + n_exec++; + } } - return 0; + return n_exec; } lrts_bool t_command_exec(struct t_command *c) { if (c->type == T_COMMAND_NONE) { u_log(U_LOG_WARN, "Command of type none was passed to exec\n"); - return LRTS_TRUE; + return LRTS_FALSE; } c->type = T_COMMAND_NONE; diff --git a/src/t_command.h b/src/t_command.h index 0e92bf4..3667457 100644 --- a/src/t_command.h +++ b/src/t_command.h @@ -4,8 +4,15 @@ #include "u_defs.h" /** - * A command is an order for a unit. - * each unit has a command queue. + * A command is a serializable action. + * Commands must have the following properties: + * - they must be unique + * - they must be sorted by type, player and tick number + * - commands are executed as soon as tick number >= current tick + * - commands must represent all changes to the game state + * - commands are sent over the network for multiplayer + * - all coordinates inside the command buffer must be in world-space + * - commands must not include client-side only interactions such as menus or camera */ #define T_COMMANDS_MAX 0x4FF @@ -13,11 +20,7 @@ enum t_command_type { T_COMMAND_NONE = 0, /* no-op command */ - T_COMMAND_NOOP, - /* moves camera in the direction of a - * provided vector - */ - T_COMMAND_MOVE_CAMERA + T_COMMAND_NOOP }; enum t_command_flags { diff --git a/src/t_map.c b/src/t_map.c index 8e09900..4f3995c 100644 --- a/src/t_map.c +++ b/src/t_map.c @@ -36,6 +36,9 @@ void t_map_draw(struct t_map *m) { end.x = ((t_main_camera.x + t_main_camera.viewport_x) / R_TILE_W) * 2; end.y = ((t_main_camera.y + t_main_camera.viewport_y) / R_TILE_H) * 2; + start.x = 0; + start.y = 0; + for (i = start.x; i < end.x; i++) { for (j = start.y; j < end.y; j++) { r_draw_tile(&m->tiles[j * m->width + i], i, j); diff --git a/src/tests/t_command.c b/src/tests/t_command.c index 99ccef6..87b5a65 100644 --- a/src/tests/t_command.c +++ b/src/tests/t_command.c @@ -5,10 +5,10 @@ int test_t_command_push(void) { struct t_command t; u32 i = 0; - t.type = T_COMMAND_MOVE_CAMERA; + t.type = T_COMMAND_NONE; t_command_push(t); T_ASSERT(t_command_queue.idx == 1, ("write index moved\n")); - T_ASSERT(t_command_queue.buffer[0].type == T_COMMAND_MOVE_CAMERA, ("command written\n")); + T_ASSERT(t_command_queue.buffer[0].type == T_COMMAND_NONE, ("command written\n")); for (i = 0; i < T_COMMANDS_MAX+1; i++) { t_command_push(t); diff --git a/src/u_math.c b/src/u_math.c index 7e2b122..52908e5 100644 --- a/src/u_math.c +++ b/src/u_math.c @@ -13,7 +13,7 @@ struct u_vec2 u_vec2_mul(i32 n, struct u_vec2 v) { struct u_vec2 u_tile_to_screen(i32 x, i32 y) { struct u_vec2 r; - r.x = (x * R_TILE_W / 2) + (y * R_TILE_W / 2);; + r.x = (x * R_TILE_W / 2) + (y * R_TILE_W / 2); r.y = (y * R_TILE_H / 2) - (x * R_TILE_H / 2); return r;