Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Collision with FloatRect  (Read 13208 times)

0 Members and 1 Guest are viewing this topic.

dotty

  • Jr. Member
  • **
  • Posts: 56
    • View Profile
Collision with FloatRect
« on: February 21, 2012, 01:16:09 pm »
Hello, I need some advice on collisions. I have setup 2 RectangleShapes and setup up 2 FloatRect around them. One of the shapes is moved around using this code

Code: [Select]

if (sf::Keyboard::IsKeyPressed( sf::Keyboard::W )) {
      this->velocity.y -= this->deltatime;
   }

   if (sf::Keyboard::IsKeyPressed( sf::Keyboard::S )) {
      this->velocity.y += this->deltatime;
   }

if (sf::Keyboard::IsKeyPressed( sf::Keyboard::A )) {
      this->velocity.x -= this->deltatime;
   }

   if (sf::Keyboard::IsKeyPressed( sf::Keyboard::D )) {
      this->velocity.x += this->deltatime;
   }


(Thanks Laurent!).

The FloatRect also move with the moveable box. I've modified the code so that when the 2 boxes intersect the movable box is no longer movable in that direction. The problem is that this code is only run once the boxes intersect, meaning I'm already inside the box and cannot get out.

This must be an obvious issue, but how would one go about fixing it?

Ptlomej

  • Newbie
  • *
  • Posts: 48
    • ICQ Messenger - 353167418
    • View Profile
    • Local
Collision with FloatRect
« Reply #1 on: February 21, 2012, 03:44:47 pm »
I use to detect Physiks with Box2d! if you want to use it to i can Teach you ;)!

unranked86

  • Newbie
  • *
  • Posts: 37
    • View Profile
Collision with FloatRect
« Reply #2 on: February 21, 2012, 05:22:58 pm »
When the boxes intersect, move the movable box back by 1 pixel.

dotty

  • Jr. Member
  • **
  • Posts: 56
    • View Profile
Collision with FloatRect
« Reply #3 on: February 21, 2012, 05:42:48 pm »
Sometimes because my movement is timed by deltatime the box doesn't move by 1px and could intersect by 3-4 pixels.

texus

  • Hero Member
  • *****
  • Posts: 505
    • View Profile
    • TGUI
    • Email
Collision with FloatRect
« Reply #4 on: February 21, 2012, 05:57:07 pm »
Quote from: "dotty"
Sometimes because my movement is timed by deltatime the box doesn't move by 1px and could intersect by 3-4 pixels.

Move it 1 pixel, check the collision again.
If it still collides then you move another pixel until the boxes no longer collide.
TGUI: C++ SFML GUI

jmcmorris

  • Jr. Member
  • **
  • Posts: 64
    • View Profile
Collision with FloatRect
« Reply #5 on: February 22, 2012, 08:46:40 am »
You'll need some slightly more complicated collision handling. I have recently been working on my own and this is what I am doing.

Set entity's previous position to position
Add gravity to the entity's velocity
Add velocity to the entity's position (multiply time delta if this is not a fixed time loop)
Check for collision with other entities
if collision then calculate the overlap between the two entities
if both entities are movable then divide the overlap between the two and move both away from one another by overlap amount.
if only one entity is movable then move the entity back overlap amount

Things can be a little trickier than that and there are a few ways do deal with them. I'm honestly still figuring them out but this should give you a good start.

Haze

  • Full Member
  • ***
  • Posts: 201
    • View Profile
    • Github Profile
Collision with FloatRect
« Reply #6 on: February 22, 2012, 02:48:49 pm »
During the movement step, store the previous position of each object before computing its new position.
Then, in the collision detection step, if two objects are overlapping, assign their previous position (before collision), so you can ensure objects are never overlapping.

jmcmorris

  • Jr. Member
  • **
  • Posts: 64
    • View Profile
Collision with FloatRect
« Reply #7 on: February 22, 2012, 07:02:33 pm »
Quote from: "Haze"
During the movement step, store the previous position of each object before computing its new position.
Then, in the collision detection step, if two objects are overlapping, assign their previous position (before collision), so you can ensure objects are never overlapping.


While this is a very simple means to get collision working, it would also mean that if an object has high velocity it would appear to not move at all even though it should have moved 20 out of the 21 pixels that it should have.

dotty

  • Jr. Member
  • **
  • Posts: 56
    • View Profile
Collision with FloatRect
« Reply #8 on: February 24, 2012, 02:33:17 pm »
Thanks everyone, all the answer were insightful.

I do have another question though. Should my main player's object be checking for collisions with all intrects in my scene? Or should all colliderable objects be checking for collisions with the main player?

If it's the former then what happens if I have 500+ colliderable "tiles" in my scene? Every frame my main player would have to loop around ALL the tiles and do it's collision checking.

How do people go about doings this?

unranked86

  • Newbie
  • *
  • Posts: 37
    • View Profile
Collision with FloatRect
« Reply #9 on: February 24, 2012, 04:30:12 pm »
Well, I was "researching" (using google :) ) the very same thing, and in general, you have two options. Implement your own Quad-tree, or the grid-based collision detection. In my personal opinion, it all depends on your game, whether you want to use quad-trees or the grid. I mean, if you have a tile-map then the quad-tree seems a better choice.

