3D isometric renderer: chunked meshes with noise-displaced walls, lit shader with flickering torches, billboard sprites, rotatable/tiltable ortho camera, ray picking

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard ZinkandClaude Opus 5.5 committed 2026-11-02 22:42:10 +01:00
1 parent 91bb91b6ee
commit 220d9543cc
6 files changed
+180 -589

No files matched your search

+17 -11
View File
@@ -3,7 +3,7 @@
use crate::game::*;
use crate::gfx::*;
use crate::map::*;
use crate::render::{minimap_color, View};
use crate::render3d::{minimap_color, Cam};
use crate::sound::SoundBank;
use macroquad::prelude::*;
@@ -49,7 +49,7 @@ pub const TOOLS: [Tool; 12] = [
Tool::Summon,
];
pub const TOOL_KEYS: [&str; 12] = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "Q", "E"];
pub const TOOL_KEYS: [&str; 12] = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "X", "V"];
pub struct ToolInfo {
pub label: &'static str,
@@ -198,7 +198,7 @@ impl Ui {
UiAction::None
}
pub fn draw(&mut self, g: &Game, gfx: &Gfx, view: &View, snd: &SoundBank, info: &[(String, Color)], now: f64) {
pub fn draw(&mut self, g: &Game, gfx: &Gfx, cam: &Cam, snd: &SoundBank, info: &[(String, Color)], now: f64) {
self.rects.clear();
let sw = screen_width();
let sh = screen_height();
@@ -325,10 +325,15 @@ impl Ui {
let (fx, fy) = xy(f);
draw_rectangle(mrx + fx as f32 * ms - 2.0, mry + fy as f32 * ms - 2.0, 5.0, 5.0, RED);
}
// Kamerarahmen
let vw = sw / view.zoom * ms;
let vh = sh / view.zoom * ms;
draw_rectangle_lines(mrx + view.cam_x * ms, mry + view.cam_y * ms, vw, vh, 1.5, WHITE);
// camera footprint on the ground
let corners = [cam.ground_point(0.0, 0.0), cam.ground_point(sw, 0.0), cam.ground_point(sw, sh), cam.ground_point(0.0, sh)];
for k in 0..4 {
let a = corners[k];
let b = corners[(k + 1) % 4];
let clampp = |p: Vec2| vec2(mrx + p.x.clamp(0.0, MW as f32) * ms, mry + p.y.clamp(0.0, MH as f32) * ms);
let (pa, pb) = (clampp(a), clampp(b));
draw_line(pa.x, pa.y, pb.x, pb.y, 1.5, WHITE);
}
// ---------------- Infofeld
if !info.is_empty() {
@@ -415,8 +420,9 @@ impl Ui {
("Linksklick Werkzeug benutzen (Graben/Räume: Rechteck ziehen)", TXT),
("Rechtsklick Einheit aus der Hand absetzen", TXT),
("Rechts ziehen Karte verschieben (auch WASD/Pfeile, Bildrand)", TXT),
("Mitte ziehen Kamera drehen und neigen (auch Q/E, R/F)", TXT),
("Mausrad Zoomen", TXT),
("1-9, 0, Q, E Werkzeug wählen", TXT),
("1-9, 0, X, V Werkzeug wählen", TXT),
("P / Leertaste Pause M Ton an/aus +/- Lautstärke", TXT),
("H Diese Hilfe", TXT),
("", TXT),
@@ -475,9 +481,9 @@ impl Ui {
}
// Infotext für Einheit oder Kachel unter dem Mauszeiger (erste Zeile = Titel)
pub fn hover_info(g: &Game, wx: f32, wy: f32) -> Vec<(String, Color)> {
pub fn hover_info(g: &Game, ent: Option<usize>, tile: Option<(i32, i32)>) -> Vec<(String, Color)> {
let mut out = Vec::new();
if let Some(j) = g.ent_at(wx, wy, false) {
if let Some(j) = ent {
let e = &g.ents[j];
let s = st(e.kind);
out.push((format!("{} (Stufe {})", s.name, e.level), if e.hero { BLUE } else { FRAME_HI }));
@@ -502,7 +508,7 @@ pub fn hover_info(g: &Game, wx: f32, wy: f32) -> Vec<(String, Color)> {
}
return out;
}
let (x, y) = (wx.floor() as i32, wy.floor() as i32);
let Some((x, y)) = tile else { return out };
let Some(t) = g.map.get(x, y) else { return out };
let owner = match t.owner {
Owner::Player => "erobert",