Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
JAcato

Game World Roadmap Follow Path on Click

Recommended Posts

We haven't set up a codepen yet, but included is the visual design created for a web-based game to develop.
We found a few examples of GSAP getting actually somewhat close to how it should work, but we find it hard to find a push in the right direction when it comes to intersections in the path below.

The marker (avatar on A) should be able to move to points B and C when the player clicks one of those points.

From point B, the player should be able to move to C or E

From point C, the player should be able to move to B or D or E.

Etcetera.

 

Is this actually possible using GSAP with the MorphSVGPlugin and BezierPath?

ex.jpg

Link to comment
Share on other sites

Hey JAcato and welcome to the GreenSock forums.

 

This is quite possible (and fairly easy) using the MotionPathPlugin. You'd have to setup some basic logic to allow certain paths once the user is at a given location but that's pretty trivial :) The animations themselves are quite straightforward with MotionPathPlugin.

Link to comment
Share on other sites

Hi ZachSaucier,

First of all thanks for the welcome and quick reply! Really appreciated!

 

The MotionPathPlugin should be the way to go then. Thanks!

I will try to setup a Codepen to have some progress to look at, and see how far I will get.

Do you know of an example using a path with multiple directions like mentioned in the OP?

 

Until now, I've been wrestling with the examples shown in 

 

Link to comment
Share on other sites

41 minutes ago, JAcato said:

Do you know of an example using a path with multiple directions like mentioned in the OP?

Not besides that thread, no. Here's some pseudo-code:

<!-- The stuff you click on goes inside -->
<div data-loc='a'></div>
<div data-loc='b'></div>
<!-- ... -->
// Setup the data
const possiblePaths = {
  a: {
    b: {anim: animAB, dir: 1},
    c: {anim: animAC, dir: 1}
  },
  b: {
    a: {anim: animAB, dir: -1},
    c: {anim: animBC, dir: 1},
    e: {anim: animBE, dir: 1}
  },
  // ...
}

// Get the DOM elements for the click
const locations = document.querySelectorAll('[data-loc]');

// Keep track of the current location and animation
let currLoc = 'a';
let currAnim = gsap.to({}, {});

// Add a click listener to check if it's valid from the given configuration
locations.forEach(loc => {
  loc.addEventListener('click', e => {
    
    if(!currAnim.isActive() // Don't allow choices while animation happening
    && possiblePaths[currLoc].hasOwnProperty(loc.dataset.loc) ) { // Make sure it can be navigated to
      const dataObj = possiblePaths[currLoc][loc.dataset.loc];
      
      // Play the animation based on the direction and update the state
      currAnim = dataObj.dir === 1 ? dataObj.anim.play() : dataObj.anim.reverse();
      currLoc = loc.dataset.loc;
    }
  });
});

 

  • Like 1
Link to comment
Share on other sites

1 minute ago, JAcato said:

I've looking into https://codepen.io/GreenSock/pen/mdyxvGX as well to find a suitable approach.

While you can learn from that pen, I don't think it's really relevant to the effect you're creating. I highly recommend creating individual paths connecting each location, not trying to animate part of a larger path.

Link to comment
Share on other sites

That's even smarterer! Thanks!

Link to comment
Share on other sites

Hi Zach,

I managed to get it all working, except.. reverse() is not working somehow. Do you have an idea why?

 

		// for each path we generate a tween
		// d is the "d" attribute,
		// id is the "id" attribute, eg. "path-a-b": path from a to b
		// we check if "a: {b: {...}}" exists
		// and we check if "b: {a: {...}}" exists
		// then we add the tween to both properties
		const anim = gsap.to('#avatar', {
            motionPath: {
                path: d,
                align: id,
                alignOrigin: [0.5, 0.5],
            },
            transformOrigin: '50% 50%',
            duration: 1,
            ease: 'power1.inOut',
            paused: true,
            onComplete: () => {
                console.group('Tween complete');
                console.log('Instance: ', instance);
                console.groupEnd();
            },
        });

		// on click on a marker
        // we grab the id, eg. "em-b", so we know where we have to go (point b)
		// then we take the current location, eg. "a", find the corresponding animation (a to b)
		// and according to the set "dir", we determine to either play or reverse the animation

		// eg. currentLocation is "a", marker is "em-b", so we look for "a: {b:{...}}"
		// dir === 1, so play() it is. this works :)

		// eg. currentLocation is "b", marker is "em-a", so we look for "b: {a:{...}}"
		// dir === -1, so reverse() it is. this doesn't work :)
		obj.dir === 1 ? obj.anim.play() : obj.anim.reverse();

 

 

Link to comment
Share on other sites

3 hours ago, JAcato said:

I managed to get it all working, except.. reverse() is not working somehow. Do you have an idea why?

Good work! 

 

I'm guessing it's because the animation hasn't been played so it's trying to .reverse() from the start (going nowhere). Sorry I didn't think that through in my pseudo-code. Try this:

obj.dir === 1 ? obj.anim.play() : obj.anim.progress(1).reverse();

Without a demo it's hard to say for sure though.

  • Like 1
Link to comment
Share on other sites

@ZachSaucier Great! That works indeed. Once the player has walked a path, the reverse is working as intended!

One note: when the player hasn't walked a certain path yet, and it's called using .progress(1).reverse(), it's playing backwards, but the start and end position are wrong. Let me try and set up a codepen demo illustrating this

 

 

Link to comment
Share on other sites

@ZachSaucier

Hi Zach!

Managed to move a step forward. I've also setup a demo in Codepen, which illustrates the progress thus far.

 

As you can see, moving from point A (where the avatar starts) to C works perfectly.

Going from C to B works as well.

At that point, going back to A, doesn't work as intended, it uses point B as finish, where as that should be the starting point.

I believe this is, because the original path from A to B hasn't been walked yet. So it doesn't know where to start.

 

See the Pen NWNqOyQ by nogzoiets-the-looper (@nogzoiets-the-looper) on CodePen

 

Link to comment
Share on other sites

Hey JAcato. I'm not sure why you're getting the path data and passing that into your motionPath... Why not let MotionPathPlugin do that for you? I think it also fixes your logic issue.

 

Additionally, once you fix the issue, then your demo has trouble replaying the same path. (say going from A->C->B->A, going back to C has issues). You can fix that by adding .progress(0) before the .play():

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

Link to comment
Share on other sites

Hi @ZachSaucier

Thanks a lot! That fixes all :) It works perfectly. Many thanks for your help and support!

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.
×