Fastloop overlap problem that has been driving me insane

Welcome to our brand new Clickteam Community Hub! We hope you will enjoy using the new features, which we will be further expanding in the coming months.

A few features including Passport are unavailable initially whilst we monitor stability of the new platform, we hope to bring these online very soon. Small issues will crop up following the import from our old system, including some message formatting, translation accuracy and other things.

Thank you for your patience whilst we've worked on this and we look forward to more exciting community developments soon!

Clickteam.
  • I've been struggling with this problem for the past few days, and it doesn't really make much sense to me.

    I'm using fastloops for the movement of two objects. The movement itself works as intended, with floating point movement and pixel perfect collisions for all static objects such as backdrops. The problem is that when two moving objects overlap, they never have pixel perfect accuracy, even though technically they should (and no, this isn't a duplicates problem, since i'm using separate objects and loops to move both).

    On each move loop, an object will move 1 pixel forward. If overlapping another object after that move forward, it will immediately move back 1 pixel, reset all of its velocities etc and then close the group so no further movement can be completed until the next tick. Theoretically, both objects should never be moving at the exact same time, since one has its movement loops above the other in the event editor like so Please login to see this link.

    When the first object moves forward, it should detect the second object (which should NOT be moving) on the first pixel overlapped, then move back. Then, the second object will attempt to move and detect the first object right above it, and move back. What actually happens, is that they are seeming to move at the same time, and perform their collision checks wrong, leaving a few pixels overlapping: Please login to see this link.

    If anyone can help me, it would be much appreciated. I have even tried abandoning loops and just using duplicated instances of the movement, and stacking them on top of each other so they read 1-2-1-2 as many times as they need. The problem still happens, even doing that!

    MFA attached

  • Lines 9 and 19
    I would try changing to:

    >>> set yremain to 0
    (...or sub yremain from yremain)

    I guess there's some extra float remaining after subtracting as int(value) that does for extra pixels?

    a selection of my Fusion examples can be found Please login to see this link.

  • Unfortunately, that didn't work. I wish it were that simple, though! Subtracting the int(yremain) makes sure to leave decimals so the objects can have float movement. Loops will only be fired if the "remain" value is >= whole number, see. This lets you skip however many frames you need until moving another pixel. I'm beginning to think this isn't an error on my part, and just a flaw in the program :(. Am I wrong and positions are updated late, like animation frame changes? If so, it would definitely explain this. If events are read from top to bottom (except fastloops, which are immediate, but since the loops are being triggered by an Always event that shouldn't matter. The loop order isn't even the problem in this case), everything should be working.

    Best person at writing incomprehensible posts. Edits are a regularity.

  • Maybe I've misunderstood something,
    but since you move the object directly relating to its X,Y coordinates,
    aren't you anyway missing float precision?

    A "float" fastloop movement should update X,Y positions into an alt. value,
    and then resulting screen positions be calculated upon that value.

    (or sorry if I don't get the point :()

    a selection of my Fusion examples can be found Please login to see this link.

  • Well see, every frame, velocity/100.0 is being added to the yremain value. Then, I always start the movement loop abs(yremain) times (so i'm not trying to start a negative loop). If yremain is 0.5 or 0.6 or whatever, it won't start a loop. It will only start a loop for whole numbers (1, 2, 3 and so forth). If yremain = 1.5, fusion will only fire 1 loop every frame. When it reaches another whole number such as 2 (since velocity/100.0 is being added each frame), then it will fire another loop, and so on. After the loops have been fired in the group, I subtract the whole number from the yremain value, so only a float remains on the next tick. This is just an alternative method to the way you described doing floating movement that lets me have direct control over the objects every time they move a pixel, allowing for perfectly precise collisions. I learned this method from Nifflas.

    If you set one of the object's velocity to something like 25 or 50, you'll see that it moves much slower than an active that always has its y position set to +1. This is because it's waiting until it reaches that whole number to fire a loop and move forward. Normally, I have a value called "move direction" that will be set to either -1 or 1, depending on whether the yremain value is negative or positive, and the object will move to it's own position+move direction, but I cut that for the example, since the objects only need to move in the directions I gave.

    Best person at writing incomprehensible posts. Edits are a regularity.

  • Ok, now I can see more clearly what's going on.
    This is indeed an interesting method!
    Although there's something awkward I can't still focus and at first sight lets me find uncomfortable with it,
    maybe I just should try using it (so that I could also hopefully end up being useful for your request... XD).

    May I ask you for advantages of this system, beside pixel-perfect collisions?

    (easily obtained also with the mehod I was referring to,
    i.e. see this "fastloop bullet" I've been linking yesterday too
    -sorry, it's not very refined, but I link it often because it's just a recent thread I recall more easily-
    Please login to see this link.)

    a selection of my Fusion examples can be found Please login to see this link.

  • Looking at the 2 methods, I don't suppose there is too much of a difference: just a different approach :P

    Either way, I edited that example to have another moving object (the enemy) and tried stopping them both on impact, and the same problem reared its ugly head again D:<

    I had a problem similar to this when I was trying to use embedded collision detectors. Unfortunately, as revealed by some forum members and I believe confirmed by Clickteam: animation sequence/frame changes always take a loop to update, so they will never be aligned, and embedded detectors aren't able to collide with each other as you would think! The same thing might be happening here. You think the objects should be in one place and detect each other, but they don't, causing the overlap because of some wonky position update thing.

  • This is very interesting.
    I'm wondering also if it has more to do with loop timing or some inconsistency in overlapping detection or in its updates timing.
    Tried some workarounds without success.

    Will keep trying for the sake of learning and report back if any good news...

    a selection of my Fusion examples can be found Please login to see this link.

  • I appreciate the help! This has been screwing my moving platforms over for a while now because the player doesn't always detect the top of the platform, among other problems. Hopefully we'll figure something out or get some more experienced input.

    Best person at writing incomprehensible posts. Edits are a regularity.

  • Though I don't know why the extra movement step is occurring, I believe I have partially resolved the issue. I added a new loop for each object. When there is an overlap between the two objects, these loops execute until no more overlap exists between the two. There are some combinations of velocity which leaves 1 or -1 overlap between the two objects, but it shouldn't be anymore than -1 or 1.

    Interestingly, check out line 17. If you switch the order from Active and Active 2 to Active 2 and Active, it'll break. I don't know why changing the order would affect this, but it looks like it just does. You could combat this by every frame or fastloop iteration, have a collision event and flag all the affected objects. In any case however, this might not work for multiple instances of either object.

  • If you move the bottom active up by 3 pixels in the frame editor in Y, you will end up with a perfect collision and zero overlap. Your method has some flaws.

    Top objects moves down 2.5 pixels.
    Bottom object moves up -3.5 pixels.

    Based on the distance they are apart from each other you run into the problem that both objects overlap each other by a maximum of 5 pixels. Then both of you actions fire and they are take back one by one for exactly 1 pixel. And you are left with 3 pixels overlap. What you need to to is to fire those events again until they no longer overlap. Sometimes they reach the same spot, sometimes not. It all depends totally on their starting positions or the velocity values.

    May I offer another approach:

    You have two objects that travel at different speed over a certain distance. You can calculate the exact point where both objects will collide and simply use that value as a stop mark (one object should of course stop at -1 or +1 from that, so both do not overlap).

    Let's take your example:

    Top object 2.5 pixels, bottom -3.5
    So 3.5 equals 100% while 2.5 equals 71.4%.

    Top object starts at Y119+32=151px
    Bottom object starts at Y351px.

    Distance between both objects is 200 pixels. Both objects combined travel at 6px per frame which means at 33.33 frames both objects reach the same location.

    So for top object Y = 151 + 2.5 * 33.33 = ~234 (Y 234,325px)
    Bottom object Y= 351 - 3.5 * 33.33 = ~234 (Y 234,345)

    Both values should always be very close together but for extra precision you could just sum both values and divide by two.

    This is easy to implement and you it will never fail at any collision. If the speed changes you could quickly re-calculate the new Y value.

  • Vaxx, my objects are incremented forward by 1 pixel every loop. On each loop (and in turn, each pixel forward), they check for overlap. If overlap occurs, movement is stopped and they are moved back 1 pixel. They never actually jump 2.5 or -3.5 pixels at a time before a collision check occurs. This method should work, but due to what I assume is an oversight in the program, the flag for overlap isn't being checked when it should (i.e every time an object is moved).

    My logic works thus:

    The Event Editor always reads from top to bottom, except for special cases such as fastloops, which are fired as soon as they are called, no matter their order in the event editor. Because of the way my events are structured, both objects should never be attempting to move simultaneously.

    -object 1 has its loops fired. object 2 is not moving at this time, since it has not been reached in the event editor yet.
    -object 1 moves down 1 pixel and checks for overlap of object 2 each loop
    -since object 2 is not moving, if object 1 overlaps it, object 1 moves back 1 pixel and no longer overlaps object 2. Every time an object tests positive for overlap, all velocities are set to 0 and the group is closed so no further loops or 'steps' can occur for that particular object.

    then

    -object 2 is reached in the event editor and has its loops fired. If object 1 overlapped object 2 in its previous loops, it will be directly above object 2 by 1 pixel.
    -object 2 attempts to move up 1 pixel. If it immediately overlaps object 1, it will move back down 1 pixel and terminate movement.

    Because things are moved on a per-pixel basis, they should always resolve. This is how things would work in many other languages. My best guess is that overlap checks are only being performed at the end of every tick, instead of every time objects move. If this is true, I don't think it is the right way to do things and I hope clickteam addresses it.

    Best person at writing incomprehensible posts. Edits are a regularity.

    Edited 3 times, last by casleziro (September 20, 2015 at 1:34 AM).

  • Casleziro,
    the other day while testing I noticed a couple very strange things,
    but I didn't report because I was thinking you were heading for the bugbox

    ...here they are:

    1) on you first example,
    if you launch both loops Abs(Floor(yremain( "Active" ) ) ) times
    you get a only 1 pixel overlapping - with starting speed values
    (at least, I get this on my machine)
    while without "floor" (example unchanged) I get 3 pixels overlap.

    And I thought it was very strange,
    because I guessed loops iterations were already rounded down,
    (and if you launch a loop 1.9 times "do_this", you in fact get only one "do_this" action)
    so the two forms (floor - no floor) should be exactly identical.

    2) also, after testing with different speeds, I sometimes get different overlapping ratios from the same speeds,
    while reloading back and restarting application from scratch I always get the same starting overlapping ratios...

    In both scenarios, I wander what may be going on?!?!


    As for a simple workaround (in a no-above-solution scenario),
    couldn't you apply a simple post-correction,
    moving back one of the two objects when they are detected overlapping "after" all the preceeding mess XD?

    Something in this way:
    Please login to see this attachment.

    Should be bullet-proof.

    Obviously, you should store "last" direction of corrected object,
    and negatively position basing on that
    (some trigonometry would do well if you're doing 360° angled movements)

    a selection of my Fusion examples can be found Please login to see this link.

  • I attached a fix without adding anything extra. I however changed some of the event order and seperated some events from each other. Why? Well I can hardly explain, but certain things simply don't work together and over the past years it have become common for me.

    I launch the loops within the groups. I use two seperate events to launch a loop and setting something in advance. I repeat line 9 and 22 simply to fix the overlap. 3 to 2 can result in 1px difference and therefor you always end up with a 1px overlap. Running the loop again simply pushes the object further out. Actually you can repeat that events the number of times that an overlap could happen. Lets say one object moves 4px and one 1px you could end up with a 3px overlay. Having 4 lines in the code pushed the object back up or down so no overlap will happen and you still have your pixel precise collision.

    Good luck with your project.

  • Schrodinger, I did head for the bugbox, but Clickteam loves taking their time to respond to those!
    Big thanks for your continued efforts to help me out, by the way :)

    This whole ordeal has really been trying my patience, and I would have given up by now if needing to have objects overlap correctly wasn't so crucial to what I have been trying to do in my project! I saw your example and initially thought it was a huge relief and something I could work with... until I dug around some and tried messing with it :(

    If I set the framerate to 1, and have a counter increment at the bottom of the event editor (so I can see how many frames have passed before something happens), the objects overlap at 7, but only move out at 8 (I changed the velocities a bit and moved their positions so I wouldn't have to wait as long for them to overlap :P). I found this strange, because your code for pushing the objects out is above the counter increment in the event editor :o It is made even weirder since you use loops, and they should be calling constantly until nothing overlaps anymore. This I think confirms my suspicion that collision detection is happening later than it should. If you set the objects to higher speeds and pay close attention you'll notice that they're getting pushed out too late, even at 60 FPS.

    The other problem is the main reason I couldn't use your push-out method: one object is always bullied out of the way by the other, instead of them meeting in the middle like they should.

    I scrapped loops and took a step-by-step approach to try and resolve this:

    i.e
    1 overlaps 2
    -push 1 up
    2 overlaps 1
    -push 2 down

    and duplicated these a ton of times. What happened is that the objects ended up NOT overlapping by as many pixels as they overlapped (-4 overlap instead of 4 overlap). This doesn't make much sense either!!

    If collision detection is happening 1 frame late, then my duplicated push-out events should make them continue to move out until the next frame, resulting in them being pushed away from each other as many times as there are my duplicated events (10 in this case), right? If they overlapped 4 pixels, then went through 10 move out events (with the idea of collision detection being a frame late in mind), they should end up at -6 pixels overlapped. They always end up at negative however many pixels they were overlapped initially, though.

    My head is hurting awfully bad by this point. I think i'm going to take a day or two of trying to fix this off so I don't get really, really angry about it, and just work on something else or use my free time to play Street Fighter or something ;D

    EDIT:

    Vaxx, I appreciate your help as well, but unfortunately you missed something in your solution:

    Line 12 should be an Always event instead of 'On loop "Blue"'. The movement doesn't work correctly without this (try changing BLUE's speed and you'll see what I mean), and if I change it to the Always event, it messes the whole overlap system up.

    I don't think this is something we'll be able to fix very easily, if at all :/

  • Yet another update: I went back and tried to start loops to push the objects back a different way. I started the loop Max(Pixels Overlapping/2, 1) times if the number of pixels overlapped is greater than 0. This works for even numbers (such as 2 or 4), pushing them back equally. Without the Max(_ ,1) there, there will be a 1 pixel overlap for odd numbers.

    The remaining problems are:

    1) I now have to find which object overlapped first, and push it out by that remaining 1 pixel if the overlap is odd (so the wrong object isn't pushed just because of event order)
    2) The push-out loops are still being registered 1 frame later than they should be, and there's still that weird problem from my earlier post about the duplicated instances.
    3) This 1 pixel push STILL happens 1 frame late, even 1 frame later than the initial push! Now i'm dealing with a 2 frame discrepancy, which is very noticeable during standard play.

    I'm not happy, even though I came up with this. I wouldn't call it a true "fix". My original method should be working in the first place too >:D

Participate now!

Don’t have an account yet? Register yourself now and be a part of our community!