Image collision checking

Discuss using and improving Lua and the Lua Player specific to the PSP.

Moderators: Shine, Insert_witty_name

Post Reply
Knifa
Posts: 4
Joined: Tue Dec 27, 2005 8:59 pm

Image collision checking

Post by Knifa »

I'm trying to get collision checking for my working.

I tried to do it this way, but it just went REALLY slow, and I'm not sure if it even worked. The way I tried to do it probably isn't the best way either.

Code: Select all

	for y = y1, y1+img1:height() do
		for x = x1, x1+img1:width() do
			for ty = y2, y2+img2:height() do
				for tx = x2, x2+img2:width() do
					tcolPix = testimg:pixel( x, y );
					tcolTPix = testimg:pixel( tx, ty );
					colPix = tcolPix:colors();
					colTPix = tcolTPix:colors();
					
					if ( colPix == colTPix ) then
						return true;
					end
				end
			end
		end
	end
Does anyone else know of a way I could do it? The way the images in my game arn't really detailed or anything, so I could just do it like bounding boxes, but I don't know how that would work.

The old way I had it was like this:

Code: Select all

	if &#40; &#40;shipX >= platformX&#41; and &#40;shipX+imgShip&#58;width&#40;&#41; <= platformX+imgPlatform&#58;width&#40;&#41;&#41; &#41; then
		if &#40; &#40;shipY+imgShip&#58;height&#40;&#41; >= platformY-1&#41; and &#40;shipY+imgShip&#58;height&#40;&#41; <= platformY&#41; &#41; then
			if &#40; shipSpeed < 0.6 &#41; then
				-- Do stuff
			end
		end
	end
