Browse Source

in-game options for audio/graphics

master
Inderjit Gill 1 year ago
parent
commit
c8a55b2eae
5 changed files with 125 additions and 41 deletions
  1. +84
    -34
      src/game.rs
  2. +18
    -2
      src/lib.rs
  3. +4
    -0
      web/js/Audio.js
  4. +6
    -3
      web/js/GLRenderer.js
  5. +13
    -2
      web/js/index.js

+ 84
- 34
src/game.rs View File

@@ -3,6 +3,7 @@ use error;
use geometry::Geometry;
use log;
use audio_play;
use audio_volume;
use colour::{Colour, Format};
use sprite::Sprite;
use std::collections::HashMap;
@@ -71,7 +72,7 @@ impl Board {
);
let width = config.board_width;
let height = config.board_height;
let crt_update_speed = config.crt_update_speed;
let crt_update_speed = 1.0; // this will be updated by Game::new() calling set_crt_update_speed

Board {
board: vec![vec![Block::new(inactive_colour); width]; height],
@@ -90,7 +91,10 @@ impl Board {
config.block_inactive_col_b,
config.block_inactive_col_a,
);
self.crt_update_speed = config.crt_update_speed;
}

pub fn set_crt_update_speed(&mut self, new_crt_update_speed: f32) {
self.crt_update_speed = new_crt_update_speed;
}

pub fn is_line_filled(&self, line_number: usize) -> bool {
@@ -216,13 +220,14 @@ pub struct Game {
t_count: i32,
z_count: i32,

debug_mode: bool,
debug_flash: bool,
debug_delta: f32,
}

impl Game {
pub fn new(config: &Config) -> Game {
Game {
let mut game = Game {
mode: GameMode::Playing,
resume_from_paused: false,

@@ -247,15 +252,12 @@ impl Game {

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,
menu_volume: config.menu_volume,
menu_max_volume: config.menu_max_volume,
menu_crt_update_speed: config.menu_crt_update_speed,
menu_max_crt_update_speed: config.menu_max_crt_update_speed,
menu_curvature: config.menu_curvature,
menu_max_curvature: config.menu_max_curvature,

is_game_over: false,

@@ -285,9 +287,21 @@ impl Game {
t_count: 0,
z_count: 0,

debug_mode: false,
debug_flash: true,
debug_delta: 0.0,
}
};

// set state according to initial config values
update_audio_volume(&game);
update_crt_update_speed(&mut game);

game
}

pub fn get_curvature(&self) -> f32 {
let f = self.menu_curvature as f32 / self.menu_max_curvature as f32;
f * (1.0 / 8.0)
}

pub fn reconfigure(&mut self, config: &Config) {
@@ -359,12 +373,14 @@ 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));
if self.debug_mode {
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));
}
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 {
@@ -379,6 +395,10 @@ impl Game {
self.resume_from_paused = true;
}
}
if controller.just_released(ControllerButton::Select) {
self.debug_mode = !self.debug_mode;
}


// always followed by a render
// returns true if tick should be called again
@@ -393,10 +413,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));
if self.debug_mode {
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 {
@@ -1011,13 +1033,11 @@ fn update_pause_menu(game: &mut Game, controller: &Controller) -> bool {

if controller.just_pressed(ControllerButton::Down) {
game.menu_active_item += 1;
play_sound(SoundEffect::MenuMove);
update = true;
}

if controller.just_pressed(ControllerButton::Up) {
game.menu_active_item -= 1;
play_sound(SoundEffect::MenuMove);
update = true;
}

@@ -1025,52 +1045,82 @@ fn update_pause_menu(game: &mut Game, controller: &Controller) -> bool {

// volume
if game.menu_active_item == 1 {
let mut volume_changed = false;

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

update_audio_volume(game);
}
game.menu_volume = clamp(game.menu_volume, 0, game.menu_max_volume);
}

// crt update speed
if game.menu_active_item == 2 {
let mut crt_update_speed_changed = false;

if controller.just_pressed(ControllerButton::Left) {
crt_update_speed_changed = true;
game.menu_crt_update_speed -= 1;
play_sound(SoundEffect::MenuMove);
update = true;
}
if controller.just_pressed(ControllerButton::Right) {
crt_update_speed_changed = true;
game.menu_crt_update_speed += 1;
play_sound(SoundEffect::MenuMove);
}

if crt_update_speed_changed {
game.menu_crt_update_speed = clamp(game.menu_crt_update_speed, 0, game.menu_max_crt_update_speed);
update = true;

update_crt_update_speed(game);
}
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);
}

if update {
play_sound(SoundEffect::MenuMove);
}
update
}

fn update_audio_volume(game: &Game) {
let volume = game.menu_volume as f32 / game.menu_max_volume as f32;
audio_volume(volume);
}

fn update_crt_update_speed(game: &mut Game) {
if game.menu_crt_update_speed == game.menu_max_crt_update_speed {
// switch off any ghosting
game.board.set_crt_update_speed(1.0);
} else {
// 0.00 -> ~1.0
// 0.01 -> 0.2
let percent = game.menu_crt_update_speed as f32 / game.menu_max_crt_update_speed as f32;
let new_crt_update_speed = (percent * 0.2) + 0.01;
game.board.set_crt_update_speed(new_crt_update_speed);
}
}

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

+ 18
- 2
src/lib.rs View File

@@ -44,6 +44,7 @@ extern "C" {
#[wasm_bindgen]
extern {
fn audio_play(id: i32);
fn audio_volume(volume: f32);
}

#[wasm_bindgen]
@@ -100,7 +101,13 @@ pub struct Config {
pub block_inactive_col_b: f32,
pub block_inactive_col_a: f32,

pub crt_update_speed: f32, // higher the value, the less 'ghosting'
pub menu_volume: i32,
pub menu_max_volume: i32,
pub menu_crt_update_speed: i32,
pub menu_max_crt_update_speed: i32,
pub menu_curvature: i32,
pub menu_max_curvature: i32,

}

#[wasm_bindgen]
@@ -130,7 +137,12 @@ impl Config {
block_inactive_col_g: 0.6,
block_inactive_col_b: 0.0,
block_inactive_col_a: 0.1,
crt_update_speed: 0.15,
menu_volume: 5,
menu_max_volume: 5,
menu_crt_update_speed: 4,
menu_max_crt_update_speed: 5,
menu_curvature: 3,
menu_max_curvature: 5,
}
}
}
@@ -212,6 +224,10 @@ impl Bridge {
self.geometry.crt_ptr()
}

