3
\$\begingroup\$

Suppose, I have a 2D overworld like in Super Mario Brothers 3, but without junctions or intermediate nodes. Only a single, contiguous path of level nodes, which should be navigated with the arrow keys.

Currently, the path is calculated automatically by the order of which the nodes appear. Each node has at most two edges, which extend from the center of each node.

Now there are multiple possible layouts of said path. In the following pictures, "P" is the position of the player. Directions formatted as code will denote arrow key presses.

Axes-aligned paths

perpendicular

This is the trivial case, since each possible direction is aligned with the arrow keys. down moves the player down, left moves him left.

Angled paths

angled

Here it gets a little trickier, since the possible directions are not aligned with the arrow keys anymore. Pressing left is ambiguous, the only option would be to use up and down to move the player up-left and down-left respectively.

Axes-aligned and angled paths mixed

enter image description here

In this case, left could be used to move the player either to the left or to the up-left. But here it would be more intuitive to use left for left and up for up-left movement.

Arbitrary paths

free

This is where I am kinda lost. Both possible paths lead up-left. Now I could say, since one node is "more left" than the other, let left walk the player to that node. The other node is "more up", so up can walk him there. But what if such a situation doesn't exist? For example, when one node is both "more left" and "more up" than the other one?


Some approaches I had

  • Give directions a priority, so when ambiguous situations exist, left gets picked over up for example. That means, left will always move the player to the most left node, no matter where the other node is. But with this I think I have to implement a lot of if-checks and it would also be not as intuitive for the player.
  • Add direction markers, so paths leading from one node to another are only connected at their direction specific markers. This will be more intuitive, since you can simply look at the markers and know, that the left marker is mapped to left.

    directionMarkers

    But this looks rather ugly and unnatural, because the edges don't originate from the center of the node anymore. Furthermore, I think this will cause the same problem as before. I need to decide beforehand, which marker is connected to which other marker. So I basically relocated the problem to another point in the logic.

  • Restrict placement, so the nodes are only placed in such a way, that the path ends up axes-aligned. Since I'm free to place the nodes anywhere I want, this would be the easiest solution. But that would make the layout of the world map rather boring. I guess this could be my fall-back approach, when everything else fails.
  • Decide by angle of an edge. Divide a circle into four sectors at (2k + 1) * PI/4 with k = 0..3. Each sector defines one direction. An edge is now mapped to this direction, when the edge lies in that sector. If two edges are in the same sector, the one closer to the main-axis (x or y) in that sector is mapped to that direction. The remaining edge is then mapped to the direction of the next closer sector.

    This one came to my mind, while writing this question, so I haven't given it much thought yet. I find this the most elegant approach so far. But I already see two problems where there is some ambiguity:

    - If an edge lies exactly on a dividing line between two sectors (e.g.: at 45°)

    - If two edges are symmetrical around an axis (e.g.: at 30° and 330°)


Questions:

  1. How could I generalize the decision-making with arbitrarily connected paths?
  2. Are my presented approaches reasonable?
  3. What approach would be the most promising? Or is there a better one, which I haven't thought of yet?


Thanks in advance for your time! I look forward to your suggestions :)

\$\endgroup\$
  • 3
    \$\begingroup\$ Or curve the paths so they only enter and exit at a horizontal or vertical location. \$\endgroup\$ – ratchet freak Nov 6 '15 at 11:47
  • 1
    \$\begingroup\$ I think you went through the options you had thoroughly. I would suggest a combination of Restrict placement with Decide by angle of an edge: you restrict the placement in a slightly smaller range than 90° just to make it clear. The other option available was suggested by @ratchetfreak and is also a great one! \$\endgroup\$ – Alexandre Vaillancourt Nov 6 '15 at 12:33
2
\$\begingroup\$

I would not overthink this: since you need some way to connect the paths to the nodes, extend that class to include the preferred direction of movement. That way you can manually tweak the movement so it feels natural to the player.

Pseudo code:

class Path
{
     Node Target;
     Direction DirectionToTarget; //enum north,northeast,east etc.
                                  //could also be an array of directions.
} 

class Node
{
   List<Path> Connections;

   void AddConnection(Node target, Direction d, bool twoway)
   {
      Connections.Add(new Path() { Target=target, DirectionToTarget=d });

      if(twoway) //if two way, add path back to me. 
      {
          target.Connections.Add(new Path() { Target = this, DirectionToTarget=Opposite(d)});
      }
   }

}

You might even extend it so into a path going southwest the directions south, southwest and west are accepted. If there is a path west and southwest from a node, you might treat the keys west, northwest for the west direction and the keys southwest and south. It gives yourself full control of all movements.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.