Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I would hope that we have all played Zelda: A Link to the Past, please correct me if I'm wrong, but I want to emulate that kind of 2D, top-down character movement with a touch of correction. It has been done in other games, but I feel this reference would be the easiest to relate to. More specifically the kind of movement and correction I'm talking about is:

  • Floating movement not restricted to tile based movement like Pokemon and other games where one tap of the movement pad moves you one square in that cardinal direction. This floating movement should be able to achieve diagonal motion.
  • If you're walking West and you come to a wall that is diagonal in a North East/South West fashion, you are corrected into a South West movement even if you continue holding left (West) on the controller. This should work for both diagonals correcting in both directions.
  • If you're a few pixels off from walking squarely into a door or hallway, you are corrected into walking through the hall or down the hallway, i.e. bumping into the corner causes you to be pushed into the hall/door.

I've hunted for efficient ways to achieve this and have had no luck. To be clear I'm talking about the human character's movement, not an NPC's movement. Are their resources available on this kind of movement? Equations or algorithms explained on a wiki or something?

I'm using the XNA Framework, is there anything in it to help with this?

share|improve this question

4 Answers 4

up vote 20 down vote accepted

Well, the first bullet point is easy. You simply store and manipulate the character's position in world or pixel coordinates instead of tile-based coordinates. If you were having an issue with this, it might be due to a a confusing choice of representation for your world and tile space, so perhaps you should post more details about it / ask a separate, specific question.

For the second point, the most direct approach would be to take the player's (normalized) movement vector and add it to the wall's normal vector, then renormalize. The sign of the components of the resulting vector will indicate how the wall relates to the player's motion while the vector itself indicates which direction the player may now move.

For the third point, assuming you have collision rectangles for both the wall and the player, you should be able to determine how much of the player's collision rectangle contacts with the wall's collision rectangle. If, for example, the player is moving to the right and hits a vertical wall, you compare the Y axis extents of the collision rectangles -- if if the player's extent exceeds the wall's extent by some threshold, say 75% of the player's Y axis extent, then you "cheat" the player towards the door.

I've made a fair number of assumptions here in how your object model looks in your code and what techniques you've chosen -- largely due to the generality of your question. I've tried to suggest approaches that are simple (although perhaps not optimal) for the same reason. If you can provide more specific information, either in this question or in a new one, I can try to provide more details or a better idea.

share|improve this answer
    
Yeah, floating the character around wasn't a problem. Just making sure people saw that it was a requirement. You did give me the key answer: Tiles having vectors! I can't believe I didn't think of that. Thank you. –  Corey Ogburn Jan 12 '11 at 14:31
    
In zelda, there was only one-angle they could be at, so there was no need for calculating normal-vectors, it was just a special case in the code. –  BlueRaja - Danny Pflughoeft May 27 '11 at 21:40
    
I don't understand how you give a tile a vector. What would that look like? –  test Oct 12 at 6:19
    
A tile already presumably has data like its graphic, whether or not it's passable, etc. this is just another field. For example: struct Tile { vector2 normal; ... } The value of the normal should come with the data that defines the tile –  Josh Petrie Oct 12 at 16:17

Great answer for Josh, but I'll add a few suggestions: - For more info on sliding against walls, check out my question - from this answer I managed to get it working really nicely. - If I'm not mistaken, when walking up the screen Link will ease to align to the closest whole horizontal grid square. This way when you get to the doors you're more likely to be properly lined up (might be wrong). - To make it easy to get through doors, make sure the collision box of your character is way smaller than the width of the door.

share|improve this answer
    
Or have the collision box be a circle perhaps? –  Oskar Duveborn Jan 13 '11 at 20:03

As a possible answer for the second point is to project the player's movement vector along the wall vector using a dot product (a.b * normalized(b)). You then get a vector that tells you how far to move the player in the direction of the wall, and if you move the player by that vector, you get a 'slide' along the wall. Worked well for me in a previous game project.

share|improve this answer

For correction of entering doors, you could make the collision object for the door slightly larger than the image of the door. This would result in the same effect proposed by Josh, but without having to calculate the proximity to the wall's collision rectangle.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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