diff options
| author | 3gg <3gg@shellblade.net> | 2025-09-04 18:41:08 -0700 |
|---|---|---|
| committer | 3gg <3gg@shellblade.net> | 2025-09-04 18:41:08 -0700 |
| commit | 1f2d5b4fcfe59e36b8c0a9fec1551b42432397bb (patch) | |
| tree | a70968fbef6dbe2c5606ee4db5506677305f92fa /src | |
| parent | 83ae1c229683fd4df973edf76948248dee0fb118 (diff) | |
Refactor coordinate computation
Diffstat (limited to 'src')
| -rw-r--r-- | src/gfx2d.c | 51 |
1 files changed, 29 insertions, 22 deletions
diff --git a/src/gfx2d.c b/src/gfx2d.c index 9767308..1c3cc39 100644 --- a/src/gfx2d.c +++ b/src/gfx2d.c | |||
| @@ -85,6 +85,14 @@ static inline vec2 vec2_add(vec2 a, vec2 b) { | |||
| 85 | 85 | ||
| 86 | static inline vec2 ivec2_to_vec2(ivec2 a) { return (vec2){a.x, a.y}; } | 86 | static inline vec2 ivec2_to_vec2(ivec2 a) { return (vec2){a.x, a.y}; } |
| 87 | 87 | ||
| 88 | /// Map map coordinates to screen coordinates, both Cartesian. | ||
| 89 | static ivec2 map2screen( | ||
| 90 | ivec2 camera, int tile_width, int tile_height, int map_x, int map_y) { | ||
| 91 | return ivec2_add( | ||
| 92 | ivec2_neg(camera), | ||
| 93 | (ivec2){.x = map_x * tile_width, .y = map_y * tile_height}); | ||
| 94 | } | ||
| 95 | |||
| 88 | // Not actually used because we pre-compute the two axis vectors instead. | 96 | // Not actually used because we pre-compute the two axis vectors instead. |
| 89 | // See make_iso_coord_system() and the other definition of iso2cart() below. | 97 | // See make_iso_coord_system() and the other definition of iso2cart() below. |
| 90 | // static inline ivec2 iso2cart(ivec2 iso, int s, int t, int w) { | 98 | // static inline ivec2 iso2cart(ivec2 iso, int s, int t, int w) { |
| @@ -116,9 +124,10 @@ static ivec2 iso2cart( | |||
| 116 | const CoordSystem iso_space, ivec2 camera, int iso_x, int iso_y) { | 124 | const CoordSystem iso_space, ivec2 camera, int iso_x, int iso_y) { |
| 117 | const ivec2 vx_offset = ivec2_scale(iso_space.x, iso_x); | 125 | const ivec2 vx_offset = ivec2_scale(iso_space.x, iso_x); |
| 118 | const ivec2 vy_offset = ivec2_scale(iso_space.y, iso_y); | 126 | const ivec2 vy_offset = ivec2_scale(iso_space.y, iso_y); |
| 119 | const ivec2 screen_origin = | 127 | const ivec2 origin_world_space = |
| 120 | ivec2_add(iso_space.o, ivec2_add(vx_offset, vy_offset)); | 128 | ivec2_add(iso_space.o, ivec2_add(vx_offset, vy_offset)); |
| 121 | const ivec2 origin_view_space = ivec2_add(screen_origin, ivec2_neg(camera)); | 129 | const ivec2 origin_view_space = |
| 130 | ivec2_add(origin_world_space, ivec2_neg(camera)); | ||
| 122 | return origin_view_space; | 131 | return origin_view_space; |
| 123 | } | 132 | } |
| 124 | 133 | ||
| @@ -575,17 +584,23 @@ static void draw_rect( | |||
| 575 | } | 584 | } |
| 576 | 585 | ||
| 577 | /// Draw a tile. | 586 | /// Draw a tile. |
| 578 | /// | 587 | static void draw_tile(IsoGfx* iso, Tile tile, int iso_x, int iso_y) { |
| 579 | /// 'screen_origin' is the screen coordinates of the top diamond-corner of the | ||
| 580 | /// tile (the base tile for super tiles). | ||
| 581 | /// World (0, 0) -> (screen_width / 2, 0). | ||
| 582 | static void draw_tile(IsoGfx* iso, ivec2 screen_origin, Tile tile) { | ||
| 583 | assert(iso); | 588 | assert(iso); |
| 584 | assert(iso->tileset); | 589 | assert(iso->tileset); |
| 590 | assert(iso_x >= 0); | ||
| 591 | assert(iso_y >= 0); | ||
| 592 | assert(iso_x < iso->map->world_width); | ||
| 593 | assert(iso_y < iso->map->world_height); | ||
| 585 | 594 | ||
| 586 | const Ts_Tile* pTile = ts_tileset_get_tile(iso->tileset, tile); | 595 | const Ts_Tile* pTile = ts_tileset_get_tile(iso->tileset, tile); |
| 587 | const Pixel* pixels = ts_tileset_get_tile_pixels(iso->tileset, tile); | 596 | const Pixel* pixels = ts_tileset_get_tile_pixels(iso->tileset, tile); |
| 588 | 597 | ||
| 598 | // Compute the screen coordinates of the top diamond-corner of the tile (the | ||
| 599 | // base tile for super tiles). | ||
| 600 | // World (0, 0) -> (screen_width / 2, 0). | ||
| 601 | const ivec2 screen_origin = | ||
| 602 | iso2cart(iso->iso_space, iso->camera, iso_x, iso_y); | ||
| 603 | |||
| 589 | // Move from the top diamond-corner to the top-left corner of the tile image. | 604 | // Move from the top diamond-corner to the top-left corner of the tile image. |
| 590 | // For regular tiles, tile height == base tile height, so the y offset is 0. | 605 | // For regular tiles, tile height == base tile height, so the y offset is 0. |
| 591 | // For super tiles, move as high up as the height of the tile. | 606 | // For super tiles, move as high up as the height of the tile. |
| @@ -609,15 +624,14 @@ static void draw_map(IsoGfx* iso) { | |||
| 609 | const Tm_Layer* layer = tm_map_get_layer(iso->map, 0); | 624 | const Tm_Layer* layer = tm_map_get_layer(iso->map, 0); |
| 610 | 625 | ||
| 611 | // TODO: Culling. | 626 | // TODO: Culling. |
| 612 | // Ex: map the screen corners to tile space to cull. | 627 | // Ex: map the screen corners to tile space to cull. |
| 613 | // Ex: walk in screen space and fetch the tile. | 628 | // Ex: walk in screen space and fetch the tile. |
| 614 | // The tile-centric approach might be more cache-friendly since the | 629 | // The tile-centric approach might be more cache-friendly since the |
| 615 | // screen-centric approach would juggle multiple tiles throughout the scan. | 630 | // screen-centric approach would juggle multiple tiles throughout the scan. |
| 616 | for (int wy = 0; wy < iso->map->world_height; ++wy) { | 631 | for (int wy = 0; wy < iso->map->world_height; ++wy) { |
| 617 | for (int wx = 0; wx < iso->map->world_width; ++wx) { | 632 | for (int wx = 0; wx < iso->map->world_width; ++wx) { |
| 618 | const Tile tile = tm_layer_get_tile(iso->map, layer, wx, wy); | 633 | const Tile tile = tm_layer_get_tile(iso->map, layer, wx, wy); |
| 619 | const ivec2 screen_origin = iso2cart(iso->iso_space, iso->camera, wx, wy); | 634 | draw_tile(iso, tile, wx, wy); |
| 620 | draw_tile(iso, screen_origin, tile); | ||
| 621 | } | 635 | } |
| 622 | } | 636 | } |
| 623 | } | 637 | } |
| @@ -669,14 +683,7 @@ void isogfx_render(IsoGfx* iso) { | |||
| 669 | } | 683 | } |
| 670 | 684 | ||
| 671 | void isogfx_draw_tile(IsoGfx* iso, int x, int y, Tile tile) { | 685 | void isogfx_draw_tile(IsoGfx* iso, int x, int y, Tile tile) { |
| 672 | assert(iso); | 686 | draw_tile(iso, tile, x, y); |
| 673 | assert(x >= 0); | ||
| 674 | assert(y >= 0); | ||
| 675 | assert(x < iso->map->world_width); | ||
| 676 | assert(y < iso->map->world_height); | ||
| 677 | |||
| 678 | const ivec2 screen_origin = iso2cart(iso->iso_space, iso->camera, x, y); | ||
| 679 | draw_tile(iso, screen_origin, tile); | ||
| 680 | } | 687 | } |
| 681 | 688 | ||
| 682 | void isogfx_get_screen_size(const IsoGfx* iso, int* width, int* height) { | 689 | void isogfx_get_screen_size(const IsoGfx* iso, int* width, int* height) { |
