space-invade.rs-hack/src/sdl2.rs

197 lines
7.8 KiB
Rust

use std::time::{Duration, SystemTime};
use sdl2::event::Event;
use sdl2::pixels::Color;
use sdl2::keyboard::Keycode;
use sdl2::rect::Rect;
use emulator::memory::Memory;
use std::thread;
use std::sync::Mutex;
use emulator::emulator::{Emulator, WIDTH, HEIGHT};
use emulator::emulator_state::SharedState;
// I replaced GREEN with blue color and WHITE with red color.
// I also made RECTANGLE_SIZE double of it's original value cuz window was too small in my opinion. -Biterr
const RECTANGLE_SIZE: u32 = 4;
const WHITE: Color = Color::RGB(128,0,0);
const BLACK: Color = Color::RGB(0, 0, 0);
const RED: Color = Color::RGB(255, 0, 0);
const GREEN: Color = Color::RGB(0, 0, 255);
pub fn sdl2() -> Result<(), String> {
let sdl_context = sdl2::init()?;
let video_subsystem = sdl_context.video()?;
let window = video_subsystem
.window("", WIDTH as u32 * RECTANGLE_SIZE, HEIGHT as u32 * RECTANGLE_SIZE)
.position_centered()
.resizable()
.build()
.map_err(|e| e.to_string())?;
let mut canvas = window.into_canvas().build().map_err(|e| e.to_string())?;
canvas.clear();
canvas.present();
//
// Spawn the game logic in a separate thread. This logic will communicate with the
// main thread (and therefore, the actual graphics on your screen) via the `SHARED_STATE`
// object returned by the start of the emilator.
//
let shared_state = Emulator::start_emulator();
// Hehe
println!("Recolorised and resized by Biterr");
canvas.clear();
canvas.present();
// Only update the title every one second or so
let mut last_title_update = SystemTime::now();
// Main game loop
let mut event_pump = sdl_context.event_pump()?;
'running: loop {
for event in event_pump.poll_iter() {
//
// Read the keyboard
//
match event {
Event::Quit { .. } | Event::KeyDown { keycode: Some(Keycode::Escape), .. }
=> break 'running,
// Pause / unpause ('p')
Event::KeyDown { keycode: Some(Keycode::P), .. } => {
let mut l = shared_state.lock().unwrap();
if l.is_paused() {
l.unpause();
} else {
l.pause();
}
},
// Insert coin
Event::KeyDown { keycode: Some(Keycode::C), .. } => {
shared_state.lock().unwrap().set_bit_in_1(0, true);
},
Event::KeyUp { keycode: Some(Keycode::C), .. } => {
shared_state.lock().unwrap().set_bit_in_1(0, false);
},
// Start 2 players
Event::KeyDown { keycode: Some(Keycode::Num2), .. } => {
shared_state.lock().unwrap().set_bit_in_1(1, true);
},
Event::KeyUp { keycode: Some(Keycode::Num2), .. } => {
shared_state.lock().unwrap().set_bit_in_1(1, false);
},
// Start 1 player
Event::KeyDown { keycode: Some(Keycode::Num1), .. } => {
shared_state.lock().unwrap().set_bit_in_1(2, true);
},
Event::KeyUp { keycode: Some(Keycode::Num1), .. } => {
shared_state.lock().unwrap().set_bit_in_1(2, false);
},
// Player 1 shot
Event::KeyDown { keycode: Some(Keycode::Space), .. } => {
if shared_state.lock().unwrap().is_paused() {
shared_state.lock().unwrap().unpause();
} else {
shared_state.lock().unwrap().set_bit_in_1(4, true);
}
},
Event::KeyUp { keycode: Some(Keycode::Space), .. } => {
shared_state.lock().unwrap().set_bit_in_1(4, false);
},
// Player 1 move left
Event::KeyDown { keycode: Some(Keycode::Left), .. } => {
shared_state.lock().unwrap().set_bit_in_1(5, true);
},
Event::KeyUp { keycode: Some(Keycode::Left), .. } => {
shared_state.lock().unwrap().set_bit_in_1(5, false);
},
// Player 1 move right
Event::KeyDown { keycode: Some(Keycode::Right), .. } => {
shared_state.lock().unwrap().set_bit_in_1(6, true);
},
Event::KeyUp { keycode: Some(Keycode::Right), .. } => {
shared_state.lock().unwrap().set_bit_in_1(6, false);
},
// Player 2 shot ('s')
Event::KeyDown { keycode: Some(Keycode::S), .. } => {
shared_state.lock().unwrap().set_bit_in_2(4, true);
},
Event::KeyUp { keycode: Some(Keycode::S), .. } => {
shared_state.lock().unwrap().set_bit_in_2(4, false);
},
// Player 2 move left ('a')
Event::KeyDown { keycode: Some(Keycode::A), .. } => {
shared_state.lock().unwrap().set_bit_in_2(5, true);
},
Event::KeyUp { keycode: Some(Keycode::A), .. } => {
shared_state.lock().unwrap().set_bit_in_2(5, false);
},
// Player 2 move right ('d')
Event::KeyDown { keycode: Some(Keycode::D), .. } => {
shared_state.lock().unwrap().set_bit_in_2(6, true);
},
Event::KeyUp { keycode: Some(Keycode::D), .. } => {
shared_state.lock().unwrap().set_bit_in_2(6, false);
},
// If the emulator is paused, any key will unpause it
Event::KeyDown { .. } => {
if shared_state.lock().unwrap().is_paused() {
shared_state.lock().unwrap().unpause();
}
}
_ => {
}
}
}
// ::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 30));
canvas.clear();
//
// Draw the graphic
// Simply map the listener's frame buffer (updated by the main logic in a separate thread)
// to the SDL canvas
//
let graphic_memory = shared_state.lock().unwrap().graphic_memory();
let mut i: usize = 0;
for ix in 0..WIDTH {
for iy in (0..HEIGHT).step_by(8) {
let mut byte = graphic_memory[i];
i += 1;
for b in 0..8 {
let x: i32 = ix as i32 * RECTANGLE_SIZE as i32;
let y: i32 = (HEIGHT as i32 - (iy as i32+ b)) * RECTANGLE_SIZE as i32;
let color = if byte & 1 == 0 { BLACK } else {
if iy > 200 && iy < 220 { RED }
else if iy < 80 { GREEN }
else { WHITE }
};
byte >>= 1;
canvas.set_draw_color(color);
canvas.fill_rect(Rect::new(x, y, RECTANGLE_SIZE as u32, RECTANGLE_SIZE as u32))
.unwrap();
}
}
}
if last_title_update.elapsed().unwrap().gt(&Duration::from_millis(1000)) {
let paused = if shared_state.lock().unwrap().is_paused() { " - Paused" } else { "" };
canvas.window_mut().set_title(
format!("Space Invaders in Rust - Hacked by Biterr - {:.2} Mhz{}",
shared_state.lock().unwrap().get_megahertz(),
paused)
.as_str()).unwrap();
last_title_update = SystemTime::now();
}
canvas.present();
}
Ok(())
}