Skip to main content
gamedev.net
🔒 Locked

Collisions

Started by starstriker1 7 replies 350+ views
Original Post
starstriker1
starstriker1
Before I can do anything more on my game, I need to get my collision code working. My game is a lot like subspace: top down, rectangular tiles, asteroids style physics... However, I am having trouble with my collision code. The ships just don''t bounce off the tiles, or at least... they don''t bounce off in the right way. I''m wondering if I''m going about it the right way, or if I''ve just messed up in my programming. This is my code:
void Tile_Ship_Collide(int counter)
{
	int count, count2, count3;
	int tiletype;
	int tiles_height = 8;
	int tiles_width = 8;
	int top_pos_x = Ships[counter].x / 16 - 4;
	int top_pos_y = Ships[counter].y / 16 - 4;
	int pos_x = top_pos_x * 16;
	int pos_y = top_pos_y * 16;
	int collx[8], colly[8];
	collx[1] = Ships[counter].x - 12;
	colly[1] = Ships[counter].y - 14;

	collx[2] = Ships[counter].x + 12;
	colly[2] = Ships[counter].y - 14;
	
	collx[3] = Ships[counter].x + 14;
	colly[3] = Ships[counter].y - 12;
	
	collx[4] = Ships[counter].x + 14;
	colly[4] = Ships[counter].y + 12;
	
	collx[5] = Ships[counter].x + 12;
	colly[5] = Ships[counter].y + 14;
	
	collx[6] = Ships[counter].x - 12;
	colly[6] = Ships[counter].y + 14;
	
	collx[7] = Ships[counter].x - 14;
	colly[7] = Ships[counter].y + 12;
	
	collx[8] = Ships[counter].x - 14;
	colly[8] = Ships[counter].y - 12;

	for(count = 1; count < 9; count++)
		Draw_Pixel(collx[count] - view_x, colly[count] - view_y, 125, back_buffer, back_lpitch);



	for(count2 = top_pos_y; count2 < top_pos_y + tiles_height; count2++)
	{
		pos_x = top_pos_x * 16;

		for(count = top_pos_x; count < top_pos_x + tiles_width; count++)
		{
			tiletype = abs(Walls[count][count2].type);

			if(tiletype != 0)// && pos_x > -1 && pos_x < 1024 * map_size && pos_y > -1 && pos_y < 768 * map_size)
			{//Check it against 8 points
				if(collx[1] > pos_x && collx[1] < pos_x + 16 && colly[1] > pos_y && colly[1] < pos_y + 16)
					Ships[counter].yv = 0 - (Ships[counter].yv);

				if(collx[2] > pos_x && collx[2] < pos_x + 16 && colly[2] > pos_y && colly[3] < pos_y + 16)
					Ships[counter].yv = 0 - (Ships[counter].yv);

				if(collx[3] > pos_x && collx[3] < pos_x + 16 && colly[3] > pos_y && colly[3] < pos_y + 16)
					Ships[counter].xv = 0 - (Ships[counter].xv);

				if(collx[4] > pos_x && collx[4] < pos_x + 16 && colly[4] > pos_y && colly[4] < pos_y + 16)
					Ships[counter].xv = 0 - (Ships[counter].xv);

				if(collx[5] > pos_x && collx[5] < pos_x + 16 && colly[5] > pos_y && colly[5] < pos_y + 16)
					Ships[counter].yv = 0 - (Ships[counter].yv);

				if(collx[6] > pos_x && collx[6] < pos_x + 16 && colly[6] > pos_y && colly[6] < pos_y + 16)
					Ships[counter].yv = 0 - (Ships[counter].yv);

				if(collx[7] > pos_x && collx[7] < pos_x + 16 && colly[7] > pos_y && colly[7] < pos_y + 16)
					Ships[counter].xv = 0 - (Ships[counter].xv);

				if(collx[8] > pos_x && collx[8] < pos_x + 16 && colly[8] > pos_y && colly[8] < pos_y + 16)
					Ships[counter].xv = 0 - (Ships[counter].xv);


			}

			pos_x += 16;
		}
	pos_y += 16;
	}
	
}
 
Any help would be appreciated.
starstriker1
starstriker1
Help please. I can''t get much more working in my game until my collision code works.
noize
noize
Hi,

First of all I think you''re taking a much to complex approach to your collision detection system. That''s fine though, I don''t expect you to change because I say so.

