Compare commits

..

5 Commits

12 changed files with 90 additions and 51 deletions

View File

@@ -1,4 +1,8 @@
[target.wasm32-unknown-emscripten] [target.wasm32-unknown-emscripten]
rustflags = [ rustflags = [
"--use-preload-plugins --preload-file assets -s USE_SDL=2 -s USE_SDL_IMAGE=2 -s ASSERTIONS=1", "-O", "-C", "link-args=-O2 --profiling",
#"-C", "link-args=-O3 --closure 1",
"-C", "link-args=-sASYNCIFY -sALLOW_MEMORY_GROWTH=1",
"-C", "link-args=-sUSE_SDL=2 -sUSE_SDL_IMAGE=2 -sSDL2_IMAGE_FORMATS=['png']",
"-C", "link-args=--preload-file assets/ -lidbfs.js",
] ]

View File

@@ -11,8 +11,8 @@ jobs:
steps: steps:
- uses: actions/checkout@v2 # repo checkout - uses: actions/checkout@v2 # repo checkout
- uses: mymindstorm/setup-emsdk@v11 # setup emscripten toolchain - uses: mymindstorm/setup-emsdk@v11 # setup emscripten toolchain
# with: with:
# version: 3.1.35 version: 1.39.20
- uses: actions-rs/toolchain@v1 # get rust toolchain for wasm - uses: actions-rs/toolchain@v1 # get rust toolchain for wasm
with: with:
toolchain: stable toolchain: stable

View File

