You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flame中对象添加到Game与World时位置不同的原因?

Flame中组件添加到Game与World的位置差异原因

当设置CircleComponent的坐标为Vector2(0, 0)时,直接添加到FlameGame会渲染在屏幕左上角,而添加到world却显示在屏幕中心,核心原因是相机变换的作用范围不同:

1. 直接添加到FlameGame的组件

FlameGame的根坐标系原点(0,0)就是屏幕的左上角,直接添加到Game的组件处于根层级,不受相机变换影响,所以设置position: Vector2(0,0)会让组件对齐屏幕左上角。

对应的代码示例:

import 'package:flame/components.dart';
import 'package:flame/game.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const FooApp());
}

class FooApp extends StatelessWidget {
  const FooApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: GameWidget.controlled(gameFactory: FooFlameGame.new),
    );
  }
}

class FooFlameGame extends FlameGame {
  late final CircleComponent _circle;

  @override
  Future<void> onLoad() async {
    super.onLoad();

    _circle = CircleComponent(
      position: Vector2(0, 0),
      radius: 44,
    );
    await add(_circle); // 直接添加到Game
  }
}

渲染结果:圆形组件显示在屏幕左上角

2. 添加到World的组件

FlameGame默认自带一个World组件,并且默认通过CameraComponent对World进行渲染,而CameraComponent的centered属性默认是true——这个设置会将World的原点(0,0)映射到屏幕中心位置。

所以添加到World的组件,其坐标会经过相机的变换,最终(0,0)位置会显示在屏幕中心。

对应的代码示例:

import 'package:flame/components.dart';
import 'package:flame/game.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const FooApp());
}

class FooApp extends StatelessWidget {
  const FooApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: GameWidget.controlled(gameFactory: FooFlameGame.new),
    );
  }
}

class FooFlameGame extends FlameGame {
  late final CircleComponent _circle;

  @override
  Future<void> onLoad() async {
    super.onLoad();

    _circle = CircleComponent(
      position: Vector2(0, 0),
      radius: 44,
    );
    await world.add(_circle); // 添加到World
  }
}

渲染结果:圆形组件显示在屏幕中心

额外验证:关闭相机居中

如果想让World中的组件也对齐屏幕左上角,可以修改相机的centered属性为false,示例代码:

@override
Future<void> onLoad() async {
  super.onLoad();
  camera.viewfinder.centered = false; // 关闭相机居中

  _circle = CircleComponent(
    position: Vector2(0, 0),
    radius: 44,
  );
  await world.add(_circle);
}

此时World的原点会和屏幕左上角对齐,组件(0,0)会显示在左上角。

内容的提问来源于stack exchange,提问作者shingo.nakanishi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 17:35:15