add goals with colors
This commit is contained in:
parent
930a7dc275
commit
7b99f3344c
@ -239,7 +239,7 @@
|
|||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
0,0,98,98,98,98,98,98,0,0,0,0,0,0,0,0,
|
0,0,98,98,98,98,98,98,0,0,0,0,0,0,0,0,
|
||||||
0,0,98,0,0,0,0,98,98,98,98,98,98,0,0,0,
|
0,0,98,0,0,0,0,98,98,98,98,98,98,0,0,0,
|
||||||
0,0,98,0,0,0,0,0,0,0,0,0,98,98,0,0
|
0,0,98,0,0,8,42,0,12,0,0,0,98,98,0,0
|
||||||
</chunk>
|
</chunk>
|
||||||
<chunk x="16" y="0" width="16" height="16">
|
<chunk x="16" y="0" 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,
|
||||||
@ -332,7 +332,7 @@
|
|||||||
0,0,0,99,0,98,98,0,0,0,0,0,0,0,0,0
|
0,0,0,99,0,98,98,0,0,0,0,0,0,0,0,0
|
||||||
</chunk>
|
</chunk>
|
||||||
<chunk x="0" y="16" width="16" height="16">
|
<chunk x="0" y="16" width="16" height="16">
|
||||||
0,0,98,0,72,0,7,0,0,0,0,40,0,98,0,0,
|
0,0,98,0,72,0,7,7,0,0,0,40,0,98,0,0,
|
||||||
0,0,98,0,0,0,0,0,0,0,0,0,98,98,0,0,
|
0,0,98,0,0,0,0,0,0,0,0,0,98,98,0,0,
|
||||||
0,0,98,98,98,98,98,98,98,98,98,98,98,0,0,0,
|
0,0,98,98,98,98,98,98,98,98,98,98,98,0,0,0,
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
@ -350,7 +350,7 @@
|
|||||||
0,0,0,0,0,0,0,0,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>
|
||||||
<chunk x="16" y="16" width="16" height="16">
|
<chunk x="16" y="16" width="16" height="16">
|
||||||
0,0,98,0,72,0,0,7,0,0,0,75,0,98,0,0,
|
0,0,98,0,72,0,0,7,0,0,0,40,0,98,0,0,
|
||||||
0,0,98,0,0,0,0,7,0,0,0,0,98,98,0,0,
|
0,0,98,0,0,0,0,7,0,0,0,0,98,98,0,0,
|
||||||
0,0,98,98,98,98,98,98,98,98,98,98,98,0,0,0,
|
0,0,98,98,98,98,98,98,98,98,98,98,98,0,0,0,
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
@ -368,7 +368,7 @@
|
|||||||
0,0,0,0,0,0,0,0,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>
|
||||||
<chunk x="32" y="16" width="16" height="16">
|
<chunk x="32" y="16" width="16" height="16">
|
||||||
0,98,0,72,0,0,7,0,0,0,75,0,98,0,0,98,
|
0,98,0,72,0,0,7,0,0,0,40,0,98,0,0,98,
|
||||||
0,98,0,0,0,0,7,0,0,99,0,98,98,0,0,98,
|
0,98,0,0,0,0,7,0,0,99,0,98,98,0,0,98,
|
||||||
0,98,98,98,98,98,98,98,98,98,98,98,0,0,0,98,
|
0,98,98,98,98,98,98,98,98,98,98,98,0,0,0,98,
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
@ -386,7 +386,7 @@
|
|||||||
0,0,0,0,0,0,0,0,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>
|
||||||
<chunk x="48" y="16" width="16" height="16">
|
<chunk x="48" y="16" width="16" height="16">
|
||||||
0,72,0,0,0,0,0,12,75,0,98,0,0,98,0,72,
|
0,72,0,0,0,0,0,12,40,0,98,0,0,98,0,72,
|
||||||
0,0,0,0,0,0,0,99,0,98,98,0,0,98,0,0,
|
0,0,0,0,0,0,0,99,0,98,98,0,0,98,0,0,
|
||||||
98,98,98,98,98,98,98,98,98,98,0,0,0,98,98,98,
|
98,98,98,98,98,98,98,98,98,98,0,0,0,98,98,98,
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
@ -404,7 +404,7 @@
|
|||||||
0,0,0,0,0,0,0,0,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>
|
||||||
<chunk x="64" y="16" width="16" height="16">
|
<chunk x="64" y="16" width="16" height="16">
|
||||||
0,7,7,0,12,12,75,0,98,0,0,98,0,72,0,0,
|
0,7,7,0,12,12,40,0,98,0,0,98,0,72,0,0,
|
||||||
0,0,0,0,99,99,0,98,98,0,0,98,0,0,0,0,
|
0,0,0,0,99,99,0,98,98,0,0,98,0,0,0,0,
|
||||||
98,98,98,98,98,98,98,98,0,0,0,98,98,98,98,98,
|
98,98,98,98,98,98,98,98,0,0,0,98,98,98,98,98,
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
@ -422,7 +422,7 @@
|
|||||||
0,0,0,0,0,0,0,0,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>
|
||||||
<chunk x="80" y="16" width="16" height="16">
|
<chunk x="80" y="16" width="16" height="16">
|
||||||
0,0,0,12,75,0,98,0,0,0,0,0,0,0,0,0,
|
0,0,0,12,40,0,98,0,0,0,0,0,0,0,0,0,
|
||||||
7,0,0,99,0,98,98,0,0,0,0,0,0,0,0,0,
|
7,0,0,99,0,98,98,0,0,0,0,0,0,0,0,0,
|
||||||
98,98,98,98,98,98,0,0,0,0,0,0,0,0,0,0,
|
98,98,98,98,98,98,0,0,0,0,0,0,0,0,0,0,
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
|||||||
@ -3,26 +3,31 @@
|
|||||||
<image source="../sokoban/sokoban_tilesheet.png" width="832" height="512"/>
|
<image source="../sokoban/sokoban_tilesheet.png" width="832" height="512"/>
|
||||||
<tile id="6">
|
<tile id="6">
|
||||||
<properties>
|
<properties>
|
||||||
|
<property name="color" value="brown"/>
|
||||||
<property name="type" value="box"/>
|
<property name="type" value="box"/>
|
||||||
</properties>
|
</properties>
|
||||||
</tile>
|
</tile>
|
||||||
<tile id="7">
|
<tile id="7">
|
||||||
<properties>
|
<properties>
|
||||||
|
<property name="color" value="red"/>
|
||||||
<property name="type" value="box"/>
|
<property name="type" value="box"/>
|
||||||
</properties>
|
</properties>
|
||||||
</tile>
|
</tile>
|
||||||
<tile id="8">
|
<tile id="8">
|
||||||
<properties>
|
<properties>
|
||||||
|
<property name="color" value="blue"/>
|
||||||
<property name="type" value="box"/>
|
<property name="type" value="box"/>
|
||||||
</properties>
|
</properties>
|
||||||
</tile>
|
</tile>
|
||||||
<tile id="9">
|
<tile id="9">
|
||||||
<properties>
|
<properties>
|
||||||
|
<property name="color" value="green"/>
|
||||||
<property name="type" value="box"/>
|
<property name="type" value="box"/>
|
||||||
</properties>
|
</properties>
|
||||||
</tile>
|
</tile>
|
||||||
<tile id="10">
|
<tile id="10">
|
||||||
<properties>
|
<properties>
|
||||||
|
<property name="color" value="gray"/>
|
||||||
<property name="type" value="box"/>
|
<property name="type" value="box"/>
|
||||||
</properties>
|
</properties>
|
||||||
</tile>
|
</tile>
|
||||||
@ -31,11 +36,23 @@
|
|||||||
<property name="type" value="box_hole"/>
|
<property name="type" value="box_hole"/>
|
||||||
</properties>
|
</properties>
|
||||||
</tile>
|
</tile>
|
||||||
|
<tile id="24">
|
||||||
|
<properties>
|
||||||
|
<property name="color" value="brown"/>
|
||||||
|
<property name="type" value="box_hole"/>
|
||||||
|
</properties>
|
||||||
|
</tile>
|
||||||
<tile id="25">
|
<tile id="25">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="type" value="goal_marker"/>
|
<property name="type" value="goal_marker"/>
|
||||||
</properties>
|
</properties>
|
||||||
</tile>
|
</tile>
|
||||||
|
<tile id="37">
|
||||||
|
<properties>
|
||||||
|
<property name="color" value="red"/>
|
||||||
|
<property name="type" value="box_hole"/>
|
||||||
|
</properties>
|
||||||
|
</tile>
|
||||||
<tile id="38">
|
<tile id="38">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="type" value="goal_marker"/>
|
<property name="type" value="goal_marker"/>
|
||||||
@ -48,34 +65,51 @@
|
|||||||
</tile>
|
</tile>
|
||||||
<tile id="40">
|
<tile id="40">
|
||||||
<properties>
|
<properties>
|
||||||
|
<property name="color" value="brown"/>
|
||||||
<property name="type" value="box_goal"/>
|
<property name="type" value="box_goal"/>
|
||||||
</properties>
|
</properties>
|
||||||
</tile>
|
</tile>
|
||||||
<tile id="41">
|
<tile id="41">
|
||||||
<properties>
|
<properties>
|
||||||
|
<property name="color" value="red"/>
|
||||||
<property name="type" value="box_goal"/>
|
<property name="type" value="box_goal"/>
|
||||||
</properties>
|
</properties>
|
||||||
</tile>
|
</tile>
|
||||||
<tile id="42">
|
<tile id="42">
|
||||||
<properties>
|
<properties>
|
||||||
|
<property name="color" value="blue"/>
|
||||||
<property name="type" value="box_goal"/>
|
<property name="type" value="box_goal"/>
|
||||||
</properties>
|
</properties>
|
||||||
</tile>
|
</tile>
|
||||||
<tile id="43">
|
<tile id="43">
|
||||||
<properties>
|
<properties>
|
||||||
|
<property name="color" value="green"/>
|
||||||
<property name="type" value="box_goal"/>
|
<property name="type" value="box_goal"/>
|
||||||
</properties>
|
</properties>
|
||||||
</tile>
|
</tile>
|
||||||
<tile id="44">
|
<tile id="44">
|
||||||
<properties>
|
<properties>
|
||||||
|
<property name="color" value="gray"/>
|
||||||
<property name="type" value="box_goal"/>
|
<property name="type" value="box_goal"/>
|
||||||
</properties>
|
</properties>
|
||||||
</tile>
|
</tile>
|
||||||
|
<tile id="50">
|
||||||
|
<properties>
|
||||||
|
<property name="color" value="blue"/>
|
||||||
|
<property name="type" value="box_hole"/>
|
||||||
|
</properties>
|
||||||
|
</tile>
|
||||||
<tile id="51">
|
<tile id="51">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="type" value="goal_marker"/>
|
<property name="type" value="goal_marker"/>
|
||||||
</properties>
|
</properties>
|
||||||
</tile>
|
</tile>
|
||||||
|
<tile id="63">
|
||||||
|
<properties>
|
||||||
|
<property name="color" value="green"/>
|
||||||
|
<property name="type" value="box_hole"/>
|
||||||
|
</properties>
|
||||||
|
</tile>
|
||||||
<tile id="64">
|
<tile id="64">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="type" value="goal_marker"/>
|
<property name="type" value="goal_marker"/>
|
||||||
@ -91,6 +125,12 @@
|
|||||||
<property name="type" value="coin"/>
|
<property name="type" value="coin"/>
|
||||||
</properties>
|
</properties>
|
||||||
</tile>
|
</tile>
|
||||||
|
<tile id="76">
|
||||||
|
<properties>
|
||||||
|
<property name="color" value="gray"/>
|
||||||
|
<property name="type" value="box_hole"/>
|
||||||
|
</properties>
|
||||||
|
</tile>
|
||||||
<tile id="77">
|
<tile id="77">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="type" value="goal_marker"/>
|
<property name="type" value="goal_marker"/>
|
||||||
|
|||||||
213
src/app.zig
213
src/app.zig
@ -21,6 +21,23 @@ const Tilesheet = @import("./tilesheet.zig");
|
|||||||
|
|
||||||
const App = @This();
|
const App = @This();
|
||||||
|
|
||||||
|
const BoxColor = enum {
|
||||||
|
none,
|
||||||
|
brown,
|
||||||
|
red,
|
||||||
|
blue,
|
||||||
|
green,
|
||||||
|
gray,
|
||||||
|
|
||||||
|
var string_mapping = std.StaticStringMap(BoxColor).initComptime(.{
|
||||||
|
.{ "brown", .brown },
|
||||||
|
.{ "red", .red },
|
||||||
|
.{ "blue", .blue },
|
||||||
|
.{ "green", .green },
|
||||||
|
.{ "gray", .gray },
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const Direction = enum {
|
const Direction = enum {
|
||||||
up,
|
up,
|
||||||
down,
|
down,
|
||||||
@ -71,6 +88,7 @@ const Entity = struct {
|
|||||||
|
|
||||||
pos: Point = .{ .x = -1, .y = -1 },
|
pos: Point = .{ .x = -1, .y = -1 },
|
||||||
box_hole_id: Entity.Id = .nil,
|
box_hole_id: Entity.Id = .nil,
|
||||||
|
color: BoxColor = .none,
|
||||||
|
|
||||||
const Type = enum {
|
const Type = enum {
|
||||||
nil,
|
nil,
|
||||||
@ -139,26 +157,28 @@ const UndoFrame = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const World = struct {
|
const World = struct {
|
||||||
|
entities_buffer: [256]Entity.SlotMap.Slot,
|
||||||
entities: Entity.SlotMap,
|
entities: Entity.SlotMap,
|
||||||
width: u32,
|
width: u32,
|
||||||
height: u32,
|
height: u32,
|
||||||
|
level_number: i32,
|
||||||
|
|
||||||
pub fn clone(self: World, gpa: Allocator) !World {
|
pub fn init(self: *World) void {
|
||||||
var entity_slots = try self.entities.slots.clone(gpa);
|
self.* = World{
|
||||||
errdefer entity_slots.deinit(gpa);
|
.entities_buffer = undefined,
|
||||||
|
.entities = .initBuffer(&self.entities_buffer),
|
||||||
var entities = self.entities;
|
.width = 0,
|
||||||
entities.slots = entity_slots;
|
.height = 0,
|
||||||
|
.level_number = 0
|
||||||
return World{
|
|
||||||
.width = self.width,
|
|
||||||
.height = self.height,
|
|
||||||
.entities = entities,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *World, gpa: Allocator) void {
|
pub fn copy(self: *World, other: World) void {
|
||||||
self.entities.deinit(gpa);
|
self.* = other;
|
||||||
|
|
||||||
|
const self_slots = self.entities_buffer[0..other.entities.slots.items.len];
|
||||||
|
self.entities.slots.items = self_slots;
|
||||||
|
@memcpy(self_slots, other.entities.slots.items);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spawnEntity(self: *World, opts: Entity) Entity.Id {
|
fn spawnEntity(self: *World, opts: Entity) Entity.Id {
|
||||||
@ -301,21 +321,28 @@ const TickContext = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const Level = struct {
|
const BoxSprites = struct {
|
||||||
number: i32,
|
regular: Gfx.Sprite.Id,
|
||||||
world: World,
|
in_hole: Gfx.Sprite.Id,
|
||||||
|
darker: Gfx.Sprite.Id,
|
||||||
|
|
||||||
|
pub const nil = BoxSprites{
|
||||||
|
.regular = .nil,
|
||||||
|
.in_hole = .nil,
|
||||||
|
.darker = .nil,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
world: World,
|
world: World,
|
||||||
undo_stack: std.ArrayList(UndoFrame) = .empty,
|
undo_stack: std.ArrayList(UndoFrame) = .empty,
|
||||||
current_level: u32 = 0,
|
current_level: u32 = 0,
|
||||||
levels: std.ArrayList(Level),
|
levels: std.ArrayList(World),
|
||||||
|
|
||||||
roboto_font: Font,
|
roboto_font: Font,
|
||||||
tilesheet: Tilesheet,
|
tilesheet: Tilesheet,
|
||||||
|
|
||||||
player_sprites: PlayerSprites,
|
player_sprites: PlayerSprites,
|
||||||
hole_with_box_sprite: Gfx.Sprite.Id,
|
box_sprites_by_color: std.EnumArray(BoxColor, BoxSprites),
|
||||||
animation_timer: Platform.Nanoseconds,
|
animation_timer: Platform.Nanoseconds,
|
||||||
|
|
||||||
footstep_buffer: Audio.BufferId,
|
footstep_buffer: Audio.BufferId,
|
||||||
@ -386,19 +413,46 @@ pub fn init(self: *App, plt: Platform.Init) !?u8 {
|
|||||||
.animation_timer = 0,
|
.animation_timer = 0,
|
||||||
.tilesheet = tilesheet,
|
.tilesheet = tilesheet,
|
||||||
.footstep_buffer = footstep_sound,
|
.footstep_buffer = footstep_sound,
|
||||||
.hole_with_box_sprite = tilesheet.get(6, 4),
|
.box_sprites_by_color = .init(.{
|
||||||
|
.none = .nil,
|
||||||
|
.brown = .{
|
||||||
|
.regular = tilesheet.get(6, 0),
|
||||||
|
.darker = tilesheet.get(6, 1),
|
||||||
|
.in_hole = tilesheet.get(6, 4),
|
||||||
|
},
|
||||||
|
.red = .{
|
||||||
|
.regular = tilesheet.get(7, 0),
|
||||||
|
.darker = tilesheet.get(7, 1),
|
||||||
|
.in_hole = tilesheet.get(7, 4),
|
||||||
|
},
|
||||||
|
.blue = .{
|
||||||
|
.regular = tilesheet.get(8, 0),
|
||||||
|
.darker = tilesheet.get(8, 1),
|
||||||
|
.in_hole = tilesheet.get(8, 4),
|
||||||
|
},
|
||||||
|
.green = .{
|
||||||
|
.regular = tilesheet.get(9, 0),
|
||||||
|
.darker = tilesheet.get(9, 1),
|
||||||
|
.in_hole = tilesheet.get(9, 4),
|
||||||
|
},
|
||||||
|
.gray = .{
|
||||||
|
.regular = tilesheet.get(10, 0),
|
||||||
|
.darker = tilesheet.get(10, 1),
|
||||||
|
.in_hole = tilesheet.get(10, 4),
|
||||||
|
}
|
||||||
|
}),
|
||||||
.sfx_bus = Audio.addBus(.{ .label = "sfx" }),
|
.sfx_bus = Audio.addBus(.{ .label = "sfx" }),
|
||||||
.world = undefined,
|
.world = undefined,
|
||||||
.levels = .empty,
|
.levels = .empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.levels = try self.loadLevels(plt.gpa, plt.assets);
|
self.levels = try self.loadLevels(plt.gpa, plt.assets);
|
||||||
self.world = try self.levels.items[0].world.clone(plt.gpa);
|
self.world.copy(self.levels.items[0]);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn loadLevels(self: *App, gpa: Allocator, assets: *Platform.Assets) !std.ArrayList(Level) {
|
fn loadLevels(self: *App, gpa: Allocator, assets: *Platform.Assets) !std.ArrayList(World) {
|
||||||
var xml_parser = try Tiled.xml.Parser.initCapacity(gpa, .{});
|
var xml_parser = try Tiled.xml.Parser.initCapacity(gpa, .{});
|
||||||
defer xml_parser.deinit(gpa);
|
defer xml_parser.deinit(gpa);
|
||||||
|
|
||||||
@ -418,9 +472,11 @@ fn loadLevels(self: *App, gpa: Allocator, assets: *Platform.Assets) !std.ArrayLi
|
|||||||
.root
|
.root
|
||||||
));
|
));
|
||||||
|
|
||||||
var levels: std.ArrayList(Level) = .empty;
|
var levels: std.ArrayList(World) = .empty;
|
||||||
|
|
||||||
const level_bounds = tilemap.getLayer("Level bounds").?;
|
const level_bounds = tilemap.getLayer("Level bounds").?;
|
||||||
|
try levels.ensureTotalCapacity(gpa, level_bounds.variant.object.items.len);
|
||||||
|
|
||||||
for (level_bounds.variant.object.items) |obj| {
|
for (level_bounds.variant.object.items) |obj| {
|
||||||
if (obj.shape != .rectangle) {
|
if (obj.shape != .rectangle) {
|
||||||
continue;
|
continue;
|
||||||
@ -445,37 +501,32 @@ fn loadLevels(self: *App, gpa: Allocator, assets: *Platform.Assets) !std.ArrayLi
|
|||||||
};
|
};
|
||||||
level_bound = tilemap.trimBoundsByEmptyTiles(level_bound);
|
level_bound = tilemap.trimBoundsByEmptyTiles(level_bound);
|
||||||
|
|
||||||
var level = try self.loadLevel(gpa, tilemap, tilesets, level_bound);
|
var level = levels.addOneAssumeCapacity();
|
||||||
level.number = level_index;
|
try self.loadLevel(level, tilemap, tilesets, level_bound);
|
||||||
try levels.append(gpa, level);
|
level.level_number = level_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Context = struct {
|
const Context = struct {
|
||||||
fn lessThan(_: @This(), lhs: Level, rhs: Level) bool {
|
fn lessThan(_: @This(), lhs: World, rhs: World) bool {
|
||||||
return lhs.number < rhs.number;
|
return lhs.level_number < rhs.level_number;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std.mem.sort(Level, levels.items, Context{}, Context.lessThan);
|
std.mem.sort(World, levels.items, Context{}, Context.lessThan);
|
||||||
|
|
||||||
return levels;
|
return levels;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn loadLevel(
|
fn loadLevel(
|
||||||
self: *App,
|
self: *App,
|
||||||
gpa: Allocator,
|
world: *World,
|
||||||
tilemap: Tiled.Tilemap,
|
tilemap: Tiled.Tilemap,
|
||||||
tilesets: Tiled.Tileset.List,
|
tilesets: Tiled.Tileset.List,
|
||||||
bounds: Tiled.Tilemap.Bounds
|
bounds: Tiled.Tilemap.Bounds
|
||||||
) !Level {
|
) !void {
|
||||||
var level = Level{
|
world.init();
|
||||||
.number = 0,
|
world.width = bounds.width();
|
||||||
.world = .{
|
world.height = bounds.height();
|
||||||
.width = bounds.width(),
|
|
||||||
.height = bounds.height(),
|
|
||||||
.entities = try .initCapacity(gpa, 256)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const ground = tilemap.getLayer("Ground").?;
|
const ground = tilemap.getLayer("Ground").?;
|
||||||
const foreground = tilemap.getLayer("Foreground").?;
|
const foreground = tilemap.getLayer("Foreground").?;
|
||||||
@ -487,7 +538,7 @@ fn loadLevel(
|
|||||||
if (tilemap.getTile(ground, tilesets, x, y)) |tiled_tile| {
|
if (tilemap.getTile(ground, tilesets, x, y)) |tiled_tile| {
|
||||||
const pos = tiled_tile.getPosition();
|
const pos = tiled_tile.getPosition();
|
||||||
|
|
||||||
_ = level.world.spawnEntity(Entity{
|
_ = world.spawnEntity(Entity{
|
||||||
.type = .nil,
|
.type = .nil,
|
||||||
.visual_layer = .ground,
|
.visual_layer = .ground,
|
||||||
.pos = .{
|
.pos = .{
|
||||||
@ -502,29 +553,34 @@ fn loadLevel(
|
|||||||
const pos = tiled_tile.getPosition();
|
const pos = tiled_tile.getPosition();
|
||||||
const props = tiled_tile.getProperties();
|
const props = tiled_tile.getProperties();
|
||||||
const props_type = props.getString("type") orelse "";
|
const props_type = props.getString("type") orelse "";
|
||||||
|
const props_color = props.getString("color") orelse "";
|
||||||
|
|
||||||
var entity_type: ?Entity.Type = null;
|
var entity_type: ?Entity.Type = null;
|
||||||
var layer: Entity.Layer = .surface;
|
var layer: Entity.Layer = .surface;
|
||||||
|
var color: BoxColor = .none;
|
||||||
if (std.mem.eql(u8, props_type, "wall")) {
|
if (std.mem.eql(u8, props_type, "wall")) {
|
||||||
entity_type = .wall;
|
entity_type = .wall;
|
||||||
} else if (std.mem.eql(u8, props_type, "box")) {
|
} else if (std.mem.eql(u8, props_type, "box")) {
|
||||||
entity_type = .box;
|
entity_type = .box;
|
||||||
|
color = BoxColor.string_mapping.get(props_color) orelse return error.UnknownBoxColor;
|
||||||
} else if (std.mem.eql(u8, props_type, "player")) {
|
} else if (std.mem.eql(u8, props_type, "player")) {
|
||||||
entity_type = .player;
|
entity_type = .player;
|
||||||
} else if (std.mem.eql(u8, props_type, "coin")) {
|
} else if (std.mem.eql(u8, props_type, "coin")) {
|
||||||
entity_type = .coin;
|
entity_type = .coin;
|
||||||
} else if (std.mem.eql(u8, props_type, "box_hole")) {
|
} else if (std.mem.eql(u8, props_type, "box_hole")) {
|
||||||
entity_type = .box_hole;
|
entity_type = .box_hole;
|
||||||
|
color = BoxColor.string_mapping.get(props_color) orelse .none;
|
||||||
layer = .on_ground;
|
layer = .on_ground;
|
||||||
} else if (std.mem.eql(u8, props_type, "box_goal")) {
|
} else if (std.mem.eql(u8, props_type, "box_goal")) {
|
||||||
entity_type = .box_goal;
|
entity_type = .box_goal;
|
||||||
layer = .on_ground;
|
layer = .on_ground;
|
||||||
|
color = BoxColor.string_mapping.get(props_color) orelse .none;
|
||||||
} else {
|
} else {
|
||||||
log.warn("Unknown tile type: '{s}' at {} {}", .{props_type, x, y});
|
log.warn("Unknown tile type: '{s}' at {} {}", .{props_type, x, y});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entity_type != null) {
|
if (entity_type != null) {
|
||||||
_ = level.world.spawnEntity(Entity{
|
_ = world.spawnEntity(Entity{
|
||||||
.type = entity_type.?,
|
.type = entity_type.?,
|
||||||
.visual_layer = layer,
|
.visual_layer = layer,
|
||||||
.pos = .{
|
.pos = .{
|
||||||
@ -532,25 +588,26 @@ fn loadLevel(
|
|||||||
.y = @intCast(oy),
|
.y = @intCast(oy),
|
||||||
},
|
},
|
||||||
.visual_pos = .initFromInt(usize, ox, oy),
|
.visual_pos = .initFromInt(usize, ox, oy),
|
||||||
.sprite = self.tilesheet.get(pos.x, pos.y)
|
.sprite = self.tilesheet.get(pos.x, pos.y),
|
||||||
|
.color = color
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return level;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const PlayerInput = struct {
|
const PlayerInput = struct {
|
||||||
move_dir: Point,
|
move_dir: Point,
|
||||||
undo: bool
|
undo: bool,
|
||||||
|
restart: bool
|
||||||
};
|
};
|
||||||
|
|
||||||
fn getPlayerInput(input: *Platform.Input) PlayerInput {
|
fn getPlayerInput(input: *Platform.Input) PlayerInput {
|
||||||
var result: PlayerInput = .{
|
var result: PlayerInput = .{
|
||||||
.move_dir = .{ .x = 0, .y = 0 },
|
.move_dir = .{ .x = 0, .y = 0 },
|
||||||
.undo = false
|
.undo = false,
|
||||||
|
.restart = false
|
||||||
};
|
};
|
||||||
|
|
||||||
if (input.isKeyPressedOrRepeat(.S)) {
|
if (input.isKeyPressedOrRepeat(.S)) {
|
||||||
@ -570,6 +627,7 @@ fn getPlayerInput(input: *Platform.Input) PlayerInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
result.undo = input.isKeyPressedOrRepeat(.Z);
|
result.undo = input.isKeyPressedOrRepeat(.Z);
|
||||||
|
result.restart = input.isKeyPressed(.R);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -596,12 +654,14 @@ pub fn frame(self: *App, plt: Platform.Frame) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (input.restart) {
|
||||||
|
try self.setWorldByLevel(self.current_level);
|
||||||
|
}
|
||||||
|
|
||||||
var tick_context: TickContext = .{
|
var tick_context: TickContext = .{
|
||||||
.world = &self.world
|
.world = &self.world
|
||||||
};
|
};
|
||||||
|
|
||||||
var goal_count: u32 = 0;
|
|
||||||
var box_at_goal_count: u32 = 0;
|
|
||||||
{
|
{
|
||||||
var entity_iter = self.world.entities.iterator();
|
var entity_iter = self.world.entities.iterator();
|
||||||
while (entity_iter.next()) |entity_id| {
|
while (entity_iter.next()) |entity_id| {
|
||||||
@ -620,12 +680,6 @@ pub fn frame(self: *App, plt: Platform.Frame) !void {
|
|||||||
self.footstep_sound = Audio.play(.{ .buffer = self.footstep_buffer, .bus = self.sfx_bus });
|
self.footstep_sound = Audio.play(.{ .buffer = self.footstep_buffer, .bus = self.sfx_bus });
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (entity.type == .box_goal) {
|
|
||||||
goal_count += 1;
|
|
||||||
|
|
||||||
if (self.world.entityExists(.{ .pos = entity.pos, .type = .box })) {
|
|
||||||
box_at_goal_count += 1;
|
|
||||||
}
|
|
||||||
} else if (entity.type == .box) {
|
} else if (entity.type == .box) {
|
||||||
interpolate_pos = true;
|
interpolate_pos = true;
|
||||||
}
|
}
|
||||||
@ -662,6 +716,28 @@ pub fn frame(self: *App, plt: Platform.Frame) !void {
|
|||||||
try self.undo_stack.append(plt.gpa, tick_context.undo_frame);
|
try self.undo_stack.append(plt.gpa, tick_context.undo_frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var goal_count: u32 = 0;
|
||||||
|
var box_at_goal_count: u32 = 0;
|
||||||
|
{
|
||||||
|
var goal_iter = self.world.iterEntities(.{ .type = .box_goal });
|
||||||
|
while (goal_iter.next()) |goal_id| {
|
||||||
|
const goal = self.world.entities.getAssumeExists(goal_id);
|
||||||
|
goal_count += 1;
|
||||||
|
|
||||||
|
if (self.world.findEntity(.{ .pos = goal.pos, .type = .box })) |box| {
|
||||||
|
var has_correct_color = true;
|
||||||
|
if (goal.color != .none) {
|
||||||
|
has_correct_color = goal.color == box.color;
|
||||||
|
}
|
||||||
|
|
||||||
|
const is_on_top = box.visual_pos.distance(goal.visual_pos) < 0.05;
|
||||||
|
if (is_on_top and has_correct_color) {
|
||||||
|
box_at_goal_count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline for (.{ Entity.Layer.ground, Entity.Layer.on_ground, Entity.Layer.surface }) |layer| {
|
inline for (.{ Entity.Layer.ground, Entity.Layer.on_ground, Entity.Layer.surface }) |layer| {
|
||||||
var entity_iter = self.world.entities.iterator();
|
var entity_iter = self.world.entities.iterator();
|
||||||
while (entity_iter.next()) |entity_id| {
|
while (entity_iter.next()) |entity_id| {
|
||||||
@ -672,7 +748,7 @@ pub fn frame(self: *App, plt: Platform.Frame) !void {
|
|||||||
|
|
||||||
var sprite = entity.sprite;
|
var sprite = entity.sprite;
|
||||||
|
|
||||||
const box_hole_margin = 0.2;
|
const box_hole_margin = 0.1;
|
||||||
if (entity.type == .box) {
|
if (entity.type == .box) {
|
||||||
const box_hole_id = self.world.findEntityId(.{ .type = .box_hole, .pos = entity.pos });
|
const box_hole_id = self.world.findEntityId(.{ .type = .box_hole, .pos = entity.pos });
|
||||||
if (self.world.entities.get(box_hole_id)) |box_hole| {
|
if (self.world.entities.get(box_hole_id)) |box_hole| {
|
||||||
@ -680,12 +756,25 @@ pub fn frame(self: *App, plt: Platform.Frame) !void {
|
|||||||
sprite = null;
|
sprite = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (self.world.findEntity(.{ .type = .box_goal, .pos = entity.pos })) |box_goal| {
|
||||||
|
if (box_goal.visual_pos.distance(entity.visual_pos) < 0.2) {
|
||||||
|
var is_correct = true;
|
||||||
|
if (box_goal.color != .none) {
|
||||||
|
is_correct = box_goal.color == entity.color;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_correct) {
|
||||||
|
sprite = self.box_sprites_by_color.get(entity.color).darker;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (entity.type == .box_hole) {
|
} else if (entity.type == .box_hole) {
|
||||||
var box_iter = self.world.iterEntities(.{ .type = .box, .pos = entity.pos });
|
var box_iter = self.world.iterEntities(.{ .type = .box, .pos = entity.pos });
|
||||||
while (box_iter.next()) |box_id| {
|
while (box_iter.next()) |box_id| {
|
||||||
const box = self.world.entities.getAssumeExists(box_id);
|
const box = self.world.entities.getAssumeExists(box_id);
|
||||||
if (box.visual_pos.distance(entity.visual_pos) < box_hole_margin) {
|
if (box.visual_pos.distance(entity.visual_pos) < box_hole_margin) {
|
||||||
sprite = self.hole_with_box_sprite;
|
sprite = self.box_sprites_by_color.get(box.color).in_hole;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -703,21 +792,19 @@ pub fn frame(self: *App, plt: Platform.Frame) !void {
|
|||||||
|
|
||||||
if (goal_count > 0 and goal_count == box_at_goal_count and self.current_level+1 < self.levels.items.len) {
|
if (goal_count > 0 and goal_count == box_at_goal_count and self.current_level+1 < self.levels.items.len) {
|
||||||
self.current_level += 1;
|
self.current_level += 1;
|
||||||
self.world.deinit(plt.gpa);
|
try self.setWorldByLevel(self.current_level);
|
||||||
self.world = try self.levels.items[self.current_level].world.clone(plt.gpa);
|
|
||||||
self.undo_stack.clearRetainingCapacity();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn setWorldByLevel(self: *App, index: u32) !void {
|
||||||
|
self.world.copy(self.levels.items[index]);
|
||||||
|
self.undo_stack.clearRetainingCapacity();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *App, plt: Platform.Deinit) void {
|
pub fn deinit(self: *App, plt: Platform.Deinit) void {
|
||||||
self.roboto_font.deinit(plt.gpa);
|
self.roboto_font.deinit(plt.gpa);
|
||||||
Gfx.deinitSpritesheet(self.roboto_font.spritesheet);
|
Gfx.deinitSpritesheet(self.roboto_font.spritesheet);
|
||||||
|
|
||||||
self.world.deinit(plt.gpa);
|
|
||||||
|
|
||||||
for (self.levels.items) |*level| {
|
|
||||||
level.world.deinit(plt.gpa);
|
|
||||||
}
|
|
||||||
self.levels.deinit(plt.gpa);
|
self.levels.deinit(plt.gpa);
|
||||||
self.undo_stack.deinit(plt.gpa);
|
self.undo_stack.deinit(plt.gpa);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user