@@ -2,18 +2,20 @@
#[cfg(target_os = "emscripten")] #[cfg(target_os = "emscripten")]
pub mod emscripten { pub mod emscripten {
use std::cell::RefCell; use std::cell::RefCell;
use std::ptr::null_mut;
use std::os::raw::{c_int, c_void, c_char, c_float};
use std::ffi::{CStr, CString}; use std::ffi::{CStr, CString};
use std::os::raw::{c_char, c_float, c_int, c_void};
use std::ptr::null_mut;
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
type em_callback_func = unsafe extern "C" fn(); type em_callback_func = unsafe extern "C" fn();
extern "C" { extern "C" {
// void emscripten_set_main_loop(em_callback_func func, int fps, int simulate_infinite_loop) // void emscripten_set_main_loop(em_callback_func func, int fps, int simulate_infinite_loop)
pub fn emscripten_set_main_loop(func: em_callback_func, pub fn emscripten_set_main_loop(
func: em_callback_func,
fps: c_int, fps: c_int,
simulate_infinite_loop: c_int); simulate_infinite_loop: c_int,
);
pub fn emscripten_cancel_main_loop(); pub fn emscripten_cancel_main_loop();
pub fn emscripten_pause_main_loop(); pub fn emscripten_pause_main_loop();
@@ -23,17 +25,20 @@ pub mod emscripten {
thread_local!(static MAIN_LOOP_CALLBACK: RefCell<*mut c_void> = RefCell::new(null_mut())); thread_local!(static MAIN_LOOP_CALLBACK: RefCell<*mut c_void> = RefCell::new(null_mut()));
pub fn set_main_loop_callback<F>(callback: F) pub fn set_main_loop_callback<F>(callback: F)
where F: FnMut() where
F: FnMut(),
{ {
MAIN_LOOP_CALLBACK MAIN_LOOP_CALLBACK.with(|log| {
.with(|log| { *log.borrow_mut() = &callback as *const _ as *mut c_void; }); *log.borrow_mut() = &callback as *const _ as *mut c_void;
});
unsafe { unsafe {
emscripten_set_main_loop(wrapper::<F>, -1, 1); emscripten_set_main_loop(wrapper::<F>, -1, 1);
} }
unsafe extern "C" fn wrapper<F>() unsafe extern "C" fn wrapper<F>()
where F: FnMut() where
F: FnMut(),
{ {
MAIN_LOOP_CALLBACK.with(|z| { MAIN_LOOP_CALLBACK.with(|z| {
let closure = *z.borrow_mut() as *mut F; let closure = *z.borrow_mut() as *mut F;

View File

@@ -74,7 +74,10 @@ impl Game<'_> {
if self.debug { if self.debug {
for x in 0..BOARD_WIDTH { for x in 0..BOARD_WIDTH {
for y in 0..BOARD_HEIGHT { for y in 0..BOARD_HEIGHT {
let tile = self.map.get_tile((x as i32, y as i32)).unwrap_or(MapTile::Empty); let tile = self
.map
.get_tile((x as i32, y as i32))
.unwrap_or(MapTile::Empty);
let mut color = None; let mut color = None;
if (x, y) == self.pacman.cell_position() { if (x, y) == self.pacman.cell_position() {

View File

@@ -1,10 +1,10 @@
use crate::constants::{WINDOW_HEIGHT, WINDOW_WIDTH}; use crate::constants::{WINDOW_HEIGHT, WINDOW_WIDTH};
use crate::game::Game; use crate::game::Game;
use tracing::{event}; use sdl2::event::Event;
use sdl2::event::{Event};
use sdl2::keyboard::Keycode; use sdl2::keyboard::Keycode;
use std::time::{Duration, Instant};
use spin_sleep::sleep; use spin_sleep::sleep;
use std::time::{Duration, Instant};
use tracing::event;
use tracing_error::ErrorLayer; use tracing_error::ErrorLayer;
use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::layer::SubscriberExt;
@@ -16,9 +16,9 @@ mod constants;
mod direction; mod direction;
mod entity; mod entity;
mod game; mod game;
mod pacman;
mod modulation;
mod map; mod map;
mod modulation;
mod pacman;
#[cfg(target_os = "emscripten")] #[cfg(target_os = "emscripten")]
mod emscripten; mod emscripten;
@@ -68,8 +68,13 @@ pub fn main() {
// The start of a period of time over which we average the frame time. // The start of a period of time over which we average the frame time.
let mut last_averaging_time = Instant::now(); let mut last_averaging_time = Instant::now();
let mut sleep_time = Duration::ZERO; let mut sleep_time = Duration::ZERO;
let mut paused = false;
event!(tracing::Level::INFO, "Starting game loop ({:.3}ms)", loop_time.as_secs_f32() * 1000.0); event!(
tracing::Level::INFO,
"Starting game loop ({:.3}ms)",
loop_time.as_secs_f32() * 1000.0
);
let mut main_loop = || { let mut main_loop = || {
let start = Instant::now(); let start = Instant::now();
@@ -83,8 +88,19 @@ pub fn main() {
.. ..
} => { } => {
event!(tracing::Level::INFO, "Exit requested. Exiting..."); event!(tracing::Level::INFO, "Exit requested. Exiting...");
return false return false;
}, }
Event::KeyDown {
keycode: Some(Keycode::P),
..
} => {
paused = !paused;
event!(
tracing::Level::INFO,
"{}",
if paused { "Paused" } else { "Unpaused" }
);
}
Event::KeyDown { keycode, .. } => { Event::KeyDown { keycode, .. } => {
game.keyboard_event(keycode.unwrap()); game.keyboard_event(keycode.unwrap());
} }
@@ -92,8 +108,11 @@ pub fn main() {
} }
} }
// TODO: Proper pausing implementation that does not interfere with statistic gathering
if !paused {
game.tick(); game.tick();
game.draw(); game.draw();
}
if start.elapsed() < loop_time { if start.elapsed() < loop_time {
let time = loop_time - start.elapsed(); let time = loop_time - start.elapsed();
@@ -109,9 +128,11 @@ pub fn main() {
tick_no += 1; tick_no += 1;
if tick_no % (60 * 60) == 0 || tick_no == (60 * 2) { const PERIOD: u32 = 60 * 60;
let average_fps = (tick_no % (60 * 60)) as f32 / last_averaging_time.elapsed().as_secs_f32(); let tick_mod = tick_no % PERIOD;
let average_sleep = sleep_time / tick_no; if tick_mod % PERIOD == 0 {
let average_fps = PERIOD as f32 / last_averaging_time.elapsed().as_secs_f32();
let average_sleep = sleep_time / PERIOD;
let average_process = loop_time - average_sleep; let average_process = loop_time - average_sleep;
event!( event!(

View File

@@ -2,7 +2,7 @@ use crate::constants::MapTile;
use crate::constants::{BOARD_HEIGHT, BOARD_WIDTH}; use crate::constants::{BOARD_HEIGHT, BOARD_WIDTH};
pub struct Map { pub struct Map {
inner: [[MapTile; BOARD_HEIGHT as usize]; BOARD_WIDTH as usize] inner: [[MapTile; BOARD_HEIGHT as usize]; BOARD_WIDTH as usize],
} }
impl Map { impl Map {
@@ -30,7 +30,7 @@ impl Map {
' ' => MapTile::Empty, ' ' => MapTile::Empty,
c @ '0' | c @ '1' | c @ '2' | c @ '3' | c @ '4' => { c @ '0' | c @ '1' | c @ '2' | c @ '3' | c @ '4' => {
MapTile::StartingPosition(c.to_digit(10).unwrap() as u8) MapTile::StartingPosition(c.to_digit(10).unwrap() as u8)
}, }
'=' => MapTile::Empty, '=' => MapTile::Empty,
_ => panic!("Unknown character in board: {}", character), _ => panic!("Unknown character in board: {}", character),
}; };
@@ -39,9 +39,7 @@ impl Map {
} }
} }
Map { Map { inner: inner }
inner: inner
}
} }
pub fn get_tile(&self, cell: (i32, i32)) -> Option<MapTile> { pub fn get_tile(&self, cell: (i32, i32)) -> Option<MapTile> {

View File

@@ -9,7 +9,7 @@ use tracing::event;
use crate::{ use crate::{
animation::AnimatedTexture, animation::AnimatedTexture,
constants::MapTile, constants::MapTile,
constants::{CELL_SIZE, BOARD_OFFSET}, constants::{BOARD_OFFSET, CELL_SIZE},
direction::Direction, direction::Direction,
entity::Entity, entity::Entity,
map::Map, map::Map,
@@ -59,14 +59,19 @@ impl Pacman<'_> {
} }
fn handle_requested_direction(&mut self) { fn handle_requested_direction(&mut self) {
if self.next_direction.is_none() { return; } if self.next_direction.is_none() {
return;
}
if self.next_direction.unwrap() == self.direction { if self.next_direction.unwrap() == self.direction {
self.next_direction = None; self.next_direction = None;
return; return;
} }
let proposed_next_cell = self.next_cell(self.next_direction); let proposed_next_cell = self.next_cell(self.next_direction);
let proposed_next_tile = self.map.get_tile(proposed_next_cell).unwrap_or(MapTile::Empty); let proposed_next_tile = self
.map
.get_tile(proposed_next_cell)
.unwrap_or(MapTile::Empty);
if proposed_next_tile != MapTile::Wall { if proposed_next_tile != MapTile::Wall {
self.direction = self.next_direction.unwrap(); self.direction = self.next_direction.unwrap();
self.next_direction = None; self.next_direction = None;
@@ -87,7 +92,10 @@ impl Entity for Pacman<'_> {
fn cell_position(&self) -> (u32, u32) { fn cell_position(&self) -> (u32, u32) {
let (x, y) = self.position; let (x, y) = self.position;
((x as u32 / CELL_SIZE) - BOARD_OFFSET.0, (y as u32 / CELL_SIZE) - BOARD_OFFSET.1) (
(x as u32 / CELL_SIZE) - BOARD_OFFSET.0,
(y as u32 / CELL_SIZE) - BOARD_OFFSET.1,
)
} }
fn internal_position(&self) -> (u32, u32) { fn internal_position(&self) -> (u32, u32) {