add bomb
This commit is contained in:
parent
ba264d7bc5
commit
c9543c72ad
@ -76,6 +76,13 @@ const Laser = struct {
|
|||||||
duration: Nanoseconds
|
duration: Nanoseconds
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const Bomb = struct {
|
||||||
|
kinetic: Kinetic,
|
||||||
|
size: f32,
|
||||||
|
explode_at: Nanoseconds,
|
||||||
|
explosion_radius: f32
|
||||||
|
};
|
||||||
|
|
||||||
const Enemy = struct {
|
const Enemy = struct {
|
||||||
kinetic: Kinetic,
|
kinetic: Kinetic,
|
||||||
speed: f32,
|
speed: f32,
|
||||||
@ -126,6 +133,7 @@ enemies: std.ArrayList(Enemy) = .empty,
|
|||||||
player: Player = .{},
|
player: Player = .{},
|
||||||
bullets: std.ArrayList(Bullet) = .empty,
|
bullets: std.ArrayList(Bullet) = .empty,
|
||||||
lasers: std.ArrayList(Laser) = .empty,
|
lasers: std.ArrayList(Laser) = .empty,
|
||||||
|
bombs: std.ArrayList(Bomb) = .empty,
|
||||||
|
|
||||||
pickups: std.ArrayList(Pickup) = .empty,
|
pickups: std.ArrayList(Pickup) = .empty,
|
||||||
next_pickup_spawn_at: Nanoseconds,
|
next_pickup_spawn_at: Nanoseconds,
|
||||||
@ -164,6 +172,7 @@ pub fn deinit(self: *CombatScreen) void {
|
|||||||
self.pickups.deinit(self.gpa);
|
self.pickups.deinit(self.gpa);
|
||||||
self.spawned_waves.deinit(self.gpa);
|
self.spawned_waves.deinit(self.gpa);
|
||||||
self.lasers.deinit(self.gpa);
|
self.lasers.deinit(self.gpa);
|
||||||
|
self.bombs.deinit(self.gpa);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spawnEnemy(self: *CombatScreen) !void {
|
pub fn spawnEnemy(self: *CombatScreen) !void {
|
||||||
@ -360,6 +369,15 @@ pub fn tick(self: *CombatScreen, state: *State, frame: *Engine.Frame) !TickResul
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
.bomb => {
|
.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 => {
|
.laser => {
|
||||||
try self.lasers.append(self.gpa, .{
|
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;
|
var index: usize = 0;
|
||||||
const laser_line = Line{
|
while (index < self.lasers.items.len) {
|
||||||
.p0 = laser.origin,
|
var destroy = false;
|
||||||
.p1 = laser.origin.add(laser.dir.multiplyScalar(laser_length))
|
var laser = &self.lasers.items[index];
|
||||||
};
|
|
||||||
const laser_quad = laser_line.getQuad(laser.size);
|
|
||||||
|
|
||||||
for (self.enemies.items) |*enemy| {
|
const laser_length = 1000;
|
||||||
const enemy_rect = getCenteredRect(enemy.kinetic.pos, enemy.size);
|
const laser_line = Line{
|
||||||
if (laser_quad.isRectOverlap(enemy_rect)) {
|
.p0 = laser.origin,
|
||||||
enemy.dead = true;
|
.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,
|
var index: usize = 0;
|
||||||
laser_line.p1,
|
while (index < self.bombs.items.len) {
|
||||||
rgb(200, 20, 255),
|
var destroy = false;
|
||||||
laser.size
|
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| {
|
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 {
|
pub fn drawRectangle(self: *Frame, opts: GraphicsCommand.DrawRectangle) void {
|
||||||
self.pushGraphicsCommand(.{ .draw_rectangle = opts });
|
self.pushGraphicsCommand(.{ .draw_rectangle = opts });
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,6 +48,12 @@ pub const Command = union(enum) {
|
|||||||
origin: Vec2 = .init(0, 0),
|
origin: Vec2 = .init(0, 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const DrawCircle = struct {
|
||||||
|
center: Vec2,
|
||||||
|
radius: f32,
|
||||||
|
color: Vec4,
|
||||||
|
};
|
||||||
|
|
||||||
set_scissor: Rect,
|
set_scissor: Rect,
|
||||||
draw_rectangle: DrawRectangle,
|
draw_rectangle: DrawRectangle,
|
||||||
draw_line: struct { pos1: Vec2, pos2: Vec2, color: Vec4, width: f32 },
|
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 },
|
push_transformation: struct { translation: Vec2, scale: Vec2 },
|
||||||
pop_transformation: void,
|
pop_transformation: void,
|
||||||
|
draw_circle: DrawCircle
|
||||||
};
|
};
|
||||||
|
|
||||||
const Texture = struct {
|
const Texture = struct {
|
||||||
@ -206,6 +213,25 @@ pub fn drawCommand(command: Command) void {
|
|||||||
font_context.setColor(color);
|
font_context.setColor(color);
|
||||||
font_context.drawText(opts.pos.x * font_resolution_scale.x, opts.pos.y * font_resolution_scale.y, opts.text);
|
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;
|
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 {
|
pub fn hasOverlap(lhs: Rect, rhs: Rect) bool {
|
||||||
return (lhs.left() < rhs.right() and lhs.right() > rhs.left()) and
|
return (lhs.left() < rhs.right() and lhs.right() > rhs.left()) and
|
||||||
(lhs.top() < rhs.bottom() and lhs.bottom() > rhs.top());
|
(lhs.top() < rhs.bottom() and lhs.bottom() > rhs.top());
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user