226 lines
No EOL
6.8 KiB
Dart
226 lines
No EOL
6.8 KiB
Dart
import 'package:flame/components.dart';
|
|
import 'package:shitman/game/levels/shit_level.dart';
|
|
import 'package:shitman/game/components/level_components.dart';
|
|
import 'package:shitman/game/components/road_components.dart';
|
|
import 'package:shitman/game/components/house_components.dart';
|
|
import 'package:shitman/game/components/security_components.dart';
|
|
import 'dart:math';
|
|
|
|
/// Level 1: Operation Shitstorm
|
|
/// A grid-based neighborhood with various house types and security systems
|
|
class OperationShitstorm extends ShitLevel {
|
|
static const double cellSize = 100.0;
|
|
static const int gridWidth = 5;
|
|
static const int gridHeight = 5;
|
|
|
|
List<List<LevelComponent?>> levelGrid = [];
|
|
List<HouseComponent> houses = [];
|
|
TargetHouseComponent? currentTarget;
|
|
|
|
OperationShitstorm() : super(levelName: "Operation: Shitstorm", difficulty: 1);
|
|
|
|
@override
|
|
Future<void> initializeLevelComponents() async {
|
|
appLog.fine('Initializing Operation Shitstorm level layout');
|
|
|
|
// Initialize the grid
|
|
levelGrid = List.generate(
|
|
gridHeight,
|
|
(row) => List.generate(gridWidth, (col) => null),
|
|
);
|
|
|
|
// Create the level layout
|
|
await createLevelLayout();
|
|
|
|
// Add all components to the level
|
|
await addComponentsToLevel();
|
|
|
|
// Initialize core components (player, etc.)
|
|
await super.initializeLevelComponents();
|
|
|
|
// Select a random target house
|
|
selectRandomTarget();
|
|
|
|
appLog.fine('Operation Shitstorm level initialized');
|
|
}
|
|
|
|
Future<void> createLevelLayout() async {
|
|
// Create a simple grid layout:
|
|
// H = House, R = Road (various types), I = Intersection
|
|
// Layout pattern:
|
|
// H R H R H
|
|
// R I R I R
|
|
// H R H R H
|
|
// R I R I R
|
|
// H R H R H
|
|
|
|
for (int row = 0; row < gridHeight; row++) {
|
|
for (int col = 0; col < gridWidth; col++) {
|
|
final gridPos = Vector2(col.toDouble(), row.toDouble());
|
|
|
|
if (row % 2 == 0) { // Even rows: Houses and vertical roads
|
|
if (col % 2 == 0) {
|
|
// House position
|
|
levelGrid[row][col] = createRandomHouse(gridPos);
|
|
} else {
|
|
// Vertical road
|
|
levelGrid[row][col] = VerticalRoad(gridPosition: gridPos);
|
|
}
|
|
} else { // Odd rows: Horizontal roads and intersections
|
|
if (col % 2 == 0) {
|
|
// Horizontal road
|
|
levelGrid[row][col] = HorizontalRoad(gridPosition: gridPos);
|
|
} else {
|
|
// Intersection
|
|
levelGrid[row][col] = IntersectionRoad(gridPosition: gridPos);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
HouseComponent createRandomHouse(Vector2 gridPos) {
|
|
final random = Random();
|
|
final houseTypes = HouseType.values;
|
|
final selectedType = houseTypes[random.nextInt(houseTypes.length)];
|
|
|
|
final house = HouseComponent(
|
|
gridPosition: gridPos,
|
|
houseType: selectedType,
|
|
);
|
|
|
|
// Randomly add security systems to some houses
|
|
if (random.nextDouble() < 0.4) { // 40% chance of security
|
|
addRandomSecurityToHouse(house, random);
|
|
}
|
|
|
|
houses.add(house);
|
|
return house;
|
|
}
|
|
|
|
void addRandomSecurityToHouse(HouseComponent house, Random random) {
|
|
final securityTypes = random.nextInt(3); // 0-2 different security types
|
|
|
|
switch (securityTypes) {
|
|
case 0:
|
|
// PIR sensor
|
|
final pirSensor = PIRSensorComponent(
|
|
position: Vector2(house.size.x * 0.9, house.size.y * 0.1),
|
|
);
|
|
house.addSecuritySystem(pirSensor);
|
|
break;
|
|
case 1:
|
|
// Security camera
|
|
final camera = SecurityCameraComponent(
|
|
position: Vector2(house.size.x * 0.9, house.size.y * 0.1),
|
|
direction: _getOptimalCameraDirection(house),
|
|
);
|
|
house.addSecuritySystem(camera);
|
|
break;
|
|
case 2:
|
|
// Guard dog
|
|
final dog = GuardDogComponent(
|
|
position: Vector2(-20, house.size.y + 10),
|
|
patrolCenter: Vector2(-20, house.size.y + 10),
|
|
);
|
|
house.addSecuritySystem(dog);
|
|
break;
|
|
}
|
|
}
|
|
|
|
double _getOptimalCameraDirection(HouseComponent house) {
|
|
// Point camera towards center of level
|
|
final levelCenter = Vector2(gridWidth * cellSize / 2, gridHeight * cellSize / 2);
|
|
final houseCenter = house.getWorldPosition(cellSize) + house.size / 2;
|
|
final toCenter = levelCenter - houseCenter;
|
|
return atan2(toCenter.y, toCenter.x);
|
|
}
|
|
|
|
Future<void> addComponentsToLevel() async {
|
|
for (int row = 0; row < gridHeight; row++) {
|
|
for (int col = 0; col < gridWidth; col++) {
|
|
final component = levelGrid[row][col];
|
|
if (component != null) {
|
|
// Set world position based on grid position
|
|
component.position = component.getWorldPosition(cellSize);
|
|
add(component);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void selectRandomTarget() {
|
|
if (houses.isEmpty) return;
|
|
|
|
// Clear previous target
|
|
currentTarget?.setAsTarget(false);
|
|
|
|
// Convert a random house to a target house
|
|
final random = Random();
|
|
final randomHouse = houses[random.nextInt(houses.length)];
|
|
|
|
// Remove the old house and create a new target house at the same position
|
|
remove(randomHouse);
|
|
houses.remove(randomHouse);
|
|
|
|
currentTarget = TargetHouseComponent(
|
|
gridPosition: randomHouse.gridPosition,
|
|
houseType: randomHouse.houseType,
|
|
);
|
|
currentTarget!.position = randomHouse.position;
|
|
currentTarget!.setAsTarget(true);
|
|
|
|
// Copy security systems
|
|
for (final security in randomHouse.securitySystems) {
|
|
currentTarget!.addSecuritySystem(security);
|
|
}
|
|
|
|
add(currentTarget!);
|
|
houses.add(currentTarget!);
|
|
|
|
appLog.info('Target selected at grid position ${currentTarget!.gridPosition}');
|
|
}
|
|
|
|
@override
|
|
Future<void> onLevelStart() async {
|
|
appLog.info('Starting Operation: Shitstorm');
|
|
// Level-specific start logic can be added here
|
|
}
|
|
|
|
@override
|
|
Future<void> onLevelEnd() async {
|
|
appLog.info('Operation: Shitstorm completed');
|
|
// Level-specific end logic can be added here
|
|
}
|
|
|
|
@override
|
|
Future<void> reset() async {
|
|
await super.reset();
|
|
|
|
// Clear level-specific data
|
|
levelGrid.clear();
|
|
houses.clear();
|
|
currentTarget = null;
|
|
|
|
// Recreate the level
|
|
await createLevelLayout();
|
|
await addComponentsToLevel();
|
|
selectRandomTarget();
|
|
|
|
appLog.fine('Operation Shitstorm level reset');
|
|
}
|
|
|
|
/// Get the current target house position
|
|
Vector2? getTargetPosition() {
|
|
return currentTarget?.doorPosition;
|
|
}
|
|
|
|
/// Check if player is near the target
|
|
bool isPlayerNearTarget(Vector2 playerPosition, {double threshold = 50.0}) {
|
|
final targetPos = getTargetPosition();
|
|
if (targetPos == null) return false;
|
|
|
|
final distance = (playerPosition - targetPos).length;
|
|
return distance < threshold;
|
|
}
|
|
} |