Compare commits
No commits in common. "a5d824817cbde1934a72668c42bf5d450ac3eba2" and "8d5e7da6a6c8d18f167c0e0b4418bf64766ff219" have entirely different histories.
a5d824817c
...
8d5e7da6a6
22
build.zig
@ -13,7 +13,6 @@ pub fn build(b: *std.Build) !void {
|
|||||||
const has_console = b.option(bool, "console", "Show console (Window only)") orelse (optimize == .Debug);
|
const has_console = b.option(bool, "console", "Show console (Window only)") orelse (optimize == .Debug);
|
||||||
|
|
||||||
const isWasm = target.result.cpu.arch.isWasm();
|
const isWasm = target.result.cpu.arch.isWasm();
|
||||||
const isWindows = target.result.os.tag == .windows;
|
|
||||||
|
|
||||||
if (isWasm) {
|
if (isWasm) {
|
||||||
has_tracy = false;
|
has_tracy = false;
|
||||||
@ -26,12 +25,7 @@ pub fn build(b: *std.Build) !void {
|
|||||||
.link_libc = true,
|
.link_libc = true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const dep_sokol = b.dependency("sokol", .{
|
const dep_sokol = b.dependency("sokol", .{ .target = target, .optimize = optimize, .with_sokol_imgui = has_imgui, .vulkan = true });
|
||||||
.target = target,
|
|
||||||
.optimize = optimize,
|
|
||||||
.with_sokol_imgui = has_imgui,
|
|
||||||
.vulkan = if (isWasm or isWindows) null else true
|
|
||||||
});
|
|
||||||
mod_main.linkLibrary(dep_sokol.artifact("sokol_clib"));
|
mod_main.linkLibrary(dep_sokol.artifact("sokol_clib"));
|
||||||
mod_main.addImport("sokol", dep_sokol.module("sokol"));
|
mod_main.addImport("sokol", dep_sokol.module("sokol"));
|
||||||
|
|
||||||
@ -68,8 +62,7 @@ pub fn build(b: *std.Build) !void {
|
|||||||
{
|
{
|
||||||
var cflags_buffer: [64][]const u8 = undefined;
|
var cflags_buffer: [64][]const u8 = undefined;
|
||||||
var cflags = std.ArrayListUnmanaged([]const u8).initBuffer(&cflags_buffer);
|
var cflags = std.ArrayListUnmanaged([]const u8).initBuffer(&cflags_buffer);
|
||||||
const backend: sokol.SokolBackend = if (isWasm or isWindows) .auto else .vulkan;
|
switch (sokol.resolveSokolBackend(.vulkan, target.result)) {
|
||||||
switch (sokol.resolveSokolBackend(backend, target.result)) {
|
|
||||||
.d3d11 => try cflags.appendBounded("-DSOKOL_D3D11"),
|
.d3d11 => try cflags.appendBounded("-DSOKOL_D3D11"),
|
||||||
.metal => try cflags.appendBounded("-DSOKOL_METAL"),
|
.metal => try cflags.appendBounded("-DSOKOL_METAL"),
|
||||||
.gl => try cflags.appendBounded("-DSOKOL_GLCORE"),
|
.gl => try cflags.appendBounded("-DSOKOL_GLCORE"),
|
||||||
@ -125,8 +118,8 @@ fn buildNative(b: *std.Build, name: []const u8, mod: *std.Build.Module, has_cons
|
|||||||
.root_source_file = b.path("tools/png-to-icon.zig"),
|
.root_source_file = b.path("tools/png-to-icon.zig"),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
const dep_stb = b.dependency("stb", .{});
|
const dep_stb_image = b.dependency("stb_image", .{});
|
||||||
png_to_icon_tool.root_module.addImport("stb_image", dep_stb.module("stb_image"));
|
png_to_icon_tool.root_module.addImport("stb_image", dep_stb_image.module("stb_image"));
|
||||||
|
|
||||||
const png_to_icon_step = b.addRunArtifact(png_to_icon_tool);
|
const png_to_icon_step = b.addRunArtifact(png_to_icon_tool);
|
||||||
png_to_icon_step.addFileArg(b.path("src/assets/icon.png"));
|
png_to_icon_step.addFileArg(b.path("src/assets/icon.png"));
|
||||||
@ -216,11 +209,7 @@ fn buildWasm(b: *std.Build, opts: BuildWasmOptions) !void {
|
|||||||
|
|
||||||
const dep_emsdk = opts.dep_sokol.builder.dependency("emsdk", .{});
|
const dep_emsdk = opts.dep_sokol.builder.dependency("emsdk", .{});
|
||||||
|
|
||||||
patchWasmIncludeDirs(
|
patchWasmIncludeDirs(opts.mod_main, dep_emsdk.path("upstream/emscripten/cache/sysroot/include"), &(opts.dep_sokol.artifact("sokol_clib").step));
|
||||||
opts.mod_main,
|
|
||||||
dep_emsdk.path("upstream/emscripten/cache/sysroot/include"),
|
|
||||||
&(opts.dep_sokol.artifact("sokol_clib").step)
|
|
||||||
);
|
|
||||||
|
|
||||||
// create a build step which invokes the Emscripten linker
|
// create a build step which invokes the Emscripten linker
|
||||||
const link_step = try sokol.emLinkStep(b, .{
|
const link_step = try sokol.emLinkStep(b, .{
|
||||||
@ -232,7 +221,6 @@ fn buildWasm(b: *std.Build, opts: BuildWasmOptions) !void {
|
|||||||
.use_emmalloc = true,
|
.use_emmalloc = true,
|
||||||
.use_filesystem = false,
|
.use_filesystem = false,
|
||||||
.shell_file_path = b.path("src/engine/shell.html"),
|
.shell_file_path = b.path("src/engine/shell.html"),
|
||||||
.extra_args = &.{ "-sASSERTIONS=1", "-sALLOW_MEMORY_GROWTH=1" }
|
|
||||||
});
|
});
|
||||||
// attach to default target
|
// attach to default target
|
||||||
b.getInstallStep().dependOn(&link_step.step);
|
b.getInstallStep().dependOn(&link_step.step);
|
||||||
|
|||||||
@ -136,7 +136,6 @@ pub const TileVariant = struct {
|
|||||||
const encoded_tiles = try lexer.nextExpectText();
|
const encoded_tiles = try lexer.nextExpectText();
|
||||||
const tiles = try parseEncoding(encoding, scratch.allocator(), encoded_tiles);
|
const tiles = try parseEncoding(encoding, scratch.allocator(), encoded_tiles);
|
||||||
try temp_tiles.appendSlice(scratch.allocator(), tiles.items);
|
try temp_tiles.appendSlice(scratch.allocator(), tiles.items);
|
||||||
continue;
|
|
||||||
|
|
||||||
} else if (node.isTag("chunk")) {
|
} else if (node.isTag("chunk")) {
|
||||||
const chunk = try initChunkDataFromXml(arena, scratch, lexer, encoding);
|
const chunk = try initChunkDataFromXml(arena, scratch, lexer, encoding);
|
||||||
@ -159,6 +158,7 @@ pub const TileVariant = struct {
|
|||||||
.fixed = try arena.dupe(u32, temp_tiles.items)
|
.fixed = try arena.dupe(u32, temp_tiles.items)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parseEncoding(
|
fn parseEncoding(
|
||||||
|
|||||||
@ -73,9 +73,6 @@ pub const TilesetReference = struct {
|
|||||||
pub const Tile = struct {
|
pub const Tile = struct {
|
||||||
tileset: *const Tileset,
|
tileset: *const Tileset,
|
||||||
id: u32,
|
id: u32,
|
||||||
flip_horizontal: bool,
|
|
||||||
flip_vertical: bool,
|
|
||||||
flip_diagonal: bool,
|
|
||||||
|
|
||||||
pub fn getProperties(self: Tile) Property.List {
|
pub fn getProperties(self: Tile) Property.List {
|
||||||
return self.tileset.getTileProperties(self.id) orelse .empty;
|
return self.tileset.getTileProperties(self.id) orelse .empty;
|
||||||
@ -219,19 +216,13 @@ fn getTilesetByGid(self: *const Tilemap, gid: u32) ?TilesetReference {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn getTile(self: *const Tilemap, tilesets: Tileset.List, gid: u32) ?Tile {
|
pub fn getTile(self: *const Tilemap, tilesets: Tileset.List, gid: u32) ?Tile {
|
||||||
const Flag = GlobalTileId.Flag;
|
const tileset_ref = self.getTilesetByGid(gid & GlobalTileId.Flag.clear) orelse return null;
|
||||||
|
|
||||||
const gid_without_flags = gid & Flag.clear;
|
|
||||||
const tileset_ref = self.getTilesetByGid(gid_without_flags) orelse return null;
|
|
||||||
const tileset = tilesets.get(tileset_ref.source) orelse return null;
|
const tileset = tilesets.get(tileset_ref.source) orelse return null;
|
||||||
const id = gid_without_flags - tileset_ref.first_gid;
|
const id = gid - tileset_ref.first_gid;
|
||||||
|
|
||||||
return Tile{
|
return Tile{
|
||||||
.tileset = tileset,
|
.tileset = tileset,
|
||||||
.id = id,
|
.id = id
|
||||||
.flip_horizontal = (gid & @intFromEnum(Flag.flipped_horizontally)) > 0,
|
|
||||||
.flip_vertical = (gid & @intFromEnum(Flag.flipped_vertically)) > 0,
|
|
||||||
.flip_diagonal = (gid & @intFromEnum(Flag.flipped_diagonally)) > 0
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
177
src/assets.zig
@ -24,6 +24,7 @@ pub const Tilemap = struct {
|
|||||||
texture: Gfx.TextureId,
|
texture: Gfx.TextureId,
|
||||||
tile_size: Engine.Vec2,
|
tile_size: Engine.Vec2,
|
||||||
|
|
||||||
|
|
||||||
pub fn getTileUV(self: Tilemap, tile_x: f32, tile_y: f32) Rect {
|
pub fn getTileUV(self: Tilemap, tile_x: f32, tile_y: f32) Rect {
|
||||||
const texture_info = Engine.Graphics.getTextureInfo(self.texture);
|
const texture_info = Engine.Graphics.getTextureInfo(self.texture);
|
||||||
const tilemap_size = Vec2.initFromInt(u32, texture_info.width, texture_info.height);
|
const tilemap_size = Vec2.initFromInt(u32, texture_info.width, texture_info.height);
|
||||||
@ -38,19 +39,14 @@ pub const Tilemap = struct {
|
|||||||
arena: std.heap.ArenaAllocator,
|
arena: std.heap.ArenaAllocator,
|
||||||
|
|
||||||
font_id: FontName.EnumArray,
|
font_id: FontName.EnumArray,
|
||||||
pistol_mask: Gfx.TextureId,
|
wood01: Audio.Data.Id,
|
||||||
bomb_mask: Gfx.TextureId,
|
|
||||||
laser_mask: Gfx.TextureId,
|
|
||||||
bullet: Gfx.TextureId,
|
|
||||||
shadow: Gfx.TextureId,
|
|
||||||
dungeon_tilemap: Tilemap,
|
|
||||||
|
|
||||||
skeleton: Gfx.Sprite,
|
|
||||||
snake: Gfx.Sprite,
|
|
||||||
fire_spirit: Gfx.Sprite,
|
|
||||||
|
|
||||||
map: tiled.Tilemap,
|
map: tiled.Tilemap,
|
||||||
tilesets: tiled.Tileset.List,
|
tilesets: tiled.Tileset.List,
|
||||||
|
move_sound: []Audio.Data.Id,
|
||||||
|
|
||||||
|
terrain_tilemap: Tilemap,
|
||||||
|
players_tilemap: Tilemap,
|
||||||
|
weapons_tilemap: Tilemap,
|
||||||
|
|
||||||
pub fn init(gpa: std.mem.Allocator) !Assets {
|
pub fn init(gpa: std.mem.Allocator) !Assets {
|
||||||
var arena = std.heap.ArenaAllocator.init(gpa);
|
var arena = std.heap.ArenaAllocator.init(gpa);
|
||||||
@ -62,88 +58,11 @@ pub fn init(gpa: std.mem.Allocator) !Assets {
|
|||||||
.italic = try Gfx.addFont("italic", @embedFile("assets/roboto-font/Roboto-Italic.ttf")),
|
.italic = try Gfx.addFont("italic", @embedFile("assets/roboto-font/Roboto-Italic.ttf")),
|
||||||
});
|
});
|
||||||
|
|
||||||
const pistol_mask_image = try STBImage.load(@embedFile("assets/pistol-mask.png"));
|
const wood01 = try Audio.load(.{
|
||||||
defer pistol_mask_image.deinit();
|
.format = .vorbis,
|
||||||
const pistol_mask_texture = try Gfx.addTexture(&.{
|
.data = @embedFile("assets/wood01.ogg"),
|
||||||
.{
|
|
||||||
.width = pistol_mask_image.width,
|
|
||||||
.height = pistol_mask_image.height,
|
|
||||||
.rgba = pistol_mask_image.rgba8_pixels
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const bomb_mask_image = try STBImage.load(@embedFile("assets/bomb-mask.png"));
|
|
||||||
defer bomb_mask_image.deinit();
|
|
||||||
const bomb_mask_texture = try Gfx.addTexture(&.{
|
|
||||||
.{
|
|
||||||
.width = bomb_mask_image.width,
|
|
||||||
.height = bomb_mask_image.height,
|
|
||||||
.rgba = bomb_mask_image.rgba8_pixels
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const laser_mask_image = try STBImage.load(@embedFile("assets/laser-mask.png"));
|
|
||||||
defer laser_mask_image.deinit();
|
|
||||||
const laser_mask_texture = try Gfx.addTexture(&.{
|
|
||||||
.{
|
|
||||||
.width = laser_mask_image.width,
|
|
||||||
.height = laser_mask_image.height,
|
|
||||||
.rgba = laser_mask_image.rgba8_pixels
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const skeleton_image = try STBImage.load(@embedFile("assets/skeleton.png"));
|
|
||||||
defer skeleton_image.deinit();
|
|
||||||
const skeleton_texture = try Gfx.addTexture(&.{
|
|
||||||
.{
|
|
||||||
.width = skeleton_image.width,
|
|
||||||
.height = skeleton_image.height,
|
|
||||||
.rgba = skeleton_image.rgba8_pixels
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const snake_image = try STBImage.load(@embedFile("assets/snake.png"));
|
|
||||||
defer snake_image.deinit();
|
|
||||||
const snake_texture = try Gfx.addTexture(&.{
|
|
||||||
.{
|
|
||||||
.width = snake_image.width,
|
|
||||||
.height = snake_image.height,
|
|
||||||
.rgba = snake_image.rgba8_pixels
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const fire_spirit_image = try STBImage.load(@embedFile("assets/fire-spirit.png"));
|
|
||||||
defer fire_spirit_image.deinit();
|
|
||||||
const fire_spirit_texture = try Gfx.addTexture(&.{
|
|
||||||
.{
|
|
||||||
.width = fire_spirit_image.width,
|
|
||||||
.height = fire_spirit_image.height,
|
|
||||||
.rgba = fire_spirit_image.rgba8_pixels
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const bullet_image = try STBImage.load(@embedFile("assets/bullet.png"));
|
|
||||||
defer bullet_image.deinit();
|
|
||||||
const bullet_texture = try Gfx.addTexture(&.{
|
|
||||||
.{
|
|
||||||
.width = bullet_image.width,
|
|
||||||
.height = bullet_image.height,
|
|
||||||
.rgba = bullet_image.rgba8_pixels
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const snake = Gfx.Sprite{
|
|
||||||
.texture = snake_texture,
|
|
||||||
.uv = .unit
|
|
||||||
};
|
|
||||||
const skeleton = Gfx.Sprite{
|
|
||||||
.texture = skeleton_texture,
|
|
||||||
.uv = .unit
|
|
||||||
};
|
|
||||||
const fire_spirit = Gfx.Sprite{
|
|
||||||
.texture = fire_spirit_texture,
|
|
||||||
.uv = .unit
|
|
||||||
};
|
|
||||||
|
|
||||||
var scratch = std.heap.ArenaAllocator.init(gpa);
|
var scratch = std.heap.ArenaAllocator.init(gpa);
|
||||||
defer scratch.deinit();
|
defer scratch.deinit();
|
||||||
|
|
||||||
@ -161,54 +80,76 @@ pub fn init(gpa: std.mem.Allocator) !Assets {
|
|||||||
gpa,
|
gpa,
|
||||||
&scratch,
|
&scratch,
|
||||||
&xml_buffers,
|
&xml_buffers,
|
||||||
@embedFile("assets/dungeon.tsx")
|
@embedFile("assets/tileset.tsx")
|
||||||
);
|
);
|
||||||
|
|
||||||
var tilesets: tiled.Tileset.List = .empty;
|
var tilesets: tiled.Tileset.List = .empty;
|
||||||
try tilesets.add(gpa, "dungeon.tsx", tileset);
|
try tilesets.add(gpa, "tilemap.tsx", tileset);
|
||||||
|
|
||||||
const dungeon_image = try STBImage.load(@embedFile("assets/tiny-dungeon/tilemap_packed.png"));
|
const players_image = try STBImage.load(@embedFile("assets/kenney_desert-shooter-pack_1.0/PNG/Players/tilemap_packed.png"));
|
||||||
defer dungeon_image.deinit();
|
defer players_image.deinit();
|
||||||
const dungeon_texture = try Gfx.addTexture(&.{
|
const players_texture = try Gfx.addTexture(&.{
|
||||||
.{
|
.{
|
||||||
.width = dungeon_image.width,
|
.width = players_image.width,
|
||||||
.height = dungeon_image.height,
|
.height = players_image.height,
|
||||||
.rgba = dungeon_image.rgba8_pixels
|
.rgba = players_image.rgba8_pixels
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const shadow_image = try STBImage.load(@embedFile("assets/shadow.png"));
|
const tileset_image = try STBImage.load(@embedFile("assets/kenney_desert-shooter-pack_1.0/PNG/Tiles/tilemap_packed.png"));
|
||||||
defer shadow_image.deinit();
|
defer tileset_image.deinit();
|
||||||
const shadow_texture = try Gfx.addTexture(&.{
|
const tileset_texture = try Gfx.addTexture(&.{
|
||||||
.{
|
.{
|
||||||
.width = shadow_image.width,
|
.width = tileset_image.width,
|
||||||
.height = shadow_image.height,
|
.height = tileset_image.height,
|
||||||
.rgba = shadow_image.rgba8_pixels
|
.rgba = tileset_image.rgba8_pixels
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const weapons_tileset = try STBImage.load(@embedFile("assets/kenney_desert-shooter-pack_1.0/PNG/Weapons/tilemap_packed.png"));
|
||||||
|
defer weapons_tileset.deinit();
|
||||||
|
const weapons_texture = try Gfx.addTexture(&.{
|
||||||
|
.{
|
||||||
|
.width = weapons_tileset.width,
|
||||||
|
.height = weapons_tileset.height,
|
||||||
|
.rgba = weapons_tileset.rgba8_pixels
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const move_c = try Audio.load(.{
|
||||||
|
.data = @embedFile("assets/kenney_desert-shooter-pack_1.0/Sounds/move-c.ogg"),
|
||||||
|
.format = .vorbis,
|
||||||
|
});
|
||||||
|
const move_d = try Audio.load(.{
|
||||||
|
.data = @embedFile("assets/kenney_desert-shooter-pack_1.0/Sounds/move-d.ogg"),
|
||||||
|
.format = .vorbis,
|
||||||
|
});
|
||||||
|
const move_sound = try arena.allocator().dupe(Audio.Data.Id, &.{ move_c, move_d });
|
||||||
|
|
||||||
return Assets{
|
return Assets{
|
||||||
.arena = arena,
|
.arena = arena,
|
||||||
.font_id = font_id_array,
|
.font_id = font_id_array,
|
||||||
.pistol_mask = pistol_mask_texture,
|
.wood01 = wood01,
|
||||||
.bomb_mask = bomb_mask_texture,
|
|
||||||
.laser_mask = laser_mask_texture,
|
|
||||||
.snake = snake,
|
|
||||||
.skeleton = skeleton,
|
|
||||||
.fire_spirit = fire_spirit,
|
|
||||||
.map = map,
|
.map = map,
|
||||||
.tilesets = tilesets,
|
.tilesets = tilesets,
|
||||||
.bullet = bullet_texture,
|
.move_sound = move_sound,
|
||||||
.shadow = shadow_texture,
|
.terrain_tilemap = .{
|
||||||
.dungeon_tilemap = .{
|
.texture = tileset_texture,
|
||||||
.texture = dungeon_texture,
|
.tile_size = .initFromInt(u32, tileset.tile_width, tileset.tile_height)
|
||||||
.tile_size = .init(16, 16)
|
},
|
||||||
}
|
.players_tilemap = .{
|
||||||
|
.texture = players_texture,
|
||||||
|
.tile_size = .init(24, 24)
|
||||||
|
},
|
||||||
|
.weapons_tilemap = .{
|
||||||
|
.texture = weapons_texture,
|
||||||
|
.tile_size = .init(24, 24)
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *Assets, gpa: std.mem.Allocator) void {
|
pub fn deinit(self: *Assets, gpa: std.mem.Allocator) void {
|
||||||
self.tilesets.deinit(gpa);
|
|
||||||
self.map.deinit();
|
self.map.deinit();
|
||||||
|
self.tilesets.deinit(gpa);
|
||||||
self.arena.deinit();
|
self.arena.deinit();
|
||||||
}
|
}
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 529 B |
|
Before Width: | Height: | Size: 279 B |
@ -1,4 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<tileset version="1.10" tiledversion="1.11.2" name="dungeon" tilewidth="16" tileheight="16" tilecount="132" columns="12">
|
|
||||||
<image source="tiny-dungeon/tilemap_packed.png" width="192" height="176"/>
|
|
||||||
</tileset>
|
|
||||||
|
Before Width: | Height: | Size: 320 B |
@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"automappingRulesFile": "",
|
|
||||||
"commands": [
|
|
||||||
],
|
|
||||||
"compatibilityVersion": 1100,
|
|
||||||
"extensionsPath": "extensions",
|
|
||||||
"folders": [
|
|
||||||
"."
|
|
||||||
],
|
|
||||||
"properties": [
|
|
||||||
],
|
|
||||||
"propertyTypes": [
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -1,9 +1,10 @@
|
|||||||
|
|
||||||
|
|
||||||
Tiny Dungeon (1.0)
|
Desert Shooter Pack (1.0)
|
||||||
|
|
||||||
Created/distributed by Kenney (www.kenney.nl)
|
Created/distributed by Kenney (www.kenney.nl)
|
||||||
Creation date: 05-07-2022
|
Sponsored by: GameMaker (www.gamemaker.io)
|
||||||
|
Creation date: 24-04-2024
|
||||||
|
|
||||||
------------------------------
|
------------------------------
|
||||||
|
|
||||||
@ -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: 1.2 KiB |
@ -3,7 +3,7 @@ Tilesheet information:
|
|||||||
Tile size • 16px × 16px
|
Tile size • 16px × 16px
|
||||||
Space between tiles • 1px × 1px
|
Space between tiles • 1px × 1px
|
||||||
---
|
---
|
||||||
Total tiles (horizontal) • 12 tiles
|
Total tiles (horizontal) • 18 tiles
|
||||||
Total tiles (vertical) • 11 tiles
|
Total tiles (vertical) • 11 tiles
|
||||||
---
|
---
|
||||||
Total tiles in sheet • 132 tiles
|
Total tiles in sheet • 198 tiles
|
||||||
|
After Width: | Height: | Size: 2.9 KiB |
@ -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: 1.1 KiB |
@ -0,0 +1,9 @@
|
|||||||
|
Tilesheet information:
|
||||||
|
|
||||||
|
Tile size • 16px × 16px
|
||||||
|
Space between tiles • 1px × 1px
|
||||||
|
---
|
||||||
|
Total tiles (horizontal) • 18 tiles
|
||||||
|
Total tiles (vertical) • 13 tiles
|
||||||
|
---
|
||||||
|
Total tiles in sheet • 234 tiles
|
||||||
|
After Width: | Height: | Size: 6.3 KiB |
@ -0,0 +1,9 @@
|
|||||||
|
Tilesheet information:
|
||||||
|
|
||||||
|
Tile size • 24px × 24px
|
||||||
|
Space between tiles • 1px × 1px
|
||||||
|
---
|
||||||
|
Total tiles (horizontal) • 10 tiles
|
||||||
|
Total tiles (vertical) • 4 tiles
|
||||||
|
---
|
||||||
|
Total tiles in sheet • 40 tiles
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/coin-a.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/coin-b.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/coin-c.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/coin-d.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/error-a.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/error-b.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/error-c.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/explosion-a.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/explosion-b.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/explosion-c.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/fall-a.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/fall-b.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/hurt-a.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/hurt-b.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/hurt-c.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/hurt-d.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/hurt-e.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/jump-a.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/jump-b.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/jump-c.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/jump-d.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/jump-e.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/jump-f.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/lose-a.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/lose-b.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/lose-c.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/lose-d.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/move-a.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/move-b.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/move-c.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/move-d.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/select-a.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/shoot-a.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/shoot-b.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/shoot-c.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/shoot-d.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/shoot-e.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/shoot-f.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/shoot-g.ogg
Normal file
BIN
src/assets/kenney_desert-shooter-pack_1.0/Sounds/shoot-h.ogg
Normal file
|
Before Width: | Height: | Size: 557 B |
@ -1,23 +1,225 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<map version="1.10" tiledversion="1.11.2" orientation="orthogonal" renderorder="right-down" width="20" height="15" tilewidth="16" tileheight="16" infinite="0" nextlayerid="2" nextobjectid="1">
|
<map version="1.10" tiledversion="1.11.2" orientation="orthogonal" renderorder="right-down" width="30" height="20" tilewidth="16" tileheight="16" infinite="1" nextlayerid="5" nextobjectid="2">
|
||||||
<tileset firstgid="1" source="dungeon.tsx"/>
|
<tileset firstgid="1" source="tilemap.tsx"/>
|
||||||
<layer id="1" name="Tile Layer 1" width="20" height="15">
|
<layer id="1" name="ground" width="30" height="20">
|
||||||
<data encoding="csv">
|
<data encoding="csv">
|
||||||
2147483701,51,51,51,52,52,51,51,51,51,51,52,52,52,51,51,51,51,51,53,
|
<chunk x="-32" y="-32" width="16" height="16">
|
||||||
536870963,49,49,49,49,49,49,49,49,50,50,50,50,50,49,49,49,49,49,2684354611,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
1610612788,49,43,43,49,49,49,49,49,50,50,50,50,50,49,49,43,43,49,2684354611,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
1610612788,49,43,43,49,49,50,49,49,49,50,50,50,50,49,49,43,43,50,2684354611,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
1610612788,50,50,49,49,49,50,50,49,49,49,49,49,49,49,49,49,50,50,3758096436,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
1610612788,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,50,3758096436,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
1610612788,49,49,49,49,49,49,50,50,50,50,49,49,50,49,49,49,49,49,3758096436,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
536870963,49,49,49,49,49,49,49,50,50,50,50,50,50,49,49,49,49,49,2684354611,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
536870963,49,50,50,49,49,49,49,49,49,50,50,50,50,49,49,49,50,50,3758096436,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
536870963,49,50,50,49,49,49,49,49,49,49,49,49,49,49,49,50,50,50,3758096436,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
1610612788,50,50,49,49,49,49,50,50,49,49,49,49,49,49,50,50,50,49,2684354611,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
1610612788,49,43,43,49,49,50,50,50,50,50,49,49,49,49,50,43,43,49,2684354611,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
536870963,49,43,43,49,50,50,50,49,49,49,49,49,49,49,50,43,43,49,3758096436,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
536870963,49,49,49,49,50,50,49,49,49,49,49,49,49,49,49,49,49,49,2684354611,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
3221225525,1073741875,1073741875,1073741875,1073741875,1073741876,1073741876,1073741875,1073741875,1073741875,1073741875,1073741875,1073741875,1073741876,1073741876,1073741875,1073741875,1073741875,1073741876,1073741877
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,91,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,109,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,109
|
||||||
|
</chunk>
|
||||||
|
<chunk x="-16" y="-32" width="16" height="16">
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,65,65,0,0,0,0,0,0,
|
||||||
|
92,92,92,92,92,92,92,93,65,65,0,0,0,0,0,0,
|
||||||
|
110,20,110,110,110,110,110,112,110,65,0,0,0,0,0,0,
|
||||||
|
110,110,110,110,20,110,110,110,110,65,65,0,0,0,0,0
|
||||||
|
</chunk>
|
||||||
|
<chunk x="-32" y="-16" width="16" height="16">
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,109,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,109,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||||
|
</chunk>
|
||||||
|
<chunk x="-16" y="-16" width="16" height="16">
|
||||||
|
110,110,20,110,110,110,110,94,110,65,65,0,0,0,65,0,
|
||||||
|
110,20,110,110,110,110,20,111,65,65,65,0,0,0,65,0,
|
||||||
|
128,128,128,128,128,128,128,129,65,65,65,0,65,65,65,0,
|
||||||
|
0,0,0,65,65,65,65,65,65,65,65,65,195,65,65,0,
|
||||||
|
0,0,0,65,65,65,65,65,65,65,65,65,65,65,65,0,
|
||||||
|
0,0,65,65,65,65,65,65,65,65,65,65,66,65,65,65,
|
||||||
|
0,0,65,65,65,65,66,65,65,66,65,65,65,65,65,65,
|
||||||
|
0,0,0,65,65,65,65,65,65,65,66,65,65,65,65,65,
|
||||||
|
0,0,0,65,65,195,65,65,65,65,65,65,65,65,65,65,
|
||||||
|
0,0,0,65,65,65,65,66,65,65,65,65,65,65,65,65,
|
||||||
|
0,0,0,65,65,65,65,65,65,66,65,65,195,65,65,65,
|
||||||
|
0,0,0,65,65,65,65,65,65,65,65,65,65,65,66,65,
|
||||||
|
0,65,65,65,65,65,66,65,65,65,65,65,65,65,65,65,
|
||||||
|
0,0,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||||
|
</chunk>
|
||||||
|
<chunk x="0" y="-16" width="16" height="16">
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
65,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
65,65,65,65,65,65,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
65,65,65,65,65,65,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
65,65,65,65,65,65,65,0,0,0,0,0,0,0,0,0,
|
||||||
|
65,65,65,65,65,65,65,0,0,0,0,0,0,0,0,0,
|
||||||
|
65,65,65,65,65,65,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
65,65,65,65,65,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
65,65,65,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
65,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||||
|
</chunk>
|
||||||
</data>
|
</data>
|
||||||
</layer>
|
</layer>
|
||||||
|
<layer id="3" name="walls" width="30" height="20">
|
||||||
|
<properties>
|
||||||
|
<property name="solid" type="bool" value="true"/>
|
||||||
|
</properties>
|
||||||
|
<data encoding="csv">
|
||||||
|
<chunk x="-16" y="-32" width="16" height="16">
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,1,2,2,2,2,3,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,19,110,20,110,20,21,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,19,110,110,20,20,21,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,37,38,38,38,38,39,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,73,56,174,174,174,57,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,73,174,174,56,174,57,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,73,174,174,174,174,57,0,0
|
||||||
|
</chunk>
|
||||||
|
<chunk x="-16" y="-16" width="16" height="16">
|
||||||
|
0,0,0,0,0,0,0,0,73,174,56,56,174,57,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,73,174,174,174,56,57,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,73,74,74,74,74,75,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||||
|
</chunk>
|
||||||
|
</data>
|
||||||
|
</layer>
|
||||||
|
<layer id="4" name="walls 2" width="30" height="20">
|
||||||
|
<properties>
|
||||||
|
<property name="solid" type="bool" value="true"/>
|
||||||
|
</properties>
|
||||||
|
<data encoding="csv">
|
||||||
|
<chunk x="-16" y="-32" width="16" height="16">
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,2,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,37,38,38
|
||||||
|
</chunk>
|
||||||
|
<chunk x="0" y="-32" width="16" height="16">
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
2,2,2,3,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
38,38,38,39,0,0,0,0,0,0,0,0,0,0,0,0
|
||||||
|
</chunk>
|
||||||
|
<chunk x="-16" y="-16" width="16" height="16">
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,73,174,174,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,73,174,174,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,73,56,174,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,73,56,56,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,73,74,74,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||||
|
</chunk>
|
||||||
|
<chunk x="0" y="-16" width="16" height="16">
|
||||||
|
56,56,174,75,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
174,174,174,75,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
174,174,56,75,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
174,56,56,75,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
74,74,74,75,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||||
|
</chunk>
|
||||||
|
</data>
|
||||||
|
</layer>
|
||||||
|
<objectgroup id="2" name="Object Layer 1">
|
||||||
|
<object id="1" name="spawnpoint" x="-118" y="-120.5">
|
||||||
|
<point/>
|
||||||
|
</object>
|
||||||
|
</objectgroup>
|
||||||
</map>
|
</map>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 552 B |
|
Before Width: | Height: | Size: 234 B |
|
Before Width: | Height: | Size: 413 B |
|
Before Width: | Height: | Size: 406 B |
4
src/assets/tilemap.tsx
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<tileset version="1.10" tiledversion="1.11.2" name="tilemap" tilewidth="16" tileheight="16" tilecount="234" columns="18">
|
||||||
|
<image source="kenney_desert-shooter-pack_1.0/PNG/Tiles/tilemap_packed.png" width="288" height="208"/>
|
||||||
|
</tileset>
|
||||||
4
src/assets/tileset.tsx
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<tileset version="1.10" tiledversion="1.11.2" name="tilemap" tilewidth="16" tileheight="16" tilecount="234" columns="18">
|
||||||
|
<image source="kenney_desert-shooter-pack_1.0/PNG/Tiles/Tilemap/tilemap_packed.png" width="288" height="208"/>
|
||||||
|
</tileset>
|
||||||
@ -1,23 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
Tiny Creatures (1.0)
|
|
||||||
|
|
||||||
Created by Clint Bellanger (clintbellanger.net)
|
|
||||||
Creation date: 03-18-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 my work by crediting Clint Bellanger (this is not mandatory)
|
|
||||||
|
|
||||||
------------------------------
|
|
||||||
|
|
||||||
This set is an expansion of Kenney's Tiny Dungeon and Tiny Town:
|
|
||||||
https://kenney.nl/assets/tiny-dungeon
|
|
||||||
https://kenney.nl/assets/tiny-town
|
|
||||||
The included sample Tiled map and example images contain works by Kenney from these sets.
|
|
||||||
|
|
||||||
Made with Kenney's permission
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
Tilesheet information:
|
|
||||||
|
|
||||||
Tile size • 16px × 16px
|
|
||||||
Space between tiles • 1px × 1px
|
|
||||||
---
|
|
||||||
Total tiles (horizontal) • 10 tiles
|
|
||||||
Total tiles (vertical) • 18 tiles
|
|
||||||
---
|
|
||||||
Total tiles in sheet • 180 tiles
|
|
||||||
|
|
||||||
|
|
||||||
Note: I've set these creatures to all face right (except where symmetrical).
|
|
||||||
You may choose to horizonally-flip these sprites when creatures are facing left.
|
|
||||||
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 5.2 KiB |
BIN
src/assets/wood01.ogg
Normal file
BIN
src/assets/wood02.ogg
Normal file
BIN
src/assets/wood03.ogg
Normal file
@ -230,16 +230,6 @@ pub fn popScissor(self: *Frame) void {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn drawCircle(self: *Frame, center: Vec2, radius: f32, color: Vec4) void {
|
|
||||||
self.pushGraphicsCommand(.{
|
|
||||||
.draw_circle = .{
|
|
||||||
.center = center,
|
|
||||||
.radius = radius,
|
|
||||||
.color = color,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn drawRectangle(self: *Frame, opts: GraphicsCommand.DrawRectangle) void {
|
pub fn drawRectangle(self: *Frame, opts: GraphicsCommand.DrawRectangle) void {
|
||||||
self.pushGraphicsCommand(.{ .draw_rectangle = opts });
|
self.pushGraphicsCommand(.{ .draw_rectangle = opts });
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,6 @@ const simgui = sokol.imgui;
|
|||||||
const sgl = sokol.gl;
|
const sgl = sokol.gl;
|
||||||
|
|
||||||
const Math = @import("./math.zig");
|
const Math = @import("./math.zig");
|
||||||
const Line = Math.Line;
|
|
||||||
const Vec2 = Math.Vec2;
|
const Vec2 = Math.Vec2;
|
||||||
const Vec4 = Math.Vec4;
|
const Vec4 = Math.Vec4;
|
||||||
const rgb = Math.rgb;
|
const rgb = Math.rgb;
|
||||||
@ -46,15 +45,6 @@ pub const Command = union(enum) {
|
|||||||
sprite: ?Sprite = null,
|
sprite: ?Sprite = null,
|
||||||
rotation: f32 = 0,
|
rotation: f32 = 0,
|
||||||
origin: Vec2 = .init(0, 0),
|
origin: Vec2 = .init(0, 0),
|
||||||
uv_flip_diagonal: bool = false,
|
|
||||||
uv_flip_horizontal: bool = false,
|
|
||||||
uv_flip_vertical: bool = false
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const DrawCircle = struct {
|
|
||||||
center: Vec2,
|
|
||||||
radius: f32,
|
|
||||||
color: Vec4,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
set_scissor: Rect,
|
set_scissor: Rect,
|
||||||
@ -69,7 +59,6 @@ pub const Command = union(enum) {
|
|||||||
},
|
},
|
||||||
push_transformation: struct { translation: Vec2, scale: Vec2 },
|
push_transformation: struct { translation: Vec2, scale: Vec2 },
|
||||||
pop_transformation: void,
|
pop_transformation: void,
|
||||||
draw_circle: DrawCircle
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const Texture = struct {
|
const Texture = struct {
|
||||||
@ -91,23 +80,6 @@ pub const TextureInfo = Texture.Info;
|
|||||||
pub const Sprite = struct {
|
pub const Sprite = struct {
|
||||||
texture: TextureId,
|
texture: TextureId,
|
||||||
uv: Rect,
|
uv: Rect,
|
||||||
|
|
||||||
pub fn flipHorizontal(self: Sprite) Sprite {
|
|
||||||
var uv = self.uv;
|
|
||||||
uv.pos.x += uv.size.x;
|
|
||||||
uv.size.x *= -1;
|
|
||||||
|
|
||||||
return Sprite{
|
|
||||||
.texture = self.texture,
|
|
||||||
.uv = uv
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn getSize(self: Sprite) Vec2 {
|
|
||||||
const texture_info = getTextureInfo(self.texture);
|
|
||||||
const texture_size = Vec2.initFromInt(u32, texture_info.width, texture_info.height);
|
|
||||||
return self.uv.size.multiply(texture_size);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var gpa: std.mem.Allocator = undefined;
|
var gpa: std.mem.Allocator = undefined;
|
||||||
@ -233,25 +205,6 @@ pub fn drawCommand(command: Command) void {
|
|||||||
font_context.setColor(color);
|
font_context.setColor(color);
|
||||||
font_context.drawText(opts.pos.x * font_resolution_scale.x, opts.pos.y * font_resolution_scale.y, opts.text);
|
font_context.drawText(opts.pos.x * font_resolution_scale.x, opts.pos.y * font_resolution_scale.y, opts.text);
|
||||||
},
|
},
|
||||||
.draw_circle => |opts| {
|
|
||||||
sgl.beginTriangleStrip();
|
|
||||||
defer sgl.end();
|
|
||||||
|
|
||||||
const angle_step: f32 = std.math.pi * 2.0 / 32.0;
|
|
||||||
|
|
||||||
sgl.c4f(opts.color.x, opts.color.y, opts.color.z, opts.color.w);
|
|
||||||
|
|
||||||
sgl.v2f(opts.center.x, opts.center.y);
|
|
||||||
var angle: f32 = 0;
|
|
||||||
while (angle < std.math.pi * 2) {
|
|
||||||
const point_on_circle = Vec2.initAngle(angle).multiplyScalar(opts.radius).add(opts.center);
|
|
||||||
sgl.v2f(point_on_circle.x, point_on_circle.y);
|
|
||||||
sgl.v2f(opts.center.x, opts.center.y);
|
|
||||||
|
|
||||||
angle += angle_step;
|
|
||||||
}
|
|
||||||
sgl.v2f(opts.center.x + opts.radius, opts.center.y);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -353,41 +306,7 @@ fn drawRectangle(opts: Command.DrawRectangle) void {
|
|||||||
|
|
||||||
if (opts.sprite) |sprite| {
|
if (opts.sprite) |sprite| {
|
||||||
const uv = sprite.uv;
|
const uv = sprite.uv;
|
||||||
var uv_top_left = Vec2.init(uv.left(), uv.top());
|
const quad = [4]Vertex{ .{ .pos = pos.add(top_left), .uv = .init(uv.left(), uv.top()) }, .{ .pos = pos.add(top_right), .uv = .init(uv.right(), uv.top()) }, .{ .pos = pos.add(bottom_right), .uv = .init(uv.right(), uv.bottom()) }, .{ .pos = pos.add(bottom_left), .uv = .init(uv.left(), uv.bottom()) } };
|
||||||
var uv_top_right = Vec2.init(uv.right(), uv.top());
|
|
||||||
var uv_bottom_right = Vec2.init(uv.right(), uv.bottom());
|
|
||||||
var uv_bottom_left = Vec2.init(uv.left(), uv.bottom());
|
|
||||||
|
|
||||||
if (opts.uv_flip_diagonal) {
|
|
||||||
std.mem.swap(Vec2, &uv_bottom_left, &uv_top_right);
|
|
||||||
}
|
|
||||||
if (opts.uv_flip_horizontal) {
|
|
||||||
std.mem.swap(Vec2, &uv_top_left, &uv_top_right);
|
|
||||||
std.mem.swap(Vec2, &uv_bottom_left, &uv_bottom_right);
|
|
||||||
}
|
|
||||||
if (opts.uv_flip_vertical) {
|
|
||||||
std.mem.swap(Vec2, &uv_top_left, &uv_bottom_left);
|
|
||||||
std.mem.swap(Vec2, &uv_top_right, &uv_bottom_right);
|
|
||||||
}
|
|
||||||
|
|
||||||
const quad = [4]Vertex{
|
|
||||||
.{
|
|
||||||
.pos = pos.add(top_left),
|
|
||||||
.uv = uv_top_left
|
|
||||||
},
|
|
||||||
.{
|
|
||||||
.pos = pos.add(top_right),
|
|
||||||
.uv = uv_top_right,
|
|
||||||
},
|
|
||||||
.{
|
|
||||||
.pos = pos.add(bottom_right),
|
|
||||||
.uv = uv_bottom_right
|
|
||||||
},
|
|
||||||
.{
|
|
||||||
.pos = pos.add(bottom_left),
|
|
||||||
.uv = uv_bottom_left
|
|
||||||
}
|
|
||||||
};
|
|
||||||
drawQuad(quad, opts.color, sprite.texture);
|
drawQuad(quad, opts.color, sprite.texture);
|
||||||
} else {
|
} else {
|
||||||
const quad = .{ pos.add(top_left), pos.add(top_right), pos.add(bottom_right), pos.add(bottom_left) };
|
const quad = .{ pos.add(top_left), pos.add(top_right), pos.add(bottom_right), pos.add(bottom_left) };
|
||||||
@ -396,22 +315,14 @@ fn drawRectangle(opts: Command.DrawRectangle) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn drawLine(from: Vec2, to: Vec2, color: Vec4, width: f32) void {
|
fn drawLine(from: Vec2, to: Vec2, color: Vec4, width: f32) void {
|
||||||
const line = Line{
|
const step = to.sub(from).normalized().multiplyScalar(width / 2);
|
||||||
.p0 = from,
|
|
||||||
.p1 = to,
|
|
||||||
};
|
|
||||||
|
|
||||||
const quad = line.getQuad(width);
|
const top_left = from.add(step.rotateLeft90());
|
||||||
|
const bottom_left = from.add(step.rotateRight90());
|
||||||
|
const top_right = to.add(step.rotateLeft90());
|
||||||
|
const bottom_right = to.add(step.rotateRight90());
|
||||||
|
|
||||||
drawQuadNoUVs(
|
drawQuadNoUVs(.{ top_right, top_left, bottom_left, bottom_right }, color);
|
||||||
.{
|
|
||||||
quad.top_right,
|
|
||||||
quad.top_left,
|
|
||||||
quad.bottom_left,
|
|
||||||
quad.bottom_right
|
|
||||||
},
|
|
||||||
color
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addFont(name: [*c]const u8, data: []const u8) !Font.Id {
|
pub fn addFont(name: [*c]const u8, data: []const u8) !Font.Id {
|
||||||
@ -467,8 +378,3 @@ pub fn getTextureInfo(id: TextureId) TextureInfo {
|
|||||||
const texture = textures.items[@intFromEnum(id)];
|
const texture = textures.items[@intFromEnum(id)];
|
||||||
return texture.info;
|
return texture.info;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getTextureSize(id: TextureId) Vec2 {
|
|
||||||
const texture_info = getTextureInfo(id);
|
|
||||||
return Vec2.initFromInt(u32, texture_info.width, texture_info.height);
|
|
||||||
}
|
|
||||||
|
|||||||
@ -368,11 +368,6 @@ pub const Rect = struct {
|
|||||||
pos: Vec2,
|
pos: Vec2,
|
||||||
size: Vec2,
|
size: Vec2,
|
||||||
|
|
||||||
pub const unit = Rect{
|
|
||||||
.pos = .zero,
|
|
||||||
.size = .init(1, 1),
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const zero = Rect{
|
pub const zero = Rect{
|
||||||
.pos = Vec2.zero,
|
.pos = Vec2.zero,
|
||||||
.size = Vec2.zero
|
.size = Vec2.zero
|
||||||
@ -402,33 +397,6 @@ pub const Rect = struct {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getTopEdge(self: Rect) Line {
|
|
||||||
return Line{
|
|
||||||
.p0 = .init(self.left(), self.top()),
|
|
||||||
.p1 = .init(self.right(), self.top()),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
pub fn getBottomEdge(self: Rect) Line {
|
|
||||||
return Line{
|
|
||||||
.p0 = .init(self.left(), self.bottom()),
|
|
||||||
.p1 = .init(self.right(), self.bottom()),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn getLeftEdge(self: Rect) Line {
|
|
||||||
return Line{
|
|
||||||
.p0 = .init(self.left(), self.top()),
|
|
||||||
.p1 = .init(self.left(), self.bottom()),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn getRightEdge(self: Rect) Line {
|
|
||||||
return Line{
|
|
||||||
.p0 = .init(self.right(), self.top()),
|
|
||||||
.p1 = .init(self.right(), self.bottom()),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn left(self: Rect) f32 {
|
pub fn left(self: Rect) f32 {
|
||||||
return self.pos.x;
|
return self.pos.x;
|
||||||
}
|
}
|
||||||
@ -463,57 +431,12 @@ pub const Rect = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn isPointInside(self: Rect, pos: Vec2) bool {
|
pub fn isInside(self: Rect, pos: Vec2) bool {
|
||||||
const x_overlap = self.pos.x <= pos.x and pos.x < self.pos.x + self.size.x;
|
const x_overlap = self.pos.x <= pos.x and pos.x < self.pos.x + self.size.x;
|
||||||
const y_overlap = self.pos.y <= pos.y and pos.y < self.pos.y + self.size.y;
|
const y_overlap = self.pos.y <= pos.y and pos.y < self.pos.y + self.size.y;
|
||||||
return x_overlap and y_overlap;
|
return x_overlap and y_overlap;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn checkEdgeLineOverlap(self: Rect, line: Line) bool {
|
|
||||||
const left_overlap = line.hasOverlap(self.getLeftEdge());
|
|
||||||
const right_overlap = line.hasOverlap(self.getRightEdge());
|
|
||||||
const top_overlap = line.hasOverlap(self.getTopEdge());
|
|
||||||
const bottom_overlap = line.hasOverlap(self.getBottomEdge());
|
|
||||||
return left_overlap or right_overlap or top_overlap or bottom_overlap;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn checkCircleOverlap(self: Rect, circle_center: Vec2, circle_radius: f32) bool {
|
|
||||||
const cx = circle_center.x;
|
|
||||||
const cy = circle_center.y;
|
|
||||||
const rx = self.pos.x;
|
|
||||||
const ry = self.pos.y;
|
|
||||||
const rw = self.size.x;
|
|
||||||
const rh = self.size.y;
|
|
||||||
|
|
||||||
// temporary variables to set edges for testing
|
|
||||||
var testX = cx;
|
|
||||||
var testY = cy;
|
|
||||||
|
|
||||||
// which edge is closest?
|
|
||||||
if (cx < rx) {
|
|
||||||
testX = rx; // test left edge
|
|
||||||
} else if (cx > rx+rw) {
|
|
||||||
testX = rx+rw; // right edge
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cy < ry) {
|
|
||||||
testY = ry; // top edge
|
|
||||||
} else if (cy > ry+rh) {
|
|
||||||
testY = ry+rh; // bottom edge
|
|
||||||
}
|
|
||||||
|
|
||||||
// get distance from closest edges
|
|
||||||
const distX = cx-testX;
|
|
||||||
const distY = cy-testY;
|
|
||||||
const distance = @sqrt( (distX*distX) + (distY*distY) );
|
|
||||||
|
|
||||||
// if the distance is less than the radius, collision!
|
|
||||||
if (distance <= circle_radius) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn hasOverlap(lhs: Rect, rhs: Rect) bool {
|
pub fn hasOverlap(lhs: Rect, rhs: Rect) bool {
|
||||||
return (lhs.left() < rhs.right() and lhs.right() > rhs.left()) and
|
return (lhs.left() < rhs.right() and lhs.right() > rhs.left()) and
|
||||||
(lhs.top() < rhs.bottom() and lhs.bottom() > rhs.top());
|
(lhs.top() < rhs.bottom() and lhs.bottom() > rhs.top());
|
||||||
@ -538,133 +461,9 @@ pub const Rect = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Quad = struct {
|
|
||||||
top_left: Vec2,
|
|
||||||
bottom_left: Vec2,
|
|
||||||
top_right: Vec2,
|
|
||||||
bottom_right: Vec2,
|
|
||||||
|
|
||||||
pub fn isRectOverlap(self: Quad, rect: Rect) bool {
|
|
||||||
const vertices = [4]Vec2{
|
|
||||||
self.top_right,
|
|
||||||
self.top_left,
|
|
||||||
self.bottom_left,
|
|
||||||
self.bottom_right,
|
|
||||||
};
|
|
||||||
const polygon = Polygon{
|
|
||||||
.vertices = &vertices
|
|
||||||
};
|
|
||||||
return polygon.isRectOverlap(rect);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const Polygon = struct {
|
|
||||||
vertices: []const Vec2,
|
|
||||||
|
|
||||||
pub fn isPointInside(self: Polygon, point: Vec2) bool {
|
|
||||||
var collision = false;
|
|
||||||
|
|
||||||
const py = point.y;
|
|
||||||
const px = point.x;
|
|
||||||
|
|
||||||
for (0..self.vertices.len) |i| {
|
|
||||||
const next_i = @mod(i + 1, self.vertices.len);
|
|
||||||
// get the PVectors at our current position
|
|
||||||
// this makes our if statement a little cleaner
|
|
||||||
const vc = self.vertices[i]; // c for "current"
|
|
||||||
const vn = self.vertices[next_i]; // n for "next"
|
|
||||||
|
|
||||||
// compare position, flip 'collision' variable
|
|
||||||
// back and forth
|
|
||||||
if (
|
|
||||||
((vc.y > py and vn.y < py) or (vc.y < py and vn.y > py))
|
|
||||||
and
|
|
||||||
(px < (vn.x-vc.x)*(py-vc.y) / (vn.y-vc.y)+vc.x)
|
|
||||||
) {
|
|
||||||
collision = !collision;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return collision;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn isRectOverlap(self: Polygon, rect: Rect) bool {
|
|
||||||
// go through each of the vertices, plus the next
|
|
||||||
// vertex in the list
|
|
||||||
for (0..self.vertices.len) |i| {
|
|
||||||
const next_i = @mod(i + 1, self.vertices.len);
|
|
||||||
|
|
||||||
// get the PVectors at our current position
|
|
||||||
// this makes our if statement a little cleaner
|
|
||||||
const vc = self.vertices[i]; // c for "current"
|
|
||||||
const vn = self.vertices[next_i]; // n for "next"
|
|
||||||
|
|
||||||
const polygon_edge = Line{
|
|
||||||
.p0 = vc,
|
|
||||||
.p1 = vn,
|
|
||||||
};
|
|
||||||
|
|
||||||
// check against all four sides of the rectangle
|
|
||||||
if (rect.checkEdgeLineOverlap(polygon_edge)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// optional: test if the rectangle is INSIDE the polygon
|
|
||||||
// note that this iterates all sides of the polygon
|
|
||||||
// again, so only use this if you need to
|
|
||||||
if (self.isPointInside(rect.pos)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const Line = struct {
|
pub const Line = struct {
|
||||||
p0: Vec2,
|
p0: Vec2,
|
||||||
p1: Vec2,
|
p1: Vec2
|
||||||
|
|
||||||
pub fn hasOverlap(lhs: Line, rhs: Line) bool {
|
|
||||||
const x1 = lhs.p0.x;
|
|
||||||
const y1 = lhs.p0.y;
|
|
||||||
const x2 = lhs.p1.x;
|
|
||||||
const y2 = lhs.p1.y;
|
|
||||||
const x3 = rhs.p0.x;
|
|
||||||
const y3 = rhs.p0.y;
|
|
||||||
const x4 = rhs.p1.x;
|
|
||||||
const y4 = rhs.p1.y;
|
|
||||||
|
|
||||||
// calculate the direction of the lines
|
|
||||||
const uA = ((x4-x3)*(y1-y3) - (y4-y3)*(x1-x3)) / ((y4-y3)*(x2-x1) - (x4-x3)*(y2-y1));
|
|
||||||
const uB = ((x2-x1)*(y1-y3) - (y2-y1)*(x1-x3)) / ((y4-y3)*(x2-x1) - (x4-x3)*(y2-y1));
|
|
||||||
|
|
||||||
// if uA and uB are between 0-1, lines are colliding
|
|
||||||
if (uA >= 0 and uA <= 1 and uB >= 0 and uB <= 1) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn getQuad(self: Line, width: f32) Quad {
|
|
||||||
const to = self.p1;
|
|
||||||
const from = self.p0;
|
|
||||||
|
|
||||||
const step = to.sub(from).normalized().multiplyScalar(width / 2);
|
|
||||||
|
|
||||||
const top_left = from.add(step.rotateLeft90());
|
|
||||||
const bottom_left = from.add(step.rotateRight90());
|
|
||||||
const top_right = to.add(step.rotateLeft90());
|
|
||||||
const bottom_right = to.add(step.rotateRight90());
|
|
||||||
|
|
||||||
return Quad{
|
|
||||||
.top_left = top_left,
|
|
||||||
.bottom_left = bottom_left,
|
|
||||||
.top_right = top_right,
|
|
||||||
.bottom_right = bottom_right
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn isInsideRect(rect_pos: Vec2, rect_size: Vec2, pos: Vec2) bool {
|
pub fn isInsideRect(rect_pos: Vec2, rect_size: Vec2, pos: Vec2) bool {
|
||||||
@ -672,7 +471,7 @@ pub fn isInsideRect(rect_pos: Vec2, rect_size: Vec2, pos: Vec2) bool {
|
|||||||
.pos = rect_pos,
|
.pos = rect_pos,
|
||||||
.size = rect_size
|
.size = rect_size
|
||||||
};
|
};
|
||||||
return rect.isPointInside(pos);
|
return rect.isInside(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rgba(r: u8, g: u8, b: u8, a: f32) Vec4 {
|
pub fn rgba(r: u8, g: u8, b: u8, a: f32) Vec4 {
|
||||||
|
|||||||
13
src/game.zig
@ -124,12 +124,12 @@ pub fn debug(self: *Game) !void {
|
|||||||
}
|
}
|
||||||
defer imgui.endWindow();
|
defer imgui.endWindow();
|
||||||
|
|
||||||
if (imgui.button("Restart")) {
|
if (imgui.button("Spawn enemy")) {
|
||||||
try self.restartAndShowCombatScreen();
|
try self.combat_screen.spawnEnemy();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (imgui.button("Toggle colliders")) {
|
if (imgui.button("Restart")) {
|
||||||
self.combat_screen.show_colliders = !self.combat_screen.show_colliders;
|
try self.restartAndShowCombatScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.show_shop) {
|
if (self.show_shop) {
|
||||||
@ -144,7 +144,10 @@ pub fn debug(self: *Game) !void {
|
|||||||
|
|
||||||
const screen = &self.combat_screen;
|
const screen = &self.combat_screen;
|
||||||
|
|
||||||
|
const time_left_til_pickup = screen.next_pickup_spawn_at - screen.wave_timer;
|
||||||
|
|
||||||
imgui.textFmt("Waves: {}\n", .{screen.waves.items.len});
|
imgui.textFmt("Waves: {}\n", .{screen.waves.items.len});
|
||||||
imgui.textFmt("Bullets: {}\n", .{screen.bullets.items.len});
|
imgui.textFmt("Bullets: {}\n", .{screen.bullets.items.len});
|
||||||
imgui.textFmt("Enemies: {}\n", .{screen.enemies.count});
|
imgui.textFmt("Enemies: {}\n", .{screen.enemies.items.len});
|
||||||
|
imgui.textFmt("Time until next pickup: {d:.2}s\n", .{@as(f32, @floatFromInt(time_left_til_pickup)) / std.time.ns_per_s});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,480 +0,0 @@
|
|||||||
const std = @import("std");
|
|
||||||
const tracy = @import("tracy");
|
|
||||||
const builtin = @import("builtin");
|
|
||||||
const assert = std.debug.assert;
|
|
||||||
const Allocator = std.mem.Allocator;
|
|
||||||
|
|
||||||
const Index = u24;
|
|
||||||
const Generation = u8;
|
|
||||||
|
|
||||||
pub fn GenerationalArrayList(Item: type) type {
|
|
||||||
assert(@bitSizeOf(Generation) % 8 == 0);
|
|
||||||
assert(@bitSizeOf(Index) % 8 == 0);
|
|
||||||
|
|
||||||
return struct {
|
|
||||||
const Self = @This();
|
|
||||||
|
|
||||||
items: [*]Item,
|
|
||||||
generations: [*]Generation,
|
|
||||||
unused: [*]u8,
|
|
||||||
|
|
||||||
len: u32,
|
|
||||||
capacity: u32,
|
|
||||||
|
|
||||||
count: u32,
|
|
||||||
|
|
||||||
pub const empty = Self{
|
|
||||||
.items = &[_]Item{},
|
|
||||||
.generations = &[_]Generation{},
|
|
||||||
.unused = &[_]u8{},
|
|
||||||
.capacity = 0,
|
|
||||||
.len = 0,
|
|
||||||
.count = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const Id = packed struct {
|
|
||||||
generation: Generation,
|
|
||||||
index: Index,
|
|
||||||
|
|
||||||
// TODO: Maybe `Id.Optional` type should be created to ensure .wrap() and .toOptional()
|
|
||||||
pub const none = Id{
|
|
||||||
.generation = std.math.maxInt(Generation),
|
|
||||||
.index = std.math.maxInt(Index),
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn format(self: Id, writer: *std.Io.Writer) std.Io.Writer.Error!void {
|
|
||||||
if (self == Id.none) {
|
|
||||||
try writer.print("Id({s}){{ .none }}", .{ @typeName(Item) });
|
|
||||||
} else {
|
|
||||||
try writer.print("Id({s}){{ {}, {} }}", .{ @typeName(Item), self.index, self.generation });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn asInt(self: Id) u32 {
|
|
||||||
return @bitCast(self);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const ItemWithId = struct {
|
|
||||||
id: Id,
|
|
||||||
item: *Item,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const Iterator = struct {
|
|
||||||
array_list: *Self,
|
|
||||||
index: Index,
|
|
||||||
|
|
||||||
pub fn nextId(self: *Iterator) ?Id {
|
|
||||||
while (self.index < self.array_list.len) {
|
|
||||||
const index = self.index;
|
|
||||||
self.index += 1;
|
|
||||||
|
|
||||||
// TODO: Inline the `byte_index` calculate for better speed.
|
|
||||||
// Probably not needed. Idk
|
|
||||||
if (self.array_list.isUnused(index)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Id{
|
|
||||||
.index = @intCast(index),
|
|
||||||
.generation = self.array_list.generations[index]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn nextItem(self: *Iterator) ?*Item {
|
|
||||||
if (self.nextId()) |id| {
|
|
||||||
return &self.array_list.items[id.index];
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn next(self: *Iterator) ?ItemWithId {
|
|
||||||
if (self.nextId()) |id| {
|
|
||||||
return ItemWithId{
|
|
||||||
.id = id,
|
|
||||||
.item = &self.array_list.items[id.index]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const Metadata = extern struct {
|
|
||||||
len: u32,
|
|
||||||
count: u32
|
|
||||||
};
|
|
||||||
|
|
||||||
fn divCeilGeneration(num: u32) u32 {
|
|
||||||
return std.math.divCeil(u32, num, @bitSizeOf(Generation)) catch unreachable;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn divFloorGeneration(num: u32) u32 {
|
|
||||||
return @divFloor(num, @bitSizeOf(Generation));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ensureTotalCapacityPrecise(self: *Self, allocator: Allocator, new_capacity: u32) !void {
|
|
||||||
if (new_capacity > std.math.maxInt(Index)) {
|
|
||||||
return error.OutOfIndexSpace;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Shrinking is not supported
|
|
||||||
assert(new_capacity >= self.capacity);
|
|
||||||
|
|
||||||
const unused_bit_array_len = divCeilGeneration(self.capacity);
|
|
||||||
const new_unused_bit_array_len = divCeilGeneration(new_capacity);
|
|
||||||
|
|
||||||
// TODO: Handle allocation failure case
|
|
||||||
const new_unused = try allocator.realloc(self.unused[0..unused_bit_array_len], new_unused_bit_array_len);
|
|
||||||
const new_items = try allocator.realloc(self.items[0..self.capacity], new_capacity);
|
|
||||||
const new_generations = try allocator.realloc(self.generations[0..self.capacity], new_capacity);
|
|
||||||
|
|
||||||
self.unused = new_unused.ptr;
|
|
||||||
self.items = new_items.ptr;
|
|
||||||
self.generations = new_generations.ptr;
|
|
||||||
self.capacity = new_capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn growCapacity(current: u32, minimum: u32) u32 {
|
|
||||||
const init_capacity = @as(comptime_int, @max(1, std.atomic.cache_line / @sizeOf(Item)));
|
|
||||||
|
|
||||||
var new = current;
|
|
||||||
while (true) {
|
|
||||||
new +|= new / 2 + init_capacity;
|
|
||||||
if (new >= minimum) {
|
|
||||||
return new;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ensureTotalCapacity(self: *Self, allocator: Allocator, new_capacity: u32) !void {
|
|
||||||
if (self.capacity >= new_capacity) return;
|
|
||||||
|
|
||||||
const better_capacity = Self.growCapacity(self.capacity, new_capacity);
|
|
||||||
try self.ensureTotalCapacityPrecise(allocator, better_capacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clearRetainingCapacity(self: *Self) void {
|
|
||||||
self.count = 0;
|
|
||||||
self.len = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ensureUnusedCapacity(self: *Self, allocator: Allocator, unused_capacity: u32) !void {
|
|
||||||
try self.ensureTotalCapacity(allocator, self.len + unused_capacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn findFirstUnused(self: *Self) ?Index {
|
|
||||||
for (0..divCeilGeneration(self.len)) |byte_index| {
|
|
||||||
if (self.unused[byte_index] != 0) {
|
|
||||||
const found = @ctz(self.unused[byte_index]) + byte_index * @bitSizeOf(Generation);
|
|
||||||
if (found < self.len) {
|
|
||||||
return @intCast(found);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn markUnused(self: *Self, index: Index, unused: bool) void {
|
|
||||||
assert(index < self.len);
|
|
||||||
|
|
||||||
const byte_index = divFloorGeneration(index);
|
|
||||||
const bit_index = @mod(index, @bitSizeOf(Generation));
|
|
||||||
const bit_flag = @as(u8, 1) << @intCast(bit_index);
|
|
||||||
if (unused) {
|
|
||||||
self.unused[byte_index] |= bit_flag;
|
|
||||||
} else {
|
|
||||||
self.unused[byte_index] &= ~bit_flag;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn isUnused(self: *Self, index: Index) bool {
|
|
||||||
assert(index < self.len);
|
|
||||||
|
|
||||||
const byte_index = divFloorGeneration(index);
|
|
||||||
const bit_index = @mod(index, @bitSizeOf(Generation));
|
|
||||||
const bit_flag = @as(u8, 1) << @intCast(bit_index);
|
|
||||||
return (self.unused[byte_index] & bit_flag) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insertUndefined(self: *Self, allocator: Allocator) !Id {
|
|
||||||
var unused_index: Index = undefined;
|
|
||||||
|
|
||||||
if (self.findFirstUnused()) |index| {
|
|
||||||
unused_index = index;
|
|
||||||
} else {
|
|
||||||
try self.ensureUnusedCapacity(allocator, 1);
|
|
||||||
|
|
||||||
unused_index = @intCast(self.len);
|
|
||||||
self.len += 1;
|
|
||||||
self.generations[unused_index] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.markUnused(unused_index, false);
|
|
||||||
self.count += 1;
|
|
||||||
|
|
||||||
const id = Id{
|
|
||||||
.index = @intCast(unused_index),
|
|
||||||
.generation = self.generations[unused_index]
|
|
||||||
};
|
|
||||||
|
|
||||||
assert(id != Id.none);
|
|
||||||
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insert(self: *Self, allocator: Allocator, item: Item) !Id {
|
|
||||||
const id = try self.insertUndefined(allocator);
|
|
||||||
|
|
||||||
const new_item_ptr = self.getAssumeExists(id);
|
|
||||||
new_item_ptr.* = item;
|
|
||||||
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn exists(self: *Self, id: Id) bool {
|
|
||||||
if (id.index >= self.len) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self.isUnused(id.index)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self.generations[id.index] != id.generation) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn removeAssumeExists(self: *Self, id: Id) void {
|
|
||||||
assert(self.exists(id));
|
|
||||||
|
|
||||||
self.markUnused(id.index, true);
|
|
||||||
// TODO: Maybe a log should be shown when a wrap-around occurs?
|
|
||||||
self.generations[id.index] +%= 1;
|
|
||||||
self.count -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn remove(self: *Self, id: Id) bool {
|
|
||||||
if (!self.exists(id)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.removeAssumeExists(id);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn getAssumeExists(self: *Self, id: Id) *Item {
|
|
||||||
assert(self.exists(id));
|
|
||||||
|
|
||||||
return &self.items[id.index];
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get(self: *Self, id: Id) ?*Item {
|
|
||||||
if (self.exists(id)) {
|
|
||||||
return self.getAssumeExists(id);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn iterator(self: *Self) Iterator {
|
|
||||||
return Iterator{
|
|
||||||
.array_list = self,
|
|
||||||
.index = 0
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deinit(self: *Self, allocator: Allocator) void {
|
|
||||||
allocator.free(self.unused[0..divCeilGeneration(self.capacity)]);
|
|
||||||
allocator.free(self.generations[0..self.capacity]);
|
|
||||||
allocator.free(self.items[0..self.capacity]);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clone(self: *Self, allocator: Allocator) !Self {
|
|
||||||
const items = try allocator.dupe(Item, self.items[0..self.capacity]);
|
|
||||||
errdefer allocator.free(items);
|
|
||||||
|
|
||||||
const generations = try allocator.dupe(Generation, self.generations[0..self.capacity]);
|
|
||||||
errdefer allocator.free(generations);
|
|
||||||
|
|
||||||
const unused = try allocator.dupe(u8, self.unused[0..divCeilGeneration(self.capacity)]);
|
|
||||||
errdefer allocator.free(unused);
|
|
||||||
|
|
||||||
return Self{
|
|
||||||
.items = items.ptr,
|
|
||||||
.generations = generations.ptr,
|
|
||||||
.unused = unused.ptr,
|
|
||||||
.len = self.len,
|
|
||||||
.count = self.count,
|
|
||||||
.capacity = self.capacity
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn getMetadata(self: *Self) Metadata {
|
|
||||||
return Metadata{
|
|
||||||
.len = self.len,
|
|
||||||
.count = self.count
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn write(self: *Self, writer: *std.Io.Writer, endian: std.builtin.Endian) !void {
|
|
||||||
const zone = tracy.beginZone(@src(), .{ .name = "gen array list write" });
|
|
||||||
defer zone.end();
|
|
||||||
|
|
||||||
try writer.writeSliceEndian(Item, self.items[0..self.len], endian);
|
|
||||||
try writer.writeSliceEndian(Generation, self.generations[0..self.len], endian);
|
|
||||||
try writer.writeAll(self.unused[0..divCeilGeneration(self.len)]);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read(
|
|
||||||
self: *Self,
|
|
||||||
allocator: Allocator,
|
|
||||||
reader: *std.Io.Reader,
|
|
||||||
endian: std.builtin.Endian,
|
|
||||||
metadata: Metadata
|
|
||||||
) !void {
|
|
||||||
const zone = tracy.beginZone(@src(), .{ .name = "gen array list read" });
|
|
||||||
defer zone.end();
|
|
||||||
|
|
||||||
try self.ensureTotalCapacity(allocator, metadata.len);
|
|
||||||
|
|
||||||
try reader.readSliceEndian(Item, self.items[0..metadata.len], endian);
|
|
||||||
try reader.readSliceEndian(Generation, self.generations[0..metadata.len], endian);
|
|
||||||
try reader.readSliceAll(self.unused[0..divCeilGeneration(metadata.len)]);
|
|
||||||
|
|
||||||
self.len = metadata.len;
|
|
||||||
self.count = metadata.count;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const TestArray = GenerationalArrayList(u32);
|
|
||||||
|
|
||||||
test "insert & remove" {
|
|
||||||
const expect = std.testing.expect;
|
|
||||||
const gpa = std.testing.allocator;
|
|
||||||
|
|
||||||
var array_list: TestArray = .empty;
|
|
||||||
defer array_list.deinit(gpa);
|
|
||||||
|
|
||||||
const id1 = try array_list.insert(gpa, 10);
|
|
||||||
try expect(array_list.exists(id1));
|
|
||||||
try expect(array_list.remove(id1));
|
|
||||||
try expect(!array_list.exists(id1));
|
|
||||||
try expect(!array_list.remove(id1));
|
|
||||||
|
|
||||||
const id2 = try array_list.insert(gpa, 10);
|
|
||||||
try expect(array_list.exists(id2));
|
|
||||||
try expect(!array_list.exists(id1));
|
|
||||||
try expect(id1.index == id2.index);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "generation wrap around" {
|
|
||||||
const expectEqual = std.testing.expectEqual;
|
|
||||||
const gpa = std.testing.allocator;
|
|
||||||
|
|
||||||
var array_list: TestArray = .empty;
|
|
||||||
defer array_list.deinit(gpa);
|
|
||||||
|
|
||||||
// Grow array list so that at least 1 slot exists
|
|
||||||
const id1 = try array_list.insert(gpa, 10);
|
|
||||||
array_list.removeAssumeExists(id1);
|
|
||||||
|
|
||||||
// Artificially increase generation count
|
|
||||||
array_list.generations[id1.index] = std.math.maxInt(Generation);
|
|
||||||
|
|
||||||
// Check if generation wraps around
|
|
||||||
const id2 = try array_list.insert(gpa, 10);
|
|
||||||
array_list.removeAssumeExists(id2);
|
|
||||||
try expectEqual(id1.index, id2.index);
|
|
||||||
try expectEqual(0, array_list.generations[id1.index]);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "iterator" {
|
|
||||||
const expectEqual = std.testing.expectEqual;
|
|
||||||
const gpa = std.testing.allocator;
|
|
||||||
|
|
||||||
var array_list: TestArray = .empty;
|
|
||||||
defer array_list.deinit(gpa);
|
|
||||||
|
|
||||||
// Create array which has a hole
|
|
||||||
const id1 = try array_list.insert(gpa, 1);
|
|
||||||
const id2 = try array_list.insert(gpa, 2);
|
|
||||||
const id3 = try array_list.insert(gpa, 3);
|
|
||||||
|
|
||||||
array_list.removeAssumeExists(id2);
|
|
||||||
|
|
||||||
var iter = array_list.iterator();
|
|
||||||
try expectEqual(
|
|
||||||
TestArray.ItemWithId{
|
|
||||||
.id = id1,
|
|
||||||
.item = array_list.getAssumeExists(id1)
|
|
||||||
},
|
|
||||||
iter.next().?
|
|
||||||
);
|
|
||||||
try expectEqual(
|
|
||||||
TestArray.ItemWithId{
|
|
||||||
.id = id3,
|
|
||||||
.item = array_list.getAssumeExists(id3)
|
|
||||||
},
|
|
||||||
iter.next().?
|
|
||||||
);
|
|
||||||
try expectEqual(null, iter.next());
|
|
||||||
}
|
|
||||||
|
|
||||||
test "read & write" {
|
|
||||||
const expectEqual = std.testing.expectEqual;
|
|
||||||
const gpa = std.testing.allocator;
|
|
||||||
|
|
||||||
var array_list1: TestArray = .empty;
|
|
||||||
defer array_list1.deinit(gpa);
|
|
||||||
|
|
||||||
var array_list2: TestArray = .empty;
|
|
||||||
defer array_list2.deinit(gpa);
|
|
||||||
|
|
||||||
const id1 = try array_list1.insert(gpa, 1);
|
|
||||||
const id2 = try array_list1.insert(gpa, 2);
|
|
||||||
const id3 = try array_list1.insert(gpa, 3);
|
|
||||||
|
|
||||||
var buffer: [1024]u8 = undefined;
|
|
||||||
var writer = std.Io.Writer.fixed(&buffer);
|
|
||||||
const native_endian = builtin.cpu.arch.endian();
|
|
||||||
|
|
||||||
try array_list1.write(&writer, native_endian);
|
|
||||||
|
|
||||||
var reader = std.Io.Reader.fixed(writer.buffered());
|
|
||||||
try array_list2.read(gpa, &reader, native_endian, array_list1.getMetadata());
|
|
||||||
|
|
||||||
try expectEqual(array_list1.getAssumeExists(id1).*, array_list2.getAssumeExists(id1).*);
|
|
||||||
try expectEqual(array_list1.getAssumeExists(id2).*, array_list2.getAssumeExists(id2).*);
|
|
||||||
try expectEqual(array_list1.getAssumeExists(id3).*, array_list2.getAssumeExists(id3).*);
|
|
||||||
try expectEqual(array_list1.count, array_list2.count);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "clear retaining capacity" {
|
|
||||||
const expect = std.testing.expect;
|
|
||||||
const expectEqual = std.testing.expectEqual;
|
|
||||||
const gpa = std.testing.allocator;
|
|
||||||
|
|
||||||
var array_list: TestArray = .empty;
|
|
||||||
defer array_list.deinit(gpa);
|
|
||||||
|
|
||||||
const id1 = try array_list.insert(gpa, 10);
|
|
||||||
try expect(array_list.exists(id1));
|
|
||||||
array_list.clearRetainingCapacity();
|
|
||||||
|
|
||||||
const id2 = try array_list.insert(gpa, 10);
|
|
||||||
try expect(array_list.exists(id2));
|
|
||||||
|
|
||||||
try expectEqual(id1, id2);
|
|
||||||
}
|
|
||||||
@ -134,7 +134,7 @@ pub fn tick(self: *ShopScreen, state: *State, frame: *Frame) !TickResult {
|
|||||||
for (self.nodes.items) |*node| {
|
for (self.nodes.items) |*node| {
|
||||||
const node_rect = Rect.initCentered(node.pos.x, node.pos.y, node_size.x, node_size.y);
|
const node_rect = Rect.initCentered(node.pos.x, node.pos.y, node_size.x, node_size.y);
|
||||||
|
|
||||||
const is_mouse_inside = mouse != null and node_rect.isPointInside(mouse.?);
|
const is_mouse_inside = mouse != null and node_rect.isInside(mouse.?);
|
||||||
const has_enough_money = state.money >= node.money_cost;
|
const has_enough_money = state.money >= node.money_cost;
|
||||||
|
|
||||||
if (has_enough_money and is_mouse_inside and frame.isMousePressed(.left)) {
|
if (has_enough_money and is_mouse_inside and frame.isMousePressed(.left)) {
|
||||||
@ -173,7 +173,7 @@ pub fn tick(self: *ShopScreen, state: *State, frame: *Frame) !TickResult {
|
|||||||
.color = rgb(255, 255, 255)
|
.color = rgb(255, 255, 255)
|
||||||
});
|
});
|
||||||
|
|
||||||
if (frame.input.mouse_position != null and back_rect.isPointInside(frame.input.mouse_position.?) and frame.isMousePressed(.left)) {
|
if (frame.input.mouse_position != null and back_rect.isInside(frame.input.mouse_position.?) and frame.isMousePressed(.left)) {
|
||||||
result.back_to_combat = true;
|
result.back_to_combat = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||