Jump to content
Search Community

Stacking blocks game syncing issue

Learning test
Moderator Tag

Recommended Posts

Hi guys,


I have a simple stacking blocks game where at the top of the screen there is a swinging block, which when you touch the screen, the block will drop down.
At the bottom there is another swinging block, if the falling block hits the bottom block, it will 'stack' and follow it's swinging animation.

The issue I have now is that everytime the stacking occurs, there is a slight 'shift' in my dropped block's X. I tried to do up a simple codepen to demo this attached, but it's not as obvious as my actual game.


My guess is that because my timeline animation is currentX +/- some amount. And adding this as an animation to my dropping block and syncing it's timeline's time() to the bottom block, it's currentX doesn't match the X it's supposed to stack at. I'm not sure if I'm explaining this correctly.

I tried calculating the bottom block's X and it's difference from its original X, and use this difference to add to my dropped block's X before I add it's timeline animation, but the shift became even more obvious in some cases while it solves it in other cases. I'm having a hard time trying to figure out what's the best way to let it sync correctly to the bottom animation while having the 'hit' or 'stack' point to be accurate.

See the Pen mdrOprw by kelvinzhao (@kelvinzhao) on CodePen

Link to comment
Share on other sites

Hey Learning. This sort of issue is usually out of scope for what we're able to help with for free since it's a logical issue and not a question about GSAP. But since it's an interesting topic and the forums are not very active today I'll help :) 


First off, some recommendations about your code:

  • I recommend that you use GSAP's ticker instead of setInterval for your updates. It's a perfect way to keep things synced and intended for this sort of thing.
  • I recommend making use of GSAP's defaults to keep your code more condensed.
  • I'd make your functions more general so that you can pass in a target so that you can reuse them more. For example with addAnimation I'd likely make it to where you pass in a target, its x position, and potentially a timeline that affecting it and have the function return a timeline that will animate the targets back and forth. That way you can use it for your starting block and other blocks you create as well.
  • I'd make all your numbers less hard coded by using variables so you have more freedom down the road if you need to change the size of things or have varying sizes of objects.
  • Your hit test calculations are off because you use the left most position of the boxes as the start point of your +/- 40. You either need to use their centers instead or compensate for the use of the left points by adjusting your limits to use two different numbers.

I think the main issue that you have is your reuse of timelines. Here's something to get you going in the right direction:

See the Pen jOMybqy?editors=0010 by GreenSock (@GreenSock) on CodePen

  • Like 2
Link to comment
Share on other sites

Hi @ZachSaucier,

Oh I see, initially I thought that perhaps there might be some gsap timeline syncing techniques that I might not know of when I posted the question, didn't realise that it's out of scope. 🙏🏻 Really thanks for taking the time to reply.

I've actually used most of the pointers you listed in the actual game, but I did a quick hack to post on codepen so I missed a lot of them.

But I did not know about the gsap ticker! I am using window.requestAnimationFrame() raw and drawing on canvas for now, but I'll look into the ticker, it seems a lot easier to manage.

Is it recommended to .kill() a timeline rather than clear() and reuse? Is it better for memory or perhaps other reasons?

Link to comment
Share on other sites

I doubt you'd ever notice a performance difference but I'd probably just kill() and create a new one for simplicity sake. I think it's technically cheaper anyway because when you clear(), it must loop through and remove all the children and prep for new additions whereas kill() can just remove it from its parent and be done. 

  • Like 2
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...