I''m looking at this source but I''m just not picturing the game.

How big is each tile? Why the /16 - 4, +/- 12, etc.?
Advanced Bug
Advanced Bug
Some ideas and suggestions:


1) You can make your code significantly clearer by passing a pointer to ship rather than its index. If you change function declaration to "void Tile_Ship_Collide(Ship *ship)" then you can write

ship->x

instead of


Ships[counter].x


And to call the function you can write:


Tile_Ship_Collide(&Ships[counter])


2) You are using wrong array indexing. If you declare your array as coll[8], then the valid element indices are 0 through 7 and not 1 through 8.

3) Lines

int top_pos_x = Ships[counter].x / 16 - 4;
int top_pos_y = Ships[counter].y / 16 - 4;

look confusing. You are calculating coordinates of tile containing the ship and then moving to another tile located 4 tiles away in both axis.

4) Loops

for(count2 = top_pos_y; count2 < top_pos_y + tiles_height; count2++)
for(count = top_pos_x; count < top_pos_x + tiles_width; count++)

iterate through 64 tiles (because both tiles_height and tiles_width are equal to 8). Is this what you want?


starstriker1
starstriker1
This is the code I have working. It behaves reasonably well. At the usual 100 FPS, its rarely sucks you into a wall. However... at low FPS (on fairly low-end machines) you get sucked into the walls constantly.


void Tile_Ship_Collide(int counter)
{
int count, count2, count3;
int tiletype;
int tiles_height = 3;
int tiles_width = 3;
int top_pos_x = (Ships[counter].x / 16) - 1;
int top_pos_y = (Ships[counter].y / 16) - 1;
int pos_x = top_pos_x * 16;
int pos_y = top_pos_y * 16;
float xvel, yvel;
int collx[12], colly[12];
int dist1 = 8;
int dist2 = 9;
int dist3 = 2;

xvel = Ships[counter].xv * 2;
yvel = Ships[counter].yv * 2;

Ship_Coll_Points(collx, colly, counter);


// for(count = 1; count < 13; count++)
// Draw_Clip_Line(collx[count] - view_x, colly[count] - view_y, collx[count] - view_x, colly[count] - view_y, 125, back_buffer, back_lpitch);



for(count2 = top_pos_y; count2 < top_pos_y + tiles_height; count2++)
{
pos_x = top_pos_x * 16;

for(count = top_pos_x; count < top_pos_x + tiles_width; count++)
{
tiletype = Walls[count][count2].type;

if(tiletype != 0)
{
//Draw it, for debug use
// if(counter == 1)
// Draw_Clip_Line(pos_x - view_x, pos_y - view_y, pos_x + 16 - view_x, pos_y + 16 - view_y, 125, back_buffer, back_lpitch);
//Check it against 8 points
if(collx[1] > pos_x && collx[1] < pos_x + 16 && colly[1] > pos_y && colly[1] < pos_y + 16)
{
Ships[counter].x -= Ships[counter].xv;
Ships[counter].y -= Ships[counter].yv;
Ship_Coll_Points(collx, colly, counter);
Ships[counter].yv = 0 - yvel * 0.3;
Ships[counter].yv += 1;
}

if(collx[2] > pos_x && collx[2] < pos_x + 16 && colly[2] > pos_y && colly[2] < pos_y + 16 && Ships[counter].Ship.Armour > 0)
{
Ships[counter].x = rand()%1024*map_size;
Ships[counter].y = rand()%768*map_size;

//Ships[counter].Chatmessage = WallMessages;
}

if(collx[3] > pos_x && collx[3] < pos_x + 16 && colly[3] > pos_y && colly[3] < pos_y + 16)
{
Ships[counter].x -= Ships[counter].xv;
Ships[counter].y -= Ships[counter].yv;
Ship_Coll_Points(collx, colly, counter);
Ships[counter].xv = 0 - xvel * 0.3;
Ships[counter].xv -= 1;
}


if(collx[5] > pos_x && collx[5] < pos_x + 16 && colly[5] > pos_y && colly[5] < pos_y + 16)
{
Ships[counter].x -= Ships[counter].xv;
Ships[counter].y -= Ships[counter].yv;
Ship_Coll_Points(collx, colly, counter);
Ships[counter].yv = 0 - yvel * 0.3;
Ships[counter].yv -= 1;
}


if(collx[7] > pos_x && collx[7] < pos_x + 16 && colly[7] > pos_y && colly[7] < pos_y + 16)
{
Ships[counter].x -= Ships[counter].xv;
Ships[counter].y -= Ships[counter].yv;
Ship_Coll_Points(collx, colly, counter);
Ships[counter].xv = 0 - xvel * 0.3;
Ships[counter].xv += 1;
}



if(collx[9] > pos_x && collx[9] < pos_x + 16 && colly[9] > pos_y && colly[9] < pos_y + 16)
{
Ships[counter].x -= Ships[counter].xv;
Ships[counter].y -= Ships[counter].yv;
Ship_Coll_Points(collx, colly, counter);
Ships[counter].xv = 0 - xvel * 0.3;
Ships[counter].yv = 0 - yvel * 0.3;
Ships[counter].xv += .1;
Ships[counter].yv += .1;
}

if(collx[10] > pos_x && collx[10] < pos_x + 16 && colly[10] > pos_y && colly[10] < pos_y + 16)
{
Ships[counter].x -= Ships[counter].xv;
Ships[counter].y -= Ships[counter].yv;
Ship_Coll_Points(collx, colly, counter);
Ships[counter].xv = 0 - xvel * 0.3;
Ships[counter].yv = 0 - yvel * 0.3;
Ships[counter].xv -= .1;
Ships[counter].yv += .1;
}

if(collx[11] > pos_x && collx[11] < pos_x + 16 && colly[11] > pos_y && colly[11] < pos_y + 16)
{
Ships[counter].x -= Ships[counter].xv;
Ships[counter].y -= Ships[counter].yv;
Ship_Coll_Points(collx, colly, counter);
Ships[counter].xv = 0 - xvel * 0.3;
Ships[counter].yv = 0 - yvel * 0.3;
Ships[counter].xv -= .1;
Ships[counter].yv -= .1;
}

if(collx[12] > pos_x && collx[12] < pos_x + 16 && colly[12] > pos_y && colly[12] < pos_y + 16)
{
Ships[counter].x -= Ships[counter].xv;
Ships[counter].y -= Ships[counter].yv;
Ship_Coll_Points(collx, colly, counter);
Ships[counter].xv = 0 - xvel * 0.3;
Ships[counter].yv = 0 - yvel * 0.3;
Ships[counter].xv += .1;
Ships[counter].yv -= .1;
}


}

pos_x = count * 16 + 16;

}
pos_y = count2 * 16 + 16;
}

}


