import 'package:flame/game.dart'; import 'package:flame/components.dart'; import 'package:flame/events.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:shitman/game/components/player.dart'; import 'package:shitman/game/levels/operation_shitstorm.dart'; import 'package:shitman/game/shitman_world.dart'; import 'package:shitman/settings/app_settings.dart'; /// Shitman Game /// A 2D top-down "hitman" style game, but instead of assassinating people, /// your objective is to place flaming bags of dog poop on the doorsteps of /// your targets without getting caught. enum GameState { mainMenu, playing, paused, gameOver, missionComplete } class ShitmanGame extends FlameGame with HasKeyboardHandlerComponents, HasCollisionDetection, AppSettings { late Player player; late OperationShitstorm currentLevel; late CameraComponent gameCamera; GameState gameState = GameState.mainMenu; int missionScore = 0; int totalMissions = 0; bool infiniteMode = false; @override Future onLoad() async { await super.onLoad(); await initSettings(); world = ShitmanWorld(); // Setup camera gameCamera = CameraComponent.withFixedResolution( world: world, width: 800, height: 600, ); camera = gameCamera; addAll([world]); // Initialize debug mode from settings try { debugMode = appSettings.getBool('game.debug_mode'); } catch (e) { debugMode = false; // Fallback if settings not ready } } Future startGame() async { gameState = GameState.playing; await initializeLevel(); } Future startInfiniteMode() async { infiniteMode = true; overlays.remove('MainMenu'); overlays.add('InGameUI'); await startGame(); } void stopGame() { gameState = GameState.mainMenu; world.removeAll(world.children); missionScore = 0; } void pauseGame() { gameState = GameState.paused; } void resumeGame() { gameState = GameState.playing; } Future initializeLevel() async { // Clear previous level world.removeAll(world.children); // Create the Operation Shitstorm level currentLevel = OperationShitstorm(); // Add and wait for the level to load await world.add(currentLevel); // Start the level await currentLevel.startLevel(); // Get the player from the level player = currentLevel.player; // Setup camera to follow player gameCamera.follow(player); } void completeCurrentMission() { gameState = GameState.missionComplete; missionScore += 100; totalMissions++; if (infiniteMode) { // Generate new mission after delay, but keep allowing input Future.delayed(Duration(seconds: 2), () { currentLevel.selectRandomTarget(); gameState = GameState.playing; }); } } void failMission() { gameState = GameState.gameOver; // TODO: Show game over screen } @override KeyEventResult onKeyEvent( KeyEvent event, Set keysPressed, ) { super.onKeyEvent(event, keysPressed); if (gameState != GameState.playing && gameState != GameState.missionComplete && gameState != GameState.gameOver) { return KeyEventResult.ignored; } // Handle pause if (keysPressed.contains(LogicalKeyboardKey.escape)) { pauseGame(); overlays.add('PauseMenu'); return KeyEventResult.handled; } // Handle player input player.handleInput(keysPressed); // Handle action keys on key down if (event is KeyDownEvent) { player.handleAction(event.logicalKey); } // Mission completion is now handled by the player's escape sequence // No automatic completion when near target return KeyEventResult.handled; } @override void update(double dt) { super.update(dt); // Only update game logic when playing if (gameState != GameState.playing) return; // Game-specific update logic here } }