Imp in 64x64 when close, 32x32 at normal zoom; detailed sprites in their own texture
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
2d1ed177a7
commit
69a6b13006
9 files changed
+173
-89
No files matched your search
+16
-10
@@ -1563,8 +1563,9 @@ impl R3d {
|
||||
// sprites as billboards
|
||||
// the world's pixel rows (detailed sprites only where they get enough pixels)
|
||||
let world_rows = pix.map_or(screen_height() * screen_dpi_scale(), |(_, th, _)| th as f32);
|
||||
if let Some(mesh) = self.billboards(g, gfx, cam, t, world_rows) {
|
||||
draw_mesh(&mesh);
|
||||
let (small, detailed) = self.billboards(g, gfx, cam, t, world_rows);
|
||||
for mesh in [small, detailed].iter().flatten() {
|
||||
draw_mesh(mesh);
|
||||
}
|
||||
// solid unlit objects (default material, depth tested)
|
||||
gl_use_default_material();
|
||||
@@ -1638,7 +1639,8 @@ impl R3d {
|
||||
self.draw_2d(g, gfx, cam, &m, t);
|
||||
}
|
||||
|
||||
fn billboards(&self, g: &Game, gfx: &Gfx, cam: &Cam, t: f32, world_rows: f32) -> Option<Mesh> {
|
||||
// the units as billboards: the 10x10 sprites and the detailed ones (two textures)
|
||||
fn billboards(&self, g: &Game, gfx: &Gfx, cam: &Cam, t: f32, world_rows: f32) -> (Option<Mesh>, Option<Mesh>) {
|
||||
let (_, r, _) = cam.basis();
|
||||
let toward = cam.eye_dir();
|
||||
let amb = |x: f32, z: f32| {
|
||||
@@ -1656,6 +1658,7 @@ impl R3d {
|
||||
let rg = vec2(r.x, r.z).normalize_or_zero();
|
||||
let tg = vec2(toward.x, toward.z).normalize_or_zero();
|
||||
let mut mb = MB::new();
|
||||
let mut mb_hd = MB::new();
|
||||
let sw = SPRITE_TEX_W;
|
||||
let sh = SPRITE_TEX_H;
|
||||
// detailed sprites only in the high-res style, and only where a sprite's cell (1.2 sizes
|
||||
@@ -1761,19 +1764,24 @@ impl R3d {
|
||||
}
|
||||
let white = e.flash > 0.07;
|
||||
let v = if e.captive != 0 { 0 } else { view };
|
||||
let detailed = hd && w * 1.2 * px_per_tile >= crate::gfx::ACELL as f32 * 0.85;
|
||||
// screen pixels of the cell per texel of a detailed cell (64x64 level), the 32x32
|
||||
// level has two texels per pixel
|
||||
let texel = w * 1.2 * px_per_tile / crate::gfx::HD_CELL as f32;
|
||||
let detailed = hd && texel * 2.0 >= 0.85;
|
||||
let fine = texel >= 0.85;
|
||||
// treasure in a sack on the back; digging as a drawn animation (detailed sprites),
|
||||
// frame by frame with the same rhythm as the swing below
|
||||
let sack = e.carry > 0 && Gfx::has_sack(e.kind);
|
||||
let hacking = e.working && !e.moving && !sleeping && matches!(e.job, Job::Dig(_) | Job::TearBridge(_));
|
||||
let frame = ((ph * 1.3 / std::f32::consts::TAU).rem_euclid(1.0) * crate::gfx::HACK_FRAMES as f32) as u32;
|
||||
let hd = if detailed { Gfx::hd_cell_view(e.kind, white, v, hacking.then_some(frame), sack) } else { None };
|
||||
let hd = if detailed { Gfx::hd_cell_view(e.kind, white, v, hacking.then_some(frame), sack, fine) } else { None };
|
||||
if hd.is_some() && hacking {
|
||||
// the frames swing the pickaxe: no tilting of the whole figure
|
||||
rot = 0.0;
|
||||
lunge = 0.0;
|
||||
}
|
||||
let src = hd.or_else(|| sack.then(|| Gfx::sprite_cell_sack(e.kind, white, e.level, v)).flatten()).unwrap_or_else(|| Gfx::sprite_cell_view(e.kind, white, e.level, v));
|
||||
let (sw, sh) = if hd.is_some() { (crate::gfx::HD_TEX_W, crate::gfx::HD_TEX_H) } else { (sw, sh) };
|
||||
let (mut u0, v0) = (src.x / sw, src.y / sh);
|
||||
let (mut u1, v1) = ((src.x + src.w) / sw, (src.y + src.h) / sh);
|
||||
if mirror {
|
||||
@@ -1813,6 +1821,7 @@ impl R3d {
|
||||
};
|
||||
// the 12x12 cell (sprite with a one pixel border for the gear): the sprite's feet
|
||||
// (bottom of its 11th pixel row) stay on the ground
|
||||
let mb = if hd.is_some() { &mut mb_hd } else { &mut mb };
|
||||
mb.quad(
|
||||
[corner(-w * 0.6, h * 1.1), corner(w * 0.6, h * 1.1), corner(w * 0.6, -h * 0.1), corner(-w * 0.6, -h * 0.1)],
|
||||
[vec2(u0, v0), vec2(u1, v0), vec2(u1, v1), vec2(u0, v1)],
|
||||
@@ -1820,11 +1829,8 @@ impl R3d {
|
||||
[toward; 4],
|
||||
);
|
||||
}
|
||||
if mb.v.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(Mesh { vertices: mb.v, indices: mb.i, texture: Some(gfx.sprites.clone()) })
|
||||
}
|
||||
let mesh = |mb: MB, tex: &Texture2D| if mb.v.is_empty() { None } else { Some(Mesh { vertices: mb.v, indices: mb.i, texture: Some(tex.clone()) }) };
|
||||
(mesh(mb, &gfx.sprites), mesh(mb_hd, &gfx.hd_sprites))
|
||||
}
|
||||
|
||||
fn draw_2d(&self, g: &Game, gfx: &Gfx, cam: &Cam, m: &Mat4, t: f32) {
|
||||
|
||||
Reference in new issue
Block a user