But that only worked if the ship was exactly inside the platform area, and not if it was half way in. (It's also only uses just a small section of the Y to check because it didn't work properly if I used the whole image.

Thanks.
romero126
Posts: 200
Joined: Sat Dec 24, 2005 2:42 pm

Re: Image collision checking

Post by romero126 »

Knifa wrote:I'm trying to get collision checking for my working.

I tried to do it this way, but it just went REALLY slow, and I'm not sure if it even worked. The way I tried to do it probably isn't the best way either.

Code: Select all

	for y = y1, y1+img1&#58;height&#40;&#41; do
		for x = x1, x1+img1&#58;width&#40;&#41; do
			for ty = y2, y2+img2&#58;height&#40;&#41; do
				for tx = x2, x2+img2&#58;width&#40;&#41; do
					tcolPix = testimg&#58;pixel&#40; x, y &#41;;
					tcolTPix = testimg&#58;pixel&#40; tx, ty &#41;;
					colPix = tcolPix&#58;colors&#40;&#41;;
					colTPix = tcolTPix&#58;colors&#40;&#41;;
					
					if &#40; colPix == colTPix &#41; then
						return true;
					end
				end
			end
		end
	end
Does anyone else know of a way I could do it? The way the images in my game arn't really detailed or anything, so I could just do it like bounding boxes, but I don't know how that would work.

The old way I had it was like this:

Code: Select all

	if &#40; &#40;shipX >= platformX&#41; and &#40;shipX+imgShip&#58;width&#40;&#41; <= platformX+imgPlatform&#58;width&#40;&#41;&#41; &#41; then
		if &#40; &#40;shipY+imgShip&#58;height&#40;&#41; >= platformY-1&#41; and &#40;shipY+imgShip&#58;height&#40;&#41; <= platformY&#41; &#41; then
			if &#40; shipSpeed < 0.6 &#41; then
				-- Do stuff
			end
		end
	end
But that only worked if the ship was exactly inside the platform area, and not if it was half way in. (It's also only uses just a small section of the Y to check because it didn't work properly if I used the whole image.

Thanks.
Personally I would place an array arranging all the images.

Like
ShipArray = { }
table.insert(ShipArray, x,y,w,h, Image.load( filename ))

That will allow you to setup bounding box's for each image as well as place the images however you wish. As long as you place each element drawn in a loop.

Another trick to speed up refresh time is to create a preimage not including your (moving image) and have everything refresh over time.

This should allow your game to be less choppy and hopefully have a little cleaner code.

If you have any other questions let me know.

The rest is up to you..
LuMo
Posts: 410
Joined: Sun Aug 21, 2005 2:45 am
Location: Austria
Contact:

Post by LuMo »

w, h, is not even required, cause you can get width and height from the loaded image itself...

Code: Select all

image&#58;width&#40;&#41;
image&#58;height&#40;&#41;
moe functions @ the wiki

greets lumo
"Good artists copy, great artists steal."
Pablo Picasso
go2lumo.com
romero126
Posts: 200
Joined: Sat Dec 24, 2005 2:42 pm

Post by romero126 »

w/h is to allow for bigger immages to be used as a smaller/colision based system. So transparancys and image:width() etc.. wont make it look bad.

(just thinking ahead for you!)
LuMo
Posts: 410
Joined: Sun Aug 21, 2005 2:45 am
Location: Austria
Contact:

Post by LuMo »

possibly use distance vector based calculation (faster?)
and you do not need to check that much...
(but ... distance would be calced as circle)

greets
"Good artists copy, great artists steal."
Pablo Picasso
go2lumo.com
Dr. Vegetable
Posts: 171
Joined: Mon Nov 14, 2005 1:32 am
Location: Boston, Massachusetts
Contact:

Post by Dr. Vegetable »

knifa wrote: The old way I had it was like this:

Code: Select all

   if &#40; &#40;shipX >= platformX&#41; and &#40;shipX+imgShip&#58;width&#40;&#41; <= platformX+imgPlatform&#58;width&#40;&#41;&#41; &#41; then 
      if &#40; &#40;shipY+imgShip&#58;height&#40;&#41; >= platformY-1&#41; and &#40;shipY+imgShip&#58;height&#40;&#41; <= platformY&#41; &#41; then 
         if &#40; shipSpeed < 0.6 &#41; then 
            -- Do stuff 
         end 
      end 
   end 

But that only worked if the ship was exactly inside the platform area, and not if it was half way in. (It's also only uses just a small section of the Y to check because it didn't work properly if I used the whole image.
It looks like you were on the right track with your original code. The trick to collision-detecting two rectangles is to compare opposite sides, like this:

Code: Select all

   if &#40; &#40;shipX+imgShip&#58;width&#40;&#41; >= platformX&#41; and &#40;shipX <= platformX+imgPlatform&#58;width&#40;&#41;&#41; &#41; then 
      if &#40; &#40;shipY+imgShip&#58;height&#40;&#41; >= platformY&#41; and &#40;shipY <= platformY+imgPlatform&#58;height&#40;&#41;&#41; &#41; then 
         if &#40; shipSpeed < 0.6 &#41; then 
            -- Do stuff 
         end 
      end 
   end 
Conceptually, what this does is to compare the left side of one rectangle with the right side of the other, and v/v. If A's right side is to the right of B's left side, and A's left side is to the left of B's right side, and if A's top is above B's bottom and A's bottom is below B's top, then A and B at least partially overlap.

Sorry if that explanation is more "Dr. Seuss" than "Dr. Vegetable..."
Knifa
Posts: 4
Joined: Tue Dec 27, 2005 8:59 pm

Post by Knifa »

Dr. Vegetable wrote:
knifa wrote:

Code: Select all

   if &#40; &#40;shipX+imgShip&#58;width&#40;&#41; >= platformX&#41; and &#40;shipX <= platformX+imgPlatform&#58;width&#40;&#41;&#41; &#41; then 
      if &#40; &#40;shipY+imgShip&#58;height&#40;&#41; >= platformY&#41; and &#40;shipY <= platformY+imgPlatform&#58;height&#40;&#41;&#41; &#41; then 
         if &#40; shipSpeed < 0.6 &#41; then 
            -- Do stuff 
         end 
      end 
   end 
Conceptually, what this does is to compare the left side of one rectangle with the right side of the other, and v/v. If A's right side is to the right of B's left side, and A's left side is to the left of B's right side, and if A's top is above B's bottom and A's bottom is below B's top, then A and B at least partially overlap.

Sorry if that explanation is more "Dr. Seuss" than "Dr. Vegetable..."
That works, thanks alot. I don't entirely understand how it works, but I'll get it eventually.[/i]
thepelkus
Posts: 1
Joined: Thu Jan 05, 2006 2:08 am

Post by thepelkus »

The other way that I've always liked, just a restatement of the good Doctor's code for the sake of legibility, is:

Code: Select all

collide=1

     if shipX>platformX+imgPlatform&#58;width&#40;&#41; then collide=nil
else if platformX>shipX+imgShip&#58;width&#40;&#41;     then collide=nil
else if shipY>platformY+imgPlatform&#58;height  then collide=nil
else if platformY>shipY+imgShip&#58;height&#40;&#41;    then collide=nil

if collide then
-- do something
Again, just checking to see if either element in the comparison is clearly to one side of the other, setting a collide flag to nil if it's ever the case. Note that, as a lua novice, I'm not sure about the syntax, but that should be close if not right.

Additionally, if you did want pixel perfect collision after that, you could run your pixel test code only on the intersection of the two rectangles.
Post Reply