1
\$\begingroup\$

The problem is when I move diagonal it moves fractions of units and therefore my coordinates might be a fraction of a unit say (40,400) might be actually (40.12,400.40) but another problem is my pink square might be moving really fast. Below is a screenshot where you can see I can make it past a pixel perfect passageway with my pink square but the other passageway with the white square is very difficult if not impossible to make it through (I have by zooming in and moving REALLY slow but sometimes it impossible for the reasons listed above) Suppose in the example above I am holding the up and left arrows how can I make it so the pink square slides across the yellow rectangle and detects it can move upward and begins to move up?

enter image description here

The code I am using right now looks like this

float d45 = (float) (1 / Math.sqrt(2));
moveX = -d45;
moveY = d45;
moveX = moveX * t * speed;
moveY = moveY * t * speed;
        for (Stuff s : collidables) {
            if (overlaps(s, moveX, 0)) {
                collidedX.add(s);
                x += moveX > 0 ? s.x - width - x : s.x + s.width - x;
            }
        }
        if (collidedX.size < 1) {
            x += moveX;
        }
        for (Stuff s : collidables) {
            if (overlaps(s, 0, moveY)) {
                collidedY.add(s);
                y += moveY > 0 ? s.y - height - y : s.y + s.height - y;
            }
        }
        if (collidedY.size < 1) {
            y += moveY;
        }

I check for collision twice once on the Y axis and another on the X axis so that it can still slide to the left even if you are pushing the up and left arrow. The problem is it skips over the 100 unit passage to the left of the picture above. If I create a passage that is 110 units wide it will slide up fine but this isn't really cool because I like how it looks where it slides perfectly. Any ideas?

\$\endgroup\$
1
2
\$\begingroup\$

Collision detection like this can be tricky. However - I do see a way around your problems.

First, you definitely want to round off your "collision" position. In most cases, decimal numbers will cause collision problems when you're working with pixels (which are measured in whole numbers, usually).

Here are two methods I thought up, in image form: (sorry everybody I know this makes my answer hard to edit... if you notice an error with the image please comment - I can correct it, thanks!)

Collision methods

\$\endgroup\$
2
  • \$\begingroup\$ how do I round off the position of my object without making it go faster to a particular corner of the screen? \$\endgroup\$ – CodeCamper Apr 6 '15 at 17:11
  • \$\begingroup\$ If you're using the first method, you can just round off the position of your collision box only (and not the actual player's position). For the second method, you can make the last "step" in any direction the remainder, so if you had X velocity = 3.4, you'd move one pixel right 3 times and then move 0.4 pixels at the end, and then again, keep the collision box's position rounded off. \$\endgroup\$ – Superdoggy Apr 6 '15 at 17:23
1
\$\begingroup\$

The easiest way to side-step this is:

x = (int)x;
y = (int)y;

or

x = round(x);
y = round(y);

Are either of these acceptable, visually?

Edit:

Diagram of modified SuperDoggy "Method 1" using floats:
Precise overlap amount given by colliders
enter image description here

Since you have so many cases, it may be helpful to make a helper for jiggling the rect:

class CollisionHelper
{
   CollisionHelper(Collider1,Collider2);
   RECT original;
   RECT test;
   void MoveUp();
   void MoveDown();
   void MoveLeft();
   void MoveRight();
   void ResetRect();
   void Test();
   bool wasValid[4];
   ...
}

This would also encapsulate any flags needed to make multiple tests in one frame and any frame-to-frame flags that might be useful. It should make the if/switch more manageable.

\$\endgroup\$
7
  • \$\begingroup\$ This doesn't quite answer the other part of the question that says "but another problem is my pink square might be moving really fast." ...or "how can I make it so the pink square slides across the yellow rectangle and detects it can move upward and begins to move up?" Rounding is definitely necessary - but see my answer for a further solution. :) \$\endgroup\$ – Superdoggy Apr 5 '15 at 22:44
  • \$\begingroup\$ @Superdoggy, I was going to suggest handling the diagonals separately by moving diagonally and if either points were valid and are now invalid, un-slide by the overlap amount, re-test. It sounded really ugly though; you did much better. \$\endgroup\$ – Jon Apr 5 '15 at 23:40
  • \$\begingroup\$ @Superdoggy, check out my edit; works with floats but separate case for each diagonal... meh? Basically (float)Method 1 \$\endgroup\$ – Jon Apr 6 '15 at 0:03
  • \$\begingroup\$ So this method is sort of moving both X and Y directions at once then trying to apply my Method 1 to it? (At least from what I gathered). If I'm right, this basically would measure how far embedded the object is into a wall for the X and Y axis and move along the axis that would lead it to not be embedded in the shortest distance? Nice idea - although I would suggest trying to explain the picture a bit more - it's a tad confusing I think. Anyway - if you liked my answer, mind upvoting it? Thanks! :) \$\endgroup\$ – Superdoggy Apr 6 '15 at 0:35
  • \$\begingroup\$ @Superdoggy, yes, this should let the box enter any space that is wide enough, from any direction. Basically, I check the two relevant points for wasValid and isValid a couple of times/ways. Combined with the data from the colliders, this gives floating-point solutions for every case. \$\endgroup\$ – Jon Apr 6 '15 at 1:11

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.