首页 > 解决方案 > 如何通过火焰库在正方形上制作蓝色半透明覆盖

问题描述

我想创建一个单词搜索游戏。我正在研究一个火焰库来做到这一点。我有一个问题,如何在正方形上制作蓝色半透明覆盖层。我试过了:

class Box2 extends PositionComponent {
  static const speed = 0.25;
  static const squareSize = 50.0;



  Box2({double size = 50}){
    height =size;
    width = size;
  }

  @override
  void render(Canvas c) {
    prepareCanvas(c);
    c.drawRect(Rect.fromLTWH(2, 2, width - 4, height - 4), PaletteEntry(Colors.green.withOpacity(0.5)).paint());

  }

  @override
  void update(double t) {
    super.update(t);
  }

  @override
  void onMount() {
    super.onMount();
    size.setValues(squareSize, squareSize);
    anchor = Anchor.center;
  }
}

class MyGame extends BaseGame with  PanDetector {

  bool running = true;


  var display =[
    ["S","T","A","R","T"],
    ["S","U","A","R","I"],
    ["C","H","N","P","T"],
    ["I","K","N","R","0"],
    ["S","H","L","R","U"],
  ];

  @override
  // TODO: implement size
  Vector2 get size => super.size;

   void generateBox(){
     double initialWidth =  (size[0]*1.1-(50*display.length))/2;
     double initialHeight =  (size[1]*1.1-(50*display.length))/2;
    for(int i=0 ;i< display.length;i++){
      for(int j=0 ;j< display.length;j++){
        add(Box(text:display[i][j])..position=
        Vector2(initialWidth +i.toDouble()*50, initialHeight+ j.toDouble()*50));
      }
    }

  }

  Future<void> onLoad() async {
    generateBox();
  }

  @override
  void onPanStart(DragStartInfo info) {
    super.onPanStart(info);
  }

  @override
  void onPanUpdate(DragUpdateInfo info) {

    final touchArea = RectExtension.fromVector2Center(
      center: info.eventPosition.game,
      width: 0,
      height: 0,
    );

    final handled = components.any((c) {
      if (c is PositionComponent && c.toRect().overlaps(touchArea)) {
        if (c is Box) {
          debugPrint("remove");

          add(Box2()..y= c.y
            ..x =c.x);
        }
      
        return true;
      }
      return false;
    });
    debugPrint("onPanUpdate  ${info.delta.game}");
    super.onPanUpdate(info);
  }

  void onPanDown(DragDownInfo info) {
     debugPrint("Pandown");

     final touchArea = RectExtension.fromVector2Center(
      center: info.eventPosition.game,
      width: 0,
      height: 0,
    );

    final handled = components.any((c) {
      if (c is PositionComponent && c.toRect().overlaps(touchArea)) {
        if (c is Box) {
          
          add(Box2()..y= c.y
          ..x =c.x);
        }
        debugPrint(c.toString());
        return true;
      }
      return false;
    });
  }

  void onPanEnd(DragEndInfo info) {
    debugPrint("onPanEnd");
  }
  void onPanCancel() {
    debugPrint("onPanCancel");
  }
}

我没有达到我所希望的。我希望如下: 图片

但我的代码生成如下: 图片 2 它完全掩盖了下面的字母!!!

我正在寻找另一个不那么复杂并且做我想做的事情的想法。

标签: flutterflame

解决方案


这是因为您在Box2彼此之上添加了许多,因为onPanUpdate在事件期间多次调用该方法,并且所有这些彼此之上的不透明度变为纯绿色。

而不是有这个Box2类,我只会bool isMarked在你的Box类上添加一个字段,然后你什么时候isMarked渲染true你的绿色矩形,上面不透明。

像这样的东西:

class Box extends PositionComponent {
  ...
  vool isMarked = false;

  @override
  void render(Canvas c) {
    super.render(c);
    // Do what you normally render in Box here

    // Render the green rectangle with opacity on top of your normal render
    if (isMarked) {
      c.drawRect(Rect.fromLTWH(2, 2, width - 4, height - 4), PaletteEntry(Colors.green.withOpacity(0.5)).paint());
    }
  }
  
  ...
}

然后在你的游戏课上做这样的事情:

class MyGame extends BaseGame with PanDetector {

  ...

  @override
  void onPanUpdate(DragUpdateInfo info) {
    super.onPanUpdate(info);
    final touchArea = RectExtension.fromVector2Center(
      center: info.eventPosition.game,
      width: 0,
      height: 0,
    );

    final handled = components.any((c) {
      if (c is PositionComponent && c.toRect().overlaps(touchArea)) {
        if (c is Box) {
          debugPrint("remove");
          c.isMarked = true;
        }
      
        return true;
      }
      return false;
    });
    debugPrint("onPanUpdate  ${info.delta.game}");
  }

  void onPanDown(DragDownInfo info) {
     debugPrint("Pandown");

     final touchArea = RectExtension.fromVector2Center(
      center: info.eventPosition.game,
      width: 0,
      height: 0,
    );

    final handled = components.any((c) {
      if (c is PositionComponent && c.toRect().overlaps(touchArea)) {
        if (c is Box) {
          c.isMarked = true;
        }
        debugPrint(c.toString());
        return true;
      }
      return false;
    });
  }

  void onPanEnd(DragEndInfo info) {
    removeMarkings();
  }

  void onPanCancel() {
    removeMarkings();
  }

  void removeMarkings() {
    components.whereType<Box>().forEach((box) => box.isMarked = false);
  }
}

(在 s 所在的位置填写其余代码...)。


推荐阅读