Flutter synthetic games

Time:2022-5-8

Flutter synthetic games
GitHub source address:https://github.com/CZXBigBrother/animals-merge-demo

Flutter synthetic games

init.gif

To realize the function, we need to understand the two shutter controls draggable and dragtarget

It can be seen from the literal meaning that draggable can be dragged, and dragtarget is the drag target, which is to receive the control of draggable

Flutter synthetic games

ddd.png

We can only receive controls that cannot be dragged. We can use dragtarget to receive data according to the onaccept method of the above code, and then refresh to the interface

DragTarget(
        onWillAccept: (data) {
          // print("data = $data onWillAccept --- 0");
          return data != null;
        },
        onAccept: (data) {
          HomeCoreModel.moveItem(widget.data, data);
        },
        onLeave: (data) {
          // print("data = $data onLeave --- 0");
        },
        builder: (context, candidateData, rejectedData) {
          return ItemView(data: widget.data);
        },
      )

Bool onwillaccept (data) will be called when draggable is slid over the dragtarget. Data is the data source carried by draggable. Judge whether to accept this data according to the conditions. If you want to receive it, return true;

Onaccept (data) will be called when draggable is slid over the dragtarget and the onwillaccept function returns true. You can handle the state change of the widget here;

Onleave (data) this method is called when draggable leaves above the dragtarget.
Author: calm a Qingda
Link: https://www.jianshu.com/p/267e030b265a
Source: developeppaper
The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.

It can drag and receive. We can nest draggable and dragtarget

return Draggable(
        data: widget.data,
        child: Container(
          width: sizeW,
          height: sizeW,
          child: DragTarget(
            onWillAccept: (data) {
              return data != null;
            },
            onAccept: (data) {
              HomeCoreModel.moveItem(widget.data, data);
            },
            onLeave: (data) {
              // print("data = $data onLeave ----- 1");
            },
            builder: (context, candidateData, rejectedData) {
              return ItemView(data: widget.data);
            },
          ),
        ),
        feedback: ItemView(
          data: widget.data,
          isDrag: true,
        ),
        childWhenDragging: ItemView(
          data: HomeItem(),
        ),
      );

Childwhendragging is a control that stays in place when dragging. Because we only display animals when dragging and leave a blank space in the original place, an object homeitem with empty data is passed when dragging
Feedback is a control in motion when dragging
Child is the content displayed at a fixed time

The following is how to create a drag control

class ItemDraggableTarget<HomeItem> extends StatefulWidget {
  HomeItem data;

  ItemDraggableTarget({@required this.data, Key key}) : super(key: key);

  @override
  State<StatefulWidget> createState() => _ItemDraggableTargetState(text: data);
}

class _ItemDraggableTargetState extends State<ItemDraggableTarget> {
  var text;

  _ItemDraggableTargetState({@required this.text});
  @override
  Widget build(BuildContext context) {
    if (0 == widget.data.level) {
      return DragTarget(
        onWillAccept: (data) {
          // print("data = $data onWillAccept --- 0");
          return data != null;
        },
        onAccept: (data) {
          HomeCoreModel.moveItem(widget.data, data);
        },
        onLeave: (data) {
          // print("data = $data onLeave --- 0");
        },
        builder: (context, candidateData, rejectedData) {
          return ItemView(data: widget.data);
        },
      );
    } else {
      return Draggable(
        data: widget.data,
        child: Container(
          width: sizeW,
          height: sizeW,
          child: DragTarget(
            onWillAccept: (data) {
              return data != null;
            },
            onAccept: (data) {
              HomeCoreModel.moveItem(widget.data, data);
            },
            onLeave: (data) {
              // print("data = $data onLeave ----- 1");
            },
            builder: (context, candidateData, rejectedData) {
              return ItemView(data: widget.data);
            },
          ),
        ),
        feedback: ItemView(
          data: widget.data,
          isDrag: true,
        ),
        childWhenDragging: ItemView(
          data: HomeItem(),
        ),
      );
    }
  }
}

The following is the control that displays the animal inside the drag control

