1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
use crate::color::Palette;
use crate::color::db32::{ORANGE, YELLOW};
use crate::gfx;
use crate::sprite::Sprite;
use crate::{GAME_H, GAME_W};
use aseprite::AsepriteFile;
use glam::{IVec2, Vec2};
const FIRE_COOLDOWN: u32 = 12;
const MOUSE_MAX: f32 = 2.0;
#[derive(Default)]
pub struct Player {
cooldown: u32,
pos: Vec2,
step: Vec2,
speed: f32,
sprite: Sprite,
}
impl Player {
pub fn new(sprites: &AsepriteFile, speed: f32) -> Self {
let cooldown = 0;
let pos = Vec2::new(GAME_W as f32 / 2.0, GAME_H as f32 / 2.0);
let step = Vec2::ZERO;
let sprite = Sprite::from_ase(sprites, "player");
Self {
cooldown,
pos,
step,
speed,
sprite,
}
}
pub fn win_anim(&mut self, t: u32) {
let before = self.pos;
if t < 40 {
self.pos.y += 0.3;
} else {
self.pos.y -= ((t - 40) as f32 * 0.25).min(8.0);
}
self.step = self.pos - before;
}
pub fn pos(&self) -> Vec2 {
self.pos
}
pub fn size(&self) -> Vec2 {
self.sprite.size.as_vec2()
}
pub fn try_fire(&mut self) -> Option<Vec2> {
(self.cooldown == 0).then(|| {
self.cooldown = FIRE_COOLDOWN;
self.pos + Vec2::new(self.sprite.size.x as f32 / 2.0, 0.0)
})
}
pub fn update(&mut self, direction: IVec2, mouse: Vec2) {
let before = self.pos;
self.cooldown = self.cooldown.saturating_sub(1);
let dir = direction.as_vec2().normalize_or_zero();
self.pos += dir * self.speed + mouse.clamp_length_max(MOUSE_MAX);
let w = self.sprite.size.x as f32;
let h = self.sprite.size.y as f32;
self.pos.x = self.pos.x.clamp(0.0, GAME_W as f32 - w);
self.pos.y = self.pos.y.clamp(0.0, GAME_H as f32 - h);
self.step = self.pos - before;
}
pub fn draw(&self, frame: &mut [u32], palette: &Palette, a: f32, tick: u32) {
let pos = (self.pos - self.step * (1.0 - a)).round().as_ivec2();
self.sprite.draw_at(frame, palette, pos);
if self.step.length_squared() > 0.01 {
let flame = if (tick / 4).is_multiple_of(2) {
ORANGE
} else {
YELLOW
};
let exhaust = [flame, flame];
let nozzle = pos + IVec2::new(self.sprite.size.x / 2, self.sprite.size.y);
gfx::blit(frame, palette, &exhaust, nozzle, 1, 0);
}
}
}
|