From 75b077c77289528260579892a44a9963642dbe35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sallai=20J=C3=B3zsef?= Date: Sat, 9 Jul 2022 18:06:22 +0300 Subject: [PATCH] add screen shake intensity setting (closes #129) --- src/builtin/locale/en.json | 6 +++++ src/builtin/locale/jp.json | 8 +++++- src/frame.rs | 21 +++++++++++----- src/menu/settings_menu.rs | 51 ++++++++++++++++++++++++++++++++------ src/settings.rs | 17 +++++++++++-- src/shared_game_state.rs | 17 +++++++++++++ 6 files changed, 104 insertions(+), 16 deletions(-) diff --git a/src/builtin/locale/en.json b/src/builtin/locale/en.json index 7368598..af42887 100644 --- a/src/builtin/locale/en.json +++ b/src/builtin/locale/en.json @@ -63,6 +63,12 @@ "graphics_menu": { "lighting_effects": "Lighting effects:", "weapon_light_cone": "Weapon light cone:", + "screen_shake": { + "entry": "Screen shake intensity:", + "full": "1x", + "half": "0.5x", + "off": "Off" + }, "motion_interpolation": "Motion interpolation:", "subpixel_scrolling": "Subpixel scrolling:", "original_textures": "Original textures:", diff --git a/src/builtin/locale/jp.json b/src/builtin/locale/jp.json index 2779d25..34afe31 100644 --- a/src/builtin/locale/jp.json +++ b/src/builtin/locale/jp.json @@ -38,7 +38,7 @@ }, "coop_menu": { "title": "プレイヤー数を選択", - "one":"1人プレイ", + "one": "1人プレイ", "two": "2人プレイ" }, "skin_menu": { @@ -56,6 +56,12 @@ "graphics_menu": { "lighting_effects": "ライティング効果:", "weapon_light_cone": "兵器のライトコーン:", + "screen_shake": { + "entry": "画面の揺れ:", + "full": "1x", + "half": "0.5x", + "off": "オフ" + }, "motion_interpolation": "モーション補間:", "subpixel_scrolling": "サブピクセルスクロール:", "original_textures": "オリジナルテクスチャ:", diff --git a/src/frame.rs b/src/frame.rs index 3d47af6..2779b74 100644 --- a/src/frame.rs +++ b/src/frame.rs @@ -95,10 +95,11 @@ impl Frame { screen_width += 10.0; } - if self.wait == 0 { // prevent zero division + if self.wait == 0 { + // prevent zero division self.wait = 1; } - + let tile_size = state.tile_size.as_int(); if (stage.map.width as usize).saturating_sub(1) * (tile_size as usize) < screen_width as usize { @@ -131,18 +132,26 @@ impl Frame { } } + let intensity = state.settings.screen_shake_intensity.to_val(); + if state.super_quake_counter > 0 { state.super_quake_counter -= 1; - self.x += state.effect_rng.range(-0x300..0x300) * 5 as i32; - self.y += state.effect_rng.range(-0x300..0x300) * 3 as i32; + let new_x = state.effect_rng.range(-0x300..0x300) * 5; + let new_y = state.effect_rng.range(-0x300..0x300) * 3; + + self.x += (f64::from(new_x) * intensity).round() as i32; + self.y += (f64::from(new_y) * intensity).round() as i32; } if state.quake_counter > 0 { state.quake_counter -= 1; - self.x += state.effect_rng.range(-0x300..0x300) as i32; - self.y += state.effect_rng.range(-0x300..0x300) as i32; + let new_x = state.effect_rng.range(-0x300..0x300) as i32; + let new_y = state.effect_rng.range(-0x300..0x300) as i32; + + self.x += (f64::from(new_x) * intensity).round() as i32; + self.y += (f64::from(new_y) * intensity).round() as i32; } } } diff --git a/src/menu/settings_menu.rs b/src/menu/settings_menu.rs index 792c227..e103fc8 100644 --- a/src/menu/settings_menu.rs +++ b/src/menu/settings_menu.rs @@ -9,7 +9,7 @@ use crate::input::combined_menu_controller::CombinedMenuController; use crate::menu::MenuEntry; use crate::menu::{Menu, MenuSelectionResult}; use crate::scene::title_scene::TitleScene; -use crate::shared_game_state::{Language, SharedGameState, TimingMode}; +use crate::shared_game_state::{Language, ScreenShakeIntensity, SharedGameState, TimingMode}; use crate::sound::InterpolationMode; use crate::{graphics, VSyncMode}; @@ -74,6 +74,15 @@ impl SettingsMenu { state.t("menus.options_menu.graphics_menu.weapon_light_cone"), state.settings.light_cone, )); + self.graphics.push_entry(MenuEntry::Options( + state.t("menus.options_menu.graphics_menu.screen_shake.entry"), + state.settings.screen_shake_intensity as usize, + vec![ + state.t("menus.options_menu.graphics_menu.screen_shake.full"), + state.t("menus.options_menu.graphics_menu.screen_shake.half"), + state.t("menus.options_menu.graphics_menu.screen_shake.off"), + ], + )); self.graphics.push_entry(MenuEntry::Toggle( state.t("menus.options_menu.graphics_menu.motion_interpolation"), state.settings.motion_interpolation, @@ -218,7 +227,7 @@ impl SettingsMenu { self.graphics.update_width(state); self.graphics.update_height(); self.graphics.x = ((state.canvas_size.0 - self.graphics.width as f32) / 2.0).floor() as isize; - self.graphics.y = 30 + ((state.canvas_size.1 - self.graphics.height as f32) / 2.0).floor() as isize; + self.graphics.y = 20 + ((state.canvas_size.1 - self.graphics.height as f32) / 2.0).floor() as isize; self.sound.update_width(state); self.sound.update_height(); @@ -332,7 +341,35 @@ impl SettingsMenu { *value = state.settings.light_cone; } } - MenuSelectionResult::Selected(3, toggle) => { + MenuSelectionResult::Selected(3, toggle) | MenuSelectionResult::Right(3, toggle, _) => { + if let MenuEntry::Options(_, value, _) = toggle { + let (new_intensity, new_value) = match *value { + 0 => (ScreenShakeIntensity::Half, 1), + 1 => (ScreenShakeIntensity::Off, 2), + _ => (ScreenShakeIntensity::Full, 0), + }; + + *value = new_value; + state.settings.screen_shake_intensity = new_intensity; + + let _ = state.settings.save(ctx); + } + } + MenuSelectionResult::Left(3, toggle, _) => { + if let MenuEntry::Options(_, value, _) = toggle { + let (new_intensity, new_value) = match *value { + 0 => (ScreenShakeIntensity::Off, 2), + 1 => (ScreenShakeIntensity::Full, 0), + _ => (ScreenShakeIntensity::Half, 1), + }; + + *value = new_value; + state.settings.screen_shake_intensity = new_intensity; + + let _ = state.settings.save(ctx); + } + } + MenuSelectionResult::Selected(4, toggle) => { if let MenuEntry::Toggle(_, value) = toggle { state.settings.motion_interpolation = !state.settings.motion_interpolation; let _ = state.settings.save(ctx); @@ -340,7 +377,7 @@ impl SettingsMenu { *value = state.settings.motion_interpolation; } } - MenuSelectionResult::Selected(4, toggle) => { + MenuSelectionResult::Selected(5, toggle) => { if let MenuEntry::Toggle(_, value) = toggle { state.settings.subpixel_coords = !state.settings.subpixel_coords; let _ = state.settings.save(ctx); @@ -348,7 +385,7 @@ impl SettingsMenu { *value = state.settings.subpixel_coords; } } - MenuSelectionResult::Selected(5, toggle) => { + MenuSelectionResult::Selected(6, toggle) => { if let MenuEntry::Toggle(_, value) = toggle { state.settings.original_textures = !state.settings.original_textures; if self.on_title { @@ -361,7 +398,7 @@ impl SettingsMenu { *value = state.settings.original_textures; } } - MenuSelectionResult::Selected(6, toggle) => { + MenuSelectionResult::Selected(7, toggle) => { if let MenuEntry::Toggle(_, value) = toggle { state.settings.seasonal_textures = !state.settings.seasonal_textures; state.reload_graphics(); @@ -370,7 +407,7 @@ impl SettingsMenu { *value = state.settings.seasonal_textures; } } - MenuSelectionResult::Selected(8, _) | MenuSelectionResult::Canceled => { + MenuSelectionResult::Selected(9, _) | MenuSelectionResult::Canceled => { self.current = CurrentMenu::MainMenu } _ => (), diff --git a/src/settings.rs b/src/settings.rs index c389133..066fd00 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -7,7 +7,7 @@ use crate::input::keyboard_player_controller::KeyboardController; use crate::input::player_controller::PlayerController; use crate::input::touch_player_controller::TouchPlayerController; use crate::player::TargetPlayer; -use crate::shared_game_state::{Language, TimingMode}; +use crate::shared_game_state::{Language, ScreenShakeIntensity, TimingMode}; use crate::sound::InterpolationMode; #[derive(serde::Serialize, serde::Deserialize)] @@ -50,6 +50,8 @@ pub struct Settings { pub locale: Language, #[serde(default = "default_vsync")] pub vsync_mode: VSyncMode, + #[serde(default = "default_screen_shake_intensity")] + pub screen_shake_intensity: ScreenShakeIntensity, pub debug_mode: bool, #[serde(skip)] pub noclip: bool, @@ -61,7 +63,7 @@ fn default_true() -> bool { #[inline(always)] fn current_version() -> u32 { - 9 + 10 } #[inline(always)] @@ -94,6 +96,11 @@ fn default_vsync() -> VSyncMode { VSyncMode::VSync } +#[inline(always)] +fn default_screen_shake_intensity() -> ScreenShakeIntensity { + ScreenShakeIntensity::Full +} + impl Settings { pub fn load(ctx: &Context) -> GameResult { if let Ok(file) = user_open(ctx, "/settings.json") { @@ -146,6 +153,11 @@ impl Settings { self.debug_mode = false; } + if self.version == 9 { + self.version = 10; + self.screen_shake_intensity = default_screen_shake_intensity(); + } + if self.version != initial_version { log::info!("Upgraded configuration file from version {} to {}.", initial_version, self.version); } @@ -198,6 +210,7 @@ impl Default for Settings { fps_counter: false, locale: Language::English, vsync_mode: VSyncMode::VSync, + screen_shake_intensity: ScreenShakeIntensity::Full, debug_mode: false, noclip: false, } diff --git a/src/shared_game_state.rs b/src/shared_game_state.rs index 85b930f..73a9ff6 100644 --- a/src/shared_game_state.rs +++ b/src/shared_game_state.rs @@ -127,6 +127,23 @@ impl Language { } } +#[derive(PartialEq, Eq, Copy, Clone, num_derive::FromPrimitive, serde::Serialize, serde::Deserialize)] +pub enum ScreenShakeIntensity { + Full, + Half, + Off, +} + +impl ScreenShakeIntensity { + pub fn to_val(self) -> f64 { + match self { + ScreenShakeIntensity::Full => 1.0, + ScreenShakeIntensity::Half => 0.5, + ScreenShakeIntensity::Off => 0.0, + } + } +} + #[derive(Clone, Debug)] pub struct FontData { pub path: String,