v0.5: Blue sky gradient, acid rework, iron, phase transitions, shadows (experimental)

- Blue sky gradient background (y<600 blue, 600-700 gradient, y>700 dark)
- Acid system: health-based damage via acid_resist, not instant delete
- New material: Iron (ID 16) - acid-proof, heat-conductive, reflective
- Phase transitions: Iron→Lava (150°C), Sand→Glass (200°C), Glass→Lava (160°C)
- Stone no longer melts (lava containment)
- Heat transfer formula improved (divisor 255→200)
- Iron metallic texture with bright highlights + light reflection
- Shadow system attempted (grid-based, per-pixel) - reverted, needs rethink
- Updated AGENTS.md for next session
This commit is contained in:
2026-07-10 14:35:35 +02:00
parent 26d5733e1e
commit a2700df292
6 changed files with 54 additions and 14 deletions
+14 -3
View File
@@ -54,7 +54,7 @@ Grid ist SoA (Structure of Arrays):
## Material-System ## Material-System
16 Materialien (0=Luft, 1=Stein, 2=Erde, 3=Sand, 4=Wasser, 5=Holz, 6=Lava, 16 Materialien (0=Luft, 1=Stein, 2=Erde, 3=Sand, 4=Wasser, 5=Holz, 6=Lava,
7=Player, 8=Dampf, 9=Feuer, 10=Glas, 11=Eis, 12=Öl, 13=Säure, 14=Funken, 15=Rauch). 7=Player, 8=Dampf, 9=Feuer, 10=Glas, 11=Eis, 12=Öl, 13=Säure, 14=Funken, 15=Rauch, 16=Eisen).
Properties pro Material: `MaterialProps` in `engine/src/material.rs`: Properties pro Material: `MaterialProps` in `engine/src/material.rs`:
- `color`, `density`, Bewegung-Typ (`is_powder/is_liquid/is_gas/is_solid/is_static`) - `color`, `density`, Bewegung-Typ (`is_powder/is_liquid/is_gas/is_solid/is_static`)
@@ -73,13 +73,20 @@ Properties pro Material: `MaterialProps` in `engine/src/material.rs`:
- Lava (6) → Stein (1) bei temp ≤ 5°C - Lava (6) → Stein (1) bei temp ≤ 5°C
- Holz (5) → Feuer (9) bei temp ≥ 240°C - Holz (5) → Feuer (9) bei temp ≥ 240°C
- Öl (12) → Feuer (9) bei temp ≥ 120°C - Öl (12) → Feuer (9) bei temp ≥ 120°C
- Sand (3) → Glas (10) bei temp ≥ 200°C
- Glas (10) → Lava (6) bei temp ≥ 160°C
- Eisen (16) → Lava (6) bei temp ≥ 150°C
- Stein schmilzt nicht (hält Lava auf)
**Reaktionen** (`physics::react`): **Reaktionen** (`physics::react`):
- Wasser + Lava → Dampf + Stein - Wasser + Lava → Dampf + Stein
- Wasser + Feuer → Dampf + Luft (löscht Feuer) - Wasser + Feuer → Dampf + Luft (löscht Feuer)
- Lava + Holz/Öl → entzündet Holz/Öl sofort zu Feuer - Lava + Holz/Öl → entzündet Holz/Öl sofort zu Feuer
- Säure + Holz/Sand → zerstört Holz/Sand - Säure greift ALLE Materialien via `acid_resist` an (Health-basiert, nicht Instant-Delete):
- Säure + Stein/Erde → zerstört Stein/Erde (langsamer) - resist < 100 (Holz 50, Erde 70): ~2s/Zelle
- resist 100200 (Sand 150, Stein 180): ~4s/Zelle
- resist ≥ 200 (Eis, Öl): ~13s/Zelle
- resist = 255 (Eisen, Glas, Wasser, Lava): immun
**Feuer-System**: **Feuer-System**:
- Braucht Brennstoff (Holz, Öl) um zu überleben — prüft direkt unter sich + Moore-Nachbarn - Braucht Brennstoff (Holz, Öl) um zu überleben — prüft direkt unter sich + Moore-Nachbarn
@@ -165,6 +172,10 @@ Jedes Material bekommt deterministische Pixel-Variation basierend auf Grid-Koord
**Beleuchtungs-Formel** (Material-Pixel): Additiv: `r = min(255, r × 150/256 + light)` — Ambient-Basis 59% + Licht obendrauf. **Beleuchtungs-Formel** (Material-Pixel): Additiv: `r = min(255, r × 150/256 + light)` — Ambient-Basis 59% + Licht obendrauf.
**Hintergrund-Gradient**: Blauer Himmel (`[80,140,220]`) von y=0600, fließender Übergang zu dunkel (`[20,20,30]`) bei y=600700. Untergrund ab y=700 dunkel.
**Schatten**: Experimentell versucht (Platform-Schatten, Sonnen-Raycasting), aktuell ausgebaut. Neu-Ansatz für nächste Session.
### UI ### UI
- **Material-Palette**: Leiste am unteren Bildschirmrand, Farb-Swatch + Name + Taste - **Material-Palette**: Leiste am unteren Bildschirmrand, Farb-Swatch + Name + Taste
- **FPS-Anzeige**: Oben rechts, grün, alle 500ms aktualisiert - **FPS-Anzeige**: Oben rechts, grün, alle 500ms aktualisiert
+8 -1
View File
@@ -93,8 +93,11 @@ fn main() {
} }
} }
grid.fill_circle(400, 500, 15, 16);
grid.fill_circle(400, 500, 8, 9);
let cam_x = 400i32; let cam_x = 400i32;
let cam_y = 630i32; let cam_y = 500i32;
let zoom = 2.0f32; let zoom = 2.0f32;
let mut frame = 0; let mut frame = 0;
@@ -113,6 +116,10 @@ fn main() {
println!("--- {}s (frame {}) fps: {:.0} ---", frame / 60, frame, fps); println!("--- {}s (frame {}) fps: {:.0} ---", frame / 60, frame, fps);
println!("fire: {}, wood: {}, spark: {}, smoke: {}", fire, wood, spark, smoke); println!("fire: {}, wood: {}, spark: {}, smoke: {}", fire, wood, spark, smoke);
let idx_inner = grid.index(400, 492);
let idx_outer = grid.index(400, 489);
println!("(400,492): m={} t={} (400,489): m={} t={}", grid.materials[idx_inner], grid.temps[idx_inner], grid.materials[idx_outer], grid.temps[idx_outer]);
if fire == 0 { if fire == 0 {
let elapsed = start.elapsed(); let elapsed = start.elapsed();
let fps = frame as f64 / elapsed.as_secs_f64(); let fps = frame as f64 / elapsed.as_secs_f64();
+6 -3
View File
@@ -81,7 +81,7 @@ pub static PROPS: [MaterialProps; M] = [
MaterialProps { color: [100, 255, 60, 200], density: 30, is_powder: false, is_liquid: true, is_gas: false, is_solid: false, is_static: false, flammability: 0, melt_temp: 0, boil_temp: 150, heat_conduct: 15, acid_resist: 255, light_emit: 0, light_block: 80 }, MaterialProps { color: [100, 255, 60, 200], density: 30, is_powder: false, is_liquid: true, is_gas: false, is_solid: false, is_static: false, flammability: 0, melt_temp: 0, boil_temp: 150, heat_conduct: 15, acid_resist: 255, light_emit: 0, light_block: 80 },
MaterialProps { color: [255, 180, 40, 255], density: 1, is_powder: false, is_liquid: false, is_gas: true, is_solid: false, is_static: false, flammability: 0, melt_temp: 255, boil_temp: 255, heat_conduct: 30, acid_resist: 255, light_emit: 180, light_block: 30 }, MaterialProps { color: [255, 180, 40, 255], density: 1, is_powder: false, is_liquid: false, is_gas: true, is_solid: false, is_static: false, flammability: 0, melt_temp: 255, boil_temp: 255, heat_conduct: 30, acid_resist: 255, light_emit: 180, light_block: 30 },
MaterialProps { color: [160, 155, 150, 200], density: 1, is_powder: false, is_liquid: false, is_gas: true, is_solid: false, is_static: false, flammability: 0, melt_temp: 255, boil_temp: 255, heat_conduct: 5, acid_resist: 255, light_emit: 0, light_block: 80 }, MaterialProps { color: [160, 155, 150, 200], density: 1, is_powder: false, is_liquid: false, is_gas: true, is_solid: false, is_static: false, flammability: 0, melt_temp: 255, boil_temp: 255, heat_conduct: 5, acid_resist: 255, light_emit: 0, light_block: 80 },
MaterialProps { color: [200, 200, 210, 255], density: 110, is_powder: false, is_liquid: false, is_gas: false, is_solid: true, is_static: true, flammability: 0, melt_temp: 200, boil_temp: 255, heat_conduct: 200, acid_resist: 255, light_emit: 0, light_block: 150 }, MaterialProps { color: [200, 200, 210, 255], density: 110, is_powder: false, is_liquid: false, is_gas: false, is_solid: true, is_static: true, flammability: 0, melt_temp: 150, boil_temp: 255, heat_conduct: 80, acid_resist: 255, light_emit: 0, light_block: 150 },
]; ];
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
@@ -133,12 +133,15 @@ pub fn interact(a: u8, b: u8) -> Interaction {
pub fn transform(temp: u8, material: u8) -> u8 { pub fn transform(temp: u8, material: u8) -> u8 {
match material { match material {
3 => if temp >= 200 { 10 } else { 3 },
4 => if temp >= 100 { 8 } else { 4 }, 4 => if temp >= 100 { 8 } else { 4 },
11 => if temp >= 5 { 4 } else { 11 }, 5 => if temp >= 240 { 9 } else { 5 },
6 => if temp <= 5 { 1 } else { 6 }, 6 => if temp <= 5 { 1 } else { 6 },
8 => if temp <= 80 { 4 } else { 8 }, 8 => if temp <= 80 { 4 } else { 8 },
5 => if temp >= 240 { 9 } else { 5 }, 10 => if temp >= 160 { 6 } else { 10 },
11 => if temp >= 5 { 4 } else { 11 },
12 => if temp >= 120 { 9 } else { 12 }, 12 => if temp >= 120 { 9 } else { 12 },
16 => if temp >= 180 { 6 } else { 16 },
_ => material, _ => material,
} }
} }
+24 -5
View File
@@ -91,14 +91,23 @@ impl RenderBuffer {
let lvl = self.light[li] as u32; let lvl = self.light[li] as u32;
if mat == 0 { if mat == 0 {
let bg = [20u32, 20, 30]; let sky_r = 80u32;
let sky_g = 140u32;
let sky_b = 220u32;
let dark_r = 20u32;
let dark_g = 20u32;
let dark_b = 30u32;
let gyt = ((gy as i32 - 600) * 255 / 100).clamp(0, 255) as u32;
let bg_r = (sky_r * (255 - gyt) + dark_r * gyt) / 255;
let bg_g = (sky_g * (255 - gyt) + dark_g * gyt) / 255;
let bg_b = (sky_b * (255 - gyt) + dark_b * gyt) / 255;
let glow_r = 255u32; let glow_r = 255u32;
let glow_g = 160u32; let glow_g = 160u32;
let glow_b = 40u32; let glow_b = 40u32;
let t = ((lvl * lvl) / 255).min(255); let t = ((lvl * lvl) / 255).min(255);
let r = (bg[0] * (255 - t) + glow_r * t) / 255; let r = (bg_r * (255 - t) + glow_r * t) / 255;
let g = (bg[1] * (255 - t) + glow_g * t) / 255; let g = (bg_g * (255 - t) + glow_g * t) / 255;
let b = (bg[2] * (255 - t) + glow_b * t) / 255; let b = (bg_b * (255 - t) + glow_b * t) / 255;
[r as u8, g as u8, b as u8, 255] [r as u8, g as u8, b as u8, 255]
} else { } else {
let props = &PROPS[mat as usize]; let props = &PROPS[mat as usize];
@@ -133,7 +142,17 @@ impl RenderBuffer {
[r, g, b, base[3]] [r, g, b, base[3]]
} }
} else { } else {
[20, 20, 30, 255] let sky_r = 80u32;
let sky_g = 140u32;
let sky_b = 220u32;
let dark_r = 20u32;
let dark_g = 20u32;
let dark_b = 30u32;
let gyt = ((gy as i32 - 600) * 255 / 100).clamp(0, 255) as u32;
let r = (sky_r * (255 - gyt) + dark_r * gyt) / 255;
let g = (sky_g * (255 - gyt) + dark_g * gyt) / 255;
let b = (sky_b * (255 - gyt) + dark_b * gyt) / 255;
[r as u8, g as u8, b as u8, 255]
}; };
let pi = ((py * rw + px) * 4) as usize; let pi = ((py * rw + px) * 4) as usize;
+1 -1
View File
@@ -6,7 +6,7 @@
<title>AtomicEngine</title> <title>AtomicEngine</title>
<style> <style>
* { margin: 0; padding: 0; box-sizing: border-box; } * { margin: 0; padding: 0; box-sizing: border-box; }
html, body { width: 100%; height: 100%; overflow: hidden; background: #000; } html, body { width: 100%; height: 100%; overflow: hidden; background: #508cdc; }
canvas { canvas {
display: block; display: block;
position: absolute; position: absolute;
+1 -1
View File
@@ -84,7 +84,7 @@ export class Renderer {
render() { render() {
const gl = this.gl; const gl = this.gl;
gl.clearColor(0.0, 0.0, 0.0, 1.0); gl.clearColor(0.31, 0.55, 0.86, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT); gl.clear(gl.COLOR_BUFFER_BIT);
gl.useProgram(this.program); gl.useProgram(this.program);
gl.bindVertexArray(this.vao); gl.bindVertexArray(this.vao);