add screen shake intensity setting (closes #129)
This commit is contained in:
parent
d8636bc693
commit
75b077c772
|
@ -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:",
|
||||
|
|
|
@ -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": "オリジナルテクスチャ:",
|
||||
|
|
21
src/frame.rs
21
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
_ => (),
|
||||
|
|
|
@ -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<Settings> {
|
||||
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,
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue