feat: Introduce comprehensive settings management with UI for video, audio, and remappable controls.

This commit is contained in:
Yogi Wiguna
2026-03-10 17:04:01 +08:00
parent c895e466b5
commit d53e4601e4
5 changed files with 382 additions and 58 deletions
+16 -6
View File
@@ -18,12 +18,22 @@ func _process(delta):
if TurnManager.turn_based_mode:
return
# Continuous movement input
var move_vec = Vector2i.ZERO
if Input.is_action_pressed("move_north"): move_vec.y -= 1
if Input.is_action_pressed("move_south"): move_vec.y += 1
if Input.is_action_pressed("move_east"): move_vec.x += 1
if Input.is_action_pressed("move_west"): move_vec.x -= 1
# 1. Controller / Joystick Movement
if SettingsManager and SettingsManager.settings.controls.get("use_controller", false):
var joystick_vec = Input.get_vector("move_west", "move_east", "move_north", "move_south")
if joystick_vec.length() > 0.3: # Deadzone
if abs(joystick_vec.x) > abs(joystick_vec.y):
move_vec.x = 1 if joystick_vec.x > 0 else -1
else:
move_vec.y = 1 if joystick_vec.y > 0 else -1
# 2. Keyboard Movement (Fallback)
if move_vec == Vector2i.ZERO:
if Input.is_action_pressed("move_north"): move_vec.y -= 1
if Input.is_action_pressed("move_south"): move_vec.y += 1
if Input.is_action_pressed("move_east"): move_vec.x += 1
if Input.is_action_pressed("move_west"): move_vec.x -= 1
# Fallback for explicit diagonal actions (if mapped)
if move_vec == Vector2i.ZERO:
@@ -33,7 +43,7 @@ func _process(delta):
elif Input.is_action_pressed("move_northwest"): move_vec = Vector2i(-1, -1)
# Action inputs (still momentary)
# 3. Action inputs (momentary)
if Input.is_action_just_pressed("action_grab"):
player.grab_item(player.current_position)
elif Input.is_action_just_pressed("action_put"):
+69 -5
View File
@@ -5,12 +5,24 @@ extends Node
const SETTINGS_FILE = "user://game_settings.cfg"
const RESOLUTIONS = [
Vector2i(1024, 576),
Vector2i(1280, 720),
Vector2i(1366, 768),
Vector2i(1600, 900),
Vector2i(1920, 1080),
Vector2i(2560, 1440)
]
# Default values
var settings = {
"video": {
"fullscreen": true,
"vsync": true,
"resolution_idx": 1
"resolution_idx": 1,
"msaa": 0, # 0: Disabled, 1: 2x, 2: 4x, 3: 8x
"shadow_quality": 2, # 0: Low, 1: Med, 2: High, 3: Ultra
"fps_cap": 2 # 0: Unlimited, 1: 30, 2: 60, 3: 120, 4: 144
},
"audio": {
"master_volume": 0.8,
@@ -18,15 +30,24 @@ var settings = {
"sfx_volume": 0.9
},
"controls": {
"use_controller": false,
# Movement (Keybinds are typically fixed to WASD/Arrows in Input Map, but we show them)
"move_up": KEY_W,
"move_down": KEY_S,
"move_left": KEY_A,
"move_right": KEY_D,
# Actions
"grab": KEY_SPACE,
"put": KEY_R,
"tekton_grab": KEY_G,
# Power-Up Controls
"powerup_1": KEY_1,
"powerup_2": KEY_2,
"powerup_3": KEY_3,
"powerup_4": KEY_4,
"grab": KEY_SPACE,
"put": KEY_R,
# Power Bar Controls / Special
"attack_mode": KEY_Q,
"spawn_boost": KEY_E,
"tekton_grab": KEY_G
"spawn_boost": KEY_E
}
}
@@ -63,16 +84,59 @@ func apply_all_settings():
func apply_video_settings():
var video = settings.video
if video.fullscreen:
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)
else:
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
# Apply resolution size when windowed
var res_idx = video.resolution_idx
if res_idx >= 0 and res_idx < RESOLUTIONS.size():
var target_res = RESOLUTIONS[res_idx]
DisplayServer.window_set_size(target_res)
# Center window after resize
var screen = DisplayServer.window_get_current_screen()
var screen_rect = DisplayServer.screen_get_usable_rect(screen)
var window_size = DisplayServer.window_get_size()
DisplayServer.window_set_position(screen_rect.position + (screen_rect.size - window_size) / 2)
if video.vsync:
DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_ENABLED)
else:
DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_DISABLED)
# Apply MSAA
var viewport = get_viewport()
match video.msaa:
0: viewport.msaa_3d = Viewport.MSAA_DISABLED
1: viewport.msaa_3d = Viewport.MSAA_2X
2: viewport.msaa_3d = Viewport.MSAA_4X
3: viewport.msaa_3d = Viewport.MSAA_8X
# Apply FPS Cap
match video.fps_cap:
0: Engine.max_fps = 0
1: Engine.max_fps = 30
2: Engine.max_fps = 60
3: Engine.max_fps = 120
4: Engine.max_fps = 144
# Apply Shadow Quality (Simplified for Forward+)
match video.shadow_quality:
0: # Low
RenderingServer.directional_soft_shadow_filter_set_quality(RenderingServer.SHADOW_QUALITY_SOFT_LOW)
RenderingServer.positional_soft_shadow_filter_set_quality(RenderingServer.SHADOW_QUALITY_SOFT_LOW)
1: # Medium
RenderingServer.directional_soft_shadow_filter_set_quality(RenderingServer.SHADOW_QUALITY_SOFT_MEDIUM)
RenderingServer.positional_soft_shadow_filter_set_quality(RenderingServer.SHADOW_QUALITY_SOFT_MEDIUM)
2: # High
RenderingServer.directional_soft_shadow_filter_set_quality(RenderingServer.SHADOW_QUALITY_SOFT_HIGH)
RenderingServer.positional_soft_shadow_filter_set_quality(RenderingServer.SHADOW_QUALITY_SOFT_HIGH)
3: # Ultra
RenderingServer.directional_soft_shadow_filter_set_quality(RenderingServer.SHADOW_QUALITY_SOFT_ULTRA)
RenderingServer.positional_soft_shadow_filter_set_quality(RenderingServer.SHADOW_QUALITY_SOFT_ULTRA)
func apply_audio_settings():
var audio = settings.audio
set_bus_volume("Master", audio.master_volume)