Flutter Flame Priority值失效求助:组件层级显示异常
Flutter Flame 组件层级优先级问题
我在Flutter Flame开发中创建了Obstacle这个SpriteComponent,父类构造方法里设置了priority值为0。但该组件通过update方法重新生成,移出屏幕后再次出现时,priority值失效,导致Player显示在障碍物后方;同时GameOverPanel始终处于底层,无法正常显示在顶层。
核心游戏类代码
@override Future<void> onLoad() async { add(ScreenHitbox()); add(gameRef.homeBackgroundParallaxComponent); add(gameRef.homeBaseParallax); add(gameRef.obstacleManager..priority = 0); add(gameRef.playerManager..priority = 1); add(gameRef.gameOverPanel..priority = 2); } @override void update(double dt) { super.update(dt); gameRef.obstacleManager.updateObstacle(GameConst.gameSpeed * dt); gameRef.playerManager.changePositionDown(value: GameConst.gravity * dt); }
GameOverPanel 初始代码
class GameOverPanel extends Component with HasGameRef<HopyBirdGame> { GameOverPanel() : super(priority: 4); @override Future<void> onLoad() async { add(GameOverText()); } @override void renderTree(Canvas canvas) { if (gameRef.gameOver) { super.renderTree(canvas); } } } class GameOverText extends SpriteComponent with HasGameRef<HopyBirdGame> { GameOverText() : super(size: Vector2(300, 80), anchor: Anchor.center); @override Future<void>? onLoad() async { sprite = await gameRef.loadSprite(Assets.gameOver.path); position = Vector2(gameRef.screenWidth / 2, gameRef.screenHeight / 2); return super.onLoad(); } }
Obstacle 相关代码
Obstacle 类
class Obstacle extends SpriteComponent with HasGameRef<HopyBirdGame>, CollisionCallbacks { final ObstacleType obstacleType; Obstacle({ required this.obstacleType, super.position, super.priority, }) : super( size: Vector2(GameConst.obstacleWidth, GameConst.obstacleHeight), anchor: Anchor.center, ); Obstacle.empty({this.obstacleType = ObstacleType.empty}); @override Future<void> onLoad() async { switch (obstacleType) { case ObstacleType.up: sprite = await gameRef.loadSprite( Assets.redPipeUp.path, ); break; case ObstacleType.down: sprite = await gameRef.loadSprite( Assets.redPipeDown.path, ); break; case ObstacleType.empty: return; } add(RectangleHitbox()); } }
Obstacles 容器类
class Obstacles extends Component with HasGameRef<HopyBirdGame> { final Obstacle upObstacle; final Obstacle downObstacle; bool isCreateNextObstacles = true; Obstacles({ required this.upObstacle, required this.downObstacle, super.priority, }); @override Future<void>? onLoad() { upObstacle.priority = 1; downObstacle.priority = 1; createChildren(); return super.onLoad(); } void createChildren() { final children = [upObstacle, downObstacle]; addAll(children); } }
ObstacleManager 代码
class ObstacleManager extends Component with HasGameRef<HopyBirdGame> { ObstacleManager() : super(priority: 1); ListQueue<Obstacles> history = ListQueue(); @override Future<void> onLoad() async { createObstacles(); } void updateObstacle(double value) { if (!gameRef.gameOver) { if (history.isNotEmpty) { history.last.upObstacle.position.x -= value; history.last.downObstacle.position.x -= value; if (history.last.upObstacle.position.x <= gameRef.screenWidth / 2) { createObstacles(); final isThereAnyObstaclesOutsideScreen = history.any( (element) => element.downObstacle.position.x <= -(GameConst.obstacleWidth / 2), ); if (isThereAnyObstaclesOutsideScreen) { final obstaclesOutsideScreen = history .lastWhere((element) => element.downObstacle.position.x <= 0); obstaclesOutsideScreen.removeFromParent(); gameRef.remove(obstaclesOutsideScreen); } } if (history.length >= 2) { history.elementAt(history.length - 2).upObstacle.position.x -= value; history.elementAt(history.length - 2).downObstacle.position.x -= value; } } } } void createObstacles() { final obstaclesGap = gameRef.screenHeight - gameRef.difficulty.spaceForPlayers; final gapAboveTheObstacleOnScreen = ((2 * GameConst.obstacleHeight) - obstaclesGap) / 2; final randomNumber = _randomGenerator( min: -gameRef.difficulty.distanceAxisYToGoUpAndDown, max: gameRef.difficulty.distanceAxisYToGoUpAndDown, ); final axisYOfUpObstacle = (GameConst.obstacleHeight / 2) - gapAboveTheObstacleOnScreen + randomNumber; final axisYOfDownObstacle = axisYOfUpObstacle + GameConst.obstacleHeight + gameRef.difficulty.spaceForPlayers; final obstacles = Obstacles( upObstacle: Obstacle( obstacleType: ObstacleType.up, position: Vector2( gameRef.screenWidth + (GameConst.obstacleWidth / 2), axisYOfUpObstacle, ), ), downObstacle: Obstacle( obstacleType: ObstacleType.down, position: Vector2( gameRef.screenWidth + (GameConst.obstacleWidth / 2), axisYOfDownObstacle, ), ), ); history.add(obstacles); gameRef.add(obstacles); } double _randomGenerator({required double min, required double max}) { final gap = (max - min).toInt(); return min + Random().nextInt(gap); } }
编辑补充:修改后的 GameOverPanel 代码
class GameOverPanel extends Component with HasGameRef<HopyBirdGame> { GameOverPanel() : super(); @override Future<void> onLoad() async { add(GameOverText()); } @override void renderTree(Canvas canvas) { if (gameRef.gameOver) { super.renderTree(canvas); } } } class GameOverText extends SpriteComponent with HasGameRef<HopyBirdGame> { GameOverText() : super( size: Vector2(300, 80), anchor: Anchor.center, ); @override Future<void>? onLoad() async { sprite = await gameRef.loadSprite(Assets.gameOver.path); position = Vector2(gameRef.screenWidth / 2, gameRef.screenHeight / 2); return super.onLoad(); } }
内容的提问来源于stack exchange,提问作者tguzel
相关产品推荐
相关产品推荐

