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
|
use ggez::event::EventHandler;
use crate::game::{Game, Status, Field};
use std::sync::{Mutex, Arc, atomic::AtomicU32};
pub struct Gui {
ctx: ggez::Context,
event_loop: ggez::event::EventsLoop,
}
impl Gui {
pub fn new() -> Self {
let (mut ctx, event_loop) =
ggez::ContextBuilder::new("neo x", "natrixaeria")
.window_setup(ggez::conf::WindowSetup::default()
.vsync(true))
.build().unwrap();
Self {
ctx, event_loop,
}
}
pub fn run<G: Game + 'static>(mut game: G) -> std::thread::JoinHandle<()> {
std::thread::spawn(|| Self::new().run_in_thread(game))
}
fn run_in_thread<G: Game + 'static>(&mut self, mut game: G) {
let status = Arc::new(Mutex::new(Some(game.status())));
let jump = Arc::new(AtomicU32::new(0));
let mut handler = GameEventHandler { status: Arc::clone(&status), size: game.size(), jump: Arc::clone(&jump) };
std::thread::spawn(move || {
let mut speed = 85.0;
while let Some(new_status) = game.update() {
if jump.fetch_and(0, std::sync::atomic::Ordering::SeqCst) > 0 {
game.jump();
}
if let Ok(mut lock) = status.lock() {
*lock = Some(new_status);
} else { break; }
std::thread::sleep(std::time::Duration::from_millis(speed as u64));
speed *= 0.9992;
println!("{:04} | {}", game.get_points(), speed);
}
println!("Points: {}", game.get_points());
{ *status.lock().unwrap() = None; }
});
match ggez::event::run(&mut self.ctx, &mut self.event_loop, &mut handler) {
Err(_) => (),
_ => (),
}
}
}
struct GameEventHandler {
status: Arc<Mutex<Option<Status>>>,
size: (u32, u32),
jump: Arc<AtomicU32>,
}
impl GameEventHandler {
fn draw_rect(&mut self, ctx: &mut ggez::Context, translation: [f32; 4], color: ggez::graphics::Color, draw_mode: &ggez::graphics::DrawParam) -> ggez::GameResult<()> {
let rect = ggez::graphics::Mesh::new_rectangle(
ctx,
ggez::graphics::DrawMode::fill(),
ggez::graphics::Rect::new(translation[0], translation[1], translation[2], translation[3]),
color
)?;
ggez::graphics::draw(ctx, &rect, *draw_mode)
}
fn draw_field(&mut self, ctx: &mut ggez::Context, col: u32, row: u32, color: ggez::graphics::Color, draw_mode: &ggez::graphics::DrawParam) -> ggez::GameResult<()> {
let (w, h) = ggez::graphics::size(ctx);
let (rx, ry) = self.size;
let (u, v) = (w / (rx as f32), h / (ry as f32));
let (u, v) = if u < v { (u, u) } else { (v, v) };
let (x, y) = (col as f32 * u, row as f32 * v);
let translation = [ x, y, u, v ];
self.draw_rect(ctx, translation, color, draw_mode)
}
}
impl EventHandler for GameEventHandler {
fn update(&mut self, ctx: &mut ggez::Context) -> ggez::GameResult<()> {
Ok(())
}
fn draw(&mut self, ctx: &mut ggez::Context) -> ggez::GameResult<()> {
let status = { (*self.status.lock().unwrap()).clone() };
if status.is_none() {
println!("exxiittt");
ggez::event::quit(ctx);
return Err(ggez::error::GameError::ResourceLoadError(format!("ending app")));
}
let status = status.unwrap();
let bg = ggez::graphics::BLACK;
let draw_mode = ggez::graphics::DrawParam::new();
ggez::graphics::clear(ctx, bg);
let (cols, rows) = self.size;
for row in 0..rows {
for col in 0..cols {
let color = match status.fields[((rows - row - 1) + col * rows) as usize] {
Field::Air => continue,
Field::Wall => ggez::graphics::Color::from_rgb(100, 100, 100),
Field::Spike => ggez::graphics::Color::from_rgb(200, 50, 6),
};
self.draw_field(ctx, col, row, color, &draw_mode)?;
}
}
let player_color = ggez::graphics::Color::from_rgb(0, 180, 250);
let (x, y) = (status.player[0], status.player[1]);
if rows >= y + 1 {
self.draw_field(ctx, x, rows - y - 1, player_color, &draw_mode)?;
}
ggez::graphics::present(ctx)
}
fn key_down_event(&mut self, _ctx: &mut ggez::Context, keycode: ggez::event::KeyCode, _keymods: ggez::event::KeyMods, _repeat: bool) {
if keycode == ggez::event::KeyCode::Space {
self.jump.store(1, std::sync::atomic::Ordering::SeqCst);
}
}
}
|