Browse Source

bug fix: multiple requestAnimationFrame calls

master
Inderjit Gill 1 year ago
parent
commit
48b7286259
5 changed files with 229 additions and 137 deletions
  1. BIN
      research/tileset.pdn
  2. +65
    -113
      src/controller.rs
  3. +153
    -21
      src/game.rs
  4. +11
    -3
      src/lib.rs
  5. BIN
      web/img/tileset.png

BIN
research/tileset.pdn View File


+ 65
- 113
src/controller.rs View File

@@ -23,10 +23,8 @@ pub struct Controller {
pub down: bool,
pub left: bool,
pub right: bool,

pub a: bool,
pub b: bool,

pub start: bool,
pub select: bool,

@@ -38,28 +36,6 @@ pub struct Controller {
b_previous: bool,
start_previous: bool,
select_previous: bool,

pub up_just_released: bool,
pub down_just_released: bool,
pub left_just_released: bool,
pub right_just_released: bool,

pub a_just_released: bool,
pub b_just_released: bool,

pub start_just_released: bool,
pub select_just_released: bool,

pub up_just_pressed: bool,
pub down_just_pressed: bool,
pub left_just_pressed: bool,
pub right_just_pressed: bool,

pub a_just_pressed: bool,
pub b_just_pressed: bool,

pub start_just_pressed: bool,
pub select_just_pressed: bool,
}

impl Controller {
@@ -82,45 +58,77 @@ impl Controller {
b_previous: false,
start_previous: false,
select_previous: false,
}
}

up_just_released: false,
down_just_released: false,
left_just_released: false,
right_just_released: false,
a_just_released: false,
b_just_released: false,
start_just_released: false,
select_just_released: false,
pub fn reset_controller(&mut self) {
self.up_previous = self.up;
self.down_previous = self.down;
self.left_previous = self.left;
self.right_previous = self.right;
self.a_previous = self.a;
self.b_previous = self.b;
self.start_previous = self.start;
self.select_previous = self.select;
}

up_just_pressed: false,
down_just_pressed: false,
left_just_pressed: false,
right_just_pressed: false,
a_just_pressed: false,
b_just_pressed: false,
start_just_pressed: false,
select_just_pressed: false,
pub fn just_released(&self, button: ControllerButton) -> bool {
match button {
ControllerButton::Left => {
!self.left && self.left_previous
},
ControllerButton::Right => {
!self.right && self.right_previous
},
ControllerButton::Up => {
!self.up && self.up_previous
},
ControllerButton::Down => {
!self.down && self.down_previous
},
ControllerButton::A => {
!self.a && self.a_previous
},
ControllerButton::B => {
!self.b && self.b_previous
},
ControllerButton::Start => {
!self.start && self.start_previous
},
ControllerButton::Select => {
!self.select && self.select_previous
},
}
}

pub fn reset_controller(&mut self) {
self.up_just_released = false;
self.down_just_released = false;
self.left_just_released = false;
self.right_just_released = false;
self.a_just_released = false;
self.b_just_released = false;
self.start_just_released = false;
self.select_just_released = false;

self.up_just_pressed = false;
self.down_just_pressed = false;
self.left_just_pressed = false;
self.right_just_pressed = false;
self.a_just_pressed = false;
self.b_just_pressed = false;
self.start_just_pressed = false;
self.select_just_pressed = false;
pub fn just_pressed(&self, button: ControllerButton) -> bool {
match button {
ControllerButton::Left => {
self.left && !self.left_previous
},
ControllerButton::Right => {
self.right && !self.right_previous
},
ControllerButton::Up => {
self.up && !self.up_previous
},
ControllerButton::Down => {
self.down && !self.down_previous
},
ControllerButton::A => {
self.a && !self.a_previous
},
ControllerButton::B => {
self.b && !self.b_previous
},
ControllerButton::Start => {
self.start && !self.start_previous
},
ControllerButton::Select => {
self.select && !self.select_previous
},
}
}

pub fn input(&mut self, button: ControllerButton, action: ControllerAction) {
@@ -136,83 +144,27 @@ impl Controller {
match button {
ControllerButton::Left => {
self.left = self.bool_from_action(action);

if self.left == true && self.left_previous == false {
self.left_just_pressed = true;
}
if self.left == false && self.left_previous == true {
self.left_just_released = true;
}
},
ControllerButton::Right => {
self.right = self.bool_from_action(action);

if self.right == true && self.right_previous == false {
self.right_just_pressed = true;
}
if self.right == false && self.right_previous == true {
self.right_just_released = true;
}
},
ControllerButton::Up => {
self.up = self.bool_from_action(action);

if self.up == true && self.up_previous == false {
self.up_just_pressed = true;
}
if self.up == false && self.up_previous == true {
self.up_just_released = true;
}
},
ControllerButton::Down => {
self.down = self.bool_from_action(action);

if self.down == true && self.down_previous == false {
self.down_just_pressed = true;
}
if self.down == false && self.down_previous == true {
self.down_just_released = true;
}
},
ControllerButton::A => {
self.a = self.bool_from_action(action);

if self.a == true && self.a_previous == false {
self.a_just_pressed = true;
}
if self.a == false && self.a_previous == true {
self.a_just_released = true;
}
},
ControllerButton::B => {
self.b = self.bool_from_action(action);

if self.b == true && self.b_previous == false {
self.b_just_pressed = true;
}
if self.b == false && self.b_previous == true {
self.b_just_released = true;
}
},
ControllerButton::Start => {
self.start = self.bool_from_action(action);

if self.start == true && self.start_previous == false {
self.start_just_pressed = true;
}
if self.start == false && self.start_previous == true {
self.start_just_released = true;
}
},
ControllerButton::Select => {
self.select = self.bool_from_action(action);

if self.select == true && self.select_previous == false {
self.select_just_pressed = true;
}
if self.select == false && self.select_previous == true {
self.select_just_released = true;
}
},
};
}

+ 153
- 21
src/game.rs View File

@@ -1,4 +1,4 @@
use controller::{Controller, ControllerAction, ControllerButton};
use controller::{Controller, ControllerButton};
use error;
use geometry::Geometry;
use log;
@@ -180,8 +180,14 @@ pub struct Game {
colour_saturation: f64,
colour_lightness: f64,

menu_num_items: i32,
menu_active_item: i32,
menu_volume: i32,
menu_max_volume: i32,
menu_crt_update_speed: i32,
menu_max_crt_update_speed: i32,
menu_curvature: i32,
menu_max_curvature: i32,

is_game_over: bool,

@@ -209,6 +215,9 @@ pub struct Game {
s_count: i32,
t_count: i32,
z_count: i32,

debug_flash: bool,
debug_delta: f32,
}

impl Game {
@@ -236,8 +245,17 @@ impl Game {
colour_saturation: config.colour_saturation,
colour_lightness: config.colour_lightness,

menu_num_items: 5,
menu_active_item: 0,

menu_volume: 4,
menu_max_volume: 5,

menu_crt_update_speed: 4,
menu_max_crt_update_speed: 5,

menu_curvature: 3,
menu_max_curvature: 5,

is_game_over: false,

@@ -266,6 +284,9 @@ impl Game {
s_count: 0,
t_count: 0,
z_count: 0,

debug_flash: true,
debug_delta: 0.0,
}
}

@@ -337,11 +358,18 @@ impl Game {
}
}
}

if self.debug_flash {
geometry.push_text("X", Block2D { x: 11, y: 1 }, Col::new(1.0, 1.0, 1.0, 1.0));
} else {
geometry.push_text("-", Block2D { x: 11, y: 1 }, Col::new(1.0, 1.0, 1.0, 1.0));
}
geometry.push_text(&format!("{}", self.debug_delta), Block2D { x: 12, y: 1 }, Col::new(1.0, 1.0, 1.0, 1.0));
}

pub fn tick(&mut self, controller: &Controller, delta: f32, random: f32) -> bool {

if controller.start_just_released {
if controller.just_released(ControllerButton::Start) {
if self.mode == GameMode::Playing {
play_sound(SoundEffect::PauseIn);
self.mode = GameMode::Paused;
@@ -365,6 +393,12 @@ impl Game {
corrected_delta = delta;
}

self.debug_flash = !self.debug_flash;
self.debug_delta = corrected_delta;
if self.debug_delta > 0.0 && self.debug_delta < 15.0 {
log(&format!("{}", self.debug_delta));
}

match self.mode {
GameMode::Playing => match self.tick_playing(controller, corrected_delta, random) {
Ok(res) => res,
@@ -620,6 +654,7 @@ fn apply_user_input(game: &mut Game, controller: &Controller, delta: f32) {
y: game.piece.pos.y,
};
if is_allowed(&game.board, shape, &new_position, &game.piece.angle) {
// log(&format!("old position: {:?}, new position {:?}", game.piece.pos, new_position));
game.piece.pos = new_position;
}
}
@@ -639,7 +674,7 @@ fn apply_user_input(game: &mut Game, controller: &Controller, delta: f32) {
}
}

if controller.up_just_pressed {
if controller.just_pressed(ControllerButton::Up) {
let new_angle;
if shape.fully_rotate {
new_angle = match game.piece.angle {
@@ -661,7 +696,7 @@ fn apply_user_input(game: &mut Game, controller: &Controller, delta: f32) {
}


if controller.down_just_pressed {
if controller.just_pressed(ControllerButton::Down) {
game.piece_is_dropping = true;
}

@@ -974,45 +1009,142 @@ fn update_pause_menu(game: &mut Game, controller: &Controller) -> bool {

let mut update = false;

if controller.down_just_pressed {
log("paused: down pressed");
if controller.just_pressed(ControllerButton::Down) {
game.menu_active_item += 1;
play_sound(SoundEffect::MenuMove);
update = true;
}

if controller.up_just_pressed {
log("paused: up pressed");
if controller.just_pressed(ControllerButton::Up) {
game.menu_active_item -= 1;
play_sound(SoundEffect::MenuMove);
update = true;
}

if game.menu_active_item < 0 {
game.menu_active_item = 2;
game.menu_active_item = wrap(game.menu_active_item, 0, game.menu_num_items - 1);

// volume
if game.menu_active_item == 1 {
if controller.just_pressed(ControllerButton::Left) {
game.menu_volume -= 1;
play_sound(SoundEffect::MenuMove);
update = true;
}
if controller.just_pressed(ControllerButton::Right) {
game.menu_volume += 1;
play_sound(SoundEffect::MenuMove);
update = true;
}
game.menu_volume = clamp(game.menu_volume, 0, game.menu_max_volume);
}

if game.menu_active_item > 2 {
game.menu_active_item = 0;
// crt update speed
if game.menu_active_item == 2 {
if controller.just_pressed(ControllerButton::Left) {
game.menu_crt_update_speed -= 1;
play_sound(SoundEffect::MenuMove);
update = true;
}
if controller.just_pressed(ControllerButton::Right) {
game.menu_crt_update_speed += 1;
play_sound(SoundEffect::MenuMove);
update = true;
}
game.menu_crt_update_speed = clamp(game.menu_crt_update_speed, 0, game.menu_max_crt_update_speed);
}

// curvature
if game.menu_active_item == 3 {
if controller.just_pressed(ControllerButton::Left) {
game.menu_curvature -= 1;
play_sound(SoundEffect::MenuMove);
update = true;
}
if controller.just_pressed(ControllerButton::Right) {
game.menu_curvature += 1;
play_sound(SoundEffect::MenuMove);
update = true;
}
game.menu_curvature = clamp(game.menu_curvature, 0, game.menu_max_curvature);
}

update
}

fn wrap(val: i32, min: i32, max: i32) -> i32 {
if val < min {
return max
} else if val > max {
return min
}
val
}

fn clamp(val: i32, min: i32, max: i32) -> i32 {
if val < min {
return min
} else if val > max {
return max
}
val
}

fn render_pause_menu(game: &Game, geometry: &mut Geometry, centre: Block2D, text_colour: Col, background_colour: Col) {
let lines = build_paused_menu(game);
let resume = build_menu_item(game, 0, "RESUME");
let vol = build_menu_item_slider(game, 1, "Volume ", game.menu_max_volume, game.menu_volume);
let crt_update_speed = build_menu_item_slider(game, 2, "CRT Refresh ", game.menu_max_crt_update_speed, game.menu_crt_update_speed);
let curvature = build_menu_item_slider(game, 3, "Curvature ", game.menu_max_curvature, game.menu_curvature);
let restart = build_menu_item(game, 4, "Restart");

// remember to update Game::menu_num_items when adding another menu option

let lines: Vec<&str> = vec![&resume[..],
&vol[..],
&crt_update_speed[..],
&curvature[..],
&restart[..]];

geometry.push_centred_boxed_multiline(&lines, centre, text_colour, background_colour);
}

fn build_paused_menu(game: &Game) -> Vec<&str> {
let mut lines: Vec<&str> = vec![" RESUME", " Volume: [---*--]", " Restart"];

match game.menu_active_item {
0 => lines[0] = "> RESUME",
1 => lines[1] = "> Volume: [---*--]",
2 => lines[2] = "> Restart",
_ => (),
fn build_menu_item(game: &Game, item_order: i32, label: &str) -> String {
let mut out = menu_item_base(game, item_order);
out.push_str(label);
out
}

fn build_menu_item_slider(game: &Game, item_order: i32, label: &str, max: i32, val: i32) -> String {
let mut out = menu_item_base(game, item_order);
let slider = build_menu_item_slider_bar(max, val);
out.push_str(label);
out.push_str(&slider[..]);
out
}

fn menu_item_base(game: &Game, item_order: i32) -> String {
let mut out = "".to_owned();
if game.menu_active_item == item_order {
out.push_str("> ");
} else {
out.push_str(" ");
}
out
}

fn build_menu_item_slider_bar(max: i32, value: i32) -> String {
let mut out = "".to_owned();

lines
out.push_str("[");
for _ in 0..value {
out.push_str("-");
}
out.push_str("*");
for _ in value..max {
out.push_str("-");
}
out.push_str("]");
out
}

fn define_shapes() -> HashMap<ShapeKind, Shape> {

+ 11
- 3
src/lib.rs View File

@@ -1,3 +1,4 @@
#![allow(dead_code)]
#![feature(use_extern_macros, wasm_custom_section, wasm_import_module)]
#![cfg_attr(
feature = "cargo-clippy",
@@ -141,6 +142,8 @@ pub struct Bridge {
game: Game,
controller: Controller,
geometry: Geometry,

game_is_ticking: bool,
}

#[wasm_bindgen]
@@ -151,6 +154,7 @@ impl Bridge {
game: Game::new(config),
controller: Controller::new(),
geometry: Geometry::new(config),
game_is_ticking: false,
}
}

@@ -180,11 +184,11 @@ impl Bridge {
}

pub fn tick(&mut self, delta: f32, random: f32) -> bool {
let res = self.game.tick(&self.controller, delta, random);
self.game_is_ticking = self.game.tick(&self.controller, delta, random);

self.controller.reset_controller();

res
self.game_is_ticking
}

// use the current gamestate to update geometry
@@ -220,12 +224,16 @@ impl Bridge {
"a" => call_tick = self.input(ControllerButton::A, action),
"z" => call_tick = self.input(ControllerButton::B, action),
"Enter" => call_tick = self.input(ControllerButton::Start, action),
"Escape" => call_tick = self.input(ControllerButton::Start, action),
"Shift" => call_tick = self.input(ControllerButton::Select, action),
_ => prevent_default = false,
}

// the js side should only call tick if the main game loop isn't already ticking
// otherwise we'll end up with multiple requestAnimationFrame invocations

KeyEventReturn {
call_tick,
call_tick: call_tick && !self.game_is_ticking,
prevent_default,
}
}

BIN
web/img/tileset.png View File

Before After
Width: 512  |  Height: 512  |  Size: 13KB Width: 512  |  Height: 512  |  Size: 13KB

Loading…
Cancel
Save