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

Author Topic: Perfect Collision Detection and explanation of functions  (Read 11108 times)

0 Members and 1 Guest are viewing this topic.

darekg11

  • Full Member
  • ***
  • Posts: 127
    • View Profile
Perfect Collision Detection and explanation of functions
« Reply #15 on: December 20, 2010, 10:28:41 pm »
Another day, another failure. I manage to get that X and Y of both sprites with view.
It without problem returns good value for standard Intersections check but it fails with PixelPerfect badly...Maybe I am too tired or it's too late but I can't think of anything that may help so please help me.
Below minimal code of needed functions:
To make a bitmask from sprite:
Code: [Select]

int StworzBitMaske(sfSprite* duch, bool** &Maska)
{
sfColor KolorPixela;
int i,j = NULL;
int x = (int)sfSprite_GetWidth(duch);
int y = (int)sfSprite_GetHeight(duch);
Maska =(bool**) malloc(x * sizeof (*Maska));
for (i = 0; i < x; i++)
{
Maska[i] =(bool*) malloc(y * sizeof(Maska));
}
for (i = 0; i < x; i++)
{
for (j = 0; j < y; j++)
{
KolorPixela = sfSprite_GetPixel(duch, i,j);
if (KolorPixela.a == 0.f)
{
Maska[i][j] = 0;
}
else
{
Maska[i][j] = 1;
}
}
}
return 1;
}


To change sprite to rect:
Code: [Select]

sfIntRect SpriteNaRect(sfSprite* &duch)
{
sfIntRect Prostokat;
int y,x;
x = (int)sfSprite_GetX(duch);
y = (int)sfSprite_GetY(duch);
//sfSprite_TransformToGlobal(duch, 0,0,&x, &y);
Prostokat.Top = (int)y;
Prostokat.Left = (int)x;
Prostokat.Bottom = (int)(y + sfSprite_GetHeight(duch));
Prostokat.Right = (int)(x + sfSprite_GetWidth(duch));
//std::cout << (int)x << std::endl;
//std::cout << (int)y << std::endl;
//system("PAUSE");
/*sfSprite_TransformToLocal(duch, 200, 30, &x,&y);
std::cout << x << y << std::endl;
system("PAUSE");*/
return Prostokat;
}


Checking function:
Code: [Select]

bool PixelPerfect(sfSprite* &Obiekt1, sfSprite* &Obiekt2,bool** &Maska, bool** &Maska2)
{
sfIntRect test1,test2,Kolizja;
test1 =  SpriteNaRect(Obiekt1);
test2 =  SpriteNaRect(Obiekt2);
if (sfIntRect_Intersects(&test1, &test2, &Kolizja))
{
WektorFloat Wektor1,Wektor2;
for (int licznik = Kolizja.Left; licznik < Kolizja.Right; licznik++)
{
for (int licznik2 = Kolizja.Top; licznik2 < Kolizja.Bottom; licznik2++)
{
sfSprite_TransformToLocal(Obiekt1,licznik,licznik2,&Wektor1.x,&Wektor1.y);
sfSprite_TransformToLocal(Obiekt2,licznik,licznik2,&Wektor2.x,&Wektor2.y);
if (Maska[(int)Wektor1.x][(int)Wektor1.y] * Maska2[(int)Wektor2.x][(int)Wektor2.y] == 1)
{
return true;
}
else
{
return false;
}
}
}

}
else
{
return false;
}
return false;
}

Wektor is a structure of x and y.
How I do maskcolor:
Code: [Select]

sfColor Kolor; //DO ANIMACJI
Kolor = sfColor_FromRGB(0,0,0); //DO ANIMACJI
bool** Macha;
bool** Macha2;
Kamien = sfImage_CreateFromFile("kamol2.png");
sfImage_CreateMaskFromColor(Kamien, Kolor, 0);
sfSprite_SetImage(sKamien, Kamien);
wsk->zdjecie = sfImage_CreateFromFile("Kubac.png");
sfImage_CreateMaskFromColor(wsk->zdjecie, Kolor, 0);
sfSprite_SetImage(wsk->duszek, wsk->zdjecie);

And how I use it in game loop:
Code: [Select]

std::cout << PixelPerfect(wsk->duszek, sKamien,Macha,Macha2) << std::endl;


Function always return No collision, please write some advices because I go to sleep now and I would like to finish this collision detection tomorrow .

Thanks.

P.S Some parts are commented out because I was testing different ways to solve it.
P.S2 Oh yeah both images have black backgrounds.

model76

  • Full Member
  • ***
  • Posts: 231
    • View Profile
Perfect Collision Detection and explanation of functions
« Reply #16 on: December 21, 2010, 02:29:19 am »
OK, I can't really help you with this, but since no one else is chiming in, I will say this:

I don't think pixel-based collision is the right way to go. It is difficult to implement (at least this way), and is bound to be slow. Most games by far do not use pixel-perfect collision, because good collision can be achieved by simpler, faster means.

A good example is the GTA 3 series (all 3 games, as far as I am aware), which use only sphere collision for the car physics.

