1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use crate::render::TerminalRenderer;
use crossterm::style::Color;
use std::io;
pub struct MoonSystem {
phase: f64, // 0.0 = New, 0.25 = First Quarter, 0.5 = Full, 0.75 = Last Quarter
x: u16,
y: u16,
}
impl MoonSystem {
pub fn new(terminal_width: u16, terminal_height: u16) -> Self {
Self {
phase: 0.5,
x: (terminal_width / 4) + 10,
y: (terminal_height / 4) + 2,
}
}
#[allow(dead_code)]
pub fn set_phase(&mut self, phase: f64) {
self.phase = phase;
}
pub fn update(&mut self, terminal_width: u16, terminal_height: u16) {
self.x = (terminal_width / 4 * 3).min(terminal_width.saturating_sub(15));
self.y = (terminal_height / 4).max(2);
}
pub fn render(&self, renderer: &mut TerminalRenderer) -> io::Result<()> {
let step = (self.phase * 8.0).round() as usize % 8;
let art = match step {
0 => vec![
// NEW MOON (Invisible)
" ",
" ",
" ",
" ",
" ",
" ",
],
1 => vec![
// WAXING CRESCENT (Thin, mostly edge)
" . ",
" . `. ",
" : ",
" : ",
" . .' ",
" ` ",
],
2 => vec![
// FIRST QUARTER (Right Half - Solid)
" _ ",
" |~ `. ",
" |~~~~: ",
" |~~~~: ",
" |~ .' ",
" |-' ",
],
3 => vec![
// WAXING GIBBOUS (Mostly full, textured)
" ..._ ",
" .'~~~~`. ",
" |~~~~o~~~: ",
" |~.~~~~o~: ",
" `.~~~~~' ",
" `...-' ",
],
4 => vec![
// FULL MOON (Full Circle, textured with craters)
" _..._ ",
" .'~o~~~`. ",
" :~~~~~o~~~: ",
" :~~o~~~~.~: ",
" `.~~~~~o~.' ",
" `-...-' ",
],
5 => vec![
// WANING GIBBOUS
" _... ",
" .'~~~~`. ",
" :~~~o~~~~| ",
" :~o~~~~.~| ",
" `.~~~~~.' ",
" `-...-' ",
],
6 => vec![
// LAST QUARTER
" _ ",
" .' ~| ",
" :~~~~| ",
" :~~~~| ",
" `.~ | ",
" `-| ",
],
7 => vec![
// WANING CRESCENT
" . ",
" .' . ",
" : ",
" : ",
" '. . ",
" ` ",
],
_ => vec![],
};
for (i, line) in art.iter().enumerate() {
let y = self.y + i as u16;
for (j, ch) in line.chars().enumerate() {
if ch == ' ' {
continue; // Transparent (Sky)
}
let x = self.x + j as u16;
if ch == '~' {
// Opaque Moon Body (hides stars) - Render as space but overwrite what's there
renderer.render_char(x, y, ' ', Color::White)?;
} else {
// Texture/Outline
renderer.render_char(x, y, ch, Color::White)?;
}
}
}
Ok(())
}
}