Sign in to follow this  

SDL - Collision Detection with an Image

This topic is 3666 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Ok, well first off I am making a simple program that has sprite animation and movement. I've got the character moving and animating properly and he moves freely and not tilebased. So basically instead of making a tilemap, I use a giant image of the map, and only draw the portion of the screen at a time, and the image scrolls as you walk. So far it looks good. I know how to do collision detection for the edges of the screen, but what about the actual objects on the map, like trees. I thought about making another image that is a mirror of the map that isn't visible on top of it. All sections that aren't able to be walked on would be black. Perhaps you could check the pixel color? This is where I'm kinda stumped. If it helps at all I am using SDL. Basically, what would be a good strategy for collision detection on a non tile based map.

Share this post


Link to post
Share on other sites
Quote:
Original post by Arbel
Ok, well first off I am making a simple program that has sprite animation and movement. I've got the character moving and animating properly and he moves freely and not tilebased. So basically instead of making a tilemap, I use a giant image of the map, and only draw the portion of the screen at a time, and the image scrolls as you walk. So far it looks good. I know how to do collision detection for the edges of the screen, but what about the actual objects on the map, like trees.

I thought about making another image that is a mirror of the map that isn't visible on top of it. All sections that aren't able to be walked on would be black. Perhaps you could check the pixel color? This is where I'm kinda stumped. If it helps at all I am using SDL. Basically, what would be a good strategy for collision detection on a non tile based map.


You're basically looking for bounding boxes.

Here's some code, and I'll explain what's going on:
bool CollisionCheck(const SDL_Rect& BoxA, const SDL_Rect& BoxB)
{
if(BoxA.x > BoxB.x + BoxB.w)
return false;
if(BoxA.x + BoxA.w < BoxB.x)
return false;
if(BoxA.y > BoxB.y + BoxB.h)
return false;
if(BoxA.y + BoxA.w < BoxB.y)
return false;
return true;
}


Basically, you check each condition in which, if true, the boxes cannot possibly be overlapping. Once all conditions have been checked, if you're still in the function, you've got a hit.

Share this post


Link to post
Share on other sites
Well the map itself is one image. But what is the other box itself representing? My map, is just a single image with all of the non-moveable object painted on it. So the trees or the rocks I would be avoiding, are a part of the image so I would have to guess there x,y coords. That's why I was thinking of maybe having another overlapping image of the map on top with the areas that are unwalkable in black. But I'm not sure how to do check based on color. Perhaps I am not making any sense?

Share this post


