Smooth camera and unit motion: display positions, camera target smoothing, pan speed setting
This commit is contained in:
1 parent
583c3fcdaf
commit
eb11cca8cb
10 files changed
+107
-23
No files matched your search
@@ -225,6 +225,7 @@ set.volume = Effekt-Lautstärke
|
|||||||
set.music = Musik-Lautstärke
|
set.music = Musik-Lautstärke
|
||||||
set.mute = Stumm
|
set.mute = Stumm
|
||||||
set.rotate_speed = Drehgeschwindigkeit
|
set.rotate_speed = Drehgeschwindigkeit
|
||||||
|
set.pan_speed = Kamerageschwindigkeit
|
||||||
set.zoom_speed = Zoomgeschwindigkeit
|
set.zoom_speed = Zoomgeschwindigkeit
|
||||||
set.edge_scroll = Bildschirmrand-Scrollen
|
set.edge_scroll = Bildschirmrand-Scrollen
|
||||||
set.invert = Mausdrehung umkehren
|
set.invert = Mausdrehung umkehren
|
||||||
|
|||||||
@@ -226,6 +226,7 @@ set.volume = Sound volume
|
|||||||
set.music = Music volume
|
set.music = Music volume
|
||||||
set.mute = Mute
|
set.mute = Mute
|
||||||
set.rotate_speed = Rotation speed
|
set.rotate_speed = Rotation speed
|
||||||
|
set.pan_speed = Pan speed
|
||||||
set.zoom_speed = Zoom speed
|
set.zoom_speed = Zoom speed
|
||||||
set.edge_scroll = Screen edge scrolling
|
set.edge_scroll = Screen edge scrolling
|
||||||
set.invert = Invert mouse rotation
|
set.invert = Invert mouse rotation
|
||||||
|
|||||||
+36
@@ -288,12 +288,20 @@ pub struct Ent {
|
|||||||
pub target: Option<u8>, // attackers: side whose core (or gate) they march on
|
pub target: Option<u8>, // attackers: side whose core (or gate) they march on
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub chained: bool, // a lone creature chained in a sealed cave: joins when the cave is claimed
|
pub chained: bool, // a lone creature chained in a sealed cave: joins when the cave is claimed
|
||||||
|
#[serde(skip, default = "zero_f32")]
|
||||||
|
pub disp_x: f32, // smoothed screen position (not part of the saved or synced world state)
|
||||||
|
#[serde(skip, default = "zero_f32")]
|
||||||
|
pub disp_y: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn yes() -> bool {
|
fn yes() -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn zero_f32() -> f32 {
|
||||||
|
0.0
|
||||||
|
}
|
||||||
|
|
||||||
impl Ent {
|
impl Ent {
|
||||||
fn dummy() -> Ent {
|
fn dummy() -> Ent {
|
||||||
Ent {
|
Ent {
|
||||||
@@ -350,6 +358,8 @@ impl Ent {
|
|||||||
side: 0,
|
side: 0,
|
||||||
target: None,
|
target: None,
|
||||||
chained: false,
|
chained: false,
|
||||||
|
disp_x: 0.0,
|
||||||
|
disp_y: 0.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn tile(&self) -> usize {
|
pub fn tile(&self) -> usize {
|
||||||
@@ -1129,6 +1139,8 @@ impl Game {
|
|||||||
e.hero = hero;
|
e.hero = hero;
|
||||||
e.x = x;
|
e.x = x;
|
||||||
e.y = y;
|
e.y = y;
|
||||||
|
e.disp_x = x;
|
||||||
|
e.disp_y = y;
|
||||||
e.level = level;
|
e.level = level;
|
||||||
e.max_hp = s.hp * (1.0 + 0.15 * (level - 1) as f32);
|
e.max_hp = s.hp * (1.0 + 0.15 * (level - 1) as f32);
|
||||||
e.hp = e.max_hp;
|
e.hp = e.max_hp;
|
||||||
@@ -1178,6 +1190,30 @@ impl Game {
|
|||||||
|
|
||||||
// ---------------------------------------------------------------- update
|
// ---------------------------------------------------------------- update
|
||||||
|
|
||||||
|
// smoothed positions for the screen only: the simulation stays fixed-step and deterministic
|
||||||
|
pub fn smooth_display(&mut self, dt: f32) {
|
||||||
|
if dt <= 0.0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let k = (1.0 - (-22.0 * dt).exp()).clamp(0.0, 1.0);
|
||||||
|
for e in self.ents.iter_mut() {
|
||||||
|
if e.disp_x == 0.0 && e.disp_y == 0.0 {
|
||||||
|
e.disp_x = e.x;
|
||||||
|
e.disp_y = e.y;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let dx = e.x - e.disp_x;
|
||||||
|
let dy = e.y - e.disp_y;
|
||||||
|
if dx * dx + dy * dy > 4.0 {
|
||||||
|
e.disp_x = e.x;
|
||||||
|
e.disp_y = e.y;
|
||||||
|
} else {
|
||||||
|
e.disp_x += dx * k;
|
||||||
|
e.disp_y += dy * k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn update(&mut self, dt: f32) {
|
pub fn update(&mut self, dt: f32) {
|
||||||
let mut steps = 0usize;
|
let mut steps = 0usize;
|
||||||
let cmds = if self.netplay.is_some() {
|
let cmds = if self.netplay.is_some() {
|
||||||
|
|||||||
+8
-3
@@ -394,6 +394,7 @@ impl App {
|
|||||||
self.game = l.game;
|
self.game = l.game;
|
||||||
if let Some(c) = l.camera {
|
if let Some(c) = l.camera {
|
||||||
self.cam = c;
|
self.cam = c;
|
||||||
|
self.cam.snap();
|
||||||
}
|
}
|
||||||
if let Some(s) = l.settings {
|
if let Some(s) = l.settings {
|
||||||
self.settings = s;
|
self.settings = s;
|
||||||
@@ -778,7 +779,7 @@ async fn main() {
|
|||||||
if playing {
|
if playing {
|
||||||
let cam = &mut app.cam;
|
let cam = &mut app.cam;
|
||||||
let (right, fwd) = cam.ground_axes();
|
let (right, fwd) = cam.ground_axes();
|
||||||
let pan = cam.zoom * 0.9 * dt;
|
let pan = cam.zoom * keys.pan_speed.max(0.25) * dt;
|
||||||
let move_cam = |dx: f32, dz: f32, cam: &mut Cam| {
|
let move_cam = |dx: f32, dz: f32, cam: &mut Cam| {
|
||||||
let d = right * dx + fwd * dz;
|
let d = right * dx + fwd * dz;
|
||||||
cam.tx += d.x;
|
cam.tx += d.x;
|
||||||
@@ -1134,6 +1135,9 @@ async fn main() {
|
|||||||
}
|
}
|
||||||
app.cam.tx = app.cam.tx.clamp(0.0, mw() as f32);
|
app.cam.tx = app.cam.tx.clamp(0.0, mw() as f32);
|
||||||
app.cam.tz = app.cam.tz.clamp(0.0, mh() as f32);
|
app.cam.tz = app.cam.tz.clamp(0.0, mh() as f32);
|
||||||
|
app.cam.rx = app.cam.rx.clamp(0.0, mw() as f32);
|
||||||
|
app.cam.rz = app.cam.rz.clamp(0.0, mh() as f32);
|
||||||
|
app.cam.update_render(dt);
|
||||||
|
|
||||||
if settings_changed {
|
if settings_changed {
|
||||||
apply_settings(&app.settings, &mut r3d);
|
apply_settings(&app.settings, &mut r3d);
|
||||||
@@ -1167,10 +1171,11 @@ async fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
app.game.smooth_display(dt);
|
||||||
let hear = app.cam.zoom * 1.2;
|
let hear = app.cam.zoom * 1.2;
|
||||||
let (right, _) = app.cam.ground_axes();
|
let (right, _) = app.cam.ground_axes();
|
||||||
for ev in app.game.events.drain(..) {
|
for ev in app.game.events.drain(..) {
|
||||||
sounds.play(ev, vec2(app.cam.tx, app.cam.tz), right, hear, now);
|
sounds.play(ev, vec2(app.cam.rx, app.cam.rz), right, hear, now);
|
||||||
}
|
}
|
||||||
// a won mission goes into the campaign progress (with the carry-over)
|
// a won mission goes into the campaign progress (with the carry-over)
|
||||||
if let (Some(i), false) = (app.game.mission.as_ref().map(|m| m.index), app.recorded) {
|
if let (Some(i), false) = (app.game.mission.as_ref().map(|m| m.index), app.recorded) {
|
||||||
@@ -1195,7 +1200,7 @@ async fn main() {
|
|||||||
| Some(Page::Account)
|
| Some(Page::Account)
|
||||||
| Some(Page::Bestiary { from_title: true, .. })
|
| Some(Page::Bestiary { from_title: true, .. })
|
||||||
);
|
);
|
||||||
music.update(&app.game, on_title, (app.cam.tx, app.cam.tz));
|
music.update(&app.game, on_title, (app.cam.rx, app.cam.rz));
|
||||||
for m in app.game.msgs.drain(..) {
|
for m in app.game.msgs.drain(..) {
|
||||||
if app.settings.voice && voice::speaks(m.key) {
|
if app.settings.voice && voice::speaks(m.key) {
|
||||||
voice.say(&i18n::trf(m.key, &m.args), now, 12);
|
voice.say(&i18n::trf(m.key, &m.args), now, 12);
|
||||||
|
|||||||
+5
-1
@@ -41,6 +41,7 @@ pub enum Item {
|
|||||||
MusicVolume,
|
MusicVolume,
|
||||||
Mute,
|
Mute,
|
||||||
RotateSpeed,
|
RotateSpeed,
|
||||||
|
PanSpeed,
|
||||||
ZoomSpeed,
|
ZoomSpeed,
|
||||||
EdgeScroll,
|
EdgeScroll,
|
||||||
InvertMouse,
|
InvertMouse,
|
||||||
@@ -59,7 +60,7 @@ fn tab_items(tab: usize) -> &'static [Item] {
|
|||||||
use Item::*;
|
use Item::*;
|
||||||
match tab {
|
match tab {
|
||||||
0 => &[Language, Volume, MusicVolume, Mute, Voice],
|
0 => &[Language, Volume, MusicVolume, Mute, Voice],
|
||||||
1 => &[RotateSpeed, ZoomSpeed, EdgeScroll, InvertMouse],
|
1 => &[RotateSpeed, PanSpeed, ZoomSpeed, EdgeScroll, InvertMouse],
|
||||||
2 => &[Outlines, WallDetail, Lights, UiScale, RenderScale],
|
2 => &[Outlines, WallDetail, Lights, UiScale, RenderScale],
|
||||||
3 => &[GameSpeed, Hints, TouchUi],
|
3 => &[GameSpeed, Hints, TouchUi],
|
||||||
_ => &[],
|
_ => &[],
|
||||||
@@ -73,6 +74,7 @@ fn item_label(it: Item) -> String {
|
|||||||
Item::MusicVolume => "set.music",
|
Item::MusicVolume => "set.music",
|
||||||
Item::Mute => "set.mute",
|
Item::Mute => "set.mute",
|
||||||
Item::RotateSpeed => "set.rotate_speed",
|
Item::RotateSpeed => "set.rotate_speed",
|
||||||
|
Item::PanSpeed => "set.pan_speed",
|
||||||
Item::ZoomSpeed => "set.zoom_speed",
|
Item::ZoomSpeed => "set.zoom_speed",
|
||||||
Item::EdgeScroll => "set.edge_scroll",
|
Item::EdgeScroll => "set.edge_scroll",
|
||||||
Item::InvertMouse => "set.invert",
|
Item::InvertMouse => "set.invert",
|
||||||
@@ -104,6 +106,7 @@ fn item_value(it: Item, s: &Settings) -> String {
|
|||||||
Item::Mute => onoff(s.muted),
|
Item::Mute => onoff(s.muted),
|
||||||
Item::Voice => onoff(s.voice),
|
Item::Voice => onoff(s.voice),
|
||||||
Item::RotateSpeed => pct(s.rotate_speed),
|
Item::RotateSpeed => pct(s.rotate_speed),
|
||||||
|
Item::PanSpeed => pct(s.pan_speed),
|
||||||
Item::ZoomSpeed => pct(s.zoom_speed),
|
Item::ZoomSpeed => pct(s.zoom_speed),
|
||||||
Item::EdgeScroll => onoff(s.edge_scroll),
|
Item::EdgeScroll => onoff(s.edge_scroll),
|
||||||
Item::InvertMouse => onoff(s.invert_mouse),
|
Item::InvertMouse => onoff(s.invert_mouse),
|
||||||
@@ -162,6 +165,7 @@ fn item_change(it: Item, s: &mut Settings, d: i32) {
|
|||||||
Item::Mute => s.muted = !s.muted,
|
Item::Mute => s.muted = !s.muted,
|
||||||
Item::Voice => s.voice = !s.voice,
|
Item::Voice => s.voice = !s.voice,
|
||||||
Item::RotateSpeed => s.rotate_speed = step(s.rotate_speed, d, 0.25, 2.5, 0.25),
|
Item::RotateSpeed => s.rotate_speed = step(s.rotate_speed, d, 0.25, 2.5, 0.25),
|
||||||
|
Item::PanSpeed => s.pan_speed = step(s.pan_speed, d, 0.25, 2.5, 0.25),
|
||||||
Item::ZoomSpeed => s.zoom_speed = step(s.zoom_speed, d, 0.25, 2.5, 0.25),
|
Item::ZoomSpeed => s.zoom_speed = step(s.zoom_speed, d, 0.25, 2.5, 0.25),
|
||||||
Item::EdgeScroll => s.edge_scroll = !s.edge_scroll,
|
Item::EdgeScroll => s.edge_scroll = !s.edge_scroll,
|
||||||
Item::InvertMouse => s.invert_mouse = !s.invert_mouse,
|
Item::InvertMouse => s.invert_mouse = !s.invert_mouse,
|
||||||
|
|||||||
+3
-3
@@ -165,15 +165,15 @@ pub fn draw_props_solid(g: &Game, cam: &Cam, t: f32) {
|
|||||||
}
|
}
|
||||||
// creatures in chains: an iron post with chains to the creature
|
// creatures in chains: an iron post with chains to the creature
|
||||||
for e in g.ents.iter().filter(|e| e.alive && e.chained) {
|
for e in g.ents.iter().filter(|e| e.alive && e.chained) {
|
||||||
if (e.x as i32) < x0 || (e.x as i32) > x1 || (e.y as i32) < z0 || (e.y as i32) > z1 {
|
if (e.disp_x as i32) < x0 || (e.disp_x as i32) > x1 || (e.disp_y as i32) < z0 || (e.disp_y as i32) > z1 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let post = vec3(e.x.floor() + 0.5, 0.0, e.y.floor() + 0.15);
|
let post = vec3(e.disp_x.floor() + 0.5, 0.0, e.disp_y.floor() + 0.15);
|
||||||
cube(post + vec3(0.0, 0.35, 0.0), vec3(0.08, 0.7, 0.08), rgb(70, 70, 78, 0.6));
|
cube(post + vec3(0.0, 0.35, 0.0), vec3(0.08, 0.7, 0.08), rgb(70, 70, 78, 0.6));
|
||||||
for n in 0..6 {
|
for n in 0..6 {
|
||||||
let f = n as f32 / 6.0;
|
let f = n as f32 / 6.0;
|
||||||
let side = if n % 2 == 0 { 0.08 } else { -0.08 };
|
let side = if n % 2 == 0 { 0.08 } else { -0.08 };
|
||||||
let p = post.lerp(vec3(e.x + side, 0.25, e.y), f) + vec3(0.0, 0.3 * (1.0 - f) + 0.05 * (f * 3.14).sin(), 0.0);
|
let p = post.lerp(vec3(e.disp_x + side, 0.25, e.disp_y), f) + vec3(0.0, 0.3 * (1.0 - f) + 0.05 * (f * 3.14).sin(), 0.0);
|
||||||
cube(p, vec3(0.05, 0.05, 0.05), rgb(120, 120, 130, 0.6));
|
cube(p, vec3(0.05, 0.05, 0.05), rgb(120, 120, 130, 0.6));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+48
-13
@@ -26,11 +26,46 @@ pub struct Cam {
|
|||||||
pub yaw: f32,
|
pub yaw: f32,
|
||||||
pub pitch: f32,
|
pub pitch: f32,
|
||||||
pub zoom: f32, // visible world height in tiles (orthographic)
|
pub zoom: f32, // visible world height in tiles (orthographic)
|
||||||
|
#[serde(skip, default = "zero_f32")]
|
||||||
|
pub rx: f32, // smoothed look-at target used by the screen (world x)
|
||||||
|
#[serde(skip, default = "zero_f32")]
|
||||||
|
pub rz: f32, // smoothed look-at target used by the screen (world z = map y)
|
||||||
|
#[serde(skip, default = "cam_uninit")]
|
||||||
|
pub render_init: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn zero_f32() -> f32 {
|
||||||
|
0.0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cam_uninit() -> bool {
|
||||||
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Cam {
|
impl Cam {
|
||||||
pub fn new(tx: f32, tz: f32) -> Cam {
|
pub fn new(tx: f32, tz: f32) -> Cam {
|
||||||
Cam { tx, tz, yaw: 0.785, pitch: 0.6155, zoom: 18.0 }
|
Cam { tx, tz, yaw: 0.785, pitch: 0.6155, zoom: 18.0, rx: tx, rz: tz, render_init: true }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn snap(&mut self) {
|
||||||
|
self.rx = self.tx;
|
||||||
|
self.rz = self.tz;
|
||||||
|
self.render_init = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_render(&mut self, dt: f32) {
|
||||||
|
if !self.render_init {
|
||||||
|
self.snap();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let dist = (self.tx - self.rx).abs() + (self.tz - self.rz).abs();
|
||||||
|
if dist > self.zoom.max(1.0) {
|
||||||
|
self.snap();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let k = (1.0 - (-28.0 * dt.max(0.0)).exp()).clamp(0.0, 1.0);
|
||||||
|
self.rx += (self.tx - self.rx) * k;
|
||||||
|
self.rz += (self.tz - self.rz) * k;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eye_dir(&self) -> Vec3 {
|
pub fn eye_dir(&self) -> Vec3 {
|
||||||
@@ -38,7 +73,7 @@ impl Cam {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn target(&self) -> Vec3 {
|
fn target(&self) -> Vec3 {
|
||||||
vec3(self.tx, 0.0, self.tz)
|
vec3(self.rx, 0.0, self.rz)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn camera(&self) -> Camera3D {
|
pub fn camera(&self) -> Camera3D {
|
||||||
@@ -990,7 +1025,7 @@ impl R3d {
|
|||||||
if !e.alive || e.held || (player_only && e.hero) {
|
if !e.alive || e.held || (player_only && e.hero) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let s = Cam::project(&m, vec3(e.x, 0.3, e.y));
|
let s = Cam::project(&m, vec3(e.disp_x, 0.3, e.disp_y));
|
||||||
let d = s.distance(vec2(sx, sy));
|
let d = s.distance(vec2(sx, sy));
|
||||||
if d < bd {
|
if d < bd {
|
||||||
bd = d;
|
bd = d;
|
||||||
@@ -1231,7 +1266,7 @@ impl R3d {
|
|||||||
if mirror {
|
if mirror {
|
||||||
std::mem::swap(&mut u0, &mut u1);
|
std::mem::swap(&mut u0, &mut u1);
|
||||||
}
|
}
|
||||||
let a = amb(e.x, e.y) * if sleeping || e.captive == 1 { 0.6 } else { 1.0 };
|
let a = amb(e.disp_x, e.disp_y) * if sleeping || e.captive == 1 { 0.6 } else { 1.0 };
|
||||||
// spell looks: stone grey, plague green, see-through when invisible
|
// spell looks: stone grey, plague green, see-through when invisible
|
||||||
let alpha = if e.invis > 0.0 { 0.35 } else { 1.0 };
|
let alpha = if e.invis > 0.0 { 0.35 } else { 1.0 };
|
||||||
let c = if white {
|
let c = if white {
|
||||||
@@ -1247,7 +1282,7 @@ impl R3d {
|
|||||||
};
|
};
|
||||||
// pulled towards the camera: unchanged on screen (orthographic), but walls behind
|
// pulled towards the camera: unchanged on screen (orthographic), but walls behind
|
||||||
// the unit no longer cut into the sprite
|
// the unit no longer cut into the sprite
|
||||||
let base = vec3(e.x, bob, e.y) + toward * 0.45 + r * (lunge * fwd);
|
let base = vec3(e.disp_x, bob, e.disp_y) + toward * 0.45 + r * (lunge * fwd);
|
||||||
let (sr, cr) = rot.sin_cos();
|
let (sr, cr) = rot.sin_cos();
|
||||||
let corner = |dx: f32, dy: f32| {
|
let corner = |dx: f32, dy: f32| {
|
||||||
let (dx, dy) = (dx * sx, dy * sy);
|
let (dx, dy) = (dx * sx, dy * sy);
|
||||||
@@ -1288,7 +1323,7 @@ impl R3d {
|
|||||||
}
|
}
|
||||||
let big = matches!(e.kind, EK::Ogre | EK::Paladin | EK::Jailer | EK::Chainbreaker | EK::Wyrm | EK::Gargoyle | EK::Giant);
|
let big = matches!(e.kind, EK::Ogre | EK::Paladin | EK::Jailer | EK::Chainbreaker | EK::Wyrm | EK::Gargoyle | EK::Giant);
|
||||||
let lift = if flies(e.kind) && !(matches!(e.job, Job::Sleep(_)) && !e.moving) { 0.45 } else { 0.0 };
|
let lift = if flies(e.kind) && !(matches!(e.job, Job::Sleep(_)) && !e.moving) { 0.45 } else { 0.0 };
|
||||||
let head = proj(vec3(e.x, lift + if big { 0.9 } else { 0.72 }, e.y));
|
let head = proj(vec3(e.disp_x, lift + if big { 0.9 } else { 0.72 }, e.disp_y));
|
||||||
// bar width in block characters, depending on the zoom
|
// bar width in block characters, depending on the zoom
|
||||||
let cols = ((px_per_tile * 0.6 / cw) as usize).clamp(3, 8);
|
let cols = ((px_per_tile * 0.6 / cw) as usize).clamp(3, 8);
|
||||||
if (e.hp < e.max_hp || e.hero) && e.captive == 0 {
|
if (e.hp < e.max_hp || e.hero) && e.captive == 0 {
|
||||||
@@ -1320,7 +1355,7 @@ impl R3d {
|
|||||||
gfx.glyph(b'z', head.x + cw * 2.0, head.y - GH * S() - rise, S(), Color::new(0.8, 0.85, 1.0, 1.0 - k));
|
gfx.glyph(b'z', head.x + cw * 2.0, head.y - GH * S() - rise, S(), Color::new(0.8, 0.85, 1.0, 1.0 - k));
|
||||||
}
|
}
|
||||||
if e.carry > 0 {
|
if e.carry > 0 {
|
||||||
let p = proj(vec3(e.x, 0.35, e.y));
|
let p = proj(vec3(e.disp_x, 0.35, e.disp_y));
|
||||||
gfx.glyph(0x0F, p.x + cw * 2.0, p.y - GH * small, small, Color::from_rgba(250, 210, 60, 255));
|
gfx.glyph(0x0F, p.x + cw * 2.0, p.y - GH * small, small, Color::from_rgba(250, 210, 60, 255));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1385,7 +1420,7 @@ fn draw_gear_glow(g: &Game, cam: &Cam, t: f32) {
|
|||||||
for e in g.ents.iter().filter(|e| gear_shown(e) && e.level >= 9) {
|
for e in g.ents.iter().filter(|e| gear_shown(e) && e.level >= 9) {
|
||||||
let w = sprite_size(e.kind);
|
let w = sprite_size(e.kind);
|
||||||
let lift = if flies(e.kind) { 0.45 } else { 0.0 };
|
let lift = if flies(e.kind) { 0.45 } else { 0.0 };
|
||||||
let base = vec3(e.x, lift, e.y) + toward * 0.5;
|
let base = vec3(e.disp_x, lift, e.disp_y) + toward * 0.5;
|
||||||
let c = if e.hero { Color::new(0.8, 0.9, 1.0, 0.8) } else { Color::new(1.0, 0.8, 0.3, 0.8) };
|
let c = if e.hero { Color::new(0.8, 0.9, 1.0, 0.8) } else { Color::new(1.0, 0.8, 0.3, 0.8) };
|
||||||
let y = w * 1.12 + (t * 2.0 + e.anim).sin() * 0.02;
|
let y = w * 1.12 + (t * 2.0 + e.anim).sin() * 0.02;
|
||||||
for k in 0..8 {
|
for k in 0..8 {
|
||||||
@@ -1394,7 +1429,7 @@ fn draw_gear_glow(g: &Game, cam: &Cam, t: f32) {
|
|||||||
line3(base + vec3(a0.cos() * 0.12, y, a0.sin() * 0.12), base + vec3(a1.cos() * 0.12, y, a1.sin() * 0.12), 0.025, c);
|
line3(base + vec3(a0.cos() * 0.12, y, a0.sin() * 0.12), base + vec3(a1.cos() * 0.12, y, a1.sin() * 0.12), 0.025, c);
|
||||||
}
|
}
|
||||||
if e.level >= 10 {
|
if e.level >= 10 {
|
||||||
disc(vec3(e.x, floor_y(g, e.x, e.y) + 0.015, e.y), 0.42 + 0.03 * (t * 3.0).sin(), Color::new(c.r, c.g, c.b, 0.18), 16);
|
disc(vec3(e.disp_x, floor_y(g, e.disp_x, e.disp_y) + 0.015, e.disp_y), 0.42 + 0.03 * (t * 3.0).sin(), Color::new(c.r, c.g, c.b, 0.18), 16);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2090,8 +2125,8 @@ fn draw_shadows(g: &Game) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let r = if matches!(e.kind, EK::Ogre | EK::Paladin | EK::Jailer | EK::Chainbreaker | EK::Giant) { 0.32 } else { 0.24 };
|
let r = if matches!(e.kind, EK::Ogre | EK::Paladin | EK::Jailer | EK::Chainbreaker | EK::Giant) { 0.32 } else { 0.24 };
|
||||||
let fy = floor_y(g, e.x, e.y);
|
let fy = floor_y(g, e.disp_x, e.disp_y);
|
||||||
disc(vec3(e.x, fy + 0.012, e.y), r, Color::new(0.0, 0.0, 0.0, 0.4), 12);
|
disc(vec3(e.disp_x, fy + 0.012, e.disp_y), r, Color::new(0.0, 0.0, 0.0, 0.4), 12);
|
||||||
let rc = if e.captive != 0 {
|
let rc = if e.captive != 0 {
|
||||||
Color::new(0.6, 0.6, 0.6, 0.6)
|
Color::new(0.6, 0.6, 0.6, 0.6)
|
||||||
} else if e.dwarf() {
|
} else if e.dwarf() {
|
||||||
@@ -2109,7 +2144,7 @@ fn draw_shadows(g: &Game) {
|
|||||||
} else {
|
} else {
|
||||||
Color::new(0.95, 0.3, 0.35, 0.7)
|
Color::new(0.95, 0.3, 0.35, 0.7)
|
||||||
};
|
};
|
||||||
ring(vec3(e.x, fy + 0.02, e.y), r + 0.03, rc);
|
ring(vec3(e.disp_x, fy + 0.02, e.disp_y), r + 0.03, rc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2190,7 +2225,7 @@ fn draw_traps_solid(g: &Game, t: f32) {
|
|||||||
}
|
}
|
||||||
CARRIED => {
|
CARRIED => {
|
||||||
if let Some(e) = g.ents.iter().find(|e| e.id + 1 == tr.carrier) {
|
if let Some(e) = g.ents.iter().find(|e| e.id + 1 == tr.carrier) {
|
||||||
trap_crate(vec3(e.x, 0.42, e.y));
|
trap_crate(vec3(e.disp_x, 0.42, e.disp_y));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ARMED => {
|
ARMED => {
|
||||||
|
|||||||
@@ -139,6 +139,7 @@ pub struct Settings {
|
|||||||
pub voice: bool, // Crookfinger's babbling voice
|
pub voice: bool, // Crookfinger's babbling voice
|
||||||
// camera
|
// camera
|
||||||
pub rotate_speed: f32,
|
pub rotate_speed: f32,
|
||||||
|
pub pan_speed: f32,
|
||||||
pub zoom_speed: f32,
|
pub zoom_speed: f32,
|
||||||
pub edge_scroll: bool,
|
pub edge_scroll: bool,
|
||||||
pub invert_mouse: bool,
|
pub invert_mouse: bool,
|
||||||
@@ -168,6 +169,7 @@ impl Default for Settings {
|
|||||||
muted: false,
|
muted: false,
|
||||||
voice: true,
|
voice: true,
|
||||||
rotate_speed: 1.0,
|
rotate_speed: 1.0,
|
||||||
|
pan_speed: 1.25,
|
||||||
zoom_speed: 1.0,
|
zoom_speed: 1.0,
|
||||||
edge_scroll: true,
|
edge_scroll: true,
|
||||||
invert_mouse: false,
|
invert_mouse: false,
|
||||||
|
|||||||
@@ -479,7 +479,7 @@ impl Ui {
|
|||||||
UiAction::Consumed
|
UiAction::Consumed
|
||||||
}
|
}
|
||||||
TBtn::OvRow(id) => match g.ents.iter().find(|e| e.id == id) {
|
TBtn::OvRow(id) => match g.ents.iter().find(|e| e.id == id) {
|
||||||
Some(e) => UiAction::MinimapJump(e.x, e.y),
|
Some(e) => UiAction::MinimapJump(e.disp_x, e.disp_y),
|
||||||
None => UiAction::Consumed,
|
None => UiAction::Consumed,
|
||||||
},
|
},
|
||||||
TBtn::Tool(i) if !g.tool_allowed(i) => {
|
TBtn::Tool(i) if !g.tool_allowed(i) => {
|
||||||
@@ -779,7 +779,7 @@ impl Ui {
|
|||||||
Color::new(0.4, 0.6, 1.0, 1.0)
|
Color::new(0.4, 0.6, 1.0, 1.0)
|
||||||
}
|
}
|
||||||
} else if e.kind == EK::Worker { Color::new(1.0, 0.6, 0.3, 1.0) } else { Color::new(1.0, 0.25, 0.25, 1.0) };
|
} else if e.kind == EK::Worker { Color::new(1.0, 0.6, 0.3, 1.0) } else { Color::new(1.0, 0.25, 0.25, 1.0) };
|
||||||
draw_rectangle((mrx + e.x.floor() * ms).floor(), (mry + e.y.floor() * ms).floor(), dot, dot, c);
|
draw_rectangle((mrx + e.disp_x.floor() * ms).floor(), (mry + e.disp_y.floor() * ms).floor(), dot, dot, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(f) = g.flag {
|
if let Some(f) = g.flag {
|
||||||
|
|||||||
Reference in new issue
Block a user