Display and input problems - Match 3 / Bejeweled

  • I am making a Match 3 / Bejeweled game.
    I created a grid made of gems. Used FlxMouseEventManager.add(...) to manage events for each gem.

    Here is my problem. Since I added one gem after the other, when I move a gem, it's drawn under the ones that were added after it.
    I used FlxSpriteGroup.remove(gem) and then FlxSpriteGroup.add(gem); to display it on top of everything else. I'm not sure that this is how I should do it, but it works.

    Then I have another problem. When I grab a gem, drag it to another gem to switch them, the MouseUp Event is not triggered on the gem I drag, but on the gem that I target. I thought it has something to do with display order, but displaying the dragged gem on top wasn't enough. I found FlxMouseEventManager.reorder(), I don't understand how to use it and if it could be what I am looking for.

    I can find a way to drag one gem, (MouseDown on the gem) and drop it (MouseUp on the gem) on a gem that was created after it. Since the MouseUp event is not triggered on my dragged gem but on the targeted gem.

  • Hi there @kaendan,

    @kaendan said in Display and input problems - Match 3 / Bejeweled:

    Here is my problem. Since I added one gem after the other, when I move a gem, it's drawn under the ones that were added after it. I used FlxSpriteGroup.remove(gem) and then FlxSpriteGroup.add(gem); to display it on top of everything else. I'm not sure that this is how I should do it, but it works.

    Use FlxTypedSpriteGroup with our own sprites, the functionality can be a bit short here and there - especially on sorting/ordering, but a quick remove/add to set something on-top is not a bad idea. I advice you to make your own layer system ontop of FlxTypedSpriteGroup (if you not have done already):

    // Source MySprite.hx
    class MySprite extends flixel.FlxSprite { }
    // Source Layer.hx
    import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup;
    class Layer extends FlxTypedSpriteGroup<MySprite> {
        public function ontop(o:MySprite) {
        // Example Function.
        public function searchSomething() {
           // Iterate trough elements....
            for (o in this) {
                trace("o.x: " + o.x); // example

    Basically extending FlxSprite, FlxTypedGroup and other classes you will be using alot is advised. There is a sort function that you can use. You can use this as example (tip: view the source). But if you don't like sort, you can do similar things with iterations (searchSomething()). Understanding sort can be handy though, because arrays use them as well.

    As for you mouse problem. A quick fix might be adding the object you are draggin' to a variable. Then on release see if the variable is set, when not null, use that variable instead of the argumented one.

    Also, does the mouse callback from setMouseUpCallback only trigger the unwanted sprite? Or does it trigger twice. Once for the unwanted one, and secondly for the wanted one. If that is the case, you can probably just set a boolean on the object (MySprite). Activate on click and deactivate on release.

    Otherwise you might want to consider setting up mouse interaction globally. And on a mouse-down search for any object it might have hit. Set the hit object in a variable and on release reset the variable (NULL).

    Hope this helps.

  • Some other thoughts...

    Why use a physical drag system on your gems? If you want to do this right you usually want to code in some restraints. If you draggin' on the X axis, you want to ignore the Y axis to make it look cool and vice versa. When the other axis becomes more prominent you want to switch them.

    Why not just make a function that can animate the swap of the gems instead of physically draggin' them. Example:

    public function swap(gem01:MySprite, gem02:MySprite) {
        // assert the swap and then execute a tween.

    This way you can use the mouse/touch input by clicking two gems, or by swiping 2. This also has the benefit of being used by other inputs like keyboards or controllers. Or called by whatever functionality you want.

    Personally I would do it like this and not physically drag them. But these are just some ideas. Of-course do what ever you wish.!!!

  • If you still want to swap physically, then you might want to consider doing it pseudo-physical.

    public function swap(gem01:MySprite, gem02:MySprite, progression:Float) {
         // Arguments: The two gems and a normalized progression. (0.0-1.0)
         // move gem01 to gem02 and gem02 to gem01 by progression*width
         // (perhaps add some scaling and other effects to make this look cool)
         // if progression is 1.0 the move is complete, do a assertion if the move 
         // is legal and if its not, then quick animate with a timer and call this 
         // function with progression reversed (1.0-0.0)

    This still has the benefits of being called by any input device, or by timers or boldly just on the update(). Also, now you dont have to use physical points to swap on. You can make the movement of the touch/mouse drag longer or shorter. Just relativize your progress to progression:Float.

    swap(somegem, othergem, (current.mousepoint-start.mousepoint)/totalamountInPixels));

    In this case you must normalize progression FlxMath.bound(progression, -1, 1); then if progression is 1 or -1 your done.

    Again, these are just some thoughts! :D

  • ... and lastly :D

    you can just give one gem as argument and figure-out the axis by movement and then you know the neighbored gem.

    public function swap(gem:MySprite, progression:Float) { }

  • @Kaendan

    After you remove/add the gem did you add the new gem to FlxMouseEventManager?

  • Thanks for your help ! What a great community ! :)

    To show it on top, I removed and added it again. It works fine. It just seemed that it was not the right way to do it but ok.

    By adding it again to the FlxMouseEventManager, it seems that I can click it correctly.
    But I did it another way. I turned on the MouseChildren param so that I can trigger event on other objects overlapped by my gem. I did it since I need to be abble to trigger tooltips when the mouse is over buttons and I am draggind my gem.

    I will look at all your other advice :) Thanks !

Log in to reply