class ItemView extends StatelessWidget {
  ItemView({Key key, this.data, this.isDrag = false}) : super(key: key);

  // static double sizeW = (ScreenService.width - 15 * 2 - 3 * 10) / 4;

  bool isDrag;
  HomeItem data;

  @override
  Widget build(BuildContext context) {
    return Container(
      width: sizeW,
      height: sizeW,
      child: Stack(
        children: <Widget>[
          Align(
            alignment: Alignment.center,
            child: data.level == 0
                ? Text("")
                : Image.asset(
              'assets/dogs/ic_dog_level${data.level}.png',
              // color: Colors.red,
              width: sizeW,
              height: sizeW,
            ),
          ),
          Align(
              alignment: Alignment.bottomRight,
              child: Offstage(
                offstage: isDrag || data.level == 0,
                child: Container(
                    alignment: Alignment.center,
                    width: 16,
                    height: 20,
                    decoration: BoxDecoration(
                        color: Colors.green,
                        borderRadius:
                        BorderRadius.all(const Radius.circular(15))),
                    child: Text(
                      '${data.level}',
                      style: TextStyle(color: Colors.white, fontSize: 12),
                    )),
              ))
        ],
      ),
      decoration: BoxDecoration(
          color: Color.fromRGBO(238, 239, 240, isDrag == false ? 1 : 0),
          borderRadius: BorderRadius.all(const Radius.circular(15))),
    );
  }
}

We can create a 3×4 two-dimensional array to store the data. X and y can be ignored. It was originally returned to the server for use

  List<List<HomeItem>> cores = [
    [
      HomeItem(x: 0, y: 0, level: 1),
      HomeItem(x: 1, y: 0, level: 1),
      HomeItem(x: 2, y: 0, level: 1),
      HomeItem(x: 3, y: 0, level: 1)
    ],
    [
      HomeItem(x: 0, y: 1),
      HomeItem(x: 1, y: 1),
      HomeItem(x: 2, y: 1),
      HomeItem(x: 3, y: 1)
    ],
    [
      HomeItem(x: 0, y: 2),
      HomeItem(x: 1, y: 2),
      HomeItem(x: 2, y: 2),
      HomeItem(x: 3, y: 2)
    ]
  ];

When moving, three situations will appear
First: move to an empty position level == 0
Second: move to a position with the same level, and the two animals will merge into a higher-level reveier level == sender. Level will accept + 1revicer Level + = 1 send set to 0 sender level = 0;
Third: move to a position with different levels, and the two animals exchange positions level != sender. level
int level = sender.level;
sender.level = revicer.level;
revicer.level = level;

  static void moveItem(HomeItem revicer, HomeItem sender) {
    if (revicer.level == 0) {
      revicer.level += sender.level;
      sender.level = 0;
    } else if (revicer.level == sender.level) {
      revicer.level += 1;
      sender.level = 0;
    } else if (revicer.level != sender.level) {
      int level = sender.level;
      sender.level = revicer.level;
      revicer.level = level;
    }
    HomeCoreModel.instance.streamController.sink.add(1);
  }

Delete direct set level to 0

///Delete a
  static void removeItem(HomeItem revicer) {
    revicer.level = 0;
    HomeCoreModel.instance.streamController.sink.add(1);
  }

Add circular lookup or empty location

///Add a
  static void addItem(int core) {
    bool isFinish = false;
    for (List ones in HomeCoreModel.instance.cores) {
      for (HomeItem one in ones) {
        if (one.level == 0) {
          one.level = core;
          isFinish = true;
          break;
        }
      }
      if (isFinish == true) {
        break;
      }
    }
    HomeCoreModel.instance.streamController.sink.add(1);
  }

GitHub source address:https://github.com/CZXBigBrother/animals-merge-demo

Recommended Today

Two health check mechanisms of spring cloud Alibaba Nacos!

As a registry, spring cloud Alibaba Nacos not only provides the functions of service registration and service discovery, but also provides a mechanism for service availability monitoring. With this mechanism, Nacos can perceive the health status of the service, so as to provide healthy service instances for service callers, and finally ensure the normal implementation […]