I'm making a 2D platformer similar to Terraria, although I'm having some problems with some collision detection code. I'm using the code from the AppHub Platformer sample, but tweaked so it fits with my character size and tilesize. Although, I am having a few problems:

Jump Problem #1

If I box myself in, and then jump. Instead of just canceling the jump it will move me through a wall (most likely to the right) and then when it can jump, it performs the jump.

Jump Problem #2

Next problem I'm having is if I have a 1x1 gap above the character, I am freely able to jump through it. The character size is 2 blocks wide by 3 high.

I don't want to use a physics engine because I will not be using 95% of the features, and I don't really want to add it if i'm not going to use most of it. I just require a basic collision detection and basic physics. Honestly, I can't see anything wrong with my code and it's pretty much the same as the sample. Just by changing the tile size must have added these bugs and I'm not exactly sure how to fix it. This is my existing code.

Basically, what I'm asking is: How could I modify my current system to eliminate these bugs, or what new system could I implement to have a better, fully functional physics system without these bugs. (Without implementing a whole engine).

  • \$\begingroup\$ Can you post your code? \$\endgroup\$
    – user159
    Commented Aug 13, 2011 at 17:02
  • \$\begingroup\$ @Joe - The physics part? I included a link to it in the OP: pastebin.com/fT5mKkfE \$\endgroup\$ Commented Aug 13, 2011 at 17:11
  • \$\begingroup\$ Unless this is reformulated as a general question about implementing 2D tile physics, I think it's too localized. \$\endgroup\$
    – user744
    Commented Aug 14, 2011 at 15:56
  • 1
    \$\begingroup\$ Collision and basic physics are the core of any physics engine. I'd reconsider using an outside physics engine, especially with all the weird edge cases that are bound to show up in a game with customizable scenery. Writing your own physics for this complex of a game really is reinventing the wheel. \$\endgroup\$ Commented Aug 14, 2011 at 16:36
  • \$\begingroup\$ @Gregory Weir, I completely agree. \$\endgroup\$ Commented Aug 19, 2011 at 20:14

3 Answers 3


Well, there is no solution to debug, so let's play a guessing game :)

  • First problem seems to be caused by resolving jump collision on the X axis alone thanks to absDepthX always being bigger in if (absDepthY < absDepthX ...) condition.

  • Second problem seems to be caused by either bad intersection detection or velocity which is bigger than single block dimension, then collision logic would fail to detect any collisions.

  • Not really a big problem, just a strange thing: it looks like velocity is scaled by frame delta time twice.

I would fix those problems by creating a strong mental image of how I want my collision system to work, imagining its progression by time, drawing several images of main hero colliding with walls and ceiling to keep weird cases in mind, and then writing code from scratch while using other developer's code sample only for insight on some concrete feature implementation details or general inspiration. Well, it's possible to tweak code of others, but then it is a must to understand the said code even better than its original author, or esoteric behavior will emerge sooner or later.

  • \$\begingroup\$ Thank you, I didn't realize that the jump power would be the cause of not only the second problem, but the first too. \$\endgroup\$ Commented Aug 14, 2011 at 11:56

What I usually do in my code is quite simple:

First of all, you must calculate how much your character has penetrated inside the other object, in each axis.

int penX = (character.Left < object.Right)
  ? character.Left - object.Right
  : character.Right - object.Left;

Then, one at a time, substract this distance, which will be smaller than the character's delta, from the character position and check if the collision is no more. If the collision still exists, undo the substraction and test the next axis (or both at the same time). If, on the other hand, the collision is no more, your character is now collision free, right beside/above/below the object it collided with.

Since it is a one step system, there is no way you'll end appearing above the object you collided with. That is, unless the character is completely inside a wall or something like that. In this case, adding a couple more calculations to take movement delta into account (knowing where you are coming from) would fix the problem.

Note: it only works when calculating collisions of one moving object against a static one. For collisions of two moving objects it requires a precedence system or some tweaks (e.g. distinguishing dynamic from kinematic objects, as Unity does). Otherwise, strange things happen.

P.S.: I'm sorry I am not adding the code. It's in an old project in my SVN, and finding it would take quite some time.

  • \$\begingroup\$ Thank you, but this is a more basic way of the current system. \$\endgroup\$ Commented Aug 14, 2011 at 11:58

A simple solution is:

  1. Calculate the new position for the character (based on velocity, or button presses, or platforms, etc), but don't move them just yet.
  2. Check for collisions with the character at the new position.
  3. If there are no collisions at the new position, then move the character, otherwise, keep the character where they are.

Apply these steps separately to the X and Y axis so that the character can slide along the unconstrained axis.

By decoupling the movement of the character from the actual position, the character will only move until it collides with an object.

Additional info: If the character is moving at high speed, then you may end up with a problem where the character collides a few pixels before a boundary. In that case you can apply the steps by recursively sub-dividing the distance in halves until the distance between the colliding and non-colliding positions is one pixel.


You must log in to answer this question.

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