summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--demos/checkerboard/checkerboard.c14
-rw-r--r--demos/isomap/isomap.c6
-rw-r--r--include/isogfx/asset.h11
-rw-r--r--include/isogfx/gfx2d.h (renamed from include/isogfx/isogfx.h)24
-rw-r--r--src/backend.c2
-rw-r--r--src/gfx2d.c (renamed from src/isogfx.c)106
-rw-r--r--tools/mkasset.py38
8 files changed, 113 insertions, 90 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e55aece..78aefa3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -10,7 +10,7 @@ set(CMAKE_C_EXTENSIONS Off)
10 10
11add_library(isogfx 11add_library(isogfx
12 src/asset.c 12 src/asset.c
13 src/isogfx.c) 13 src/gfx2d.c)
14 14
15target_include_directories(isogfx PUBLIC 15target_include_directories(isogfx PUBLIC
16 include) 16 include)
diff --git a/demos/checkerboard/checkerboard.c b/demos/checkerboard/checkerboard.c
index 0c8ff37..4f43526 100644
--- a/demos/checkerboard/checkerboard.c
+++ b/demos/checkerboard/checkerboard.c
@@ -1,5 +1,5 @@
1#include <isogfx/backend.h> 1#include <isogfx/backend.h>
2#include <isogfx/isogfx.h> 2#include <isogfx/gfx2d.h>
3 3
4#include <gfx/app.h> 4#include <gfx/app.h>
5 5
@@ -81,12 +81,12 @@ static bool init(GfxApp* app, GfxAppState* state, int argc, const char** argv) {
81 } 81 }
82 IsoGfx* iso = state->iso; 82 IsoGfx* iso = state->iso;
83 83
84 isogfx_make_world( 84 isogfx_make_map(
85 iso, &(WorldDesc){.tile_width = TILE_WIDTH, 85 iso, &(MapDesc){.tile_width = TILE_WIDTH,
86 .tile_height = TILE_HEIGHT, 86 .tile_height = TILE_HEIGHT,
87 .world_width = WORLD_WIDTH, 87 .world_width = WORLD_WIDTH,
88 .world_height = WORLD_HEIGHT, 88 .world_height = WORLD_HEIGHT,
89 .num_tiles = NUM_TILES}); 89 .num_tiles = NUM_TILES});
90 90
91 const Tile black = isogfx_make_tile(iso, &tile_set[Black]); 91 const Tile black = isogfx_make_tile(iso, &tile_set[Black]);
92 const Tile white = isogfx_make_tile(iso, &tile_set[White]); 92 const Tile white = isogfx_make_tile(iso, &tile_set[White]);
diff --git a/demos/isomap/isomap.c b/demos/isomap/isomap.c
index 27c2bf3..bca27f6 100644
--- a/demos/isomap/isomap.c
+++ b/demos/isomap/isomap.c
@@ -1,5 +1,5 @@
1#include <isogfx/backend.h> 1#include <isogfx/backend.h>
2#include <isogfx/isogfx.h> 2#include <isogfx/gfx2d.h>
3 3
4#include <gfx/app.h> 4#include <gfx/app.h>
5#include <math/vec2.h> 5#include <math/vec2.h>
@@ -46,7 +46,7 @@ static bool init(GfxApp* app, GfxAppState* state, int argc, const char** argv) {
46 } 46 }
47 IsoGfx* iso = state->iso; 47 IsoGfx* iso = state->iso;
48 48
49 if (!isogfx_load_world( 49 if (!isogfx_load_map(
50 iso, "/home/jeanne/Nextcloud/assets/tilemaps/scrabling1.tm")) { 50 iso, "/home/jeanne/Nextcloud/assets/tilemaps/scrabling1.tm")) {
51 return false; 51 return false;
52 } 52 }
@@ -59,7 +59,7 @@ static bool init(GfxApp* app, GfxAppState* state, int argc, const char** argv) {
59 } 59 }
60 60
61 state->stag = isogfx_make_sprite(iso, state->stag_sheet); 61 state->stag = isogfx_make_sprite(iso, state->stag_sheet);
62 isogfx_set_sprite_position(iso, state->stag, 5, 4); 62 isogfx_set_sprite_position(iso, state->stag, 0, 0);
63 63
64 if (!((state->backend = iso_backend_init(iso)))) { 64 if (!((state->backend = iso_backend_init(iso)))) {
65 return false; 65 return false;
diff --git a/include/isogfx/asset.h b/include/isogfx/asset.h
index 6050500..361ffcd 100644
--- a/include/isogfx/asset.h
+++ b/include/isogfx/asset.h
@@ -43,6 +43,16 @@ typedef struct Ts_TileSet {
43// Tile map (TM) file format. 43// Tile map (TM) file format.
44// ----------------------------------------------------------------------------- 44// -----------------------------------------------------------------------------
45 45
46typedef enum Tm_Orientation {
47 Tm_Orthogonal = 0,
48 Tm_Isometric = 1,
49} Tm_Orientation;
50
51typedef struct Tm_Flags {
52 Tm_Orientation orientation : 1;
53 int unused : 15;
54} Tm_Flags;
55
46typedef struct Tm_Layer { 56typedef struct Tm_Layer {
47 Tile tiles[1]; // Count: world_width * world_height. 57 Tile tiles[1]; // Count: world_width * world_height.
48} Tm_Layer; 58} Tm_Layer;
@@ -54,6 +64,7 @@ typedef struct Tm_Map {
54 uint16_t base_tile_width; 64 uint16_t base_tile_width;
55 uint16_t base_tile_height; 65 uint16_t base_tile_height;
56 uint16_t num_layers; 66 uint16_t num_layers;
67 uint16_t flags; // Tm_flagsFlags
57 Tm_Layer layers[]; // Count: num_layers. 68 Tm_Layer layers[]; // Count: num_layers.
58} Tm_Map; 69} Tm_Map;
59 70
diff --git a/include/isogfx/isogfx.h b/include/isogfx/gfx2d.h
index e901231..323b389 100644
--- a/include/isogfx/isogfx.h
+++ b/include/isogfx/gfx2d.h
@@ -37,13 +37,13 @@ typedef struct TileDesc {
37 }; 37 };
38} TileDesc; 38} TileDesc;
39 39
40typedef struct WorldDesc { 40typedef struct MapDesc {
41 int tile_width; // Base tile width in pixels. 41 int tile_width; // Base tile width in pixels.
42 int tile_height; // Base tile height in pixels. 42 int tile_height; // Base tile height in pixels.
43 int world_width; // World width in tiles. 43 int world_width; // World width in tiles.
44 int world_height; // World height in tiles. 44 int world_height; // World height in tiles.
45 int num_tiles; // Number of tiles to allocate memory for. 45 int num_tiles; // Number of tiles to allocate memory for.
46} WorldDesc; 46} MapDesc;
47 47
48typedef struct IsoGfxDesc { 48typedef struct IsoGfxDesc {
49 void* memory; // Block of memory for the engine to use. 49 void* memory; // Block of memory for the engine to use.
@@ -61,11 +61,11 @@ void isogfx_del(IsoGfx**);
61/// Clear all loaded worlds and sprites. 61/// Clear all loaded worlds and sprites.
62void isogfx_clear(IsoGfx*); 62void isogfx_clear(IsoGfx*);
63 63
64/// Create an empty world. 64/// Create an empty map.
65void isogfx_make_world(IsoGfx*, const WorldDesc*); 65void isogfx_make_map(IsoGfx*, const MapDesc*);
66 66
67/// Load a world from a tile map (.TM) file. 67/// Load a tile map (.TM) file.
68bool isogfx_load_world(IsoGfx*, const char* filepath); 68bool isogfx_load_map(IsoGfx*, const char* filepath);
69 69
70/// Return the world's width. 70/// Return the world's width.
71int isogfx_world_width(const IsoGfx*); 71int isogfx_world_width(const IsoGfx*);
@@ -88,8 +88,10 @@ SpriteSheet isogfx_load_sprite_sheet(IsoGfx*, const char* filepath);
88/// Create an animated sprite. 88/// Create an animated sprite.
89Sprite isogfx_make_sprite(IsoGfx*, SpriteSheet); 89Sprite isogfx_make_sprite(IsoGfx*, SpriteSheet);
90 90
91/// Destroy all the sprites. 91// TODO: Add a function to delete a sprite. Making the caller manage and re-use
92void isogfx_del_sprites(IsoGfx*); 92// sprites is a shitty API.
93// Not that the stack allocator gets completely in the way; implement a free
94// list of sprites so that we can re-use the ones that have been "freed".
93 95
94/// Set the sprite's position. 96/// Set the sprite's position.
95void isogfx_set_sprite_position(IsoGfx*, Sprite, int x, int y); 97void isogfx_set_sprite_position(IsoGfx*, Sprite, int x, int y);
@@ -99,9 +101,13 @@ void isogfx_set_sprite_animation(IsoGfx*, Sprite, int animation);
99 101
100/// Update the renderer. 102/// Update the renderer.
101/// 103///
102/// Currently this updates the sprite animations. 104/// Currently, this updates the sprite animations.
103void isogfx_update(IsoGfx*, double t); 105void isogfx_update(IsoGfx*, double t);
104 106
107// TODO: Do we really need to store the camera in the library? It's not used
108// for anything other than to render, so we could remove library state and
109// take a camera argument in render() instead.
110
105/// Set the camera. 111/// Set the camera.
106void isogfx_set_camera(IsoGfx*, int x, int y); 112void isogfx_set_camera(IsoGfx*, int x, int y);
107 113
diff --git a/src/backend.c b/src/backend.c
index 94f1728..80c5974 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -1,5 +1,5 @@
1#include <isogfx/backend.h> 1#include <isogfx/backend.h>
2#include <isogfx/isogfx.h> 2#include <isogfx/gfx2d.h>
3 3
4#include <gfx/core.h> 4#include <gfx/core.h>
5#include <gfx/gfx.h> 5#include <gfx/gfx.h>
diff --git a/src/isogfx.c b/src/gfx2d.c
index c3a87bf..9767308 100644
--- a/src/isogfx.c
+++ b/src/gfx2d.c
@@ -1,4 +1,4 @@
1#include <isogfx/isogfx.h> 1#include <isogfx/gfx2d.h>
2 2
3#include <isogfx/asset.h> 3#include <isogfx/asset.h>
4 4
@@ -79,17 +79,49 @@ static inline ivec2 ivec2_scale(ivec2 a, int s) {
79 79
80static inline ivec2 ivec2_neg(ivec2 a) { return (ivec2){.x = -a.x, .y = -a.y}; } 80static inline ivec2 ivec2_neg(ivec2 a) { return (ivec2){.x = -a.x, .y = -a.y}; }
81 81
82static inline ivec2 iso2cart(ivec2 iso, int s, int t, int w) {
83 return (ivec2){.x = (iso.x - iso.y) * (s / 2) + (w / 2),
84 .y = (iso.x + iso.y) * (t / 2)};
85}
86
87static inline vec2 vec2_add(vec2 a, vec2 b) { 82static inline vec2 vec2_add(vec2 a, vec2 b) {
88 return (vec2){.x = a.x + b.x, .y = a.y + b.y}; 83 return (vec2){.x = a.x + b.x, .y = a.y + b.y};
89} 84}
90 85
91static inline vec2 ivec2_to_vec2(ivec2 a) { return (vec2){a.x, a.y}; } 86static inline vec2 ivec2_to_vec2(ivec2 a) { return (vec2){a.x, a.y}; }
92 87
88// 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.
90// static inline ivec2 iso2cart(ivec2 iso, int s, int t, int w) {
91// return (ivec2){.x = (iso.x - iso.y) * (s / 2) + (w / 2),
92// .y = (iso.x + iso.y) * (t / 2)};
93// }
94
95/// Create the basis for the isometric coordinate system with origin and vectors
96/// expressed in the Cartesian system.
97static CoordSystem make_iso_coord_system(
98 const Tm_Map* const map, const Screen* const screen) {
99 assert(map);
100 assert(screen);
101 const ivec2 o = {screen->width / 2, 0};
102 const ivec2 x = {
103 .x = map->base_tile_width / 2, .y = map->base_tile_height / 2};
104 const ivec2 y = {
105 .x = -map->base_tile_width / 2, .y = map->base_tile_height / 2};
106 return (CoordSystem){o, x, y};
107}
108
109/// Map isometric coordinates to Cartesian coordinates.
110///
111/// For a tile, this gets the screen position of the top diamond-corner of the
112/// tile.
113///
114/// Takes the camera displacement into account.
115static ivec2 iso2cart(
116 const CoordSystem iso_space, ivec2 camera, int iso_x, int iso_y) {
117 const ivec2 vx_offset = ivec2_scale(iso_space.x, iso_x);
118 const ivec2 vy_offset = ivec2_scale(iso_space.y, iso_y);
119 const ivec2 screen_origin =
120 ivec2_add(iso_space.o, ivec2_add(vx_offset, vy_offset));
121 const ivec2 origin_view_space = ivec2_add(screen_origin, ivec2_neg(camera));
122 return origin_view_space;
123}
124
93// Method 1. 125// Method 1.
94// static inline vec2 cart2iso(vec2 cart, int s, int t, int w) { 126// static inline vec2 cart2iso(vec2 cart, int s, int t, int w) {
95// const double x = cart.x - (double)(w / 2); 127// const double x = cart.x - (double)(w / 2);
@@ -125,20 +157,6 @@ static inline Pixel* screen_xy_mut(Screen* screen, int x, int y) {
125 return (Pixel*)screen_xy_const_ref(screen, x, y); 157 return (Pixel*)screen_xy_const_ref(screen, x, y);
126} 158}
127 159
128/// Create the basis for the isometric coordinate system with origin and vectors
129/// expressed in the Cartesian system.
130static CoordSystem make_iso_coord_system(
131 const Tm_Map* const map, const Screen* const screen) {
132 assert(map);
133 assert(screen);
134 const ivec2 o = {screen->width / 2, 0};
135 const ivec2 x = {
136 .x = map->base_tile_width / 2, .y = map->base_tile_height / 2};
137 const ivec2 y = {
138 .x = -map->base_tile_width / 2, .y = map->base_tile_height / 2};
139 return (CoordSystem){o, x, y};
140}
141
142// ----------------------------------------------------------------------------- 160// -----------------------------------------------------------------------------
143// Renderer, world and tile management. 161// Renderer, world and tile management.
144// ----------------------------------------------------------------------------- 162// -----------------------------------------------------------------------------
@@ -198,7 +216,7 @@ void isogfx_del(IsoGfx** ppIso) {
198 } 216 }
199} 217}
200 218
201void isogfx_make_world(IsoGfx* iso, const WorldDesc* desc) { 219void isogfx_make_map(IsoGfx* iso, const MapDesc* desc) {
202 assert(iso); 220 assert(iso);
203 assert(desc); 221 assert(desc);
204 assert(desc->tile_width > 0); 222 assert(desc->tile_width > 0);
@@ -246,7 +264,7 @@ void isogfx_make_world(IsoGfx* iso, const WorldDesc* desc) {
246 iso->iso_space = make_iso_coord_system(iso->map, &iso->screen); 264 iso->iso_space = make_iso_coord_system(iso->map, &iso->screen);
247} 265}
248 266
249bool isogfx_load_world(IsoGfx* iso, const char* filepath) { 267bool isogfx_load_map(IsoGfx* iso, const char* filepath) {
250 assert(iso); 268 assert(iso);
251 assert(filepath); 269 assert(filepath);
252 270
@@ -267,6 +285,8 @@ bool isogfx_load_world(IsoGfx* iso, const char* filepath) {
267 } 285 }
268 Tm_Map* const map = iso->map; 286 Tm_Map* const map = iso->map;
269 287
288 printf("Map orientation: %d\n", ((Tm_Flags*)&map->flags)->orientation);
289
270 // Load the tile set. 290 // Load the tile set.
271 // 291 //
272 // Tile set path is relative to the tile map file. Make it relative to the 292 // Tile set path is relative to the tile map file. Make it relative to the
@@ -496,18 +516,6 @@ void isogfx_update(IsoGfx* iso, double t) {
496// Rendering and picking. 516// Rendering and picking.
497// ----------------------------------------------------------------------------- 517// -----------------------------------------------------------------------------
498 518
499/// Get the screen position of the top diamond-corner of the tile at world
500/// (x,y).
501static ivec2 GetTileScreenOrigin(
502 const CoordSystem iso_space, ivec2 camera, int world_x, int world_y) {
503 const ivec2 vx_offset = ivec2_scale(iso_space.x, world_x);
504 const ivec2 vy_offset = ivec2_scale(iso_space.y, world_y);
505 const ivec2 screen_origin =
506 ivec2_add(iso_space.o, ivec2_add(vx_offset, vy_offset));
507 const ivec2 origin_view_space = ivec2_add(screen_origin, ivec2_neg(camera));
508 return origin_view_space;
509}
510
511static Pixel alpha_blend(Pixel src, Pixel dst) { 519static Pixel alpha_blend(Pixel src, Pixel dst) {
512 if ((src.a == 255) || (dst.a == 0)) { 520 if ((src.a == 255) || (dst.a == 0)) {
513 return src; 521 return src;
@@ -590,7 +598,7 @@ static void draw_tile(IsoGfx* iso, ivec2 screen_origin, Tile tile) {
590 &iso->screen, top_left, pTile->width, pTile->height, pixels, nullptr); 598 &iso->screen, top_left, pTile->width, pTile->height, pixels, nullptr);
591} 599}
592 600
593static void draw_world(IsoGfx* iso) { 601static void draw_map(IsoGfx* iso) {
594 assert(iso); 602 assert(iso);
595 603
596 const int W = iso->screen.width; 604 const int W = iso->screen.width;
@@ -607,17 +615,15 @@ static void draw_world(IsoGfx* iso) {
607 // screen-centric approach would juggle multiple tiles throughout the scan. 615 // screen-centric approach would juggle multiple tiles throughout the scan.
608 for (int wy = 0; wy < iso->map->world_height; ++wy) { 616 for (int wy = 0; wy < iso->map->world_height; ++wy) {
609 for (int wx = 0; wx < iso->map->world_width; ++wx) { 617 for (int wx = 0; wx < iso->map->world_width; ++wx) {
610 const Tile tile = tm_layer_get_tile(iso->map, layer, wx, wy); 618 const Tile tile = tm_layer_get_tile(iso->map, layer, wx, wy);
611 const ivec2 screen_origin = 619 const ivec2 screen_origin = iso2cart(iso->iso_space, iso->camera, wx, wy);
612 GetTileScreenOrigin(iso->iso_space, iso->camera, wx, wy);
613 draw_tile(iso, screen_origin, tile); 620 draw_tile(iso, screen_origin, tile);
614 } 621 }
615 } 622 }
616} 623}
617 624
618static void draw_sprite( 625static void draw_sprite(
619 IsoGfx* iso, ivec2 origin, const SpriteInstance* sprite, 626 IsoGfx* iso, const SpriteInstance* sprite, const Ss_SpriteSheet* sheet) {
620 const Ss_SpriteSheet* sheet) {
621 assert(iso); 627 assert(iso);
622 assert(sprite); 628 assert(sprite);
623 assert(sheet); 629 assert(sheet);
@@ -625,10 +631,18 @@ static void draw_sprite(
625 assert(sprite->animation < sheet->num_rows); 631 assert(sprite->animation < sheet->num_rows);
626 assert(sprite->frame >= 0); 632 assert(sprite->frame >= 0);
627 633
634 // Apply an offset similarly to how we offset tiles. The sprite is offset by
635 // -base_tile_width/2 along the x-axis to align the sprite with the leftmost
636 // edge of the tile it is on.
637 const ivec2 screen_origin = iso2cart(
638 iso->iso_space, iso->camera, sprite->position.x, sprite->position.y);
639 const ivec2 offset = {-(iso->map->base_tile_width / 2), 0};
640 const ivec2 top_left = ivec2_add(screen_origin, offset);
641
628 const Ss_Row* row = ss_get_sprite_sheet_row(sheet, sprite->animation); 642 const Ss_Row* row = ss_get_sprite_sheet_row(sheet, sprite->animation);
629 const uint8_t* frame = ss_get_sprite_sheet_sprite(sheet, row, sprite->frame); 643 const uint8_t* frame = ss_get_sprite_sheet_sprite(sheet, row, sprite->frame);
630 draw_rect( 644 draw_rect(
631 &iso->screen, origin, sheet->sprite_width, sheet->sprite_height, 645 &iso->screen, top_left, sheet->sprite_width, sheet->sprite_height,
632 sheet->palette.colours, frame); 646 sheet->palette.colours, frame);
633} 647}
634 648
@@ -639,10 +653,7 @@ static void draw_sprites(IsoGfx* iso) {
639 sprite = sprite->next) { 653 sprite = sprite->next) {
640 const Ss_SpriteSheet* sheet = sprite->sheet; 654 const Ss_SpriteSheet* sheet = sprite->sheet;
641 assert(sheet); 655 assert(sheet);
642 656 draw_sprite(iso, sprite, sheet);
643 const ivec2 screen_origin = GetTileScreenOrigin(
644 iso->iso_space, iso->camera, sprite->position.x, sprite->position.y);
645 draw_sprite(iso, screen_origin, sprite, sheet);
646 } 657 }
647} 658}
648 659
@@ -653,7 +664,7 @@ void isogfx_set_camera(IsoGfx* iso, int x, int y) {
653 664
654void isogfx_render(IsoGfx* iso) { 665void isogfx_render(IsoGfx* iso) {
655 assert(iso); 666 assert(iso);
656 draw_world(iso); 667 draw_map(iso);
657 draw_sprites(iso); 668 draw_sprites(iso);
658} 669}
659 670
@@ -664,8 +675,7 @@ void isogfx_draw_tile(IsoGfx* iso, int x, int y, Tile tile) {
664 assert(x < iso->map->world_width); 675 assert(x < iso->map->world_width);
665 assert(y < iso->map->world_height); 676 assert(y < iso->map->world_height);
666 677
667 const ivec2 screen_origin = 678 const ivec2 screen_origin = iso2cart(iso->iso_space, iso->camera, x, y);
668 GetTileScreenOrigin(iso->iso_space, iso->camera, x, y);
669 draw_tile(iso, screen_origin, tile); 679 draw_tile(iso, screen_origin, tile);
670} 680}
671 681
diff --git a/tools/mkasset.py b/tools/mkasset.py
index 9b9dc76..f21a2f9 100644
--- a/tools/mkasset.py
+++ b/tools/mkasset.py
@@ -13,6 +13,7 @@
13import argparse 13import argparse
14import ctypes 14import ctypes
15import sys 15import sys
16from enum import IntEnum
16from typing import Generator 17from typing import Generator
17from xml.etree import ElementTree 18from xml.etree import ElementTree
18 19
@@ -23,6 +24,12 @@ from PIL import Image
23MAX_PATH_LENGTH = 128 24MAX_PATH_LENGTH = 128
24 25
25 26
27class Orientation(IntEnum):
28 """Map orientation. Must match Tm_Orientation in asset.h"""
29 Orthogonal = 0
30 Isometric = 1
31
32
26def drop_extension(filepath): 33def drop_extension(filepath):
27 return filepath[:filepath.rfind('.')] 34 return filepath[:filepath.rfind('.')]
28 35
@@ -51,14 +58,9 @@ def carve_image(rgba_bytes, tile_width, tile_height, columns) -> Generator[bytea
51 image_width = columns * tile_width 58 image_width = columns * tile_width
52 image_height = len(rgba_bytes) // image_width // 4 59 image_height = len(rgba_bytes) // image_width // 4
53 60
54 tiles_x = image_width // tile_width
55 tiles_y = image_height // tile_height
56
57 tile_bytes = bytearray(tile_width * tile_height * 4) 61 tile_bytes = bytearray(tile_width * tile_height * 4)
58 for i in range(tiles_y): 62 for image_y0 in range(0, image_height, tile_height): # y-origin of tile inside image
59 image_y0 = i * tile_height # y-origin of tile inside image 63 for image_x0 in range(0, image_width, tile_width): # x-origin of tile inside image
60 for j in range(tiles_x):
61 image_x0 = j * tile_width # x-origin of tile inside image
62 for y in range(tile_height): 64 for y in range(tile_height):
63 image_y = image_y0 + y # y of current pixel inside image 65 image_y = image_y0 + y # y of current pixel inside image
64 for x in range(tile_width): 66 for x in range(tile_width):
@@ -183,11 +185,13 @@ def convert_tmx(input_filepath, output_filepath):
183 base_tile_width = int(root.attrib["tilewidth"]) 185 base_tile_width = int(root.attrib["tilewidth"])
184 base_tile_height = int(root.attrib["tileheight"]) 186 base_tile_height = int(root.attrib["tileheight"])
185 num_layers = 1 187 num_layers = 1
188 flags = Orientation.Isometric if (root.attrib["orientation"] == "isometric") else Orientation.Orthogonal
186 189
187 print(f"Map width: {map_width}") 190 print(f"Map width: {map_width}")
188 print(f"Map height: {map_height}") 191 print(f"Map height: {map_height}")
189 print(f"Tile width: {base_tile_width}") 192 print(f"Tile width: {base_tile_width}")
190 print(f"Tile height: {base_tile_height}") 193 print(f"Tile height: {base_tile_height}")
194 print(f"Orientation: {flags}")
191 195
192 tileset_path = None 196 tileset_path = None
193 197
@@ -210,6 +214,7 @@ def convert_tmx(input_filepath, output_filepath):
210 output.write(ctypes.c_uint16(base_tile_width)) 214 output.write(ctypes.c_uint16(base_tile_width))
211 output.write(ctypes.c_uint16(base_tile_height)) 215 output.write(ctypes.c_uint16(base_tile_height))
212 output.write(ctypes.c_uint16(num_layers)) 216 output.write(ctypes.c_uint16(num_layers))
217 output.write(ctypes.c_uint16(flags))
213 elif child.tag == "layer": 218 elif child.tag == "layer":
214 layer = child 219 layer = child
215 layer_id = int(layer.attrib["id"]) 220 layer_id = int(layer.attrib["id"])
@@ -349,25 +354,16 @@ def convert_sprite_sheet(input_file_paths, sprite_width, sprite_height,
349 # that. getcolors() returns the number of unique colors. 354 # that. getcolors() returns the number of unique colors.
350 # getpalette() also returns a flattened list, which is why we must *4. 355 # getpalette() also returns a flattened list, which is why we must *4.
351 num_colours = len(im.getcolors()) 356 num_colours = len(im.getcolors())
352 colours = im.getpalette(rawmode="RGBA")[:4 * num_colours] 357 palette = bytearray(im.getpalette(rawmode="RGBA")[:4 * num_colours])
353 # TODO: This palette list does not seem really necessary. 358 assert (num_colours == (len(palette) // 4))
354 # Define palette = bytearray(im.getpalette(...))
355 palette = []
356 for i in range(0, 4 * num_colours, 4):
357 palette.append((colours[i], colours[i + 1], colours[i + 2],
358 colours[i + 3]))
359 359
360 output.write(ctypes.c_uint16(len(palette))) 360 output.write(ctypes.c_uint16(num_colours))
361 output.write(bytearray(colours)) 361 output.write(palette)
362 362
363 print(f"Sprite width: {sprite_width}") 363 print(f"Sprite width: {sprite_width}")
364 print(f"Sprite height: {sprite_height}") 364 print(f"Sprite height: {sprite_height}")
365 print(f"Rows: {len(rows)}") 365 print(f"Rows: {len(rows)}")
366 print(f"Colours: {len(palette)}") 366 print(f"Colours: {num_colours}")
367
368 # print("Palette")
369 # for i, colour in enumerate(palette):
370 # print(f"{i}: {colour}")
371 367
372 for row, num_columns in enumerate(rows): 368 for row, num_columns in enumerate(rows):
373 output.write(ctypes.c_uint16(num_columns)) 369 output.write(ctypes.c_uint16(num_columns))