2
\$\begingroup\$

I want to develop a system to constraint a character movement to a certain path, defined a-priori by the level designer to give some sort of 2D/2.5D look.

Right now I have a list of splines that make a path, I also can project a arbitary point to a specific spline. So what I do is this:

  • Iterate over all the splines in a path
  • Find the closest point on all the splines that make a path
  • And return the point with the minimum distance (thats my current point)

Now one issue that this leaves me with is: how do I find if I am actually out of the current path?

How would you implement this sort of system? I feel my way is not even close to a robust system.

For those of you wondering, lets say I am trying to implement something like Sonic Generations' 2D Segments (just the movement constraints). And by a path I mean like this. Its full 3D environment, but Sonic follows a predefined path.

\$\endgroup\$
2
  • \$\begingroup\$ Some suggestions for editing: When you say "out of a path", what do you mean exactly? What type of spline are you talking about? \$\endgroup\$
    – Anko
    Dec 18, 2014 at 20:18
  • 1
    \$\begingroup\$ Added a video, that shows somewhat what I want to achive, by splines I mean anykind really. \$\endgroup\$
    – Morphex
    Dec 18, 2014 at 23:11

3 Answers 3

1
\$\begingroup\$

Update:


Even if you do use splines, doing spline computations during the game is wasteful. Normally one would break the spline in advance into a series of even segments (specifically positions on the spline with similar distances between them) [p_0, p_1, p_2 ..p_n] and use this to guide the players' character motion. The logic is still very much 2d in nature.. move right, increase your characters x value and advance towards p[i+1]

specifically:

position = x / distanceBetweenPoints;
m = Math.floor(position);
t = position - m;

position3d = p[m] * (1 - t) + p[m+1] * t;

Where

  • p[m] is the point you have passed
  • p[m+1] is the next point
  • The fraction t represents the % of progress you made from p[m] to p[m+1]

There is no way or reason to escape the fact that if your character is stuck on a spline, the gameplay mechanics during that portion of your game are completely 2d (if not 1d assuming they can't jump).

One more thing to mention, to compute some p[m] assuming you have p[m-1] starting with p[0] which is the first point on the spline, you could do the following:

distanceBetweenPoints = someDesiredValue; //  Use the value you want
                   //(smaller value = higher fidelity = more points)

epsilon = 0.0001; some small value
stepSize = epsilon;
nextPoint = previousPoint + stepSize; // The points are a t value betweeb 0 and 1

// As long as the distance isn't right (too small)
while (distance(previousPoint, nextPoint) < distanceBetweenPoints && nextPoint < 1)
{
    stepSize *= 2;
    nextPoint += stepSize;
}

// TODO: Check for edge case where nextPoint == 1 
// Distance is bigger now

While (Math.abs(distance(previousPoint, nextPoint) - distanceBetweenPoints) > epsilon)
{
    dist = distance(previousPoint, nextPoint);
    stepSize /= 2;
    if (dist > distanceBetweenPoints) nextPoint -= stepSize;
    else nextPoint += stepSize;
}
// nextPoint is just about right

p[i++] = spline(nextPoint);
previousPoint = nextPoint;

//repeat...

Old answer:


Outside of loops and constructs that cause the player character to shift position in the depth axis, what you wish to achieve can be done by implementing the game in 2d first with programmer art. Playtest the 2d game to tweak the game and level mechanics. Then use the 2d level as reference to construct a full blown 3d level that lives across the x, y plane and matches the original 2d design across that plain. The meshes can still have some depth for platforms and walls of course but that depth needs to be sliced in the middle by the 2d plane that defines the level spatially.

The gameplay will be completely 2d as before (other than some minor tweaks like the loop where the player character may need to be in two different depths in the same area). The only difference being that you will now use the xy values to position a player character model and use a camera to render the scene instead of simply using sprites.

The is no reason to use a spline or a path cause that will allow for no vertical motion. You definitely need a plane to allow the character to move freely, up and down and left to right.

\$\endgroup\$
3
  • \$\begingroup\$ I was trying to avoid having to reimplement the logic in 2D, and I managed it with a few tricks, using t were not what I was looking forhe spline, although all your points are valid, theywere not what I was looking for. \$\endgroup\$
    – Morphex
    Dec 24, 2014 at 1:05
  • \$\begingroup\$ @Morphex I updated the answer, If you are doing 2d logic, you haven't fully explained your plan or you are doing something wrong. \$\endgroup\$
    – AturSams
    Dec 24, 2014 at 8:14
  • \$\begingroup\$ I am using 3D Logic constrained to a spline, I am accepting you answer though because It is somewhat what I ended up doing :D. So thanks for the answer - thats pretty much all there is to it :D \$\endgroup\$
    – Morphex
    Dec 25, 2014 at 14:53
3
\$\begingroup\$

Here's how I do it in my games:

  1. Keep track of a "current path target" that is constrained to lie along the path.
  2. At the start, the "path target" is the very first point in the path.
  3. As the character moves along the path, update the target as follows: The target is the closest point to the character projected forward in time by a parameter t, representing a "lookahead".

    • To do this, project the character's position onto the nearest spline and call it p. The time from the start of the spline to this point is t_0, the target position is that point along the spline which lies at time t_0 + t.
  4. The character seeks the target.

  5. When the target reaches the end of the path, it gets clamped there.
  6. The character is done with the path when:
    • the character is near the target and
    • the target is at the end of the path.

What this will do is cause the character to move along the path at a more or less fixed rate corresponding to the parameter t. When the character reaches the end of the path, they stop. Note that you will implicitly need to know the timing of your path as well as the position to do this correctly.

\$\endgroup\$
1
  • \$\begingroup\$ Although this is "the correct" way of doing this, in my case it wouldnt work. But I managed to do what I want with a bunch of offsets and points projections :D Thanks for the help though. \$\endgroup\$
    – Morphex
    Dec 24, 2014 at 0:59
1
\$\begingroup\$

Most of the linked video seems to be just 2D logic with 3D rendering. There is also some occasional 2.5D parts like here, where the player follows a predefined path but can adjust the horizontal offset in addition to the vertical one.

I don't think either of those need projecting points to paths. Instead the player is either jumping in a 2D world in the first case or directly following a path with a controllable offset in the second case. You can then control how large offsets are allowed. This way you don't even have the question "how do I find if I am actually out of the current path?", because you are always on the path.

\$\endgroup\$
3
  • \$\begingroup\$ So you are saying that if I want to accomplish what they have in the first case, I would be better doing 2D logic than full 3D? \$\endgroup\$
    – Morphex
    Dec 21, 2014 at 1:25
  • \$\begingroup\$ @Morphex Yes. 2D logic with 3D rendering is often pretty good solution. Gameplay in 2D is simpler for the player and easier to implement for you. \$\endgroup\$
    – msell
    Dec 21, 2014 at 10:18
  • \$\begingroup\$ hmm.. @msell is absolutely right. First implement the game in 2d with programmer art. Then instead of display the 2d graphics in the view, display 3d graphics. The x & y values should remain the same. You simply need to figure out the correct z value which is something msell neglected to mention in the answer. \$\endgroup\$
    – AturSams
    Dec 23, 2014 at 22:35

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .