Added basic game stage | Animations, ig?
This commit is contained in:
parent
c8a735314e
commit
d149a61f46
26 changed files with 293 additions and 31 deletions
|
|
@ -9,8 +9,8 @@
|
|||
|
||||
.dependencies = .{
|
||||
.app = .{
|
||||
.url = "git+http://2.120.146.66:25569/abux/NYXA.git#4113f667319559c6bddb83c89042deb54e63b3de",
|
||||
.hash = "app-0.0.0-AOV9_eK_AAA4ZmEGkvsFUM2xMTb0lYbzq4vSShMRnKZj",
|
||||
.url = "git+http://2.120.146.66:25569/abux/NYXA.git#7b8b2833a9047969031bb9a179abad0115c2ca07",
|
||||
.hash = "app-0.0.0-AOV9_Q_ZAADKe6v7NIwmnTpQR3Yup9j-NUc1OM522R-7",
|
||||
},
|
||||
.gtl = .{
|
||||
.url = "git+http://2.120.146.66:25569/abux/GTL.git#b87f315b57788ee81af592fc85532f751951966d",
|
||||
|
|
|
|||
BIN
src/assets/fonts/Dynamix.ttf
Normal file
BIN
src/assets/fonts/Dynamix.ttf
Normal file
Binary file not shown.
BIN
src/assets/textures/projectile.png
Normal file
BIN
src/assets/textures/projectile.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 461 B |
1
src/component/ai.zig
Normal file
1
src/component/ai.zig
Normal file
|
|
@ -0,0 +1 @@
|
|||
target_to_chase: u64,
|
||||
9
src/component/animate.zig
Normal file
9
src/component/animate.zig
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
pub const Style = union(enum) {
|
||||
bob: struct {
|
||||
amplitude: f32 = 6.0,
|
||||
frequency: f32 = 6.0,
|
||||
phase: f32 = 0.0,
|
||||
},
|
||||
};
|
||||
|
||||
style: Style,
|
||||
|
|
@ -1,2 +1,2 @@
|
|||
cooldown: f32 = 0.2,
|
||||
cooldown: f32 = 1.2,
|
||||
current_cooldown: f32 = 0.0,
|
||||
|
|
|
|||
2
src/component/health.zig
Normal file
2
src/component/health.zig
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
max: u32 = 100,
|
||||
current: u32 = 0,
|
||||
|
|
@ -2,9 +2,18 @@
|
|||
pub const Transform = @import("transform.zig");
|
||||
pub const Velocity = @import("velocity.zig");
|
||||
pub const Friction = @import("friction.zig");
|
||||
pub const Speed = @import("speed.zig");
|
||||
|
||||
// --- STYLE ---
|
||||
pub const Material = @import("material.zig");
|
||||
pub const Animate = @import("animate.zig");
|
||||
pub const Text = @import("text.zig");
|
||||
|
||||
// --- LIFETIME ---
|
||||
pub const Health = @import("health.zig");
|
||||
|
||||
// --- AI ---
|
||||
pub const AI = @import("ai.zig");
|
||||
|
||||
// --- CAMERA ---
|
||||
pub const Camera = @import("camera.zig");
|
||||
|
|
|
|||
1
src/component/speed.zig
Normal file
1
src/component/speed.zig
Normal file
|
|
@ -0,0 +1 @@
|
|||
value: f32 = 100.0,
|
||||
5
src/component/text.zig
Normal file
5
src/component/text.zig
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
const Handle = @import("gtl").Handle;
|
||||
const Font = @import("../resource/fonts.zig").Font;
|
||||
|
||||
content: []const u8 = "Hello World!",
|
||||
font: Handle(Font),
|
||||
|
|
@ -0,0 +1 @@
|
|||
pub const TakeDamage = @import("take_damage.zig");
|
||||
2
src/event/take_damage.zig
Normal file
2
src/event/take_damage.zig
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
entity: u32,
|
||||
value: u32,
|
||||
|
|
@ -17,6 +17,15 @@ pub fn main(init: std.process.Init) !void {
|
|||
try app.schedules.run(App.stage.init, .{ .app = &app });
|
||||
defer app.schedules.run(App.stage.deinit, .{ .app = &app }) catch unreachable;
|
||||
|
||||
// --- IO ---
|
||||
var prng = std.Random.DefaultPrng.init(6969);
|
||||
const rng = prng.random();
|
||||
try app.resources.set(resource.IO{
|
||||
.io = init.io,
|
||||
.rng = rng,
|
||||
.prng = prng,
|
||||
});
|
||||
|
||||
// errdefer {
|
||||
// app.schedules.run(App.stage.deinit, .{ .app = &app }) catch unreachable;
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ fn build(
|
|||
system.frame.updateTimers,
|
||||
system.frame.updateTransforms,
|
||||
system.frame.cast,
|
||||
system.ai.spawn,
|
||||
system.ai.chaseTarget,
|
||||
});
|
||||
try ctx.app.schedules.add(App.stage.draw, system.draw.draw);
|
||||
}
|
||||
|
|
|
|||
64
src/resource/fonts.zig
Normal file
64
src/resource/fonts.zig
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
// --- # ---
|
||||
const std = @import("std");
|
||||
const gtl = @import("gtl");
|
||||
const sdl = @import("sdl");
|
||||
const Self = @This();
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub const Font = struct { id: u64 };
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub const GPUFont = struct {
|
||||
path: []const u8,
|
||||
size: [2]i32 = .{ 0, 0 },
|
||||
raw: ?*sdl.TTF_Font,
|
||||
};
|
||||
|
||||
//
|
||||
// FIELDS
|
||||
//
|
||||
|
||||
data: gtl.KeyedSlotMap(Font, GPUFont),
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn init(alloc: std.mem.Allocator) Self {
|
||||
return .{
|
||||
.data = .init(alloc),
|
||||
};
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn deinit(self: *Self) void {
|
||||
for (self.data.items()) |entry| {
|
||||
sdl.TTF_CloseFont(entry.value.raw);
|
||||
}
|
||||
self.data.deinit();
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn load(
|
||||
self: *Self,
|
||||
path: []const u8,
|
||||
) !gtl.Handle(Font) {
|
||||
// --- ID ---
|
||||
const id = std.hash.Wyhash.hash(
|
||||
6969,
|
||||
path,
|
||||
);
|
||||
|
||||
// --- # ---
|
||||
if (self.data.getHandle(.{ .id = id })) |h| {
|
||||
return h;
|
||||
}
|
||||
|
||||
// --- # ---
|
||||
return try self.data.put(.{ .id = id }, .{
|
||||
.path = path,
|
||||
.raw = null,
|
||||
});
|
||||
}
|
||||
6
src/resource/game.zig
Normal file
6
src/resource/game.zig
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
// --- WAVES ---
|
||||
current_wave: u32 = 0,
|
||||
current_wave_time: f32 = 0,
|
||||
time_for_next_wave: f32 = 20.0,
|
||||
next_wave_enemy_count: u32 = 3,
|
||||
enemy_multiplyer_each_wave: u32 = 2,
|
||||
5
src/resource/io.zig
Normal file
5
src/resource/io.zig
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
const std = @import("std");
|
||||
|
||||
io: std.Io,
|
||||
rng: std.Random,
|
||||
prng: std.Random.DefaultPrng,
|
||||
|
|
@ -1,6 +1,13 @@
|
|||
// --- CORE ---
|
||||
pub const IO = @import("io.zig");
|
||||
pub const Window = @import("window.zig");
|
||||
pub const Renderer = @import("renderer.zig");
|
||||
pub const Frame = @import("frame.zig");
|
||||
pub const Time = @import("time.zig");
|
||||
|
||||
// --- ASSETS ---
|
||||
pub const Fonts = @import("fonts.zig");
|
||||
pub const Textures = @import("textures.zig");
|
||||
|
||||
// --- GAME ---
|
||||
pub const Game = @import("game.zig");
|
||||
|
|
|
|||
|
|
@ -4,12 +4,6 @@ const gtl = @import("gtl");
|
|||
const sdl = @import("sdl");
|
||||
const Self = @This();
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
pub const Player = struct {};
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub const Texture = struct { id: u64 };
|
||||
|
|
@ -51,17 +45,20 @@ pub fn deinit(self: *Self) void {
|
|||
/// ----------------------------------------------------
|
||||
pub fn load(
|
||||
self: *Self,
|
||||
comptime T: type,
|
||||
path: []const u8,
|
||||
) !gtl.Handle(Texture) {
|
||||
// --- ID ---
|
||||
const id = gtl.TypeID(T);
|
||||
const id = std.hash.Wyhash.hash(
|
||||
6969,
|
||||
path,
|
||||
);
|
||||
|
||||
// --- # ---
|
||||
if (self.data.getHandle(.{ .id = id })) |h| {
|
||||
return h;
|
||||
}
|
||||
|
||||
// --- # ---
|
||||
return try self.data.put(.{ .id = id }, .{
|
||||
.path = path,
|
||||
.raw = null,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
dt: f32 = 0.0,
|
||||
now: u64 = 0,
|
||||
last: u64 = 0,
|
||||
elapsed: f32 = 0.0,
|
||||
frequency: u64 = 0,
|
||||
target_dt: f32 = 1.0 / 60.0,
|
||||
|
|
|
|||
110
src/system/ai.zig
Normal file
110
src/system/ai.zig
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
const std = @import("std");
|
||||
const sdl = @import("sdl");
|
||||
const App = @import("app");
|
||||
|
||||
const component = @import("../component/root.zig");
|
||||
const resource = @import("../resource/root.zig");
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn spawn(ctx: App.scheduler.Context) !void {
|
||||
const res = try ctx.app.resources.getMany(struct {
|
||||
io: *resource.IO,
|
||||
time: *resource.Time,
|
||||
game: *resource.Game,
|
||||
textures: *resource.Textures,
|
||||
});
|
||||
|
||||
// --- CURRENT TARGET ---
|
||||
var target: ?u64 = 0;
|
||||
|
||||
// --- GET TARGET ---
|
||||
var query = ctx.app.world.query(struct {
|
||||
player: *component.Player,
|
||||
}, .{});
|
||||
while (query.next()) |_| {
|
||||
target = query.entity();
|
||||
}
|
||||
|
||||
// --- SUBTRACT COOLDOWN ---
|
||||
res.game.current_wave_time -= @max(0, res.time.dt);
|
||||
|
||||
// --- SKIP IF ON COOLDOWN ---
|
||||
if (res.game.current_wave_time >= 0)
|
||||
return;
|
||||
|
||||
// --- SPAWN ---
|
||||
for (0..@intCast(res.game.next_wave_enemy_count)) |_| {
|
||||
try ctx.app.world.spawn(.{
|
||||
component.AI{
|
||||
.target_to_chase = target orelse return,
|
||||
},
|
||||
component.Transform{
|
||||
.pos = .{
|
||||
@floatFromInt(res.io.rng.intRangeAtMost(i32, -400, 400)),
|
||||
@floatFromInt(res.io.rng.intRangeAtMost(i32, -400, 400)),
|
||||
},
|
||||
.size = blk: {
|
||||
const size: f32 = @floatFromInt(res.io.rng.intRangeAtMost(i32, 16, 64));
|
||||
break :blk .{ size, size };
|
||||
},
|
||||
},
|
||||
component.Velocity{},
|
||||
component.Friction{},
|
||||
component.Speed{ .value = 200 },
|
||||
component.Animate{ .style = .{ .bob = .{} } },
|
||||
|
||||
component.Material{
|
||||
.style = .{
|
||||
// .solid = .{ 200, 20, 20, 255 },
|
||||
.textured = try res.textures.load("src/assets/textures/player.png"),
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// --- SET COOLDOWN ---
|
||||
res.game.current_wave_time = res.game.time_for_next_wave;
|
||||
res.game.next_wave_enemy_count *= res.game.enemy_multiplyer_each_wave;
|
||||
}
|
||||
|
||||
/// ----------------------------------------------------
|
||||
/// ----------------------------------------------------
|
||||
pub fn chaseTarget(ctx: App.scheduler.Context) !void {
|
||||
const res = try ctx.app.resources.getMany(struct {
|
||||
frame: *resource.Frame,
|
||||
time: *resource.Time,
|
||||
});
|
||||
|
||||
var query = ctx.app.world.query(struct {
|
||||
ai: *component.AI,
|
||||
speed: *component.Speed,
|
||||
transform: *component.Transform,
|
||||
velocity: *component.Velocity,
|
||||
}, .{});
|
||||
while (query.next()) |e| {
|
||||
// --- GET TARGETS POSITION ---
|
||||
const target = ctx.app.world.getComponent(
|
||||
component.Transform,
|
||||
e.ai.target_to_chase,
|
||||
) orelse continue;
|
||||
|
||||
// --- GET DIR ---
|
||||
const dir: [2]f32 = .{
|
||||
(target.pos[0] + target.size[0] / 2) - (e.transform.pos[0] + e.transform.size[0] / 2),
|
||||
(target.pos[1] + target.size[1] / 2) - (e.transform.pos[1] + e.transform.size[1] / 2),
|
||||
};
|
||||
|
||||
// --- GET LEN ---
|
||||
const len: f32 = @sqrt(
|
||||
dir[0] * dir[0] + dir[1] * dir[1],
|
||||
);
|
||||
|
||||
// --- MOVE ---
|
||||
if (len > 0.0001) {
|
||||
const accel = e.speed.value * res.time.dt;
|
||||
e.velocity.value[0] += (dir[0] / len) * accel;
|
||||
e.velocity.value[1] += (dir[1] / len) * accel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@ const resource = @import("../resource/root.zig");
|
|||
/// ----------------------------------------------------
|
||||
pub fn init(ctx: App.scheduler.Context) !void {
|
||||
// --- SDL3 INIT ---
|
||||
if (!sdl.SDL_Init(sdl.SDL_INIT_VIDEO)) {
|
||||
if (!sdl.SDL_Init(sdl.SDL_INIT_VIDEO) or !sdl.TTF_Init()) {
|
||||
return error.SDL_Init;
|
||||
}
|
||||
|
||||
|
|
@ -38,6 +38,14 @@ pub fn init(ctx: App.scheduler.Context) !void {
|
|||
.frequency = sdl.SDL_GetPerformanceFrequency(),
|
||||
});
|
||||
try ctx.app.resources.set(resource.Frame{});
|
||||
|
||||
// --- GAME ---
|
||||
try ctx.app.resources.set(
|
||||
resource.Game{},
|
||||
);
|
||||
|
||||
// --- ASSETS ---
|
||||
_ = try ctx.app.resources.getOrSet(resource.Fonts.init(ctx.app.alloc));
|
||||
const textures = try ctx.app.resources.getOrSet(resource.Textures.init(ctx.app.alloc));
|
||||
|
||||
// --- DEBUG ---
|
||||
|
|
@ -57,12 +65,13 @@ pub fn init(ctx: App.scheduler.Context) !void {
|
|||
try ctx.app.world.spawn(.{
|
||||
component.Player{},
|
||||
component.Caster{},
|
||||
component.Speed{},
|
||||
|
||||
component.Friction{},
|
||||
component.Velocity{},
|
||||
component.Transform{ .size = .{ 64, 64 } },
|
||||
component.Material{ .style = .{
|
||||
.textured = try textures.load(resource.Textures.Player, "src/assets/textures/player.png"),
|
||||
.textured = try textures.load("src/assets/textures/player.png"),
|
||||
} },
|
||||
component.CameraTarget{},
|
||||
});
|
||||
|
|
@ -83,10 +92,14 @@ pub fn deinit(ctx: App.scheduler.Context) !void {
|
|||
window: *resource.Window,
|
||||
renderer: *resource.Renderer,
|
||||
textures: *resource.Textures,
|
||||
fonts: *resource.Fonts,
|
||||
});
|
||||
|
||||
res.fonts.deinit();
|
||||
res.textures.deinit();
|
||||
|
||||
sdl.SDL_DestroyRenderer(res.renderer.raw);
|
||||
sdl.SDL_DestroyWindow(res.window.raw);
|
||||
sdl.TTF_Quit();
|
||||
sdl.SDL_Quit();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,10 @@ pub fn draw(ctx: App.scheduler.Context) !void {
|
|||
window: *resource.Window,
|
||||
renderer: *resource.Renderer,
|
||||
frame: *resource.Frame,
|
||||
time: *resource.Time,
|
||||
|
||||
textures: *resource.Textures,
|
||||
fonts: *resource.Fonts,
|
||||
});
|
||||
|
||||
// --- SET CLEAR COLOR ---
|
||||
|
|
@ -33,14 +36,27 @@ pub fn draw(ctx: App.scheduler.Context) !void {
|
|||
transform: *component.Transform,
|
||||
material: *component.Material,
|
||||
camera_target: ?*component.CameraTarget,
|
||||
animate: ?*component.Animate,
|
||||
text: ?*component.Text,
|
||||
}, .{});
|
||||
while (query.next()) |e| {
|
||||
// --- DATA ---
|
||||
const camera = if (res.frame.camera) |*v| v else continue;
|
||||
var draw_pos = e.transform.pos;
|
||||
|
||||
// --- SHAPE ---
|
||||
// --- ANIMATIONS ---
|
||||
if (e.animate) |animate| {
|
||||
switch (animate.style) {
|
||||
.bob => |bob| {
|
||||
draw_pos[1] += @sin(res.time.elapsed * bob.frequency + bob.phase) * bob.amplitude;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// --- DRAW RECT ---
|
||||
var rect: sdl.SDL_FRect = .{
|
||||
.x = e.transform.pos[0] + camera.transform.pos[0],
|
||||
.y = e.transform.pos[1] + camera.transform.pos[1],
|
||||
.x = draw_pos[0] + camera.transform.pos[0],
|
||||
.y = draw_pos[1] + camera.transform.pos[1],
|
||||
.w = e.transform.size[0],
|
||||
.h = e.transform.size[1],
|
||||
};
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ pub fn beginFrame(ctx: App.scheduler.Context) !void {
|
|||
|
||||
// --- SET TEXTURE FILTER ---
|
||||
_ = sdl.SDL_SetTextureScaleMode(
|
||||
entry.value.raw,
|
||||
raw,
|
||||
sdl.SDL_SCALEMODE_PIXELART,
|
||||
);
|
||||
|
||||
|
|
@ -115,6 +115,7 @@ pub fn endFrame(ctx: App.scheduler.Context) !void {
|
|||
});
|
||||
|
||||
res.frame.camera = null;
|
||||
res.time.elapsed += res.time.dt;
|
||||
|
||||
const frame_time =
|
||||
@as(f32, @floatFromInt(sdl.SDL_GetPerformanceCounter() - res.time.now)) /
|
||||
|
|
@ -208,17 +209,17 @@ pub fn cast(ctx: App.scheduler.Context) !void {
|
|||
// --- SPAWN PROJECTILE ---
|
||||
try ctx.app.world.spawn(.{
|
||||
component.Transform{
|
||||
.pos = e.transform.pos,
|
||||
.pos = .{
|
||||
e.transform.pos[0] + (e.transform.size[0] / 2.0),
|
||||
e.transform.pos[1] + (e.transform.size[1] / 2.0),
|
||||
},
|
||||
},
|
||||
component.Velocity{
|
||||
.value = .{ 400, 0 },
|
||||
},
|
||||
component.Material{
|
||||
.style = .{
|
||||
// .solid = .{ 200, 20, 20, 255 },
|
||||
.textured = try res.textures.load(resource.Textures.Player, "src/assets/textures/player.png"),
|
||||
},
|
||||
.value = .{ 200, 0 },
|
||||
},
|
||||
component.Material{ .style = .{
|
||||
.textured = try res.textures.load("src/assets/textures/projectile.png"),
|
||||
} },
|
||||
component.Projectile{},
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -28,12 +28,12 @@ pub fn pollEvents(ctx: App.scheduler.Context) !void {
|
|||
var query = ctx.app.world.query(struct {
|
||||
player: *component.Player,
|
||||
velocity: *component.Velocity,
|
||||
speed: *component.Speed,
|
||||
}, .{});
|
||||
while (query.next()) |e| {
|
||||
const speed: f32 = 100.0;
|
||||
if (keyboard[sdl.SDL_SCANCODE_W]) e.velocity.value[1] = -speed;
|
||||
if (keyboard[sdl.SDL_SCANCODE_S]) e.velocity.value[1] = speed;
|
||||
if (keyboard[sdl.SDL_SCANCODE_A]) e.velocity.value[0] = -speed;
|
||||
if (keyboard[sdl.SDL_SCANCODE_D]) e.velocity.value[0] = speed;
|
||||
if (keyboard[sdl.SDL_SCANCODE_W]) e.velocity.value[1] = -e.speed.value;
|
||||
if (keyboard[sdl.SDL_SCANCODE_S]) e.velocity.value[1] = e.speed.value;
|
||||
if (keyboard[sdl.SDL_SCANCODE_A]) e.velocity.value[0] = -e.speed.value;
|
||||
if (keyboard[sdl.SDL_SCANCODE_D]) e.velocity.value[0] = e.speed.value;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,3 +2,4 @@ pub const core = @import("core.zig");
|
|||
pub const frame = @import("frame.zig");
|
||||
pub const inputs = @import("inputs.zig");
|
||||
pub const draw = @import("draw.zig");
|
||||
pub const ai = @import("ai.zig");
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue