add bomb
This commit is contained in:
parent
ba264d7bc5
commit
c9543c72ad
@ -76,6 +76,13 @@ const Laser = struct {
|
||||
duration: Nanoseconds
|
||||
};
|
||||
|
||||
const Bomb = struct {
|
||||
kinetic: Kinetic,
|
||||
size: f32,
|
||||
explode_at: Nanoseconds,
|
||||
explosion_radius: f32
|
||||
};
|
||||
|
||||
const Enemy = struct {
|
||||
kinetic: Kinetic,
|
||||
speed: f32,
|
||||
@ -126,6 +133,7 @@ enemies: std.ArrayList(Enemy) = .empty,
|
||||
player: Player = .{},
|
||||
bullets: std.ArrayList(Bullet) = .empty,
|
||||
lasers: std.ArrayList(Laser) = .empty,
|
||||
bombs: std.ArrayList(Bomb) = .empty,
|
||||
|
||||
pickups: std.ArrayList(Pickup) = .empty,
|
||||
next_pickup_spawn_at: Nanoseconds,
|
||||
@ -164,6 +172,7 @@ pub fn deinit(self: *CombatScreen) void {
|
||||
self.pickups.deinit(self.gpa);
|
||||
self.spawned_waves.deinit(self.gpa);
|
||||
self.lasers.deinit(self.gpa);
|
||||
self.bombs.deinit(self.gpa);
|
||||
}
|
||||
|
||||
pub fn spawnEnemy(self: *CombatScreen) !void {
|
||||
@ -360,6 +369,15 @@ pub fn tick(self: *CombatScreen, state: *State, frame: *Engine.Frame) !TickResul
|
||||
});
|
||||
},
|
||||
.bomb => {
|
||||
try self.bombs.append(self.gpa, .{
|
||||
.kinetic = .{
|
||||
.pos = self.player.kinetic.pos,
|
||||
.vel = bullet_dir.multiplyScalar(800)
|
||||
},
|
||||
.size = 10,
|
||||
.explode_at = frame.time_ns + std.time.ns_per_s,
|
||||
.explosion_radius = 50
|
||||
});
|
||||
},
|
||||
.laser => {
|
||||
try self.lasers.append(self.gpa, .{
|
||||
@ -400,27 +418,79 @@ pub fn tick(self: *CombatScreen, state: *State, frame: *Engine.Frame) !TickResul
|
||||
});
|
||||
}
|
||||
|
||||
for (self.lasers.items) |*laser| {
|
||||
const laser_length = 1000;
|
||||
const laser_line = Line{
|
||||
.p0 = laser.origin,
|
||||
.p1 = laser.origin.add(laser.dir.multiplyScalar(laser_length))
|
||||
};
|
||||
const laser_quad = laser_line.getQuad(laser.size);
|
||||
{
|
||||
var index: usize = 0;
|
||||
while (index < self.lasers.items.len) {
|
||||
var destroy = false;
|
||||
var laser = &self.lasers.items[index];
|
||||
|
||||
for (self.enemies.items) |*enemy| {
|
||||
const enemy_rect = getCenteredRect(enemy.kinetic.pos, enemy.size);
|
||||
if (laser_quad.isRectOverlap(enemy_rect)) {
|
||||
enemy.dead = true;
|
||||
const laser_length = 1000;
|
||||
const laser_line = Line{
|
||||
.p0 = laser.origin,
|
||||
.p1 = laser.origin.add(laser.dir.multiplyScalar(laser_length))
|
||||
};
|
||||
const laser_quad = laser_line.getQuad(laser.size);
|
||||
|
||||
for (self.enemies.items) |*enemy| {
|
||||
const enemy_rect = getCenteredRect(enemy.kinetic.pos, enemy.size);
|
||||
if (laser_quad.isRectOverlap(enemy_rect)) {
|
||||
enemy.dead = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (frame.time_ns > (laser.created_at + laser.duration)) {
|
||||
destroy = true;
|
||||
}
|
||||
|
||||
frame.drawLine(
|
||||
laser_line.p0,
|
||||
laser_line.p1,
|
||||
rgb(200, 20, 255),
|
||||
laser.size
|
||||
);
|
||||
|
||||
if (destroy) {
|
||||
_ = self.lasers.swapRemove(index);
|
||||
} else {
|
||||
index += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
frame.drawLine(
|
||||
laser_line.p0,
|
||||
laser_line.p1,
|
||||
rgb(200, 20, 255),
|
||||
laser.size
|
||||
);
|
||||
{
|
||||
var index: usize = 0;
|
||||
while (index < self.bombs.items.len) {
|
||||
var destroy = false;
|
||||
var bomb = &self.bombs.items[index];
|
||||
bomb.kinetic.update(dt, .{
|
||||
.friction = 0.998
|
||||
});
|
||||
|
||||
if (frame.time_ns >= bomb.explode_at) {
|
||||
destroy = true;
|
||||
|
||||
for (self.enemies.items) |*enemy| {
|
||||
const enemy_rect = getCenteredRect(enemy.kinetic.pos, enemy.size);
|
||||
if (enemy_rect.checkCircleOverlap(bomb.kinetic.pos, bomb.explosion_radius)) {
|
||||
enemy.dead = true;
|
||||
frame.drawCircle(bomb.kinetic.pos, bomb.explosion_radius, rgb(200, 20, 20));
|
||||
}
|
||||
}
|
||||
}
|
||||
frame.drawCircle(bomb.kinetic.pos, bomb.explosion_radius, rgba(200, 20, 20, 0.2));
|
||||
|
||||
const bomb_rect = getCenteredRect(bomb.kinetic.pos, bomb.size);
|
||||
frame.drawRectangle(.{
|
||||
.rect = bomb_rect,
|
||||
.color = rgb(200, 20, 255)
|
||||
});
|
||||
|
||||
if (destroy) {
|
||||
_ = self.bombs.swapRemove(index);
|
||||
} else {
|
||||
index += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (self.enemies.items) |*enemy| {
|
||||
|
||||
@ -230,6 +230,16 @@ 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 });
|
||||
}
|
||||
|
||||
@ -48,6 +48,12 @@ pub const Command = union(enum) {
|
||||
origin: Vec2 = .init(0, 0),
|
||||
};
|
||||
|
||||
pub const DrawCircle = struct {
|
||||
center: Vec2,
|
||||
radius: f32,
|
||||
color: Vec4,
|
||||
};
|
||||
|
||||
set_scissor: Rect,
|
||||
draw_rectangle: DrawRectangle,
|
||||
draw_line: struct { pos1: Vec2, pos2: Vec2, color: Vec4, width: f32 },
|
||||
@ -60,6 +66,7 @@ pub const Command = union(enum) {
|
||||
},
|
||||
push_transformation: struct { translation: Vec2, scale: Vec2 },
|
||||
pop_transformation: void,
|
||||
draw_circle: DrawCircle
|
||||
};
|
||||
|
||||
const Texture = struct {
|
||||
@ -206,6 +213,25 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -472,6 +472,43 @@ pub const Rect = struct {
|
||||
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());
|
||||
|
||||
Loading…
Reference in New Issue
Block a user