Link to post
Share on other sites
You CAN do it by a color key (which is what you're asking about), but I wouldn't recommend it. You see, if you just have a map + color key to determine collision, it's static. In other words, you can't move around the non-passable areas very easily. For instance, you can't have a special trigger that moves a wall. Furthermore, you can't have any freely moving entities that the player cannot move on.

You shouldn't think about the "map" so much as a play area populated with objects. Each object has a bounding box, IE, a rectangle to define its boundaries.

For example, you might have a tree, like this:
class Tree
{
private:
SDL_Rect SizeAndPosition;

public:
SDL_Rect GetSizeAndPosition() const;
}


The SDL_Rect details where it is, along with its boundaries. Then, you might have another object like this:
class Player
{
private:
SDL_Rect SizeAndPosition;

public:
SDL_Rect GetSizeAndPosition() const;
void Dance();
}


Then, to see if they overlap:

Tree ObjectA;
Player ObjectB;

if(CollisionCheck(ObjectA.GetSizeAndPosition(), ObjectB.GetSizeAndPosition))
StopObjectFromMoving(ObjectB);

//Elsewhere in the code
bool CollisionCheck(const SDL_Rect& BoxA, const SDL_Rect& BoxB)
{
if(BoxA.x > BoxB.x + BoxB.w)
return false;
if(BoxA.x + BoxA.w < BoxB.x)
return false;
if(BoxA.y > BoxB.y + BoxB.h)
return false;
if(BoxA.y + BoxA.w < BoxB.y)
return false;
return true;
}


In this way, you can move around such hitable objects smoothly and easily. You can even dynamically spawn more if you like.

Share this post


Link to post
Share on other sites
It makes sense what you are doing. It would require a lot of rectangles since there a ton of trees/other objects scattered on the map and I would have to hand code each coordinate. That's kinda why I wanted to do something that would be a lot quicker and I need it done fairly soon. I have no plans of changing the static background. I may add NPC's, but I would handle that collision detection differently. So I guess what would be a good strategy with the color mechanism (even though it is inefficient in most cases)

Sorry to be difficult hehe and I appreciate your replies.

Share this post


Link to post
Share on other sites
Quote:
Original post by Arbel
It makes sense what you are doing. It would require a lot of rectangles since there a ton of trees/other objects scattered on the map and I would have to hand code each coordinate. That's kinda why I wanted to do something that would be a lot quicker and I need it done fairly soon. I have no plans of changing the static background. I may add NPC's, but I would handle that collision detection differently. So I guess what would be a good strategy with the color mechanism (even though it is inefficient in most cases)

Sorry to be difficult hehe and I appreciate your replies.


There are many many ways to handle collision. If you're worried about having too many bounding boxes all over the place, you can do something of a combination of the two, where static imagery is controlled by the color map, but entities collide with each other via bounding boxes.

As for how it's actually done, that can be tricky. Lazy Foo has a great write up for accessing individual pixels in a surface here:
http://lazyfoo.net/SDL_tutorials/lesson31/index.php

and here:
http://lazyfoo.net/SDL_tutorials/lesson30/index.php

Basically, when you move an object, you need the check all the pixels under where the object is moving to. If any of the pixels is, say, black, prevent it from moving. If you have many moving objects, this can get tedious. Furthermore, you need to lock the surface in order to read the pixel data, which can hold up SDL from doing its thing.

Share this post


Link to post
Share on other sites
I see what you mean. It looks like it would actually be more difficult using pixels. Perhaps making a single image for my map was not the best idea, but for now I will try what you told me by bounding in certain areas just to get some type of collision detection working for my project. Thanks for the helpful info :)

Much appreciated.

Share this post


Link to post
Share on other sites
Hey I'm newly registered here (but not to games development, nor lurking on gamedev), my first post :-D

I'm not quite sure why your collision map would need to be an SDL surface.

Couldn't it just be a bitmap in memory? Sure you would draw it and save it as ideally a 2bit image such as a PNG. It really wouldn't be too tricky to load the PNG into memory. If required you could use SDL to load it into a surface, lock that surface and then copy it back to normal memory and release the surface. Or if possible get SDL to load it into a system memory surface? Personally I'd use the png lib to pull it into system memory.

If the image is a contiguous linear bitmap in system memory then accessing the colour of any pixel is really simple from the 2D coordinate. It's memory location is offset to the start of the image to Y*Width+X.

You could also encode other things in there too if you wanted. Such as having black for collision and a different colour for (say) water that makes the character move slowly, different colours for movement properties of surfaces. Have different footstep sounds for grass than for wooden floors for example. The image would probably want to be palletized for that to work best.

If you do want to go with bounding boxes or other basic primitives, circles (spheres in 3D) then you could also have a tool or process in you game that reads the collision map you've drawn and pulls out the positions of the boxes. It would be a much easier and flexible way than hand-coding them.

Share this post


Link to post
Share on other sites
He means simply pulling all the pixels in the image file at load time, and storing the pixel array into a separate container for use. This prevents you from having to lock the surface every 5 seconds.

Share this post


Link to post
Share on other sites
There are plenty solutions to your problem.

Per pixel collision detection seems to be the more direct approach, anyway it can easily lead to fps consuming.

Shape approximation is a common and very useful technique in collision detection since it can save your application from a lot of expensive calculations.
That's why they've suggest you to use bounding objects as squares or, even better, circles.

You can also try with math involving approaches like separation axis method. To better understand this you should have basic vectors knowledges.

Try and test the best solution for your application.
Hope this helps,



Share this post


Link to post
Share on other sites

This topic is 3666 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this