diff options
Diffstat (limited to 'src/gfx2d.c')
-rw-r--r-- | src/gfx2d.c | 55 |
1 files changed, 36 insertions, 19 deletions
diff --git a/src/gfx2d.c b/src/gfx2d.c index 14e0539..eaed2b8 100644 --- a/src/gfx2d.c +++ b/src/gfx2d.c | |||
@@ -26,6 +26,9 @@ | |||
26 | /// Take the minimum of two values. | 26 | /// Take the minimum of two values. |
27 | #define min(a, b) ((a) < (b) ? (a) : (b)) | 27 | #define min(a, b) ((a) < (b) ? (a) : (b)) |
28 | 28 | ||
29 | /// The 0-tile denotes "no tile". The renderer skips drawing 0-tiles. | ||
30 | static const Tile NoTile = 0; | ||
31 | |||
29 | typedef struct ivec2 { | 32 | typedef struct ivec2 { |
30 | int x, y; | 33 | int x, y; |
31 | } ivec2; | 34 | } ivec2; |
@@ -606,6 +609,10 @@ static void draw_tile_ortho(Gfx2d* gfx, Tile tile, int x, int y) { | |||
606 | assert(x < gfx->map->world_width); | 609 | assert(x < gfx->map->world_width); |
607 | assert(y < gfx->map->world_height); | 610 | assert(y < gfx->map->world_height); |
608 | 611 | ||
612 | if (tile == NoTile) { | ||
613 | return; | ||
614 | } | ||
615 | |||
609 | const Ts_Tile* pTile = ts_tileset_get_tile(gfx->tileset, tile); | 616 | const Ts_Tile* pTile = ts_tileset_get_tile(gfx->tileset, tile); |
610 | const Pixel* pixels = ts_tileset_get_tile_pixels(gfx->tileset, tile); | 617 | const Pixel* pixels = ts_tileset_get_tile_pixels(gfx->tileset, tile); |
611 | 618 | ||
@@ -626,6 +633,10 @@ static void draw_tile_iso(Gfx2d* gfx, Tile tile, int iso_x, int iso_y) { | |||
626 | assert(iso_x < gfx->map->world_width); | 633 | assert(iso_x < gfx->map->world_width); |
627 | assert(iso_y < gfx->map->world_height); | 634 | assert(iso_y < gfx->map->world_height); |
628 | 635 | ||
636 | if (tile == NoTile) { | ||
637 | return; | ||
638 | } | ||
639 | |||
629 | const Ts_Tile* pTile = ts_tileset_get_tile(gfx->tileset, tile); | 640 | const Ts_Tile* pTile = ts_tileset_get_tile(gfx->tileset, tile); |
630 | const Pixel* pixels = ts_tileset_get_tile_pixels(gfx->tileset, tile); | 641 | const Pixel* pixels = ts_tileset_get_tile_pixels(gfx->tileset, tile); |
631 | 642 | ||
@@ -651,16 +662,21 @@ static void draw_map_ortho(Gfx2d* gfx) { | |||
651 | assert(gfx); | 662 | assert(gfx); |
652 | assert(gfx->map); | 663 | assert(gfx->map); |
653 | 664 | ||
665 | // Render the tiles that the camera view rectangle intersects. | ||
666 | // +1 when computing x1,y1 because the screen dimensions need not be a | ||
667 | // multiple of the base tile dimensions. | ||
668 | const int x_tiles = gfx->screen.width / gfx->map->base_tile_width; | ||
669 | const int y_tiles = gfx->screen.height / gfx->map->base_tile_height; | ||
670 | const int x0 = gfx->camera.x / gfx->map->base_tile_width; | ||
671 | const int y0 = gfx->camera.y / gfx->map->base_tile_height; | ||
672 | const int x1 = min(gfx->map->world_width, x0 + x_tiles + 1); | ||
673 | const int y1 = min(gfx->map->world_height, y0 + y_tiles + 1); | ||
674 | |||
654 | for (uint16_t l = 0; l < gfx->map->num_layers; ++l) { | 675 | for (uint16_t l = 0; l < gfx->map->num_layers; ++l) { |
655 | const Tm_Layer* layer = tm_map_get_layer(gfx->map, l); | 676 | const Tm_Layer* layer = tm_map_get_layer(gfx->map, l); |
656 | 677 | ||
657 | // TODO: This currently renders with tile granularity. Do so instead in | 678 | for (int wy = y0; wy < y1; ++wy) { |
658 | // terms of pixels for more accurate camera panning. The camera coordinates | 679 | for (int wx = x0; wx < x1; ++wx) { |
659 | // are already given in pixels. | ||
660 | for (int wy = gfx->camera.y / gfx->map->base_tile_height; | ||
661 | wy < gfx->map->world_height; ++wy) { | ||
662 | for (int wx = gfx->camera.x / gfx->map->base_tile_width; | ||
663 | wx < gfx->map->world_width; ++wx) { | ||
664 | const Tile tile = tm_layer_get_tile(gfx->map, layer, wx, wy); | 680 | const Tile tile = tm_layer_get_tile(gfx->map, layer, wx, wy); |
665 | draw_tile_ortho(gfx, tile, wx, wy); | 681 | draw_tile_ortho(gfx, tile, wx, wy); |
666 | } | 682 | } |
@@ -672,18 +688,19 @@ static void draw_map_iso(Gfx2d* gfx) { | |||
672 | assert(gfx); | 688 | assert(gfx); |
673 | assert(gfx->map); | 689 | assert(gfx->map); |
674 | 690 | ||
675 | // TODO: Support for multiple layers. | 691 | for (uint16_t l = 0; l < gfx->map->num_layers; ++l) { |
676 | const Tm_Layer* layer = tm_map_get_layer(gfx->map, 0); | 692 | const Tm_Layer* layer = tm_map_get_layer(gfx->map, l); |
677 | 693 | ||
678 | // TODO: Culling. | 694 | // TODO: Culling. |
679 | // Ex: map the screen corners to tile space to cull. | 695 | // Ex: map the screen corners to tile space to cull. |
680 | // Ex: walk in screen space and fetch the tile. | 696 | // Ex: walk in screen space and fetch the tile. |
681 | // The tile-centric approach might be more cache-friendly since the | 697 | // The tile-centric approach might be more cache-friendly since the |
682 | // screen-centric approach would juggle multiple tiles throughout the scan. | 698 | // screen-centric approach would juggle multiple tiles throughout the scan. |
683 | for (int wy = 0; wy < gfx->map->world_height; ++wy) { | 699 | for (int wy = 0; wy < gfx->map->world_height; ++wy) { |
684 | for (int wx = 0; wx < gfx->map->world_width; ++wx) { | 700 | for (int wx = 0; wx < gfx->map->world_width; ++wx) { |
685 | const Tile tile = tm_layer_get_tile(gfx->map, layer, wx, wy); | 701 | const Tile tile = tm_layer_get_tile(gfx->map, layer, wx, wy); |
686 | draw_tile_iso(gfx, tile, wx, wy); | 702 | draw_tile_iso(gfx, tile, wx, wy); |
703 | } | ||
687 | } | 704 | } |
688 | } | 705 | } |
689 | } | 706 | } |