import 'package:flame/components.dart';
import 'package:flame/input.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flame/game.dart';
import 'package:flame/events.dart';
class Player extends CircleComponent with KeyboardHandler {
final double speed = 200;
Vector2 worldSize;
Player({
required this.worldSize,
required Vector2 position,
required double radius,
required Color color,
}) : super(
position: position,
radius: radius,
paint: Paint()..color = color,
priority: 1,
);
@override
bool onKeyEvent(KeyEvent event, Set<LogicalKeyboardKey> keysPressed) {
final direction = Vector2.zero();
if (keysPressed.contains(LogicalKeyboardKey.arrowLeft)) {
direction.x -= 1;
}
if (keysPressed.contains(LogicalKeyboardKey.arrowRight)) {
direction.x += 1;
}
if (keysPressed.contains(LogicalKeyboardKey.arrowUp)) {
direction.y -= 1;
}
if (keysPressed.contains(LogicalKeyboardKey.arrowDown)) {
direction.y += 1;
}
if (direction.isZero()) return false;
direction.normalize();
position += direction * speed * 1 / 60;
position.clamp(
Vector2(radius, radius),
Vector2(worldSize.x - radius, worldSize.y - radius),
);
return true;
}
}
class Portal extends RectangleComponent with TapCallbacks {
final Vector2 targetPosition;
final int targetWorldIndex;
Portal({
required Vector2 position,
required Vector2 size,
required this.targetPosition,
required this.targetWorldIndex,
}) : super(
position: position,
size: size,
paint: Paint()..color = Colors.purple,
priority: 0,
);
@override
bool onTapDown(TapDownEvent event) {
final player = parent?.children.whereType<Player>().first;
if (player != null) {
final game = findGame() as MyPortalGame;
game.switchWorld(targetPosition, targetWorldIndex);
}
return true;
}
}
class WorldFactory {
static World createWorld(int index) {
switch (index) {
case 0:
return MyWorld();
case 1:
return SecondWorld();
case 2:
return ThirdWorld();
default:
throw Exception('Unknown world index: $index');
}
}
}
class MyWorld extends World {
final Vector2 size = Vector2(800, 600);
@override
Future<void> onLoad() async {
add(RectangleComponent(
position: Vector2.zero(),
size: size,
paint: Paint()..color = Colors.lightBlue,
priority: -1,
));
add(Portal(
position: Vector2(700, 500),
size: Vector2(50, 50),
targetPosition: Vector2(100, 100),
targetWorldIndex: 1,
));
}
}
class SecondWorld extends World {
final Vector2 size = Vector2(1200, 800);
@override
Future<void> onLoad() async {
add(RectangleComponent(
position: Vector2.zero(),
size: size,
paint: Paint()..color = Colors.lightGreen,
priority: -1,
));
add(Portal(
position: Vector2(100, 100),
size: Vector2(50, 50),
targetPosition: Vector2(700, 500),
targetWorldIndex: 0,
));
add(Portal(
position: Vector2(1000, 700),
size: Vector2(50, 50),
targetPosition: Vector2(100, 100),
targetWorldIndex: 2,
));
}
}
class ThirdWorld extends World {
final Vector2 size = Vector2(1000, 700);
@override
Future<void> onLoad() async {
add(RectangleComponent(
position: Vector2.zero(),
size: size,
paint: Paint()..color = Colors.orange,
priority: -1,
));
add(Portal(
position: Vector2(100, 100),
size: Vector2(50, 50),
targetPosition: Vector2(1000, 700),
targetWorldIndex: 1,
));
}
}
class MyPortalGame extends FlameGame with HasKeyboardHandlerComponents {
late List<World> worlds;
late Player player;
int currentWorldIndex = 0;
@override
Future<void> onLoad() async {
// Создаем миры
worlds = List.generate(3, (index) => WorldFactory.createWorld(index));
// Создаем игрока
player = Player(
worldSize: (worlds[0] as MyWorld).size,
position: (worlds[0] as MyWorld).size / 2,
radius: 20,
color: Colors.red,
);
// Загружаем первый мир
await add(worlds[0]);
await worlds[0].onLoad();
worlds[0].add(player);
// Настраиваем камеру
camera = CameraComponent.withFixedResolution(
width: 800,
height: 600,
world: worlds[0],
);
// Центрируем камеру
camera.viewfinder.anchor = Anchor.center;
camera.follow(player);
}
@override
void update(double dt) {
super.update(dt);
if (player.isMounted) {
camera.follow(player);
}
}
Future<void> switchWorld(Vector2 targetPosition, int targetWorldIndex) async {
// Удаляем текущий мир
worlds[currentWorldIndex].removeFromParent();
// Переключаемся на целевой мир
currentWorldIndex = targetWorldIndex;
// Создаем новый экземпляр мира
worlds[currentWorldIndex] = WorldFactory.createWorld(currentWorldIndex);
// Добавляем следующий мир
final newWorld = worlds[currentWorldIndex];
await add(newWorld);
await newWorld.onLoad();
// Обновляем размер мира для игрока
player.worldSize = (newWorld as dynamic).size;
// Добавляем игрока в новый мир и обновляем его позицию
newWorld.add(player);
player.position = targetPosition;
// Обновляем камеру
camera.world = newWorld;
camera.follow(player);
}
}
void main() {
runApp(GameWidget(
game: MyPortalGame(),
));
}