What I would do in your case, is look into rectangle- and circle-based collision. Both are fairly simple to implement, can be very fast, and should be enough to create a believable experience in most 2D games.

The basic idea is to create a set of circles or rectangles that approximate the collidable area of a sprite. It doesn't have to be perfect, just good enough that it feels "right". You will have to experiment to get the right balance.

Here is a visual example of what a set of collision circles could look like on one of your sprites:


I hope you can use it.


/EDIT
Oh, and it looks like there is a GetPixel method in Sprite, so I wonder if that won't deal with the clip rect for you? I couldn't say, since I haven't worked with it.

darekg11

  • Full Member
  • ***
  • Posts: 127
    • View Profile
Perfect Collision Detection and explanation of functions
« Reply #17 on: December 21, 2010, 08:22:13 am »
I will try to figure out why that PixelColiision isn't working, I think it's because of wrong calculations of X and Y of moving sprite.

Anyway how would look implementation of that circle method?

model76

  • Full Member
  • ***
  • Posts: 231
    • View Profile
Perfect Collision Detection and explanation of functions
« Reply #18 on: December 21, 2010, 01:18:19 pm »
I am not going to give you a full implementation here - that is for you to figure out. But I will say this:

The basic idea behind circle collision is to test the distance between 2 circle centers.
If the distance is less than the radius of both circles, you have a collision.

Have a look at the wiki and see if someone didn't already implement such a system (remember to check the license if you use it). If not, you can try your luck at http://www.gpwiki.org/, or search the net.

But don't stop there. You should also look into rectangle collision, sometimes called box collision. That is even easier to implement, and might be just right for you.

darekg11

  • Full Member
  • ***
  • Posts: 127
    • View Profile
Perfect Collision Detection and explanation of functions
« Reply #19 on: December 21, 2010, 01:41:26 pm »
Yeah I did not want source code.
Thanks I will try to fix that PixelPerfect, if I won't be able to do so then I will try to use another technique.

darekg11

  • Full Member
  • ***
  • Posts: 127
    • View Profile
Perfect Collision Detection and explanation of functions
« Reply #20 on: December 21, 2010, 04:10:51 pm »
The problem is somewhere in that code:
Code: [Select]

bool PixelPerfect(sfSprite* &Obiekt1, sfSprite* &Obiekt2,bool** &Maska, bool** &Maska2)
{
      sfIntRect test1,test2,Kolizja;
      test1 =  SpriteNaRect(Obiekt1);
      test2 =  SpriteNaRect(Obiekt2);
      if (sfIntRect_Intersects(&test1, &test2, &Kolizja))
      {
         WektorFloat Wektor1,Wektor2; //SOMEWHERE HERE
         for (int licznik = Kolizja.Left; licznik < Kolizja.Right; licznik++)
         { //SOMEWHERE HERE
            for (int licznik2 = Kolizja.Top; licznik2 < Kolizja.Bottom;  licznik2++) //SOMEWHERE HERE
            {
               sfSprite_TransformToLocal(Obiekt1,licznik,licznik2,&Wektor1.x,&Wektor1.y); //SOMEWHERE HERE
               sfSprite_TransformToLocal(Obiekt2,licznik,licznik2,&Wektor2.x,&Wektor2.y); //SOMEWHERE HERE
               if (Maska[(int)Wektor1.x][(int)Wektor1.y] * Maska2[(int)Wektor2.x][(int)Wektor2.y] == 1) //SOMEWHERE HERE
               {
                  return true;
               }
               else
               {
                  return false;
               }
            }
         }
         
      }
      else
      {
         return false;
      }
return false;
}

Because when I do just Intersections check with 2 rectangles by using the same code but only with following:
if (sfIntRect_Intersects(&test1, &test2, &Kolizja))
It works great so I decided to see where the error is and when debugging one thing really looks bad because it's showing that:
Maska[(int)Wektor1.x][(int)Wektor1.y]
Wektor1.x = some minus value
Wektor1.y = some minus value and it's always false for that Maska
But:
Maska2[(int)Wektor2.x][(int)Wektor2.y] shows normal values.

I can't find what is wrong but I bet it's something with coordinates but damn can't find it.

Link to whole projects including resources like images etc.
Link:
Megaupload: http://www.megaupload.com/?d=2OLHYM8M
Rapidshare: http://rapidshare.com/#!download|297l3|438551296|Test.rar|8673
P.S There is a lot of commented code out and some not needed files.

darekg11

  • Full Member
  • ***
  • Posts: 127
    • View Profile
Perfect Collision Detection and explanation of functions
« Reply #21 on: December 22, 2010, 12:07:20 pm »
Okay I am so done with it, fak it even when I translated Collision code from SFML Wiki to C I get negative value at local coords of sprite that is moving... Fak it, I spent 5 days on it, probably there is some shitty litlle mistake somewhere and it won't work.

You can delete tit/lock/whatever.

darekg11

  • Full Member
  • ***
  • Posts: 127
    • View Profile
