feat: asymmetric characters that flip when turning
- Player template is now asymmetric: - Weapon arm extends forward (right side, x=3..4) - Hair flows backward (left side, x=-3..-4) - Cape drapes to the left (x=-3..-4) - Front hand colored as 'weapon' (bright steel) - Goblin template asymmetric: weapon arm extends forward (x=4) - Entity.flip_facing() mirrors all rest_offsets X and body positions - Entity.facing_right field (default true) - Game loop detects mouse crossing player center X and calls flip_facing() - Verlet constraints adapt smoothly to mirrored positions - 'weapon' label added to preview_ascii All 171 tests + 14 scenarios pass.
This commit is contained in:
+15
-11
@@ -46,13 +46,13 @@ impl BodyTemplate {
|
|||||||
p!(0, -5, 40, 30, 50, "eye"),
|
p!(0, -5, 40, 30, 50, "eye"),
|
||||||
p!(-1, -5, 60, 40, 70, "eye"),
|
p!(-1, -5, 60, 40, 70, "eye"),
|
||||||
p!(1, -5, 60, 40, 70, "eye"),
|
p!(1, -5, 60, 40, 70, "eye"),
|
||||||
p!(-2, -6, 120, 80, 40, "hair"),
|
p!(-3, -6, 120, 80, 40, "hair"),
|
||||||
p!(-1, -7, 140, 90, 50, "hair"),
|
p!(-2, -7, 140, 90, 50, "hair"),
|
||||||
|
p!(-1, -7, 150, 100, 55, "hair"),
|
||||||
p!(0, -7, 150, 100, 55, "hair"),
|
p!(0, -7, 150, 100, 55, "hair"),
|
||||||
p!(1, -7, 140, 90, 50, "hair"),
|
p!(1, -7, 140, 90, 50, "hair"),
|
||||||
p!(2, -6, 120, 80, 40, "hair"),
|
p!(-3, -5, 110, 70, 35, "hair"),
|
||||||
p!(-3, -7, 110, 70, 35, "hair"),
|
p!(-4, -5, 100, 60, 30, "hair"),
|
||||||
p!(3, -7, 110, 70, 35, "hair"),
|
|
||||||
p!(-2, -4, 80, 50, 130, "hat"),
|
p!(-2, -4, 80, 50, 130, "hat"),
|
||||||
p!(2, -4, 80, 50, 130, "hat"),
|
p!(2, -4, 80, 50, 130, "hat"),
|
||||||
p!(-1, -5, 90, 55, 140, "hat"),
|
p!(-1, -5, 90, 55, 140, "hat"),
|
||||||
@@ -70,23 +70,25 @@ impl BodyTemplate {
|
|||||||
p!(1, -3, 150, 90, 210, "shirt"),
|
p!(1, -3, 150, 90, 210, "shirt"),
|
||||||
p!(-2, -3, 210, 185, 240, "hand"),
|
p!(-2, -3, 210, 185, 240, "hand"),
|
||||||
p!(2, -3, 210, 185, 240, "hand"),
|
p!(2, -3, 210, 185, 240, "hand"),
|
||||||
|
p!(3, -3, 220, 195, 245, "weapon"),
|
||||||
|
p!(4, -3, 230, 205, 250, "weapon"),
|
||||||
p!(-1, -2, 150, 90, 210, "shirt"),
|
p!(-1, -2, 150, 90, 210, "shirt"),
|
||||||
p!(0, -2, 160, 100, 220, "shirt"),
|
p!(0, -2, 160, 100, 220, "shirt"),
|
||||||
p!(1, -2, 150, 90, 210, "shirt"),
|
p!(1, -2, 150, 90, 210, "shirt"),
|
||||||
p!(-2, -2, 200, 170, 230, "hand"),
|
p!(-2, -2, 200, 170, 230, "hand"),
|
||||||
p!(2, -2, 200, 170, 230, "hand"),
|
p!(2, -2, 200, 170, 230, "hand"),
|
||||||
p!(-3, -2, 80, 50, 130, "cape"),
|
p!(-4, -2, 80, 50, 130, "cape"),
|
||||||
p!(3, -2, 80, 50, 130, "cape"),
|
p!(-3, -2, 75, 45, 120, "cape"),
|
||||||
p!(-1, -1, 150, 90, 210, "shirt"),
|
p!(-1, -1, 150, 90, 210, "shirt"),
|
||||||
p!(0, -1, 160, 100, 220, "shirt"),
|
p!(0, -1, 160, 100, 220, "shirt"),
|
||||||
p!(1, -1, 150, 90, 210, "shirt"),
|
p!(1, -1, 150, 90, 210, "shirt"),
|
||||||
p!(-3, -1, 75, 45, 120, "cape"),
|
p!(-4, -1, 70, 40, 110, "cape"),
|
||||||
p!(3, -1, 75, 45, 120, "cape"),
|
p!(-3, -1, 70, 40, 110, "cape"),
|
||||||
p!(-1, 0, 230, 190, 110, "belt"),
|
p!(-1, 0, 230, 190, 110, "belt"),
|
||||||
p!(0, 0, 240, 200, 120, "belt"),
|
p!(0, 0, 240, 200, 120, "belt"),
|
||||||
p!(1, 0, 230, 190, 110, "belt"),
|
p!(1, 0, 230, 190, 110, "belt"),
|
||||||
p!(-3, 0, 70, 40, 110, "cape"),
|
p!(-4, 0, 60, 35, 100, "cape"),
|
||||||
p!(3, 0, 70, 40, 110, "cape"),
|
p!(-3, 0, 65, 38, 105, "cape"),
|
||||||
p!(-1, 1, 95, 55, 155, "pants"),
|
p!(-1, 1, 95, 55, 155, "pants"),
|
||||||
p!(0, 1, 95, 55, 155, "pants"),
|
p!(0, 1, 95, 55, 155, "pants"),
|
||||||
p!(1, 1, 95, 55, 155, "pants"),
|
p!(1, 1, 95, 55, 155, "pants"),
|
||||||
@@ -145,6 +147,7 @@ impl BodyTemplate {
|
|||||||
p!(2, -3, 110, 180, 85, "hand"),
|
p!(2, -3, 110, 180, 85, "hand"),
|
||||||
p!(-3, -3, 100, 170, 75, "hand"),
|
p!(-3, -3, 100, 170, 75, "hand"),
|
||||||
p!(3, -3, 100, 170, 75, "hand"),
|
p!(3, -3, 100, 170, 75, "hand"),
|
||||||
|
p!(4, -3, 180, 160, 60, "weapon"),
|
||||||
p!(-1, -2, 55, 130, 45, "shirt"),
|
p!(-1, -2, 55, 130, 45, "shirt"),
|
||||||
p!(0, -2, 65, 140, 50, "shirt"),
|
p!(0, -2, 65, 140, 50, "shirt"),
|
||||||
p!(1, -2, 55, 130, 45, "shirt"),
|
p!(1, -2, 55, 130, 45, "shirt"),
|
||||||
@@ -357,6 +360,7 @@ impl BodyTemplate {
|
|||||||
("cape", '>'),
|
("cape", '>'),
|
||||||
("tooth", '.'),
|
("tooth", '.'),
|
||||||
("ear", '<'),
|
("ear", '<'),
|
||||||
|
("weapon", '/'),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
for part in &self.parts {
|
for part in &self.parts {
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ pub struct Entity {
|
|||||||
pub toughness: u32,
|
pub toughness: u32,
|
||||||
pub willpower: u32,
|
pub willpower: u32,
|
||||||
pub counted_for_score: bool,
|
pub counted_for_score: bool,
|
||||||
|
pub facing_right: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for Entity {
|
impl Clone for Entity {
|
||||||
@@ -76,6 +77,7 @@ impl Clone for Entity {
|
|||||||
toughness: self.toughness,
|
toughness: self.toughness,
|
||||||
willpower: self.willpower,
|
willpower: self.willpower,
|
||||||
counted_for_score: self.counted_for_score,
|
counted_for_score: self.counted_for_score,
|
||||||
|
facing_right: self.facing_right,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -111,6 +113,7 @@ impl Entity {
|
|||||||
toughness: 10,
|
toughness: 10,
|
||||||
willpower: 10,
|
willpower: 10,
|
||||||
counted_for_score: false,
|
counted_for_score: false,
|
||||||
|
facing_right: true,
|
||||||
half_w: 3.5,
|
half_w: 3.5,
|
||||||
half_h: 3.0,
|
half_h: 3.0,
|
||||||
}
|
}
|
||||||
@@ -195,6 +198,21 @@ impl Entity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn flip_facing(&mut self) {
|
||||||
|
self.facing_right = !self.facing_right;
|
||||||
|
for off in &mut self.rest_offsets {
|
||||||
|
off.0 = -off.0;
|
||||||
|
}
|
||||||
|
for b in &mut self.bodies {
|
||||||
|
if b.alive {
|
||||||
|
let dx = b.x - self.cx;
|
||||||
|
b.x = self.cx - dx;
|
||||||
|
let old_dx = b.old_x - self.cx;
|
||||||
|
b.old_x = self.cx - old_dx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_horizontal_vel(&mut self, vx: f32) {
|
pub fn set_horizontal_vel(&mut self, vx: f32) {
|
||||||
if self.rigid {
|
if self.rigid {
|
||||||
self.cvx = vx;
|
self.cvx = vx;
|
||||||
|
|||||||
+7
-1
@@ -329,7 +329,13 @@ fn run_gpu_mode<R: GpuRenderer>(title: &str) {
|
|||||||
{
|
{
|
||||||
let (px, _py) = game.player.center(&game.entities);
|
let (px, _py) = game.player.center(&game.entities);
|
||||||
let player_screen_x = ((px as i32 - game.cam_x) as f64) * 8.0 + 4.0;
|
let player_screen_x = ((px as i32 - game.cam_x) as f64) * 8.0 + 4.0;
|
||||||
game.player.facing_right = input.mouse_x >= player_screen_x;
|
let should_face_right = input.mouse_x >= player_screen_x;
|
||||||
|
if should_face_right != game.player.facing_right {
|
||||||
|
if let Some(e) = game.player.entity_mut(&mut game.entities) {
|
||||||
|
e.flip_facing();
|
||||||
|
}
|
||||||
|
game.player.facing_right = should_face_right;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if input.cam_left {
|
if input.cam_left {
|
||||||
|
|||||||
Reference in New Issue
Block a user