You need to enable JavaScript to run this app. 如何使用Flame库为单词搜索游戏的方格添加蓝色半透明覆盖层
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Flame库为单词搜索游戏的方格添加蓝色半透明覆盖层

问题原因

你的代码无法达到预期效果主要有三个核心问题:

  1. 每次触摸方格都会新增一个Box2覆盖层,同一个位置多次叠加后半透明效果累加,最终变成几乎完全不透明,遮挡下层文字
  2. Box2设置的锚点是Anchor.center,而你直接复用了Box组件的x/y坐标赋值,导致覆盖层和方格位置错位,进一步放大了遮挡问题
  3. 新增的Box2组件层级始终高于先添加的Box文字组件,文字默认在下层,自然会被上层的覆盖层遮挡

最优解决方案(复杂度最低)

不需要额外新增Box2组件,直接改造原有Box组件的渲染逻辑即可,通过状态控制是否绘制半透明覆盖层:

  1. 给Box组件新增isSelected选中状态标记
  2. 在Box的渲染逻辑中,先绘制方格背景,选中状态下绘制半透明蓝色覆盖层,最后绘制文字,保证文字永远在最上层不会被遮挡
  3. 触摸事件中直接修改对应Box的选中状态即可,不需要新增任何组件

改造后的代码示例

1. 改造Box组件
class Box extends PositionComponent {
  final String text;
  // 新增选中状态标记
  bool isSelected = false;
  static const squareSize = 50.0;
  // 文字绘制工具
  final TextPaint _textPainter = TextPaint(
    style: const TextStyle(color: Colors.black, fontSize: 24, fontWeight: FontWeight.bold),
  );

  Box({
    required this.text,
    Vector2? position,
  }) : super(
    size: Vector2.all(squareSize),
    position: position,
    // 统一使用topLeft锚点,避免位置计算混乱
    anchor: Anchor.topLeft,
  );

  @override
  void render(Canvas c) {
    super.render(c);
    // 1. 绘制方格默认背景
    c.drawRect(
      Rect.fromLTWH(2, 2, size.x - 4, size.y - 4),
      PaletteEntry(Colors.white).paint(),
    );
    // 2. 选中状态下绘制半透明蓝色覆盖层
    if (isSelected) {
      c.drawRect(
        Rect.fromLTWH(2, 2, size.x - 4, size.y - 4),
        PaletteEntry(Colors.blue.withOpacity(0.5)).paint(),
      );
    }
    // 3. 最后绘制文字,保证文字在最上层
    _textPainter.render(
      c,
      text,
      Vector2(size.x/2 - 7, size.y/2 - 12),
    );
  }
}
2. 简化触摸事件逻辑
@override
void onPanDown(DragDownInfo info) {
  final touchPos = info.eventPosition.game;
  // 遍历所有Box组件,选中触摸位置的方格
  components.whereType<Box>().forEach((box) {
    if (box.toRect().contains(touchPos)) {
      box.isSelected = true;
    }
  });
  super.onPanDown(info);
}

@override
void onPanUpdate(DragUpdateInfo info) {
  final touchPos = info.eventPosition.game;
  components.whereType<Box>().forEach((box) {
    if (box.toRect().contains(touchPos) && !box.isSelected) {
      box.isSelected = true;
    }
  });
  super.onPanUpdate(info);
}

如果需要在滑动结束后清除选中状态,只需要在onPanEnd和onPanCancel中遍历所有Box把isSelected设为false即可。

内容的提问来源于stack exchange,提问作者Trần Văn Hiếu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.13 18:45:00