Skip to content

Commit 67788ff

Browse files
committed
feat: boss level
Close #7
1 parent 615871b commit 67788ff

8 files changed

Lines changed: 293 additions & 53 deletions

File tree

assets/boss_1.png

255 KB
Loading

src/components.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ pub struct Mission {
1616
// level difficulty settings
1717
pub enemy_spawn_interval: f32,
1818
pub asteroid_count: usize,
19+
20+
/// If true, this level has a single boss; no asteroids, no other enemies.
21+
pub is_boss_level: bool,
1922
}
2023

2124
pub enum GameState {
@@ -90,6 +93,17 @@ pub struct EnemyShip {
9093
pub enemy_type: EnemyType, // Type of enemy (Regular or Kamikaze)
9194
}
9295

96+
pub struct Boss {
97+
pub pos: Vec2,
98+
pub vel: Vec2,
99+
pub rotation: f32,
100+
pub health: f32,
101+
pub max_health: f32,
102+
pub shoot_timer: f32,
103+
/// How many shots left in current burst (0 = waiting for next burst).
104+
pub burst_shots_left: u32,
105+
}
106+
93107
pub struct Ship {
94108
pub pos: Vec2,
95109
pub vel: Vec2,
@@ -252,6 +266,26 @@ impl EnemyShip {
252266
}
253267
}
254268

269+
impl Boss {
270+
pub fn new() -> Self {
271+
let max_health = 300.0;
272+
Self {
273+
pos: vec2(screen_width() / 2.0, 80.0),
274+
vel: vec2(45.0, 25.0),
275+
rotation: 0.0,
276+
health: max_health,
277+
max_health,
278+
shoot_timer: 0.0,
279+
burst_shots_left: 0,
280+
}
281+
}
282+
283+
pub fn take_damage(&mut self, damage: f32) -> bool {
284+
self.health -= damage;
285+
self.health <= 0.0
286+
}
287+
}
288+
255289
impl Ship {
256290
// Returns true if the game is over
257291
// Damage is first applied to shield if active, then to ship health

src/draw.rs

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::components::{Asteroid, EnemyShip, Engine, Explosion, LootItem, LootType, Ship};
1+
use crate::components::{Asteroid, Boss, EnemyShip, Engine, Explosion, LootItem, LootType, Ship};
22
use crate::resources::Resources;
33
use macroquad::prelude::*;
44
use macroquad::rand::gen_range;
@@ -206,6 +206,46 @@ pub fn draw_enemy(enemy: &EnemyShip, res: &Resources) {
206206
);
207207
}
208208

209+
const BOSS_SIZE: f32 = 120.0;
210+
const BOSS_HP_BAR_HEIGHT: f32 = 8.0;
211+
const BOSS_HP_BAR_GAP: f32 = 8.0;
212+
213+
pub fn draw_boss(boss: &Boss, res: &Resources) {
214+
let size = vec2(BOSS_SIZE, BOSS_SIZE);
215+
let texture = &res.boss_1;
216+
217+
let bar_width = size.x * 1.2;
218+
let bar_left = boss.pos.x - bar_width / 2.0;
219+
let bar_top = boss.pos.y - size.y / 2.0 - BOSS_HP_BAR_GAP - BOSS_HP_BAR_HEIGHT;
220+
221+
draw_rectangle(
222+
bar_left,
223+
bar_top,
224+
bar_width,
225+
BOSS_HP_BAR_HEIGHT,
226+
ENEMY_HP_BAR_BG_COLOR,
227+
);
228+
229+
let ratio = (boss.health / boss.max_health).clamp(0.0, 1.0);
230+
let fill_width = bar_width * ratio;
231+
if fill_width > 0.0 {
232+
let hp_color = Color::new(1.0 - ratio, ratio, 0.0, 1.0);
233+
draw_rectangle(bar_left, bar_top, fill_width, BOSS_HP_BAR_HEIGHT, hp_color);
234+
}
235+
236+
draw_texture_ex(
237+
texture,
238+
boss.pos.x - size.x / 2.0,
239+
boss.pos.y - size.y / 2.0,
240+
WHITE,
241+
DrawTextureParams {
242+
dest_size: Some(size),
243+
rotation: boss.rotation,
244+
..Default::default()
245+
},
246+
);
247+
}
248+
209249
pub fn draw_loot(item: &LootItem, res: &Resources) {
210250
let texture = match item.item_type {
211251
LootType::Scrap(_) => &res.loot_scrap,

0 commit comments

Comments
 (0)