Skip to main content
gamedev.net
🔒 Locked 🎲 GameMaker

Tile Based Collision Detection

Started by KG_Brad Jan 26, 2008 at 1:33 PM 10 replies 4.2k views
Original Post
KG_Brad
KG_Brad
I've been working at getting my collision detection fixed for a while, but nothing I'm trying is helping. What I'm trying to do is make a calculation based on the location of the player sprite to determine it's location on my tilemap. Here's my source:

int find_player_cell()
{
	playerData.cell_x = playerData.x/CELLWIDTH;
	playerData.cell_y = playerData.y/CELLHEIGHT;
	
	return playerData.cell_x;
	return playerData.cell_y;
}

int collision_detection()
{
	find_player_cell();
	
	if (map[playerData.cell_y][playerData.cell_x] != 0)
		collision = 1;
	else
		collision = 0;
}

It works on some tiles but on others, it doesn't work. What am I missing? Thanks, all!
Quote: Of course justice isn't equal. Rich people can afford lawyers, where poor people get McLawyers.
Shakedown
Shakedown
I'm assuming this is Cplusplus.

There are a few large problems and I'm surprised it actually compiled. First of all, you cannot have 2 return statements in a method like you have. You can only return one int or another, so if you wanted to return both you would have to wrap them in an object or an array or container of some sort.

Second, when you call the find_player_cell() method it will return an int, but you're not doing anything with that int. You need a variable to store that return int so you can use it.

Third, your collision_detection() method is of type int, but you have no return statement.
EmrldDrgn
EmrldDrgn
As to why this works on some cells and not others... it's hard to tell without being able to see where some of your variables come from, but I'm guessing that either playerData.x, playerData.cell_x or CELLWIDTH are floats/doubles, or possibly that even if they are ints, the / is doing floating-point division. This would be an easy source of error. What exactly is it doing when it's "not working"?

A few other things:

CELLWIDTH/HEIGHT is a const int, not a #define, right?
Are those methods part of the class which playerData is an instance of? If not, should they be?
Where is collision defined? Do you need it beyond the scope of this function? Would it be possible to just have the function return 1 or 0 and capture the return value?

In short, think about variable scope and data accessability, and maybe post a bit more code next time.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~I program in C++, on MSVC++ '05 Express, and on Windows. Most of my programs are also for windows.
KG_Brad
KG_Brad
Quote:
I'm assuming this is Cplusplus.

Nope. This is C.

Quote:
First of all, you cannot have 2 return statements in a method like you have.

I didn't know that. Fixed.

Quote:
Second, when you call the find_player_cell() method it will return an int, but you're not doing anything with that int.

The collision_detection() function uses it.

Quote:
Third, your collision_detection() method is of type int, but you have no return statement.

I must have left that out of my post. It returns whether or not "collision" is 1 or 0.

Quote:
I'm guessing that either playerData.x, playerData.cell_x or CELLWIDTH are floats/doubles, or possibly that even if they are ints, the / is doing floating-point division.

playerData.x and playerData.y are both ints. CELLWIDTH/HEIGHT is a #define. I'll look into that.

Thanks. I'll get on that and if I run into anything else, I'll post it.
Quote: Of course justice isn't equal. Rich people can afford lawyers, where poor people get McLawyers.
Shakedown
Shakedown

Quote:

Quote:
Second, when you call the find_player_cell() method it will return an int, but you're not doing anything with that int.

The collision_detection() function uses it.


Yes that's what you want, but you have to either insert your function call into your formula, or store the int that is returned by your function into a variable so you can then use that int. The function only creates an int, it does not store that int for you, which is why you have to assign it to a variable.

This also explains why you cannot have a function return 2 ints (or anything). That would be like "int x = 2 4;" which obviously doesn't work. Which int should be stored in x?
KG_Brad
KG_Brad
Ok, I split the get_player_cell() function into two functions, one dealing with x, one dealing with y.

Here's my source:

int find_player_cell_x(){	playerData.cell_x = playerData.x/CELLWIDTH;		return playerData.cell_x;}int find_player_cell_y(){	playerData.cell_y = playerData.y/CELLHEIGHT;		return playerData.cell_y;}int collision_detection(){	find_player_cell_x();	find_player_cell_y();		if (map[playerData.cell_y][playerData.cell_x] != 0)		collision = 1;	else		collision = 0;			return collision;}


It's still doing the same thing. Would it help if I made a video to demonstrate what it's doing?
Quote: Of course justice isn't equal. Rich people can afford lawyers, where poor people get McLawyers.
EmrldDrgn
EmrldDrgn
A video isn't exactly necessary. What behavior are you experiencing? What behavior do you desire?

