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 isWasm = target.result.cpu.arch.isWasm();
|
||||
const isWindows = target.result.os.tag == .windows;
|
||||
|
||||
if (isWasm) {
|
||||
has_tracy = false;
|
||||
@ -26,12 +25,7 @@ pub fn build(b: *std.Build) !void {
|
||||
.link_libc = true,
|
||||
});
|
||||
|
||||
const dep_sokol = b.dependency("sokol", .{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.with_sokol_imgui = has_imgui,
|
||||
.vulkan = if (isWasm or isWindows) null else true
|
||||
});
|
||||
const dep_sokol = b.dependency("sokol", .{ .target = target, .optimize = optimize, .with_sokol_imgui = has_imgui, .vulkan = true });
|
||||
mod_main.linkLibrary(dep_sokol.artifact("sokol_clib"));
|
||||
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 = std.ArrayListUnmanaged([]const u8).initBuffer(&cflags_buffer);
|
||||
const backend: sokol.SokolBackend = if (isWasm or isWindows) .auto else .vulkan;
|
||||
switch (sokol.resolveSokolBackend(backend, target.result)) {
|
||||
switch (sokol.resolveSokolBackend(.vulkan, target.result)) {
|
||||
.d3d11 => try cflags.appendBounded("-DSOKOL_D3D11"),
|
||||
.metal => try cflags.appendBounded("-DSOKOL_METAL"),
|
||||
.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"),
|
||||
}),
|
||||
});
|
||||
const dep_stb = b.dependency("stb", .{});
|
||||
png_to_icon_tool.root_module.addImport("stb_image", dep_stb.module("stb_image"));
|
||||
const dep_stb_image = b.dependency("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);
|
||||
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", .{});
|
||||
|
||||
patchWasmIncludeDirs(
|
||||
opts.mod_main,
|
||||
dep_emsdk.path("upstream/emscripten/cache/sysroot/include"),
|
||||
&(opts.dep_sokol.artifact("sokol_clib").step)
|
||||
);
|
||||
patchWasmIncludeDirs(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
|
||||
const link_step = try sokol.emLinkStep(b, .{
|
||||
@ -232,7 +221,6 @@ fn buildWasm(b: *std.Build, opts: BuildWasmOptions) !void {
|
||||
.use_emmalloc = true,
|
||||
.use_filesystem = false,
|
||||
.shell_file_path = b.path("src/engine/shell.html"),
|
||||
.extra_args = &.{ "-sASSERTIONS=1", "-sALLOW_MEMORY_GROWTH=1" }
|
||||
});
|
||||
// attach to default target
|
||||
b.getInstallStep().dependOn(&link_step.step);
|
||||
|
||||
@ -136,7 +136,6 @@ pub const TileVariant = struct {
|
||||
const encoded_tiles = try lexer.nextExpectText();
|
||||
const tiles = try parseEncoding(encoding, scratch.allocator(), encoded_tiles);
|
||||
try temp_tiles.appendSlice(scratch.allocator(), tiles.items);
|
||||
continue;
|
||||
|
||||
} else if (node.isTag("chunk")) {
|
||||
const chunk = try initChunkDataFromXml(arena, scratch, lexer, encoding);
|
||||
@ -159,6 +158,7 @@ pub const TileVariant = struct {
|
||||
.fixed = try arena.dupe(u32, temp_tiles.items)
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn parseEncoding(
|
||||
|
||||
@ -73,9 +73,6 @@ pub const TilesetReference = struct {
|
||||
pub const Tile = struct {
|
||||
tileset: *const Tileset,
|
||||
id: u32,
|
||||
flip_horizontal: bool,
|
||||
flip_vertical: bool,
|
||||
flip_diagonal: bool,
|
||||
|
||||
pub fn getProperties(self: Tile) Property.List {
|
||||
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 {
|
||||
const Flag = GlobalTileId.Flag;
|
||||
|
||||
const gid_without_flags = gid & Flag.clear;
|
||||
const tileset_ref = self.getTilesetByGid(gid_without_flags) orelse return null;
|
||||
const tileset_ref = self.getTilesetByGid(gid & GlobalTileId.Flag.clear) 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{
|
||||
.tileset = tileset,
|
||||
.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
|
||||
.id = id
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
177
src/assets.zig
@ -24,6 +24,7 @@ pub const Tilemap = struct {
|
||||
texture: Gfx.TextureId,
|
||||
tile_size: Engine.Vec2,
|
||||
|
||||
|
||||
pub fn getTileUV(self: Tilemap, tile_x: f32, tile_y: f32) Rect {
|
||||
const texture_info = Engine.Graphics.getTextureInfo(self.texture);
|
||||
const tilemap_size = Vec2.initFromInt(u32, texture_info.width, texture_info.height);
|
||||
@ -38,19 +39,14 @@ pub const Tilemap = struct {
|
||||
arena: std.heap.ArenaAllocator,
|
||||
|
||||
font_id: FontName.EnumArray,
|
||||
pistol_mask: Gfx.TextureId,
|
||||
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,
|
||||
|
||||
wood01: Audio.Data.Id,
|
||||
map: tiled.Tilemap,
|
||||
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 {
|
||||
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")),
|
||||
});
|
||||
|
||||
const pistol_mask_image = try STBImage.load(@embedFile("assets/pistol-mask.png"));
|
||||
defer pistol_mask_image.deinit();
|
||||
const pistol_mask_texture = try Gfx.addTexture(&.{
|
||||
.{
|
||||
.width = pistol_mask_image.width,
|
||||
.height = pistol_mask_image.height,
|
||||
.rgba = pistol_mask_image.rgba8_pixels
|
||||
}
|
||||
const wood01 = try Audio.load(.{
|
||||
.format = .vorbis,
|
||||
.data = @embedFile("assets/wood01.ogg"),
|
||||
});
|
||||
|
||||
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);
|
||||
defer scratch.deinit();
|
||||
|
||||
@ -161,54 +80,76 @@ pub fn init(gpa: std.mem.Allocator) !Assets {
|
||||
gpa,
|
||||
&scratch,
|
||||
&xml_buffers,
|
||||
@embedFile("assets/dungeon.tsx")
|
||||
@embedFile("assets/tileset.tsx")
|
||||
);
|
||||
|
||||
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"));
|
||||
defer dungeon_image.deinit();
|
||||
const dungeon_texture = try Gfx.addTexture(&.{
|
||||
const players_image = try STBImage.load(@embedFile("assets/kenney_desert-shooter-pack_1.0/PNG/Players/tilemap_packed.png"));
|
||||
defer players_image.deinit();
|
||||
const players_texture = try Gfx.addTexture(&.{
|
||||
.{
|
||||
.width = dungeon_image.width,
|
||||
.height = dungeon_image.height,
|
||||
.rgba = dungeon_image.rgba8_pixels
|
||||
.width = players_image.width,
|
||||
.height = players_image.height,
|
||||
.rgba = players_image.rgba8_pixels
|
||||
}
|
||||
});
|
||||
|
||||
const shadow_image = try STBImage.load(@embedFile("assets/shadow.png"));
|
||||
defer shadow_image.deinit();
|
||||
const shadow_texture = try Gfx.addTexture(&.{
|
||||
const tileset_image = try STBImage.load(@embedFile("assets/kenney_desert-shooter-pack_1.0/PNG/Tiles/tilemap_packed.png"));
|
||||
defer tileset_image.deinit();
|
||||
const tileset_texture = try Gfx.addTexture(&.{
|
||||
.{
|
||||
.width = shadow_image.width,
|
||||
.height = shadow_image.height,
|
||||
.rgba = shadow_image.rgba8_pixels
|
||||
.width = tileset_image.width,
|
||||
.height = tileset_image.height,
|
||||
.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{
|
||||
.arena = arena,
|
||||
.font_id = font_id_array,
|
||||
.pistol_mask = pistol_mask_texture,
|
||||
.bomb_mask = bomb_mask_texture,
|
||||
.laser_mask = laser_mask_texture,
|
||||
.snake = snake,
|
||||
.skeleton = skeleton,
|
||||
.fire_spirit = fire_spirit,
|
||||
.wood01 = wood01,
|
||||
.map = map,
|
||||
.tilesets = tilesets,
|
||||
.bullet = bullet_texture,
|
||||
.shadow = shadow_texture,
|
||||
.dungeon_tilemap = .{
|
||||
.texture = dungeon_texture,
|
||||
.tile_size = .init(16, 16)
|
||||
}
|
||||
.move_sound = move_sound,
|
||||
.terrain_tilemap = .{
|
||||
.texture = tileset_texture,
|
||||
.tile_size = .initFromInt(u32, tileset.tile_width, tileset.tile_height)
|
||||
},
|
||||
.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 {
|
||||
self.tilesets.deinit(gpa);
|
||||
self.map.deinit();
|
||||
self.tilesets.deinit(gpa);
|
||||
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)
|
||||
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
|
||||
Space between tiles • 1px × 1px
|
||||
---
|
||||
Total tiles (horizontal) • 12 tiles
|
||||
Total tiles (horizontal) • 18 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"?>
|
||||
<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">
|
||||
<tileset firstgid="1" source="dungeon.tsx"/>
|
||||
<layer id="1" name="Tile Layer 1" width="20" height="15">
|
||||
<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="tilemap.tsx"/>
|
||||
<layer id="1" name="ground" width="30" height="20">
|
||||
<data encoding="csv">
|
||||
2147483701,51,51,51,52,52,51,51,51,51,51,52,52,52,51,51,51,51,51,53,
|
||||
536870963,49,49,49,49,49,49,49,49,50,50,50,50,50,49,49,49,49,49,2684354611,
|
||||
1610612788,49,43,43,49,49,49,49,49,50,50,50,50,50,49,49,43,43,49,2684354611,
|
||||
1610612788,49,43,43,49,49,50,49,49,49,50,50,50,50,49,49,43,43,50,2684354611,
|
||||
1610612788,50,50,49,49,49,50,50,49,49,49,49,49,49,49,49,49,50,50,3758096436,
|
||||
1610612788,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,50,3758096436,
|
||||
1610612788,49,49,49,49,49,49,50,50,50,50,49,49,50,49,49,49,49,49,3758096436,
|
||||
536870963,49,49,49,49,49,49,49,50,50,50,50,50,50,49,49,49,49,49,2684354611,
|
||||
536870963,49,50,50,49,49,49,49,49,49,50,50,50,50,49,49,49,50,50,3758096436,
|
||||
536870963,49,50,50,49,49,49,49,49,49,49,49,49,49,49,49,50,50,50,3758096436,
|
||||
1610612788,50,50,49,49,49,49,50,50,49,49,49,49,49,49,50,50,50,49,2684354611,
|
||||
1610612788,49,43,43,49,49,50,50,50,50,50,49,49,49,49,50,43,43,49,2684354611,
|
||||
536870963,49,43,43,49,50,50,50,49,49,49,49,49,49,49,50,43,43,49,3758096436,
|
||||
536870963,49,49,49,49,50,50,49,49,49,49,49,49,49,49,49,49,49,49,2684354611,
|
||||
3221225525,1073741875,1073741875,1073741875,1073741875,1073741876,1073741876,1073741875,1073741875,1073741875,1073741875,1073741875,1073741875,1073741876,1073741876,1073741875,1073741875,1073741875,1073741876,1073741877
|
||||
</data>
|
||||
<chunk x="-32" 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,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>
|
||||
</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>
|
||||
|
||||
|
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 {
|
||||
self.pushGraphicsCommand(.{ .draw_rectangle = opts });
|
||||
}
|
||||
|
||||
@ -7,7 +7,6 @@ const simgui = sokol.imgui;
|
||||
const sgl = sokol.gl;
|
||||
|
||||
const Math = @import("./math.zig");
|
||||
const Line = Math.Line;
|
||||
const Vec2 = Math.Vec2;
|
||||
const Vec4 = Math.Vec4;
|
||||
const rgb = Math.rgb;
|
||||
@ -46,15 +45,6 @@ pub const Command = union(enum) {
|
||||
sprite: ?Sprite = null,
|
||||
rotation: f32 = 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,
|
||||
@ -69,7 +59,6 @@ pub const Command = union(enum) {
|
||||
},
|
||||
push_transformation: struct { translation: Vec2, scale: Vec2 },
|
||||
pop_transformation: void,
|
||||
draw_circle: DrawCircle
|
||||
};
|
||||
|
||||
const Texture = struct {
|
||||
@ -91,23 +80,6 @@ pub const TextureInfo = Texture.Info;
|
||||
pub const Sprite = struct {
|
||||
texture: TextureId,
|
||||
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;
|
||||
@ -233,25 +205,6 @@ pub fn drawCommand(command: Command) void {
|
||||
font_context.setColor(color);
|
||||
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| {
|
||||
const uv = sprite.uv;
|
||||
var uv_top_left = Vec2.init(uv.left(), uv.top());
|
||||
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
|
||||
}
|
||||
};
|
||||
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()) } };
|
||||
drawQuad(quad, opts.color, sprite.texture);
|
||||
} else {
|
||||
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 {
|
||||
const line = Line{
|
||||
.p0 = from,
|
||||
.p1 = to,
|
||||
};
|
||||
const step = to.sub(from).normalized().multiplyScalar(width / 2);
|
||||
|
||||
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(
|
||||
.{
|
||||
quad.top_right,
|
||||
quad.top_left,
|
||||
quad.bottom_left,
|
||||
quad.bottom_right
|
||||
},
|
||||
color
|
||||
);
|
||||
drawQuadNoUVs(.{ top_right, top_left, bottom_left, bottom_right }, color);
|
||||
}
|
||||
|
||||
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)];
|
||||
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,
|
||||
size: Vec2,
|
||||
|
||||
pub const unit = Rect{
|
||||
.pos = .zero,
|
||||
.size = .init(1, 1),
|
||||
};
|
||||
|
||||
pub const zero = Rect{
|
||||
.pos = 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 {
|
||||
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 y_overlap = self.pos.y <= pos.y and pos.y < self.pos.y + self.size.y;
|
||||
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 {
|
||||
return (lhs.left() < rhs.right() and lhs.right() > rhs.left()) and
|
||||
(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 {
|
||||
p0: 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
|
||||
};
|
||||
}
|
||||
p1: Vec2
|
||||
};
|
||||
|
||||
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,
|
||||
.size = rect_size
|
||||
};
|
||||
return rect.isPointInside(pos);
|
||||
return rect.isInside(pos);
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
if (imgui.button("Restart")) {
|
||||
try self.restartAndShowCombatScreen();
|
||||
if (imgui.button("Spawn enemy")) {
|
||||
try self.combat_screen.spawnEnemy();
|
||||
}
|
||||
|
||||
if (imgui.button("Toggle colliders")) {
|
||||
self.combat_screen.show_colliders = !self.combat_screen.show_colliders;
|
||||
if (imgui.button("Restart")) {
|
||||
try self.restartAndShowCombatScreen();
|
||||
}
|
||||
|
||||
if (self.show_shop) {
|
||||
@ -144,7 +144,10 @@ pub fn debug(self: *Game) !void {
|
||||
|
||||
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("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| {
|
||||
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;
|
||||
|
||||
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)
|
||||
});
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||