Mercurial > molko
changeset 55:87b32293b95a
core: improve map_state organization
author | David Demelier <markand@malikania.fr> |
---|---|
date | Mon, 20 Jan 2020 13:38:05 +0100 |
parents | 779352498a8a |
children | 43d1102a367e |
files | src/main.c src/map_state.c src/map_state.h src/splashscreen.c |
diffstat | 4 files changed, 206 insertions(+), 139 deletions(-) [+] |
line wrap: on
line diff
--- a/src/main.c Sat Jan 18 15:27:40 2020 +0100 +++ b/src/main.c Mon Jan 20 13:38:05 2020 +0100 @@ -35,13 +35,25 @@ static void init(void) { + struct texture *image; + if (!sys_init()) error_fatal(); if (!window_init("Molko's Adventure", WINDOW_WIDTH, WINDOW_HEIGHT)) error_fatal(); + image = image_openf(sys_datapath("sprites/test-walk.png")); + + if (!image) + error_fatal(); + if (!map_open(&map_state_data.map.map, sys_datapath("maps/test.map"))) + error_fatal(); + + sprite_init(&map_state_data.player.sprite, image, 48, 48); + game_switch(&map_state); + /* Default state is splash screen */ - game_switch(&splashscreen_state); + //game_switch(&splashscreen_state); } static void
--- a/src/map_state.c Sat Jan 18 15:27:40 2020 +0100 +++ b/src/map_state.c Mon Jan 20 13:38:05 2020 +0100 @@ -81,20 +81,66 @@ [0xC] = 5 }; +/* + * Additional data that is not necessary to expose in map_state_data. + */ static struct { - struct map map; - struct walksprite player_sprite; - int player_x; - int player_y; - int player_orientation; - int view_x; - int view_y; - enum movement moving; -} data; + struct { + enum movement moving; + struct walksprite ws; + } player; + + struct { + int x; + int y; + unsigned int w; + unsigned int h; + } margin; +} cache; + +static void +center(void) +{ + map_state_data.view.x = map_state_data.player.x - (map_state_data.view.w / 2); + map_state_data.view.y = map_state_data.player.y - (map_state_data.view.h / 2); + + if (map_state_data.view.x < 0) + map_state_data.view.x = 0; + else if ((unsigned int)map_state_data.view.x > map_state_data.map.w - map_state_data.view.w) + map_state_data.view.x = map_state_data.map.w - map_state_data.view.w; + + if (map_state_data.view.y < 0) + map_state_data.view.y = 0; + else if ((unsigned int)map_state_data.view.y > map_state_data.map.h - map_state_data.view.h) + map_state_data.view.y = map_state_data.map.h - map_state_data.view.h; +} static void enter(void) { + /* Adjust map properties. */ + struct map *m = &map_state_data.map.map; + + if (!m->picture) + map_repaint(m); + + map_repaint(m); + map_state_data.map.w = texture_width(m->picture); + map_state_data.map.h = texture_height(m->picture); + + /* Adjust view. */ + map_state_data.view.w = window_width(); + map_state_data.view.h = window_height(); + + /* Adjust margin. */ + cache.margin.w = map_state_data.view.w - (MARGIN_WIDTH * 2); + cache.margin.h = map_state_data.view.h - (MARGIN_HEIGHT * 2); + + /* Center the view by default. */ + center(); + + /* Final bits. */ + walksprite_init(&cache.player.ws, &map_state_data.player.sprite, 300); } static void @@ -107,22 +153,22 @@ { switch (event->key.key) { case KEY_UP: - data.moving |= MOVING_UP; + cache.player.moving |= MOVING_UP; break; case KEY_RIGHT: - data.moving |= MOVING_RIGHT; + cache.player.moving |= MOVING_RIGHT; break; case KEY_DOWN: - data.moving |= MOVING_DOWN; + cache.player.moving |= MOVING_DOWN; break; case KEY_LEFT: - data.moving |= MOVING_LEFT; + cache.player.moving |= MOVING_LEFT; break; default: break; } - data.player_orientation = orientations[data.moving]; + map_state_data.player.angle = orientations[cache.player.moving]; } static void @@ -130,16 +176,16 @@ { switch (event->key.key) { case KEY_UP: - data.moving &= ~(MOVING_UP); + cache.player.moving &= ~(MOVING_UP); break; case KEY_RIGHT: - data.moving &= ~(MOVING_RIGHT); + cache.player.moving &= ~(MOVING_RIGHT); break; case KEY_DOWN: - data.moving &= ~(MOVING_DOWN); + cache.player.moving &= ~(MOVING_DOWN); break; case KEY_LEFT: - data.moving &= ~(MOVING_LEFT); + cache.player.moving &= ~(MOVING_LEFT); break; default: break; @@ -147,94 +193,106 @@ } static void +move_right(unsigned int delta) +{ + map_state_data.player.x += delta; + + if (map_state_data.player.x > (int)(cache.margin.x + cache.margin.w)) { + map_state_data.view.x = (map_state_data.player.x - map_state_data.view.w) + MARGIN_WIDTH; + + if (map_state_data.view.x >= (int)(map_state_data.map.w - map_state_data.view.w)) + map_state_data.view.x = map_state_data.map.w - map_state_data.view.w; + } + + if (map_state_data.player.x > (int)map_state_data.map.w - 48) + map_state_data.player.x = map_state_data.map.w - 48; +} + +static void +move_left(unsigned int delta) +{ + map_state_data.player.x -= delta; + + if (map_state_data.player.x < cache.margin.x) { + map_state_data.view.x = map_state_data.player.x - MARGIN_WIDTH; + + if (map_state_data.view.x < 0) + map_state_data.view.x = 0; + } + + if (map_state_data.player.x < 0) + map_state_data.player.x = 0; +} + +static void +move_down(unsigned int delta) +{ + map_state_data.player.y += delta; + + if (map_state_data.player.y > (int)(cache.margin.y + cache.margin.h)) { + map_state_data.view.y = (map_state_data.player.y - map_state_data.view.h) + MARGIN_HEIGHT; + + if (map_state_data.view.y >= (int)(map_state_data.map.h - map_state_data.view.h)) + map_state_data.view.y = map_state_data.map.h - map_state_data.view.h; + } + + if (map_state_data.player.y > (int)map_state_data.map.h - 48) + map_state_data.player.y = map_state_data.map.h - 48; +} + +static void +move_up(unsigned int delta) +{ + map_state_data.player.y -= delta; + + if (map_state_data.player.y < cache.margin.y) { + map_state_data.view.y = map_state_data.player.y - MARGIN_HEIGHT; + + if (map_state_data.view.y < 0) + map_state_data.view.y = 0; + } + + if (map_state_data.player.y < 0) + map_state_data.player.y = 0; +} + +static void move(unsigned int ticks) { /* This is the amount of pixels the player must move. */ const int delta = SPEED * ticks / SEC; - /* This is the view width which simply equals to the screen. */ - const unsigned int view_w = window_width(); - const unsigned int view_h = window_height(); - /* This is the rectangle within the view where users must be. */ - const int margin_x = data.view_x + MARGIN_WIDTH; - const int margin_y = data.view_y + MARGIN_HEIGHT; - const unsigned int margin_w = window_width() - (MARGIN_WIDTH * 2); - const unsigned int margin_h = window_height() - (MARGIN_HEIGHT * 2); - - /* This is map size. */ - const unsigned int map_w = texture_width(data.map.picture); - const unsigned int map_h = texture_height(data.map.picture); + cache.margin.x = map_state_data.view.x + MARGIN_WIDTH; + cache.margin.y = map_state_data.view.y + MARGIN_HEIGHT; int dx = 0; int dy = 0; - if (data.moving == 0) + if (cache.player.moving == 0) return; - if (data.moving & MOVING_UP) + if (cache.player.moving & MOVING_UP) dy = -1; - if (data.moving & MOVING_DOWN) + if (cache.player.moving & MOVING_DOWN) dy = 1; - if (data.moving & MOVING_LEFT) + if (cache.player.moving & MOVING_LEFT) dx = -1; - if (data.moving & MOVING_RIGHT) + if (cache.player.moving & MOVING_RIGHT) dx = 1; /* Move the player and adjust view if needed. */ - if (dx > 0) { - data.player_x += delta; - - if (data.player_x > (int)(margin_x + margin_w)) { - data.view_x = (data.player_x - view_w) + MARGIN_WIDTH; - - if (data.view_x >= (int)(map_w - view_w)) - data.view_x = map_w - view_w; - } - - if (data.player_x > (int)map_w - 48) - data.player_x = map_w - 48; - } else if (dx < 0) { - data.player_x -= delta; - - if (data.player_x < margin_x) { - data.view_x = data.player_x - MARGIN_WIDTH; - - if (data.view_x < 0) - data.view_x = 0; - } - - if (data.player_x < 0) - data.player_x = 0; - } + if (dx > 0) + move_right(delta); + else if (dx < 0) + move_left(delta); - if (dy > 0) { - data.player_y += delta; - - if (data.player_y > (int)(margin_y + margin_h)) { - data.view_y = (data.player_y - view_h) + MARGIN_HEIGHT; - - if (data.view_y >= (int)(map_h - view_h)) - data.view_y = map_h - view_h; - } + if (dy > 0) + move_down(delta); + else if (dy < 0) + move_up(delta); - if (data.player_y > (int)map_h - 48) - data.player_y = map_h - 48; - } else if (dy < 0) { - data.player_y -= delta; - - if (data.player_y < margin_y) { - data.view_y = data.player_y - MARGIN_HEIGHT; - - if (data.view_y < 0) - data.view_y = 0; - } - - if (data.player_y < 0) - data.player_y = 0; - } - - walksprite_update(&data.player_sprite, ticks); + walksprite_update(&cache.player.ws, ticks); } static void @@ -263,47 +321,16 @@ { painter_set_color(0x000000ff); painter_clear(); - map_repaint(&data.map); - map_draw(&data.map, data.view_x, data.view_y); - walksprite_draw(&data.player_sprite, data.player_orientation, data.player_x - data.view_x, data.player_y - data.view_y); + map_draw(&map_state_data.map.map, map_state_data.view.x, map_state_data.view.y); + walksprite_draw( + &cache.player.ws, + map_state_data.player.angle, + map_state_data.player.x - map_state_data.view.x, + map_state_data.player.y - map_state_data.view.y); painter_present(); } -static void -center(void) -{ - /* This is map size. */ - const unsigned int win_w = window_width(); - const unsigned int win_h = window_height(); - const unsigned int map_w = texture_width(data.map.picture); - const unsigned int map_h = texture_height(data.map.picture); - - data.view_x = data.player_x - (win_w / 2); - data.view_y = data.player_y - (win_h / 2); - - if (data.view_x < 0) - data.view_x = 0; - else if (data.view_x > (int)(map_w - win_w)) - data.view_x = map_w - win_w; - - if (data.view_y < 0) - data.view_y = 0; - else if (data.view_y > (int)(map_h - win_h)) - data.view_y = map_h - win_h; -} - -void -map_state_start(struct map *map, struct sprite *s) -{ - /* Copy essential. */ - data.map = *map; - data.player_x = map->origin_x; - data.player_y = map->origin_y; - - center(); - walksprite_init(&data.player_sprite, s, 250); - game_switch(&map_state); -} +struct map_state_data map_state_data; struct state map_state = { .enter = enter,
--- a/src/map_state.h Sat Jan 18 15:27:40 2020 +0100 +++ b/src/map_state.h Mon Jan 20 13:38:05 2020 +0100 @@ -24,23 +24,51 @@ * \brief State when player is on a map. */ -struct map; -struct sprite; +#include "map.h" +#include "sprite.h" + +/** + * \brief Data for the state. + * + * Update this structure before switching to this state. + */ +extern struct map_state_data { + /** + * Map properties. + */ + struct { + struct map map; /*!< (RO) The map definition */ + unsigned int w; /*!< (RO) Map width */ + unsigned int h; /*!< (RO) Map height */ + } map; + + /** + * Player position. + * + * If you adjust this structure, it is strictly encouraged to update + * the view as well. + */ + struct { + struct sprite sprite; /*!< (RW) The sprite to use */ + int x; /*!< (RO) Player position in x */ + int y; /*!< (RO) Player position in y */ + int angle; /*!< (RO) Player angle (see walksprite) */ + } player; + + /** + * Position and size of the view. + */ + struct { + int x; /*!< (RW) Position in x */ + int y; /*!< (RW) Position in y */ + unsigned int w; /*!< (RO) View width */ + unsigned int h; /*!< (RO) View height */ + } view; +} map_state_data; /*!< Access to data. */ /** * \brief State when player is on a map. */ extern struct state map_state; -/** - * Convenient function that switch game state with the given map. - * - * \pre map != NULL - * \pre sprite != NULL - * \param map the map to use (will take ownership) - * \param sprite the player sprite - */ -void -map_state_start(struct map *map, struct sprite *s); - #endif /* !MOLKO_MAP_STATE_H */