You might want to take a look at the Smart Questions FAQ. This will help people help you with problems you might have.

Again, as I said, the definition of the playerData class (struct, I suppose, which answers a lot of questions) would be a big help, but try this. As the other guy said, you're not actually capturing the ints returned from your find_cell functions. To do that, replace:

find_player_cell_x();find_player_cell_y();	if (map[playerData.cell_y][playerData.cell_x] != 0)


with:

int x, y;x = find_player_cell_x();y = find_player_cell_y();if (map[y][x] !=0)


See the difference?

When a function returns a value, what happens (in oversimplified terms) is that the function call (find_player_cell()) is replaced by the return value in the expression. So:

x = find_player_cell_x();

becomes:

x = playerData.cell_x;

which is what your function returns.

One last thing - where do you create the playerData instance of whatever struct? More simply, where is:

playerData;

?

On a side note, do you have any particular reason for using C as opposed to C++? Not that it's not a perfectly valid choice, I was just wondering if it was really a concious (and educated) choice you made, and the reasons for it.

EDIT: Really last thing - playerData.x and playerData.y are the x and y coordinates in pixels, right?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~I program in C++, on MSVC++ '05 Express, and on Windows. Most of my programs are also for windows.
Zakwayda
Zakwayda
Quote:
Original post by KG_Brad
Ok, I split the get_player_cell() function into two functions, one dealing with x, one dealing with y.

Here's my source:

*** Source Snippet Removed ***

It's still doing the same thing. Would it help if I made a video to demonstrate what it's doing?
I don't know that there's enough information in your post for us to tell what's wrong.

It does look, though, as if you're a bit confused about some aspects of the language you're using. Specifically, you appear to be modifying global variables of some sort within your functions, but you are also returning those values - and, at least in the case of your 'find cell' functions, ignoring those return values.

Now, it doesn't look like it matters, given that you access the global 'player data' variable directly in the collision detection function. But, the somewhat confused nature of the functions you've posted suggests that maybe similar errors are being made elsewhere.

Also, I assume you meant to index your map in the order (y,x) rather than (x,y)? Are you sure that the way you're indexing the map for collision detection purposes matches the way you're indexing it for rendering?
KG_Brad
KG_Brad
Quote:
One last thing - where do you create the playerData instance of whatever struct?
In the player.h header file.

Quote:
On a side note, do you have any particular reason for using C as opposed to C++?
No real reason. I just like it better.

Quote:
Really last thing - playerData.x and playerData.y are the x and y coordinates in pixels, right?
Correct.

Quote:
Also, I assume you meant to index your map in the order (y,x) rather than (x,y)? Are you sure that the way you're indexing the map for collision detection purposes matches the way you're indexing it for rendering?
Yes.
Quote: Of course justice isn't equal. Rich people can afford lawyers, where poor people get McLawyers.
KG_Brad
KG_Brad
I hate to double post, but I feel like I need to explain.

The reason why my code is bad is because I've never used this collision method. I'm still learning how to do it this way.
Quote: Of course justice isn't equal. Rich people can afford lawyers, where poor people get McLawyers.
EmrldDrgn
EmrldDrgn
Quote:
Original post by KG_Brad
I hate to double post, but I feel like I need to explain.

The reason why my code is bad is because I've never used this collision method. I'm still learning how to do it this way.


Instead of double posting, you can edit your previous post.

That being said, some fairly basic flaws would tend to suggest a lack of familiarity with your chosen language. I'm not saying you don't have that familiarity, just explaining why the possibility occured to me.

When I asked where you create the struct, I meant that we'll need to actually see the code that does so (i.e., please post player.h).

And one last time: What behavior are you observing? What behavior are you expecting? Is your code supposed to print 1 when there's a collision, or is it supposed to start tap-dancing and singing "The Joker" by the Steve Miller Band? Is it instead printing 0, or performing the highlights of Pearljam? What is happening?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~I program in C++, on MSVC++ '05 Express, and on Windows. Most of my programs are also for windows.
KG_Brad
KG_Brad
Quote:
What behavior are you observing? What behavior are you expecting?
Sorry about that. I was so burned out on code yesterday and it totally slipped my mind.

Basically, what I'm trying to do is check if there will be a collision before it actually happens. Then it determines if the player should move or not by checking if collision is 0 or 1.

For some reason, it's only looking for a collision in the lower left hand corner of the "solid" tiles.

Also, here's my player.h source:

struct {	int x;	int y;		int cell_x;	int cell_y;} playerData;
Quote: Of course justice isn't equal. Rich people can afford lawyers, where poor people get McLawyers.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.