Enabled tile randomization.
This commit is contained in:
parent
e66908ca71
commit
7a51415e5e
@ -3,6 +3,7 @@ const assets = @import("engine/assets.zig");
|
|||||||
pub const Fonts = assets.Fonts;
|
pub const Fonts = assets.Fonts;
|
||||||
pub const FPS = @import("engine/fps.zig").FPS;
|
pub const FPS = @import("engine/fps.zig").FPS;
|
||||||
pub const Keys = @import("engine/keys.zig").Keys;
|
pub const Keys = @import("engine/keys.zig").Keys;
|
||||||
|
pub const Object = @import("engine/object.zig").Object;
|
||||||
pub const OpaquePtr = @import("engine/opaque_ptr.zig").OpaquePtr;
|
pub const OpaquePtr = @import("engine/opaque_ptr.zig").OpaquePtr;
|
||||||
pub const Point = @import("engine/point.zig").Point;
|
pub const Point = @import("engine/point.zig").Point;
|
||||||
pub const PointF = @import("engine/point_f.zig").PointF;
|
pub const PointF = @import("engine/point_f.zig").PointF;
|
||||||
|
19
src/engine/object.zig
Normal file
19
src/engine/object.zig
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub fn Object(comptime T: type) type {
|
||||||
|
return struct {
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
allocator: std.mem.Allocator,
|
||||||
|
ptr: *T,
|
||||||
|
|
||||||
|
pub fn create(allocator: std.mem.Allocator) !Self {
|
||||||
|
const ptr = try allocator.create(T);
|
||||||
|
return Self{ .allocator = allocator, .ptr = ptr };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn destroy(self: Self) void {
|
||||||
|
self.allocator.destroy(self.ptr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
@ -2,8 +2,9 @@ const std = @import("std");
|
|||||||
const allegro = @import("allegro");
|
const allegro = @import("allegro");
|
||||||
const engine = @import("../engine.zig");
|
const engine = @import("../engine.zig");
|
||||||
const Animation = @import("animation.zig").Animation;
|
const Animation = @import("animation.zig").Animation;
|
||||||
const Renderer = @import("../renderer.zig").Renderer;
|
|
||||||
const Level = @import("level.zig").Level;
|
const Level = @import("level.zig").Level;
|
||||||
|
const Renderer = @import("../renderer.zig").Renderer;
|
||||||
|
const TileMap = @import("tile_map.zig").TileMap;
|
||||||
|
|
||||||
pub const Game = struct {
|
pub const Game = struct {
|
||||||
pub const Direction = enum {
|
pub const Direction = enum {
|
||||||
@ -13,6 +14,8 @@ pub const Game = struct {
|
|||||||
|
|
||||||
pub const TileSize = 32;
|
pub const TileSize = 32;
|
||||||
|
|
||||||
|
prng: std.rand.DefaultPrng = std.rand.DefaultPrng.init(0),
|
||||||
|
|
||||||
level: Level,
|
level: Level,
|
||||||
health: i64 = 4,
|
health: i64 = 4,
|
||||||
|
|
||||||
@ -25,10 +28,11 @@ pub const Game = struct {
|
|||||||
starAnimation: Animation,
|
starAnimation: Animation,
|
||||||
|
|
||||||
renderer: *Renderer,
|
renderer: *Renderer,
|
||||||
|
randomTile: TileMap(usize),
|
||||||
// current viewport translated to tiles.
|
// current viewport translated to tiles.
|
||||||
boundsInTiles: engine.RectangleF,
|
boundsInTiles: engine.RectangleF,
|
||||||
|
|
||||||
pub fn init(level: Level, renderer: *Renderer) Game {
|
pub fn init(allocator: std.mem.Allocator, level: Level, renderer: *Renderer) Game {
|
||||||
const playerPosition = level.character.float();
|
const playerPosition = level.character.float();
|
||||||
return Game{
|
return Game{
|
||||||
.level = level,
|
.level = level,
|
||||||
@ -39,10 +43,16 @@ pub const Game = struct {
|
|||||||
.isPlayerWalking = false,
|
.isPlayerWalking = false,
|
||||||
.starAnimation = Animation.init(renderer.sprites.get("item_star_32").?, 0.15),
|
.starAnimation = Animation.init(renderer.sprites.get("item_star_32").?, 0.15),
|
||||||
.renderer = renderer,
|
.renderer = renderer,
|
||||||
|
.randomTile = TileMap(usize).init(allocator),
|
||||||
.boundsInTiles = Game.calculateBoundsInTiles(playerPosition),
|
.boundsInTiles = Game.calculateBoundsInTiles(playerPosition),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *Game) void {
|
||||||
|
self.level.deinit();
|
||||||
|
self.randomTile.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
fn calculateBoundsInTiles(position: engine.PointF) engine.RectangleF {
|
fn calculateBoundsInTiles(position: engine.PointF) engine.RectangleF {
|
||||||
return engine.RectangleF.initRelative(
|
return engine.RectangleF.initRelative(
|
||||||
position.x - 15,
|
position.x - 15,
|
||||||
@ -77,6 +87,15 @@ pub const Game = struct {
|
|||||||
self.boundsInTiles = Game.calculateBoundsInTiles(self.playerPosition);
|
self.boundsInTiles = Game.calculateBoundsInTiles(self.playerPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn randomTileOffset(self: *Game, x: i64, y: i64, maxOffset: usize) usize {
|
||||||
|
if (self.randomTile.get(x, y)) |offset| {
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
const offset = self.prng.random().intRangeLessThan(usize, 0, maxOffset);
|
||||||
|
self.randomTile.set(x, y, offset) catch {};
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
// return values are in view coordinates
|
// return values are in view coordinates
|
||||||
pub fn tile(self: Game, x: f32, y: f32) engine.PointF {
|
pub fn tile(self: Game, x: f32, y: f32) engine.PointF {
|
||||||
return self.tileP(engine.PointF.init(x, y));
|
return self.tileP(engine.PointF.init(x, y));
|
||||||
|
@ -15,7 +15,7 @@ pub const Level = struct {
|
|||||||
tiles: TileMap(Tile),
|
tiles: TileMap(Tile),
|
||||||
collectables: TileMap(Collectable),
|
collectables: TileMap(Collectable),
|
||||||
|
|
||||||
pub fn load(allocator: std.mem.Allocator, path: []const u8) !Level {
|
pub fn init(allocator: std.mem.Allocator, path: []const u8) !Level {
|
||||||
const path_ = try std.fs.realpathAlloc(allocator, path);
|
const path_ = try std.fs.realpathAlloc(allocator, path);
|
||||||
defer allocator.free(path_);
|
defer allocator.free(path_);
|
||||||
|
|
||||||
@ -25,10 +25,10 @@ pub const Level = struct {
|
|||||||
const data = try file.readToEndAlloc(allocator, 1024 * 1024);
|
const data = try file.readToEndAlloc(allocator, 1024 * 1024);
|
||||||
defer allocator.free(data);
|
defer allocator.free(data);
|
||||||
|
|
||||||
return try Level.loadFromMemory(allocator, data);
|
return try Level.initFromMemory(allocator, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn loadFromMemory(allocator: std.mem.Allocator, data: []const u8) !Level {
|
pub fn initFromMemory(allocator: std.mem.Allocator, data: []const u8) !Level {
|
||||||
const n = std.mem.count(u8, data, "\n");
|
const n = std.mem.count(u8, data, "\n");
|
||||||
_ = n;
|
_ = n;
|
||||||
|
|
||||||
@ -41,9 +41,6 @@ pub const Level = struct {
|
|||||||
while (lines.next()) |line| {
|
while (lines.next()) |line| {
|
||||||
defer y += 1;
|
defer y += 1;
|
||||||
|
|
||||||
try tiles.ensureColumns(line.len);
|
|
||||||
try collectables.ensureColumns(line.len);
|
|
||||||
|
|
||||||
for (line, 0..) |tile, column| {
|
for (line, 0..) |tile, column| {
|
||||||
var x = @intCast(i64, column);
|
var x = @intCast(i64, column);
|
||||||
switch (tile) {
|
switch (tile) {
|
||||||
@ -61,4 +58,9 @@ pub const Level = struct {
|
|||||||
.collectables = collectables,
|
.collectables = collectables,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *Level) void {
|
||||||
|
self.tiles.deinit();
|
||||||
|
self.collectables.deinit();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const Object = @import("../engine/object.zig").Object;
|
||||||
|
|
||||||
pub fn TileMap(comptime Value: type) type {
|
pub fn TileMap(comptime Value: type) type {
|
||||||
return struct {
|
return struct {
|
||||||
@ -13,7 +14,7 @@ pub fn TileMap(comptime Value: type) type {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: Column) void {
|
pub fn deinit(self: *Column) void {
|
||||||
self.values.deinit();
|
self.values.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,35 +28,45 @@ pub fn TileMap(comptime Value: type) type {
|
|||||||
};
|
};
|
||||||
|
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
columns: std.ArrayList(Column),
|
columns: std.AutoHashMap(i64, Column),
|
||||||
|
|
||||||
pub fn init(allocator: std.mem.Allocator) Self {
|
pub fn init(allocator: std.mem.Allocator) Self {
|
||||||
return Self{
|
return Self{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
.columns = std.ArrayList(Column).init(allocator),
|
.columns = std.AutoHashMap(i64, Column).init(allocator),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: Self) void {
|
pub fn deinit(self: *Self) void {
|
||||||
for (self.columns.items) |item| {
|
var columns = self.columns.valueIterator();
|
||||||
item.deinit();
|
while (columns.next()) |c| {
|
||||||
|
c.deinit();
|
||||||
}
|
}
|
||||||
self.columns.deinit();
|
self.columns.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn column(self: Self, i: i64) *Column {
|
pub fn column(self: Self, x: i64) *Column {
|
||||||
return &self.columns.items[@intCast(usize, i)];
|
return self.columns.getPtr(x).?;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ensureColumns(self: *Self, n: usize) !void {
|
pub fn ensureColumn(self: *Self, x: i64) !*Column {
|
||||||
while (self.columns.items.len < n) {
|
if (self.columns.getPtr(x)) |c| {
|
||||||
try self.columns.append(Column.init(self.allocator));
|
return c;
|
||||||
}
|
}
|
||||||
|
try self.columns.put(x, Column.init(self.allocator));
|
||||||
|
return self.columns.getPtr(x).?;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set(self: *Self, c: i64, r: i64, value: Value) !void {
|
pub fn get(self: Self, x: i64, y: i64) ?Value {
|
||||||
try self.ensureColumns(@intCast(usize, c) + 1);
|
if (self.columns.get(x)) |c| {
|
||||||
try self.column(c).set(r, value);
|
return c.get(y);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set(self: *Self, x: i64, y: i64, value: Value) !void {
|
||||||
|
const c = try self.ensureColumn(x);
|
||||||
|
try c.set(y, value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -10,13 +10,13 @@ pub const GameScene = struct {
|
|||||||
game: game.Game = undefined,
|
game: game.Game = undefined,
|
||||||
|
|
||||||
pub fn enter(self: *GameScene, ctx: *Context) void {
|
pub fn enter(self: *GameScene, ctx: *Context) void {
|
||||||
const level = game.Level.load(ctx.allocator, paths.AssetsDir ++ "/levels/level1.txt") catch unreachable;
|
const level = game.Level.init(ctx.allocator, paths.AssetsDir ++ "/levels/level1.txt") catch unreachable;
|
||||||
self.game = game.Game.init(level, &ctx.renderer);
|
self.game = game.Game.init(ctx.allocator, level, &ctx.renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exit(self: *GameScene, ctx: *Context) void {
|
pub fn exit(self: *GameScene, ctx: *Context) void {
|
||||||
|
self.game.deinit();
|
||||||
_ = ctx;
|
_ = ctx;
|
||||||
_ = self;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle(self: *GameScene, ctx: *Context, event: *allegro.Event) !void {
|
pub fn handle(self: *GameScene, ctx: *Context, event: *allegro.Event) !void {
|
||||||
@ -68,20 +68,22 @@ pub const GameScene = struct {
|
|||||||
|
|
||||||
var x = tileBounds.min.x;
|
var x = tileBounds.min.x;
|
||||||
while (x < tileBounds.max.x) : (x += 1) {
|
while (x < tileBounds.max.x) : (x += 1) {
|
||||||
self.game.drawSpriteFrame("tiles_dirt_32", 0, x, 19);
|
const randomDirtOffset = self.game.randomTileOffset(x, 99, 3);
|
||||||
self.game.drawSpriteFrame("tiles_dirt_32", 3, x, 20);
|
self.game.drawSpriteFrame("tiles_dirt_32", 0 + randomDirtOffset, x, 19);
|
||||||
|
self.game.drawSpriteFrame("tiles_dirt_32", 3 + randomDirtOffset, x, 20);
|
||||||
|
|
||||||
if (x < 0) continue;
|
if (x < 0) continue;
|
||||||
|
|
||||||
const tiles = self.game.level.tiles.column(x);
|
const tiles = self.game.level.tiles.ensureColumn(x) catch continue;
|
||||||
const collectables = self.game.level.collectables.column(x);
|
const collectables = self.game.level.collectables.ensureColumn(x) catch continue;
|
||||||
var y = tileBounds.min.y;
|
var y = tileBounds.min.y;
|
||||||
while (y < tileBounds.max.y) : (y += 1) {
|
while (y < tileBounds.max.y) : (y += 1) {
|
||||||
if (tiles.get(y)) |tile| {
|
if (tiles.get(y)) |tile| {
|
||||||
switch (tile) {
|
switch (tile) {
|
||||||
game.Level.Tile.Grass => {
|
game.Level.Tile.Grass => {
|
||||||
self.game.drawSpriteFrame("tiles_grass_32", 1, x, y - 1);
|
const randomOffset = self.game.randomTileOffset(x, y, 2);
|
||||||
self.game.drawSpriteFrame("tiles_grass_32", 5, x, y);
|
self.game.drawSpriteFrame("tiles_grass_32", 1 + randomOffset, x, y - 1);
|
||||||
|
self.game.drawSpriteFrame("tiles_grass_32", 5 + randomOffset, x, y);
|
||||||
},
|
},
|
||||||
// else => {},
|
// else => {},
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user