pub fn crt_curvature(&self) -> f32 {
self.game.get_curvature()
}

fn input_event(&mut self, key: String, action: ControllerAction) -> KeyEventReturn {
let mut prevent_default = true;
let mut call_tick = false;

+ 4
- 0
web/js/Audio.js View File

@@ -45,6 +45,10 @@ export class Audio {
case 9: this.menu_move.play(); break;
default: console.error(`Audio: unable to play: ${label}`);
}
}

volume(amount) {
// volume is in range 0..1
Howler.volume(amount);
}
}

+ 6
- 3
web/js/GLRenderer.js View File

@@ -120,6 +120,7 @@ function setupCRTShader(gl) {
uniform sampler2D texture;
uniform vec2 res;
uniform vec2 uv_max;
uniform vec2 warp2;

// Amount of shadow mask.
float maskDark=0.7;
@@ -128,12 +129,12 @@ function setupCRTShader(gl) {
// Display warp.
// 0.0 = none
// 1.0/8.0 = extreme
vec2 warp=vec2(1.0/20.0, 1.0/20.0);
// vec2 warp=vec2(1.0/20.0, 1.0/20.0);

// Distortion of scanlines, and end of screen alpha.
vec2 Warp(vec2 pos) {
pos = pos * 2.0 - 1.0;
pos *= vec2(1.0 + (pos.y * pos.y) * warp.x, 1.0 + (pos.x * pos.x) * warp.y);
pos *= vec2(1.0 + (pos.y * pos.y) * warp2.x, 1.0 + (pos.x * pos.x) * warp2.y);
return pos * 0.5 + 0.5;
}

@@ -211,6 +212,7 @@ function setupCRTShader(gl) {

shader.resolutionLocation = gl.getUniformLocation(shader.program, 'res');
shader.uvMaxLocation = gl.getUniformLocation(shader.program, 'uv_max');
shader.warp2 = gl.getUniformLocation(shader.program, 'warp2');

return shader;
}
@@ -424,7 +426,7 @@ export class GLRenderer {
gl.drawArrays(gl.TRIANGLE_STRIP, 0, geo_len / totalSize);
}

renderTextureToScreen(canvasWidth, canvasHeight, memoryF32, geo_len, geo_ptr) {
renderTextureToScreen(canvasWidth, canvasHeight, memoryF32, geo_len, geo_ptr, curvature) {
const gl = this.gl;

let shader = this.crtShader;
@@ -461,6 +463,7 @@ export class GLRenderer {

gl.uniform2f(shader.resolutionLocation, canvasWidth, canvasHeight);
gl.uniform2f(shader.uvMaxLocation, 0.5000, 0.6875);
gl.uniform2f(shader.warp2, curvature, curvature);

const glVertexBuffer = this.glVertexBuffer;
const glColourBuffer = this.glColourBuffer;

+ 13
- 2
web/js/index.js View File

@@ -53,8 +53,9 @@ const render = () => {
// apply a CRT effect
const crt_len = bridge.crt_len();
const crt_ptr = bridge.crt_ptr();
const curvature = bridge.crt_curvature();
renderer.renderTextureToScreen(gState.config.canvas_width, gState.config.canvas_height,
memoryF32, crt_len, crt_ptr);
memoryF32, crt_len, crt_ptr, curvature);
};

function reconfigure() {
@@ -65,9 +66,14 @@ function audio_play(id) {
gState.audio.play(id);
}

function audio_volume(volume) {
gState.audio.volume(volume);
}

window.reconfigure = reconfigure;
window.config = gState.config;
window.audio_play = audio_play;
window.audio_volume = audio_volume;

function get_canvas_aspect_ratio(config) {

@@ -136,7 +142,12 @@ function main() {
gState.config.block_inactive_col_b = 0.0,
gState.config.block_inactive_col_a = 0.1,

gState.config.crt_update_speed = 0.15;
gState.config.menu_volume = 5;
gState.config.menu_max_volume = 5;
gState.config.menu_crt_update_speed = 4;
gState.config.menu_max_crt_update_speed = 5;
gState.config.menu_curvature = 3;
gState.config.menu_max_curvature = 5;

resize_canvas_element(canvasElement, gState.config);


Loading…
Cancel
Save