Perfect Collision Detection and explanation of functions
« Reply #22 on: December 23, 2010, 09:21:51 am »
Okay, I still don't wanan to give up on this.

Does anybody knows why TransformToLocal returns negative values?
I use the same code to cillisions as placed on Wiki. At the beggining I set new view by rectangle:
sfView* Widok = NULL;
sfFloatRect prostychuj;
prostychuj.Bottom = 600;
prostychuj.Left = 0;
prostychuj.Right = 800;
prostychuj.Top = 0;
Widok = sfView_CreateFromRect(prostychuj);
My window is 800x600.

Then at the begging of GameLoop I want to test collision but it always return no collision.

Durning game loop I change position of animated character by moving it by TimeSinceLastFrame * Pixels. I do the same with View, it looks like:
Code: [Select]

OffsetXWidoku +=Offset;
OffsetX += Offset;
sfView_Move(Widok, OffsetXWidoku, 0);
sfSprite_Move(wsk->duszek, OffsetX, 0);


How I manag drawing sprites on different views:
Code: [Select]

sfRenderWindow_SetView(App, Widok);
sfRenderWindow_Clear(App, sfBlack);
sfRenderWindow_DrawSprite(App, Sprite);
sfRenderWindow_DrawSprite(App, sKamien);
sfRenderWindow_DrawSprite(App, wsk->duszek);
         /* Draw the sprite */
sfRenderWindow_SetView(App, sfRenderWindow_GetDefaultView(App));
Update(wsk);
       /* Update the window */
sfRenderWindow_Display(App);


Transalted Collision code:
Collision.c:
http://www.wklejto.pl/84514
Collision.h:
http://www.wklejto.pl/84515

darekg11

  • Full Member
  • ***
  • Posts: 127
    • View Profile
Perfect Collision Detection and explanation of functions
« Reply #23 on: December 23, 2010, 07:10:20 pm »
Really nobody?
Also when I do GetSubRect from Sprite that is like 305x300 I get 1x1 so bassicly this if:
Code: [Select]
if (o1v.x > 0 && o1v.y > 0 && o2v.x > 0 && o2v.y > 0 &&
o1v.x < Obiekt1SubRectWielkosc.x && o1v.y < Obiekt1SubRectWielkosc.y &&
o2v.x < Obiekt2SubRectWielkosc.x && o2v.y < Obiekt2SubRectWielkosc.y)


Will never be truth, I can't figure what si wrong I used debugger to run throught all that code and I can say that part where problems appear is:
Code: [Select]

for (int i = Nakladanie.Left; i < Nakladanie.Right; i++)
{
for (int j = Nakladanie.Top; j < Nakladanie.Bottom; j++)
{
sfSprite_TransformToLocal(Obiekt1,i,j,&o1v.x,&o1v.y);
sfSprite_TransformToLocal(Obiekt2,i,j,&o2v.x,&o2v.y);
if (o1v.x > 0 && o1v.y > 0 && o2v.x > 0 && o2v.y > 0 &&
o1v.x < Obiekt1SubRectWielkosc.x && o1v.y < Obiekt1SubRectWielkosc.y &&
o2v.x < Obiekt2SubRectWielkosc.x && o2v.y < Obiekt2SubRectWielkosc.y)
{
if ((sfSprite_GetPixel(Obiekt1, (int) (o1v.x), (int) (o1v.y)).a > LimitAlphy) &&
  (sfSprite_GetPixel(Obiekt2, (int) (o2v.x), (int) (o2v.y)).a >  LimitAlphy))
  {
return true;
      }
}
}
}


At first it returns negatives values for my moving character, second is desribed upper. Anyone can help me? I would really like to fix it and I tryied i think like everything different sheets like ConvertCoords etc but can't get it to working.

Maybe I get wrong idea of views? And I wrote to oryginal author of Collision code but he/she is on holidays right now so I don't suppose to get anwser back. I will try everything from zero tomorrow but if any of You find time please test this code posted in previous post.

Okay I found out that when I do something like:
 sfRenderWindow_ConvertCoords(App,sfSprite_GetX(wsk->duszek),sfSprite_GetY(wsk->duszek),&x2,&y2,sfRenderWindow_GetDefaultView(App));
 sfSprite_TransformToLocal(wsk->duszek,x2,y2,&x1,&y1);
std::cout << x1 << y1;

I get some negative values which are almost the same as when I do collision, I will play with it a bit and maybe I will find solution >.>

And when I do the same with custom view I get some  values but negative, I think I will list for myself all possible posistions of objects and see if there is some kind of conections between these negative vaules and maybe I will fix it.

darekg11

  • Full Member
  • ***
  • Posts: 127
    • View Profile
Perfect Collision Detection and explanation of functions
« Reply #24 on: December 24, 2010, 10:46:49 am »
Okay it's real weird even when I created new project with no custom view and placed there background, a stone which can't move and sprite that can't move it still doesn't work and still returning negative values.

EDIT: OMFG, I putted Update function of animation in different place and commented out some code in collision detection and it works : o

Damn after 1 week finally, it's like Christmas gift : > Good thing that I did not give up on this, I would regret it later.