159 lines
3.9 KiB
Dart
159 lines
3.9 KiB
Dart
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<void> 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<void> startGame() async {
|
|
gameState = GameState.playing;
|
|
await initializeLevel();
|
|
}
|
|
|
|
Future<void> 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<void> 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<LogicalKeyboardKey> 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
|
|
}
|
|
}
|