Flutter Flame相机无法跟随玩家问题求助
相机无法跟随Flame玩家的解决方案
问题根源
- 全局维护玩家位置状态(
birdX/birdY)并在update中直接覆盖player.position,外部强制赋值可能导致相机无法正确监听玩家位置变更。 - 将
camera.follow移到update中重复调用,会创建多个跟随控制器引发冲突报错。
解决方案
将玩家的运动逻辑封装到组件内部,仅在初始化时调用一次相机跟随。
修改后的Player组件
import 'package:flame/components.dart'; import 'package:flutter/material.dart'; class Player extends PositionComponent { final VoidCallback collisionCallback; double speedY = 0; // 可根据需求调整玩家大小 Player({required Vector2 position, required this.collisionCallback}) : super(position: position, size: Vector2(50, 50)); void flap() { speedY = -5; } @override void update(double dt) { // 组件内部处理垂直运动逻辑 position.y += speedY; speedY += 0.1; super.update(dt); } }
修改后的MainGame代码
import 'dart:async'; import 'dart:math'; import 'package:flame/events.dart'; import 'package:flame/flame.dart'; import 'package:flame/game.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:whirlybird/components/obstacle.dart'; import 'package:whirlybird/components/player.dart'; class GameScreen extends StatelessWidget { const GameScreen({super.key}); @override Widget build(BuildContext context) { return GameWidget( game: MainGame(), ); } } class MainGame extends FlameGame with HorizontalDragDetector, HasCollisionDetection, TapDetector { @override Color backgroundColor() => Colors.white; late double touchDownX; late final Player player; @override bool get debugMode => kDebugMode; @override void onRemove() { Flame.images.clearCache(); Flame.assets.clearCache(); super.onRemove(); } @override FutureOr<void> onLoad() async { // 生成障碍物 final random = Random(); for (int i = 0; i < 10; i++) { final x = random.nextDouble() * (size[0] - 10) + 10; final y = random.nextDouble() * (size[1] - 10) + 10; add(Obstacle(positionVector: Vector2(x, y))); } // 创建并添加玩家 player = Player( position: Vector2(50, 500), collisionCallback: flap, ); add(player); // 配置相机跟随:以玩家为中心,关闭平滑过渡方便测试 camera.follow(player, anchor: Anchor.center, maxSpeed: double.infinity); return super.onLoad(); } void flap() { player.flap(); } @override void onHorizontalDragDown(DragDownInfo info) { touchDownX = info.raw.globalPosition.dx; } @override void onHorizontalDragUpdate(DragUpdateInfo info) { double touchX = info.raw.globalPosition.dx; double deltaX = touchX - touchDownX; // 直接修改玩家水平位置 player.position.x += deltaX; touchDownX = touchX; } @override void update(double dt) { // 玩家垂直运动逻辑已移至组件内部,此处无需额外处理 super.update(dt); } }
关键修改说明
- 组件化封装:将玩家的垂直运动、速度状态移到
Player组件内部,让组件自行管理位置更新,确保相机能正确监听位置变化。 - 相机跟随配置:仅在
onLoad中调用一次camera.follow,通过anchor: Anchor.center让相机以玩家为中心,maxSpeed: double.infinity关闭平滑跟随(如需平滑效果可改为具体数值,如200)。 - 移除全局状态:删除全局的
birdX/birdY/birdSpeed,直接操作player.position处理水平拖拽,代码结构更符合Flame组件化设计规范。
内容的提问来源于stack exchange,提问作者Yaros
相关产品推荐
相关产品推荐

