Search code examples
flame

how to create an infinite List loop


I tried to create an infinite scrolling effect which is similar to a slot machine, I have done such things just with flutter and cupertino widget, but with flame I have no clue how to create it, for instance this is my code:

late List<GemComponent> firstColumnGemList;
late PositionComponent firstSlotColumn;
late List<Sprite> _sprites;

and here is for onload method:

_sprites = ['some elements for slotmachine']

firstColumnGemList = List.generate(_sprites.length, (index) {
  return GemComponent(
    gemSprite: _sprites[index],
    gemSize: gemSize,
    gemPosition: Vector2(0, index * gemSize.y),
    // position: position
  );
});

firstSlotColumn = PositionComponent(
  position: Vector2(0, 0),
  size: gemSize,
);

firstColumnGemList.forEach((element) {
  firstSlotColumn.add(element);
});

add(firstSlotColumn);

var firstMoveEffect = MoveEffect.by(
  Vector2(0, -5 * gemSize.y),
  EffectController(duration: 1, curve: Curves.easeOut),
);

firstSlotColumn.add(firstMoveEffect);

I think the code is not clean, and not to mention I have to create three columns, so everything has to multiple three times. I understand how to remove this GemComponent if it is out of screen, but I have no clue to add a GemComponent while firstSlotColumn is scrolling, or is there any inspiration to create such effect instead of MoveEffect? Many thanks!


Solution

  • I think the easiest way is to use SpriteComponents and use MoveToEffects on them, then you can also get a curve for the spin (so that it spins slower in the beginning and then speeds up for example).

    So first you could create a PositionComponent that will represent each column, since you will need multiple columns:

    class ColumnComponent extend PositionComponent {
      ColumnComponent(super.position) : super(size: Vector2(<<width>>, <<height>>));
    
      @override
      Future<void> onLoad() async {
        // Next step
      }
    }
    

    Then in the onLoad method you can create one SpriteComponent per gem and store in a list. Then you can position the first first three (or however many you want visible) + one underneath each other adding them as children to the ColumnComponent.

    The first component should be added outside of the ColumnComponent so that it can spin in later, let's call that one -1. To cover the -1 component and the components spinning out of view you have to either use a CropComponent to wrap the ColumnComponent or simply put a component on top of the ColumnComponents so that only the part of the columns that you want visible are in view (you can put another component on top by setting the priority higher than what the ColumnComponent has).

    When you want to start the spin you add a MoveToEffect that moves each sprite to the bottom of the ColumnComponent and in the MoveToEffect you add the onComplete callback and in that one you add the next component in your list at the -1 position, and use for the component that just completed its effect you do component.removeFromParent() and add it at the end of your list with gem components.

    You also have to add some logic for when it should stop spinning, but that should be trivial once you got it spinning.