Sorry I haven''t cleaned up the code yet. Its on my todo list.
starstriker1
starstriker1
Am I going about my collisions right? Should I be doing something else?
VladR
VladR
Please be more specific about your current problem, since a week passed so now your function may look differently.

Generally, when youre looking at something not working for a week, scrap it and start again from scratch. Sometimes youll be able to solve the problem the same day you scrapped the code since after so much looking into same source, youre inevitably biased. AND you might be overlooking something obvious. Your code looks like many parts have been copied and just updated. This is usually source of the problems that are hardest to spot (i.e. there is physically +1, but you "see" -1 ).
At present when I
m looking at the function for two days, have debugged it thoroughly and it aint working and it should, I delete it and within an hour, voila ! Even Carmack admits that sometimes he rewrites his code 5 times. Yes, 4 of it might be optimizations, but you get the point. Its hard to find the balance but it comes with experience. Yes, its hard to delete it, but how rewarding it is when it works and it took you just an hour or two to rewrite it and you may come up with different ways of solving the problem !

I
d personally replace the same parts of code with a function call - its easier to debug then because you just look at the parameters.

If you want to avoid collision problems when the fps is low, you
ll have to change the rendering to a such way that it tests in advance whether the object can be rendered at the relevant position in current frame (i.e. doesnt collide with other objects). And if it collides, you just change its position so that it deosnt collide. Plain simple. Im assuming you calculate its position based on time. This leads to a problem that if theres a big time difference between two consecutive frames (i.e. email coming, some win background task, HDD swapping and such) the objects just jump across the screen and they may collide. And if you have your collision detection code good, it wont let you out, since it collides ! So its a magic circle unless you check& update position before rendering.

hope that helps.
VladR
starstriker1
starstriker1
(sigh)

I guess its back to the code...

Damn it. Collisions is being the most agravating so far.

Topic Locked

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

Sign in to reply to this topic.