jmcmorris

  • Jr. Member
  • **
  • Posts: 64
    • View Profile
Collision with FloatRect
« Reply #10 on: February 24, 2012, 07:11:28 pm »
If you have a tile-based map then the only tiles you need to check to see if the player is colliding with a tile are the tiles that the player is on. Here is my function for detecting if a player is overlapping a tile.

Code: [Select]
std::vector<Vector2i> TileLayer::overlaps(const sf::FloatRect& rect, const bool solidOnly, const bool includeTouching) {
    std::vector<Vector2i> overlapped;
    float touching = includeTouching ? 0 : 0.001f;
    Int32 startX = std::max<float>(0, rect.Left / TileSystem::TILE_WIDTH);
    Int32 startY = std::max<float>(0, rect.Top / TileSystem::TILE_HEIGHT);
    Int32 endX = std::min<float>((rect.Left + rect.Width - touching) / TileSystem::TILE_WIDTH, m_tiles[0].size() - 1);
    Int32 endY = std::min<float>((rect.Top + rect.Height - touching) / TileSystem::TILE_HEIGHT, m_tiles.size() - 1);
    for (Int32 y = startY; y <= endY; ++y) {
        for (Int32 x = startX; x <= endX; ++x) {
            Int32 tileId = m_tiles[y][x];
            if (tileId != 0 && (!solidOnly || m_tileSystem->getTile(tileId)->isSolid())) {
                overlapped.push_back(Vector2i(x, y));
            }
        }
    }
    return overlapped;
}


This takes a rect (the collidable rect of the player), the solidOnly is to check for only solid tiles (you could quite possibly remove this and related code), and the includeTouching is kind of a hack to specify if a rect should be considered overlapping a tile if it is on the tile border. The return value is a list of tiles that the rect is overlapping.

For my collision algorithm I do
Code: [Select]
std::vector<Vector2i> overlapping = tileLayer->(player.getRect(), true, false);
if (!overlapping.empty()) {
    //Collision detected!
}


Doing the actual collision testing is tricky and I'm still working on that code and not happy enough with it yet to share it. The basic logic is along the lines of what I sent in my first post in this topic. The player is movable while the tiles are not.

I hope this helps some!

dotty

  • Jr. Member
  • **
  • Posts: 56
    • View Profile
Collision with FloatRect
« Reply #11 on: February 26, 2012, 02:30:35 pm »
I'm having difficulties with getting 2 FloatRects to react to each other.

Can someone write a simple sample showing how to to del with this? Having 2 FloatRects on the screen (displayed with RectangleShapes), one of them movable with WASD keys, the other stationary. The movable one needs to collide with the stationary one and not be able to move through it.

This would be very helpful so I can inspect how this is handled.

Thanks

Weeve

  • Jr. Member
  • **
  • Posts: 87
  • C++ Programmer (Intermediate), 3D Artist (Skilled)
    • View Profile
    • Email
Collision with FloatRect
« Reply #12 on: February 26, 2012, 11:25:31 pm »
err.. I'm not going to build the entire code (I'm still working on my own project), but I will give a little help, if your doing only rectangular collision checking, its easy:

Code: [Select]
for (int i=0;i<tiles.size();++i){
    if (PlayerPosition.x + PlayerSize.x/2 <= TilePosition.x + TileSize.x/2 && PlayerPosition.x - PlayerSize.x/2 >= TilePosition.x - TileSize.x/2) {
        //collision on the x
        PlayerPosition.x += (PlayerPosition.x - TilePosition.x)
    }
    if (PlayerPosition.y + PlayerSize.y/2 <= TilePosition.y + TileSize.y/2 && PlayerPosition.y - PlayerSize.y/2 >= TilePosition.y - TileSize.y/2) {
        //collision on the y
        PlayerPosition.y += (PlayerPosition.y - TilePosition.y)
    }
}


I might have a few signs reversed, cause I havent tested this, I just wrote it for you (I've kinda done this before, but in lua, and not C++), but thats the jist of rectangle collision checking, you can break off the && onto another if to make it more efficient if you want :)
Long live rapid project development! -- Kestrel3D Game-Engine nearing completion

unranked86

  • Newbie
  • *
  • Posts: 37
    • View Profile
Collision with FloatRect
« Reply #13 on: February 27, 2012, 09:53:49 am »
Why don't you use the Intersects(...) and Contains(...) functions of the sf::FloatRect class ? I guess, that's why they exist, you know, to make our lives easier. :)

dotty

  • Jr. Member
  • **
  • Posts: 56
    • View Profile
Collision with FloatRect
« Reply #14 on: February 27, 2012, 05:18:43 pm »
sorry, I don't think I explained myself very well. I'm using Intersects and that successfully returns a boolean (true on collision, else false).

I'm having difficulties actually dealing with the FloatRects once they actually collide (making FloatRect A stop moving and revert to the boarder of FloatRect B).