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