shitman/lib/ui/in_game_ui.dart
zeyus 76408247b0
Some checks failed
/ build-web (push) Has been cancelled
some basic movement
2025-07-22 22:35:21 +02:00

417 lines
14 KiB
Dart

import 'package:flutter/material.dart';
import 'package:nes_ui/nes_ui.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:shitman/game/shitman_game.dart';
import 'package:shitman/settings/app_settings.dart';
class InGameUI extends StatelessWidget with AppSettings {
static const String overlayID = 'InGameUI';
final ShitmanGame game;
InGameUI(this.game, {super.key});
@override
Widget build(BuildContext context) {
return Material(
color: Colors.transparent,
child: Stack(
children: [
// Top HUD
Positioned(
top: 20,
left: 20,
right: 20,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
// Stealth indicator
NesContainer(
backgroundColor: Colors.black87,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Icon(Icons.visibility_off, size: 16),
SizedBox(width: 8),
Text('gameplay.hidden'.tr(), style: TextStyle(color: Colors.green)),
],
),
),
),
// Mission objective
NesContainer(
backgroundColor: Colors.black87,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text('gameplay.find_target'.tr(), style: TextStyle(color: Colors.white)),
),
),
// Pause button
IconButton(
icon: Icon(Icons.pause, color: Colors.white),
onPressed: () => game.overlays.add(PauseMenuUI.overlayID),
),
],
),
),
// Bottom controls hint
Positioned(
bottom: 20,
left: 20,
right: 20,
child: NesContainer(
backgroundColor: Colors.black54,
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text('controls.move'.tr(), style: TextStyle(color: Colors.white)),
Text('controls.place_bag'.tr(), style: TextStyle(color: Colors.white)),
Text('controls.ring_bell'.tr(), style: TextStyle(color: Colors.white)),
],
),
),
),
),
],
),
);
}
}
class MainMenuUI extends StatelessWidget with AppSettings {
static const String overlayID = 'MainMenu';
final ShitmanGame game;
MainMenuUI(this.game, {super.key});
@override
Widget build(BuildContext context) {
return Material(
color: Colors.black,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Game title
Text(
'game.title'.tr(),
style: Theme.of(context).textTheme.headlineLarge?.copyWith(
color: Colors.orange,
fontSize: 48,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 8),
Text(
'game.subtitle'.tr(),
style: TextStyle(color: Colors.white70, fontSize: 16),
),
SizedBox(height: 40),
// Menu buttons
Column(
children: [
NesButton(
type: NesButtonType.primary,
onPressed: () {
game.overlays.remove(MainMenuUI.overlayID);
game.overlays.add(InGameUI.overlayID);
game.startGame();
},
child: Text('menu.start_mission'.tr()),
),
SizedBox(height: 16),
NesButton(
type: NesButtonType.normal,
onPressed: () {
game.overlays.remove(MainMenuUI.overlayID);
game.overlays.add(SettingsUI.overlayID);
},
child: Text('menu.settings'.tr()),
),
SizedBox(height: 16),
NesButton(
type: NesButtonType.normal,
onPressed: () => game.startInfiniteMode(),
child: Text('menu.infinite_mode'.tr()),
),
],
),
SizedBox(height: 40),
Text(
'game.description'.tr(),
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white54, fontSize: 12),
),
],
),
),
);
}
}
class SettingsUI extends StatefulWidget with AppSettings {
static const String overlayID = 'Settings';
final ShitmanGame game;
SettingsUI(this.game, {super.key});
@override
State<SettingsUI> createState() => _SettingsUIState();
}
class _SettingsUIState extends State<SettingsUI> with AppSettings {
bool showVisionCones = false;
bool showDetectionRadius = false;
bool debugMode = false;
@override
void initState() {
super.initState();
_loadSettings();
}
void _loadSettings() {
try {
showVisionCones = widget.game.appSettings.getBool('game.show_vision_cones');
showDetectionRadius = widget.game.appSettings.getBool('game.show_detection_radius');
debugMode = widget.game.appSettings.getBool('game.debug_mode');
} catch (e) {
// Settings not ready, use defaults
showVisionCones = false;
showDetectionRadius = false;
debugMode = false;
}
}
@override
Widget build(BuildContext context) {
return Material(
color: Colors.black87,
child: Center(
child: NesContainer(
backgroundColor: Colors.black,
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'menu.settings'.tr(),
style: Theme.of(context).textTheme.headlineMedium?.copyWith(
color: Colors.white,
),
),
IconButton(
icon: Icon(Icons.close, color: Colors.white),
onPressed: () {
widget.game.overlays.remove(SettingsUI.overlayID);
widget.game.overlays.add(MainMenuUI.overlayID);
},
),
],
),
SizedBox(height: 24),
// Language selector
Text('Language / Sprog / Sprache:', style: TextStyle(color: Colors.white)),
SizedBox(height: 8),
NesDropdownMenu<String>(
initialValue: context.locale.languageCode,
entries: const [
NesDropdownMenuEntry(
value: 'en',
label: 'English',
),
NesDropdownMenuEntry(
value: 'da',
label: 'Dansk',
),
NesDropdownMenuEntry(
value: 'de',
label: 'Deutsch',
),
],
onChanged: (String? value) {
if (value != null) {
context.setLocale(Locale(value));
setState(() {});
}
},
),
SizedBox(height: 16),
// Gameplay Settings Section
Text(
'settings.gameplay'.tr(),
style: TextStyle(color: Colors.orange, fontSize: 16, fontWeight: FontWeight.bold),
),
SizedBox(height: 12),
// Vision Cones toggle
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('settings.show_vision_cones'.tr(), style: TextStyle(color: Colors.white)),
Text('settings.vision_cones_help'.tr(), style: TextStyle(color: Colors.white60, fontSize: 11)),
],
),
),
NesCheckBox(
value: showVisionCones,
onChange: (value) async {
setState(() {
showVisionCones = value;
});
await widget.game.appSettings.setBool('game.show_vision_cones', value);
},
),
],
),
SizedBox(height: 8),
// Detection Radius toggle
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('settings.show_detection_radius'.tr(), style: TextStyle(color: Colors.white)),
Text('settings.detection_help'.tr(), style: TextStyle(color: Colors.white60, fontSize: 11)),
],
),
),
NesCheckBox(
value: showDetectionRadius,
onChange: (value) async {
setState(() {
showDetectionRadius = value;
});
await widget.game.appSettings.setBool('game.show_detection_radius', value);
},
),
],
),
SizedBox(height: 20),
// Accessibility Section
Text(
'settings.accessibility'.tr(),
style: TextStyle(color: Colors.orange, fontSize: 16, fontWeight: FontWeight.bold),
),
SizedBox(height: 12),
// Debug mode toggle
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('ui.debug_mode'.tr(), style: TextStyle(color: Colors.white)),
NesCheckBox(
value: debugMode,
onChange: (value) async {
setState(() {
debugMode = value;
});
await widget.game.appSettings.setBool('game.debug_mode', value);
widget.game.debugMode = value;
},
),
],
),
SizedBox(height: 40),
Center(
child: NesButton(
type: NesButtonType.primary,
onPressed: () {
widget.game.overlays.remove(SettingsUI.overlayID);
widget.game.overlays.add(MainMenuUI.overlayID);
},
child: Text('menu.back_to_menu'.tr()),
),
),
],
),
),
),
),
);
}
}
class PauseMenuUI extends StatelessWidget {
static const String overlayID = 'PauseMenu';
final ShitmanGame game;
const PauseMenuUI(this.game, {super.key});
@override
Widget build(BuildContext context) {
return Material(
color: Colors.black54,
child: Center(
child: NesContainer(
backgroundColor: Colors.black,
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
'ui.paused'.tr(),
style: Theme.of(context).textTheme.headlineMedium?.copyWith(
color: Colors.white,
),
),
SizedBox(height: 24),
NesButton(
type: NesButtonType.primary,
onPressed: () => game.overlays.remove(PauseMenuUI.overlayID),
child: Text('menu.resume'.tr()),
),
SizedBox(height: 12),
NesButton(
type: NesButtonType.normal,
onPressed: () {
game.overlays.remove(PauseMenuUI.overlayID);
game.overlays.remove(InGameUI.overlayID);
game.overlays.add(SettingsUI.overlayID);
},
child: Text('menu.settings'.tr()),
),
SizedBox(height: 12),
NesButton(
type: NesButtonType.warning,
onPressed: () {
game.overlays.remove(PauseMenuUI.overlayID);
game.overlays.remove(InGameUI.overlayID);
game.overlays.add(MainMenuUI.overlayID);
game.stopGame();
},
child: Text('menu.main_menu'.tr()),
),
],
),
),
),
),
);
}
}