partial progress on chunked tilemap
@ -9,38 +9,135 @@ const Position = @import("./position.zig");
|
||||
const Layer = @This();
|
||||
|
||||
pub const TileVariant = struct {
|
||||
pub const Chunk = struct {
|
||||
x: i32,
|
||||
y: i32,
|
||||
width: u32,
|
||||
height: u32,
|
||||
data: []u32,
|
||||
};
|
||||
|
||||
pub const Data = union(enum) {
|
||||
fixed: []u32,
|
||||
chunks: []Chunk
|
||||
};
|
||||
|
||||
const Encoding = enum {
|
||||
csv,
|
||||
|
||||
const map: std.StaticStringMap(Encoding) = .initComptime(.{
|
||||
.{ "csv", .csv },
|
||||
});
|
||||
};
|
||||
|
||||
width: u32,
|
||||
height: u32,
|
||||
data: Data,
|
||||
|
||||
fn initChunkDataFromXml(
|
||||
arena: std.mem.Allocator,
|
||||
scratch: *std.heap.ArenaAllocator,
|
||||
lexer: *xml.Lexer,
|
||||
encoding: Encoding
|
||||
) !Chunk {
|
||||
var iter = xml.TagParser.init(lexer);
|
||||
const attrs = try iter.begin("chunk");
|
||||
|
||||
const x = try attrs.getNumber(i32, "x") orelse return error.MissingAttribute;
|
||||
const y = try attrs.getNumber(i32, "y") orelse return error.MissingAttribute;
|
||||
const width = try attrs.getNumber(u32, "width") orelse return error.MissingAttribute;
|
||||
const height = try attrs.getNumber(u32, "height") orelse return error.MissingAttribute;
|
||||
|
||||
var temp_tiles: std.ArrayList(u32) = .empty;
|
||||
|
||||
while (try iter.next()) |node| {
|
||||
if (node == .text) {
|
||||
const encoded_tiles = try lexer.nextExpectText();
|
||||
const tiles = try parseEncoding(encoding, scratch.allocator(), encoded_tiles);
|
||||
try temp_tiles.appendSlice(scratch.allocator(), tiles.items);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
try iter.skip();
|
||||
}
|
||||
|
||||
try iter.finish("chunk");
|
||||
|
||||
return Chunk{
|
||||
.x = x,
|
||||
.y = y,
|
||||
.width = width,
|
||||
.height = height,
|
||||
.data = try arena.dupe(u32, temp_tiles.items)
|
||||
};
|
||||
}
|
||||
|
||||
fn initDataFromXml(
|
||||
arena: std.mem.Allocator,
|
||||
scratch: *std.heap.ArenaAllocator,
|
||||
lexer: *xml.Lexer,
|
||||
) ![]u32 {
|
||||
) !Data {
|
||||
var iter = xml.TagParser.init(lexer);
|
||||
const attrs = try iter.begin("data");
|
||||
|
||||
const encoding = attrs.get("encoding") orelse "csv";
|
||||
const encoding = try attrs.getEnum(Encoding, "encoding", Encoding.map) orelse .csv;
|
||||
// TODO: compression
|
||||
|
||||
var temp_chunks: std.ArrayList(Chunk) = .empty;
|
||||
var temp_tiles: std.ArrayList(u32) = .empty;
|
||||
|
||||
if (std.mem.eql(u8, encoding, "csv")) {
|
||||
const text = try lexer.nextExpectText();
|
||||
var split_iter = std.mem.splitScalar(u8, text, ',');
|
||||
while (split_iter.next()) |raw_tile_id| {
|
||||
const tile_id_str = std.mem.trim(u8, raw_tile_id, &std.ascii.whitespace);
|
||||
const tile_id = try std.fmt.parseInt(u32, tile_id_str, 10);
|
||||
try temp_tiles.append(scratch.allocator(), tile_id);
|
||||
while (try iter.next()) |node| {
|
||||
if (node == .text) {
|
||||
const encoded_tiles = try lexer.nextExpectText();
|
||||
const tiles = try parseEncoding(encoding, scratch.allocator(), encoded_tiles);
|
||||
try temp_tiles.appendSlice(scratch.allocator(), tiles.items);
|
||||
|
||||
} else if (node.isTag("chunk")) {
|
||||
const chunk = try initChunkDataFromXml(scratch.allocator(), scratch, lexer, encoding);
|
||||
try temp_chunks.append(scratch.allocator(), chunk);
|
||||
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
return error.UnknownEncodingType;
|
||||
|
||||
try iter.skip();
|
||||
}
|
||||
|
||||
try iter.finish("data");
|
||||
|
||||
return try arena.dupe(u32, temp_tiles.items);
|
||||
return .{
|
||||
.fixed = try arena.dupe(u32, temp_tiles.items)
|
||||
};
|
||||
}
|
||||
|
||||
fn parseEncoding(
|
||||
encoding: Encoding,
|
||||
allocator: std.mem.Allocator,
|
||||
text: []const u8
|
||||
) !std.ArrayList(u32) {
|
||||
return switch (encoding) {
|
||||
.csv => try parseCSVEncoding(allocator, text)
|
||||
};
|
||||
}
|
||||
|
||||
fn parseCSVEncoding(
|
||||
allocator: std.mem.Allocator,
|
||||
text: []const u8
|
||||
) !std.ArrayList(u32) {
|
||||
var result: std.ArrayList(u32) = .empty;
|
||||
|
||||
var split_iter = std.mem.splitScalar(u8, text, ',');
|
||||
while (split_iter.next()) |raw_tile_id| {
|
||||
const tile_id_str = std.mem.trim(u8, raw_tile_id, &std.ascii.whitespace);
|
||||
const tile_id = try std.fmt.parseInt(u32, tile_id_str, 10);
|
||||
try result.append(allocator, tile_id);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn getBounds(self: TileVariant) void {
|
||||
_ = self; // autofix
|
||||
}
|
||||
|
||||
pub fn get(self: TileVariant, x: usize, y: usize) ?u32 {
|
||||
@ -181,7 +278,7 @@ pub fn initFromXml(
|
||||
.tile = TileVariant{
|
||||
.width = width,
|
||||
.height = height,
|
||||
.data = &[0]u32{}
|
||||
.data = .{ .fixed = &[0]u32{} }
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
const std = @import("std");
|
||||
|
||||
const tiled = @import("tiled");
|
||||
|
||||
const Math = @import("./engine/math.zig");
|
||||
const Engine = @import("./engine/root.zig");
|
||||
const Gfx = Engine.Graphics;
|
||||
@ -16,11 +18,11 @@ const FontName = enum {
|
||||
};
|
||||
|
||||
font_id: FontName.EnumArray,
|
||||
|
||||
wood01: Audio.Data.Id,
|
||||
map: tiled.Tilemap,
|
||||
tilesets: tiled.Tileset.List,
|
||||
|
||||
pub fn init(gpa: std.mem.Allocator) !Assets {
|
||||
_ = gpa; // autofix
|
||||
const font_id_array: FontName.EnumArray = .init(.{
|
||||
.regular = try Gfx.addFont("regular", @embedFile("assets/roboto-font/Roboto-Regular.ttf")),
|
||||
.bold = try Gfx.addFont("bold", @embedFile("assets/roboto-font/Roboto-Bold.ttf")),
|
||||
@ -32,13 +34,38 @@ pub fn init(gpa: std.mem.Allocator) !Assets {
|
||||
.data = @embedFile("assets/wood01.ogg"),
|
||||
});
|
||||
|
||||
var scratch = std.heap.ArenaAllocator.init(gpa);
|
||||
defer scratch.deinit();
|
||||
|
||||
var xml_buffers = tiled.xml.Lexer.Buffers.init(gpa);
|
||||
defer xml_buffers.deinit();
|
||||
|
||||
const map = try tiled.Tilemap.initFromBuffer(
|
||||
gpa,
|
||||
&scratch,
|
||||
&xml_buffers,
|
||||
@embedFile("assets/map.tmx")
|
||||
);
|
||||
|
||||
const tileset = try tiled.Tileset.initFromBuffer(
|
||||
gpa,
|
||||
&scratch,
|
||||
&xml_buffers,
|
||||
@embedFile("assets/tileset.tsx")
|
||||
);
|
||||
|
||||
var tilesets: tiled.Tileset.List = .empty;
|
||||
try tilesets.add(gpa, "tileset.tsx", tileset);
|
||||
|
||||
return Assets{
|
||||
.font_id = font_id_array,
|
||||
.wood01 = wood01
|
||||
.wood01 = wood01,
|
||||
.map = map,
|
||||
.tilesets = tilesets
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Assets, gpa: std.mem.Allocator) void {
|
||||
_ = self; // autofix
|
||||
_ = gpa; // autofix
|
||||
self.map.deinit();
|
||||
self.tilesets.deinit(gpa);
|
||||
}
|
||||
|
||||
14
src/assets/game-2026-01-18.tiled-project
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"automappingRulesFile": "",
|
||||
"commands": [
|
||||
],
|
||||
"compatibilityVersion": 1100,
|
||||
"extensionsPath": "extensions",
|
||||
"folders": [
|
||||
"."
|
||||
],
|
||||
"properties": [
|
||||
],
|
||||
"propertyTypes": [
|
||||
]
|
||||
}
|
||||
50
src/assets/game-2026-01-18.tiled-session
Normal file
@ -0,0 +1,50 @@
|
||||
{
|
||||
"Map/SizeTest": {
|
||||
"height": 4300,
|
||||
"width": 2
|
||||
},
|
||||
"activeFile": "map.tmx",
|
||||
"expandedProjectPaths": [
|
||||
],
|
||||
"fileStates": {
|
||||
"map.tmx": {
|
||||
"scale": 1.5,
|
||||
"selectedLayer": 0,
|
||||
"viewCenter": {
|
||||
"x": 49.33333333333337,
|
||||
"y": 182
|
||||
}
|
||||
},
|
||||
"tilemap.tsx": {
|
||||
"dynamicWrapping": false,
|
||||
"scaleInDock": 1.5,
|
||||
"scaleInEditor": 5.5
|
||||
},
|
||||
"tiles.tsx": {
|
||||
"dynamicWrapping": true,
|
||||
"scaleInDock": 1,
|
||||
"scaleInEditor": 1
|
||||
}
|
||||
},
|
||||
"last.imagePath": "/home/rokas/code/games/game-2026-01-18/src/assets/kenney_desert-shooter-pack_1.0/PNG/Tiles/Tilemap",
|
||||
"map.fixedSize": false,
|
||||
"map.lastUsedFormat": "tmx",
|
||||
"map.tileHeight": 16,
|
||||
"map.tileWidth": 16,
|
||||
"openFiles": [
|
||||
"tilemap.tsx",
|
||||
"map.tmx"
|
||||
],
|
||||
"project": "game-2026-01-18.tiled-project",
|
||||
"recentFiles": [
|
||||
"tilemap.tsx",
|
||||
"map.tmx",
|
||||
"tiles.tsx"
|
||||
],
|
||||
"tileset.lastUsedFormat": "tsx",
|
||||
"tileset.tileSize": {
|
||||
"height": 16,
|
||||
"width": 16
|
||||
},
|
||||
"tileset.type": 0
|
||||
}
|
||||
23
src/assets/kenney_desert-shooter-pack_1.0/License.txt
Normal file
@ -0,0 +1,23 @@
|
||||
|
||||
|
||||
Desert Shooter Pack (1.0)
|
||||
|
||||
Created/distributed by Kenney (www.kenney.nl)
|
||||
Sponsored by: GameMaker (www.gamemaker.io)
|
||||
Creation date: 24-04-2024
|
||||
|
||||
------------------------------
|
||||
|
||||
License: (Creative Commons Zero, CC0)
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
This content is free to use in personal, educational and commercial projects.
|
||||
Support us by crediting Kenney or www.kenney.nl (this is not mandatory)
|
||||
|
||||
------------------------------
|
||||
|
||||
Donate: http://support.kenney.nl
|
||||
Patreon: http://patreon.com/kenney/
|
||||
|
||||
Follow on Twitter for updates:
|
||||
http://twitter.com/KenneyNL
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 219 B |
|
After Width: | Height: | Size: 216 B |
|
After Width: | Height: | Size: 232 B |
|
After Width: | Height: | Size: 189 B |
|
After Width: | Height: | Size: 257 B |
|
After Width: | Height: | Size: 242 B |
|
After Width: | Height: | Size: 244 B |
|
After Width: | Height: | Size: 218 B |
|
After Width: | Height: | Size: 220 B |
|
After Width: | Height: | Size: 223 B |
|
After Width: | Height: | Size: 236 B |
|
After Width: | Height: | Size: 208 B |
|
After Width: | Height: | Size: 243 B |
|
After Width: | Height: | Size: 256 B |
|
After Width: | Height: | Size: 259 B |
|
After Width: | Height: | Size: 227 B |
@ -0,0 +1,9 @@
|
||||
Tilesheet information:
|
||||
|
||||
Tile size • 24px × 24px
|
||||
Space between tiles • 1px × 1px
|
||||
---
|
||||
Total tiles (horizontal) • 4 tiles
|
||||
Total tiles (vertical) • 4 tiles
|
||||
---
|
||||
Total tiles in sheet • 16 tiles
|
||||
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 181 B |
|
After Width: | Height: | Size: 187 B |
|
After Width: | Height: | Size: 183 B |
|
After Width: | Height: | Size: 136 B |
|
After Width: | Height: | Size: 144 B |
|
After Width: | Height: | Size: 151 B |
|
After Width: | Height: | Size: 170 B |
|
After Width: | Height: | Size: 128 B |
|
After Width: | Height: | Size: 170 B |
|
After Width: | Height: | Size: 168 B |
|
After Width: | Height: | Size: 130 B |
|
After Width: | Height: | Size: 163 B |
|
After Width: | Height: | Size: 145 B |
|
After Width: | Height: | Size: 120 B |
|
After Width: | Height: | Size: 148 B |
|
After Width: | Height: | Size: 182 B |
|
After Width: | Height: | Size: 128 B |
|
After Width: | Height: | Size: 181 B |
|
After Width: | Height: | Size: 176 B |
|
After Width: | Height: | Size: 99 B |
|
After Width: | Height: | Size: 176 B |
|
After Width: | Height: | Size: 130 B |
|
After Width: | Height: | Size: 99 B |
|
After Width: | Height: | Size: 130 B |
|
After Width: | Height: | Size: 119 B |
|
After Width: | Height: | Size: 99 B |
|
After Width: | Height: | Size: 119 B |
|
After Width: | Height: | Size: 125 B |
|
After Width: | Height: | Size: 99 B |
|
After Width: | Height: | Size: 128 B |
|
After Width: | Height: | Size: 113 B |
|
After Width: | Height: | Size: 99 B |
|
After Width: | Height: | Size: 113 B |
|
After Width: | Height: | Size: 119 B |
|
After Width: | Height: | Size: 99 B |
|
After Width: | Height: | Size: 119 B |
|
After Width: | Height: | Size: 186 B |
|
After Width: | Height: | Size: 188 B |
|
After Width: | Height: | Size: 186 B |
|
After Width: | Height: | Size: 151 B |
|
After Width: | Height: | Size: 143 B |
|
After Width: | Height: | Size: 151 B |
|
After Width: | Height: | Size: 170 B |
|
After Width: | Height: | Size: 122 B |
|
After Width: | Height: | Size: 169 B |
|
After Width: | Height: | Size: 162 B |
|
After Width: | Height: | Size: 128 B |
|
After Width: | Height: | Size: 159 B |
|
After Width: | Height: | Size: 143 B |
|
After Width: | Height: | Size: 129 B |
|
After Width: | Height: | Size: 144 B |
|
After Width: | Height: | Size: 187 B |
|
After Width: | Height: | Size: 122 B |
|
After Width: | Height: | Size: 185 B |
|
After Width: | Height: | Size: 167 B |
|
After Width: | Height: | Size: 175 B |
|
After Width: | Height: | Size: 160 B |
|
After Width: | Height: | Size: 174 B |
|
After Width: | Height: | Size: 177 B |
|
After Width: | Height: | Size: 169 B |
|
After Width: | Height: | Size: 175 B |
|
After Width: | Height: | Size: 139 B |
|
After Width: | Height: | Size: 133 B |
|
After Width: | Height: | Size: 139 B |
|
After Width: | Height: | Size: 144 B |
|
After Width: | Height: | Size: 146 B |
|
After Width: | Height: | Size: 133 B |
|
After Width: | Height: | Size: 146 B |
|
After Width: | Height: | Size: 154 B |
|
After Width: | Height: | Size: 114 B |
|
After Width: | Height: | Size: 110 B |
|
After Width: | Height: | Size: 115 B |
|
After Width: | Height: | Size: 149 B |
|
After Width: | Height: | Size: 157 B |