PDA

View Full Version : Create own (surface-obstacles) collision detection - problem



Firlefanz
02-11-2005, 10:11 AM
Hello,

I also asked this in Omega's own forums. But it is very quiet there those days. And I got so much help here the last time and cannot find the problem myself and it has not much to do with Omega at least, perhaps somebody here can help me. :D

I wanted to have an own collision detection because I only need the collision detection to work on a part of each sprite, when moving sprites on the surface. So a player cannot walk 'through' a tree, but it can walk behind the top of the tree etc.

So I added to OmegaSprite Item a public RectCol: TRect;
This should be the area to make the collision check.

First thing is in each Sprite creation method I do it like this:


Rectcol.Top:=35;
Rectcol.left:=55;
Rectcol.bottom:=90;
Rectcol.right:=105;


So this is the area for this sprite to collide.

Then in sprites move method:


begin
lastxco:=xco;
lastyco:=yco;
...
move the sprite whereever
...
if commandoform.rect_collide(tsprite(self)) then begin
xco:=lastxco;
yco:=lastyco;
end;
//if a collision detection returns true set the sprite
//back to location it had before
end;


So in the move method the collision detection is called, and when it collides, the sprite is set back to the location it had before. Xco and Yco are my own coordinates for the sprite in the world, X and Y are calculated from them.

Here my collision detection:


function TCommandoForm.rect_collide(SpriteSelf:TSprite): boolean;
var i: integer;
l,r,t,b: single;
begin
result:=false;
for i:=0 to xensprite.count-1 do begin
if (spriteself <> xensprite.Items[i]) and (xensprite.Items[i].name<>'Bullet') and
((max(spriteSelf.rectcol.left+spriteSelf.x,xenspri te.Items[i].Rectcol.left+xensprite.Items[i].x) < min(spriteSelf.Rectcol.right+spriteSelf.x, xensprite.Items[i].Rectcol.right+xensprite.Items[i].x)) and
(max(spriteSelf.Rectcol.top+spriteSelf.y, xensprite.Items[i].Rectcol.top+xensprite.Items[i].y) < min(spriteSelf.Rectcol.bottom+spriteSelf.y, xensprite.Items[i].Rectcol.bottom+xensprite.Items[i].y))) then begin
result:=true;
exit;
end;
end;
result:=false;
end


This works very well in most cases, but just sometimes my man or monster can walk through a tree or another sprite. And it is sometimes hard to get away from another sprite when I am near to it, but not always.

Do you have a better idea how to do it or a suggestion how to improve it or an idea why it is not working better?

Firle

Paulius
02-11-2005, 04:15 PM
Walking trough the trees happens because you?¢_Tre objects can move in larger steps then you?¢_Tre smallest collision box. The simplest way to avoid this is to do some more collision tests along you?¢_Tre objects path if its movement speed is high. Collision response is the second problem, rather than moving an object back you should collect a list of objects colliding with it and by their attributes (position, speed, mass, etc.) determine where they?¢_Tll push or otherwise affect each other.

Firlefanz
03-11-2005, 07:08 AM
Hi Paulius,

thanks for the reply.

You are right, this could be a possible reason. But I checked it, it is not. :roll:

I have small step and I reduced them by half. These steps are so small that a collision must happen, but it does not (only in some cases).

I still have no idea why, most times it is working, some times not...

Firle

Traveler
03-11-2005, 08:31 AM
I'm have no idea about a solution, but I noticed in your source that you're doing a string comparison. May I suggest that you convert this to a boolean check as its a bit faster?

Also there's a function called IntersectRect. It think you'll find it useful in your collision tests.

Firlefanz
03-11-2005, 08:39 AM
Hi Traveler,

yes, you're right, you talk about this: xensprite.Items[i].name<>'Bullet'

Should be faster if boolean, correct. I'll change it. Thanks. :D
See any errors in the code or about the idea?

Firle