rust_console_game_engine/
noconsole.rs

1use super::KeyState;
2use super::sprite::RustConsoleSprite;
3
4use std::io::Error;
5use std::mem::{swap, MaybeUninit};
6
7pub struct RustConsole {
8    width: usize,
9    height: usize,
10    font_width: i16,
11    font_height: i16,
12    keys: [KeyState; 256],
13    old_key_states: [i16; 256],
14    new_key_states: [i16; 256]
15}
16
17impl RustConsole {
18    pub const FG_BLACK: u16 = 0x0000;
19    pub const FG_DARK_BLUE: u16 = 0x0001; 
20    pub const FG_DARK_GREEN: u16 = 0x0002;
21    pub const FG_DARK_CYAN: u16 = 0x0003;
22    pub const FG_DARK_RED: u16 = 0x0004;
23    pub const FG_DARK_MAGENTA: u16 = 0x0005;
24    pub const FG_DARK_YELLOW: u16 = 0x0006;
25    pub const FG_GREY: u16 = 0x0007;
26    pub const FG_DARK_GREY: u16 = 0x0008;
27    pub const FG_BLUE: u16 = 0x0009;
28    pub const FG_GREEN: u16 = 0x000a;
29    pub const FG_CYAN: u16 = 0x000b;
30    pub const FG_RED: u16 = 0x000c;
31    pub const FG_MAGENTA: u16 = 0x000d;
32    pub const FG_YELLOW: u16 = 0x000e;
33    pub const FG_WHITE: u16 = 0x000f;
34    pub const BG_BLACK: u16 = 0x0000;
35    pub const BG_DARK_BLUE: u16 = 0x0010;
36    pub const BG_DARK_GREEN: u16 = 0x0020;
37    pub const BG_DARK_CYAN: u16 = 0x0030;
38    pub const BG_DARK_RED: u16 = 0x0040;
39    pub const BG_DARK_MAGENTA: u16 = 0x0050;
40    pub const BG_DARK_YELLOW: u16 = 0x0060;
41    pub const BG_GREY: u16 = 0x0070;
42    pub const BG_DARK_GREY: u16 = 0x0080;
43    pub const BG_BLUE: u16 = 0x0090;
44    pub const BG_GREEN: u16 = 0x00a0;
45    pub const BG_CYAN: u16 = 0x00b0;
46    pub const BG_RED: u16 = 0x00c0;
47    pub const BG_MAGENTA: u16 = 0x00d0;
48    pub const BG_YELLOW: u16 = 0x00e0;
49    pub const BG_WHITE: u16 = 0x00f0;
50    
51    pub const PIXEL_SOLID: char = '\u{2588}';
52    pub const PIXEL_THREEQUARTER: char = '\u{2593}';
53    pub const PIXEL_HALF: char  = '\u{2592}';
54    pub const PIXEL_QUARTER: char = '\u{2591}';
55
56    pub const VK_UP: u32 = 38u32;
57    pub const VK_DOWN: u32 = 40u32;
58    pub const VK_LEFT: u32 = 37u32;
59    pub const VK_RIGHT: u32 = 39u32;
60    
61    pub(crate) fn new(width: usize, height: usize, font_width: i16, font_height: i16) -> Result<RustConsole, Error> {
62        Ok(RustConsole {
63            width,
64            height,
65            font_width,
66            font_height,
67            keys: [KeyState { pressed: false, released: false, held: false }; 256],
68            old_key_states: unsafe { MaybeUninit::<[i16; 256]>::zeroed().assume_init() },
69            new_key_states: unsafe { MaybeUninit::<[i16; 256]>::zeroed().assume_init() }
70        })
71    }
72    
73    pub(crate) fn write_output(&mut self) {}
74    
75    pub(crate) fn update_key_states(&mut self) {
76        for v_key in 0..256 {
77            self.new_key_states[v_key] = 0;
78            
79            self.keys[v_key].pressed = false;
80            self.keys[v_key].released = false;
81            
82            if self.new_key_states[v_key] != self.old_key_states[v_key] {
83                if self.new_key_states[v_key] != 0 {
84                    self.keys[v_key].pressed = !self.keys[v_key].held;
85                    self.keys[v_key].held = true;
86                } else {
87                    self.keys[v_key].released = true;
88                    self.keys[v_key].held = false;
89                }
90            }
91            
92            self.old_key_states[v_key] = self.new_key_states[v_key];
93        }
94    }
95    
96    pub(crate) fn flush_input_events(&self) {}
97    
98    pub(crate) fn handle_input_events(&mut self) {}
99    
100    pub fn width(&self) -> usize { self.width }
101    
102    pub fn height(&self) -> usize { self.height }
103    
104    pub fn font_width(&self) -> i16 { self.font_width }
105    
106    pub fn font_height(&self) -> i16 { self.font_height }
107    
108    pub fn key(&self, v_key: usize) -> KeyState { self.keys[v_key] }
109
110    pub fn set_title(&self, _title: String) {}
111    
112    pub fn resize(&mut self, new_width: usize, new_height: usize, new_font_width: i16, new_font_height: i16) {
113        self.flush_input_events();
114        
115        self.width = new_width;
116        self.height = new_height;
117        self.font_width = new_font_width;
118        self.font_height = new_font_height;
119    }
120    
121    pub fn clear(&mut self) {}
122    
123    pub fn draw(&mut self, _x: usize, _y: usize, _c: char, _col: u16) {}
124    
125    pub fn fill(&mut self, x1: usize, y1: usize, x2: usize, y2: usize, c: char, col: u16) {
126        for x in x1..x2 {
127            for y in y1..y2 {
128                self.draw(x, y, c, col);
129            }
130        }
131    }
132    
133    pub fn draw_string(&mut self, _x: usize, _y: usize, _s: &str, _col: u16) {}
134    
135    pub fn draw_string_alpha(&mut self, _x: usize, _y: usize, _s: &str, _col: u16) {}
136    
137    pub fn draw_line(&mut self, x1: usize, y1: usize, x2: usize, y2: usize, c: char, col: u16) {
138        let dx = x2 as isize - x1 as isize;
139        let dy = y2 as isize - y1 as isize;
140        let dx1 = dx.abs();
141        let dy1 = dy.abs();
142        let mut px = 2 * dy1 - dx1;
143        let mut py = 2 * dx1 - dy1;
144        if dy1 <= dx1 {
145            let (mut x, mut y, xe) = if dx >= 0 {
146                (x1, y1, x2)
147            } else {
148                (x2, y2, x1)
149            };
150            
151            self.draw(x, y, c, col);
152            
153            for _i in x..xe {
154                x += 1;
155                if px < 0 {
156                    px = px + 2 * dy1;
157                } else {
158                    if (dx < 0 && dy < 0) || (dx > 0 && dy > 0) {
159                        y += 1;
160                    } else {
161                        y -= 1;
162                    }
163                    px = px + 2 * (dy1 - dx1);
164                }
165                self.draw(x, y, c, col);
166            }
167        } else {
168            let (mut x, mut y, ye) = if dy >= 0 {
169                (x1, y1, y2)
170            } else {
171                (x2, y2, y1)
172            };
173            
174            self.draw(x, y, c, col);
175            
176            for _i in y..ye {
177                y += 1;
178                if py <= 0 {
179                    py = py + 2 * dx1;
180                } else {
181                    if (dx < 0 && dy < 0) || (dx > 0 && dy > 0) {
182                        x += 1;
183                    } else {
184                        x -= 1;
185                    }
186                    py = py + 2 * (dx1 - dy1);
187                }
188                self.draw(x, y, c, col);
189            }
190        }
191    }
192    
193    pub fn draw_triangle(&mut self, x1: usize, y1: usize, x2: usize, y2: usize, x3: usize, y3: usize, c: char, col: u16) {
194        self.draw_line(x1, y1, x2, y2, c, col);
195        self.draw_line(x2, y2, x3, y3, c, col);
196        self.draw_line(x3, y3, x1, y1, c, col);
197    }
198    
199    pub fn fill_triangle(&mut self, mut x1: usize, mut y1: usize, mut x2: usize, mut y2: usize, mut x3: usize, mut y3: usize, c: char, col: u16) {
200        let mut changed1 = false;
201        let mut changed2 = false;
202        
203        // sort vertices
204        if y1 > y2 {
205            swap(&mut y1, &mut y2);
206            swap(&mut x1, &mut x2);
207        }
208        if y1 > y3 {
209            swap(&mut y1, &mut y3);
210            swap(&mut x1, &mut x3);
211        }
212        if y2 > y3 {
213            swap(&mut y2, &mut y3);
214            swap(&mut x2, &mut x3);
215        }
216        
217        // starting points
218        let mut t1x = x1 as isize;
219        let mut t2x = x1 as isize;
220        let mut y = y1;
221        let mut dx1 = x2 as isize - x1 as isize;
222        let signx1 = if dx1 < 0 {
223            dx1 = -dx1;
224            -1
225        } else {
226            1
227        };
228        let mut dy1 = y2 as isize - y1 as isize;
229        
230        let mut dx2 = x3 as isize - x1 as isize;
231        let signx2 = if dx2 < 0 {
232            dx2 = -dx2;
233            -1
234        } else {
235            1
236        };
237        let mut dy2 = y3 as isize - y1 as isize;
238        
239        if dy1 > dx1 {
240            swap(&mut dx1, & mut dy1);
241            changed1 = true;
242        }
243        if dy2 > dx2 {
244            swap(&mut dy2, &mut dx2);
245            changed2 = true;
246        }
247        
248        let mut e2 = dx2 >> 1;
249        if y1 != y2 { // not flat top, so do the first half
250            let mut e1 = dx1 >> 1;
251            
252            for mut i in 0..dx1 {
253                let mut t1xp = 0;
254                let mut t2xp = 0;
255                let (mut minx, mut maxx) = if t1x < t2x {
256                    (t1x, t2x)
257                } else {
258                    (t2x, t1x)
259                };
260                // process first line until y value is about to change
261                'first_line_1: while i < dx1 {
262                    i += 1;
263                    e1 += dy1;
264                    while e1 >= dx1 {
265                        e1 -= dx1;
266                        if changed1 {
267                            t1xp = signx1;
268                        } else {
269                            break 'first_line_1;
270                        }
271                    }
272                    if changed1 {
273                        break 'first_line_1;
274                    } else {
275                        t1x += signx1;
276                    }
277                }
278                
279                // process second line until y value is about to change
280                'second_line_1: loop {
281                    e2 += dy2;
282                    while e2 >= dx2 {
283                        e2 -= dx2;
284                        if changed2 {
285                            t2xp = signx2;
286                        } else {
287                            break 'second_line_1;
288                        }
289                    }
290                    if changed2 {
291                        break 'second_line_1;
292                    } else {
293                        t2x += signx2;
294                    }
295                }
296                
297                if minx > t1x {
298                    minx = t1x;
299                }
300                if minx > t2x {
301                    minx = t2x;
302                }
303                if maxx < t1x {
304                    maxx = t1x;
305                }
306                if maxx < t2x {
307                    maxx = t2x;
308                }
309                // draw line from min to max points found on the y
310                for j in minx..=maxx {
311                    self.draw(j as usize, y, c, col);
312                }
313                
314                // now increase y
315                if !changed1 {
316                    t1x += signx1;
317                }
318                t1x += t1xp;
319                if !changed2 {
320                    t2x += signx2;
321                }
322                t2x += t2xp;
323                y += 1;
324                if y == y2 {
325                    break;
326                }
327            }
328        }
329        
330        // now, do the second half
331        dx1 = x3 as isize - x2 as isize;
332        let signx1 = if dx1 < 0 {
333            dx1 = -dx1;
334            -1
335        } else {
336            1
337        };
338        dy1 = y3 as isize - y2 as isize;
339        t1x = x2 as isize;
340        
341        if dy1 > dx1 {
342            swap(&mut dy1, &mut dx1);
343            changed1 = true;
344        } else {
345            changed1 = false;
346        }
347        let mut e1 = dx1 >> 1;
348        
349        for mut i in 0..=dx1 {
350            let mut t1xp = 0;
351            let mut t2xp = 0;
352            let (mut minx, mut maxx) = if t1x < t2x {
353                (t1x, t2x)
354            } else {
355                (t2x, t1x)
356            };
357            // process first line until y value is about to change
358            'first_line_2: while i < dx1 {
359                e1 += dy1;
360                while e1 >= dx1 {
361                    e1 -= dx1;
362                    if changed1 {
363                        t1xp = signx1;
364                        break;
365                    } else {
366                        break 'first_line_2;
367                    }
368                }
369                if changed1 {
370                    break 'first_line_2;
371                } else {
372                    t1x += signx1;
373                }
374                if i < dx1 {
375                    i += 1;
376                }
377            }
378            
379            // process second line until y value is about to change
380            'second_line_2: while t2x != x3 as isize {
381                e2 += dy2;
382                while e2 >= dx2 {
383                    e2 -= dx2;
384                    if changed2 {
385                        t2xp = signx2;
386                    } else {
387                        break 'second_line_2;
388                    }
389                }
390                if changed2 {
391                    break 'second_line_2;
392                } else {
393                    t2x += signx2;
394                }
395            }
396            
397            if minx > t1x {
398                minx = t1x;
399            }
400            if minx > t2x {
401                minx = t2x;
402            }
403            if maxx < t1x {
404                maxx = t1x;
405            }
406            if maxx < t2x {
407                maxx = t2x;
408            }
409            // draw line from min to max points found on the y
410            for j in minx..=maxx {
411                self.draw(j as usize, y, c, col);
412            }
413            
414            // now increase y
415            if !changed1 {
416                t1x += signx1;
417            }
418            t1x += t1xp;
419            if !changed2 {
420                t2x += signx2;
421            }
422            t2x += t2xp;
423            y += 1;
424            if y > y3 {
425                return;
426            }
427        }
428    }
429    
430    pub fn draw_circle(&mut self, xc: usize, yc: usize, r: usize, c: char, col: u16) {
431        let mut x = 0;
432        let mut y = r;
433        let mut p = 3 - 2 * r as isize;
434        if r == 0 { return; }
435        
436        while y >= x {
437            self.draw(xc - x, yc - y, c, col); // upper left left
438            self.draw(xc - y, yc - x, c, col); // upper upper left
439            self.draw(xc + y, yc - x, c, col); // upper upper right
440            self.draw(xc + x, yc - y, c, col); // upper right right
441            self.draw(xc - x, yc + y, c, col); // lower left left
442            self.draw(xc - y, yc + x, c, col); // lower lower left
443            self.draw(xc + y, yc + x, c, col); // lower lower right
444            self.draw(xc + x, yc + y, c, col); // lower right right
445            if p < 0 {
446                p += 4 * x as isize + 6;
447                x += 1;
448            } else {
449                p += 4 * (x as isize - y as isize) + 10;
450                x += 1;
451                y -= 1;
452            }
453        }
454    }
455
456    pub fn fill_circle(&mut self, xc: usize, yc: usize, r: usize, c: char, col: u16) {
457        let mut x = 0;
458        let mut y = r;
459        let mut p = 3 - 2 * r as isize;
460        if r == 0 { return; }
461        
462        while y >= x {
463            for i in xc - x..=xc + x {
464                self.draw(i, yc - y, c, col);
465            }
466            for i in xc - y..=xc + y {
467                self.draw(i, yc - x, c, col);
468            }
469            for i in xc - x..=xc + x {
470                self.draw(i, yc + y, c, col);
471            }
472            for i in xc - y..=xc + y {
473                self.draw(i, yc + x, c, col);
474            }
475
476            if p < 0 {
477                p += 4 * x as isize + 6;
478                x += 1;
479            } else {
480                p += 4 * (x as isize - y as isize) + 10;
481                x += 1;
482                y -= 1;
483            }
484        }
485    }
486
487    pub fn draw_sprite(&mut self, x: usize, y: usize, sprite: &RustConsoleSprite) {
488        for i in 0..sprite.width() {
489            for j in 0..sprite.height() {
490                if sprite.get_glyph(i, j) != ' ' {
491                    self.draw(x + i, y + j, sprite.get_glyph(i, j), sprite.get_color(i, j));
492                }
493            }
494        }
495    }
496}