Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
error doing image collision detection with _MemGet
#41
OK that didn't take long.

There are 2 ways you can do the intersect of 2 image rectangles:
1) Just run som numbers and say if intersect or not ie True or False 
Code: (Select All)
Function BoxCollision% (b1x, b1y, b1w, b1h, b2x, b2y, b2w, b2h)
    ' x, y represent the box left most x and top most y
    ' w, h represent the box width and height which is the usual way sprites / tiles / images are described
    ' such that boxbottom = by + bh
    '        and boxright = bx + bw

    If (b1y + b1h < b2y) Or (b1y > b2y + b2h) Or (b1x > b2x + b2w) Or (b1x + b1w < b2x) Then
        BoxCollision% = 0
    Else
        BoxCollision% = -1
    End If
End Function

2nd way, you not only say if they intersect but you also say exactly where they intersect.
Code: (Select All)
' this needs max, min functions as well as BoxCollision%
Sub Intersect2Boxes (b1x, b1y, b1w, b1h, b2x, b2y, b2w, b2h, bix As Long, biy As Long, biw As Long, bih As Long)
    If b2x >= b1x And b2x <= b1x + b1w And b2y >= b1y And b2y <= b1y + b1h Then 'top left corner in 2nd box
        bix = b2x: biy = b2y
        If b2x + b2w <= b1x + b1w Then biw = b2w Else biw = b1x + b1w - b2x
        If b2y + b2h <= b1y + b1h Then bih = b2h Else bih = b1y + b1h - b2y
    ElseIf b2x >= b1x And b2x <= b1x + b1w And b2y + b2h >= b1y And b2y + b2h <= b1y + b1h Then 'bottom left corner of 2nd box in first
        bix = b2x
        If b2x + b2w <= b1x + b1w Then biw = b2w Else biw = b1x + b1w - b2x
        If b2y <= b1y Then biy = b1y: bih = b2y + b2h - b1y Else biy = b2y: bih = b2h
    ElseIf b2x + b2w >= b1x And b2x + b2w <= b1x + b1w And b2y >= b1y And b2y <= b1y + b1h Then 'right top corner 2nd box in first
        If b2x >= b1x Then bix = b2x: biw = b2w Else bix = b1x: biw = b2x + b2w - b1x
        biy = b2y
        If b2y + b2h <= b1y + b1h Then bih = b2h Else bih = b1y + b1h - b2y
    ElseIf b2x + b2w >= b1x And b2x + b2w <= b1x + b1w And b2y + b2h >= b1y And b2y + b2h <= b1y + b1h Then 'left bottom corners in first box
        If b2x >= b1x Then bix = b2x: biw = b2w Else bix = b1x: biw = b2x + b2w - b1x
        If b2y >= b1y Then biy = b2y: bih = b2h Else biy = b1y: bih = b2y + b2h - b1y
    ElseIf BoxCollision%(b1x, b1y, b1w, b1h, b2x, b2y, b2w, b2h) Then
        bix = max(b1x, b2x): biy = max(b1y, b2y)
        biw = min(b1x + b1w, b2x + b2w) - bix: bih = min(b1y + b1h, b2y + b2h) - biy
    Else 'no intersect
        bix = -1: biy = -1: biw = 0: bih = 0
    End If
End Sub


Here I strongly suspect this is where you are getting thrown of the scent @madscijr.

So lets look at the parameters to this SUB
(b1x, b1y, b1w, b1h, b2x, b2y, b2w, b2h, bix As Long, biy As Long, biw As Long, bih As Long)

Long story short they are 3 boxes
box 1 image 1 is  b1x, b1y, b1w, b1h
box 2 image 2 is  b2x, b2y, b2w, b2h

and the last box describes the box of intersect (which could be also a line or point but would have at least and x, y value.

box intersect   bix As Long, biy As Long, biw As Long, bih As Long
note bi stands for box intersect

So my box intersect collision says where the box of intersect is, where points in common to both images might be, so we've only a very small box, smaller than either image likely to search for over lapping pixels!

That  is key point to understanding the pixel collision sub routine. *** It already knows from the 2nd box intersect SUB where exactly to look for pixel collisons inside both image rectangles:
Code: (Select All)
' this sub needs Intersect2Boxes which uses  max, min, and BoxCollision Functions
Function PixelCollision& (img1 As boxType, img2 As boxType, intx As Long, inty As Long)
    ' boxType here needs at least an x, y, w, h and img
    Dim As Long x, y, ix, iy, iw, ih
    Dim As _Unsigned Long p1, p2
    intx = -1: inty = -1 ' no collision set
    Intersect2Boxes img1.x, img1.y, img1.w, img1.h, img2.x, img2.y, img2.w, img2.h, ix, iy, iw, ih   ' ***
    If ix <> -1 Then ' the boxes intersect
        y = iy: x = ix
        Do
            _Source img1.img
            p1 = Point(x - img1.x, y - img1.y) ' point minus img x, y location = location in image I hope
            _Source img2.img
            p2 = Point(x - img2.x, y - img2.y)
            If (p1 <> 0) And (p2 <> 0) Then
                PixelCollision& = -1: intx = x: inty = y: Exit Function
            End If
            If (x + 1) > (ix + iw - 1) Then ' get rid of 2 slow For Loops
                x = ix: y = y + 1
                If y >= (iy + ih - 1) Then
                    _Source 0: Exit Function
                Else
                    y = y + 1
                End If
            Else
                x = x + 1
            End If
        Loop
    End If
End Function

@madscijr is that enough of a clue to the PixelCollision routine?

BTW my code assumes the object point color in the intersecting images is not 0 ie all background of object is Black.

BTW the spiders legs of the images are moving all the time so an updated image is drawn I assume in separate container on each frame.
So really cool to catch an intersect off a dynamically changing image, way way way more tricky than merely getting intersect of polygons!
  724  855  599  923  575  468  400  206  147  564  878  823  652  556 bxor cross forever
Reply
#42
@bplus you need to update these routines for the newest versions of QB64PE.

Code: (Select All)

Function BoxCollision% (b1x, b1y, b1w, b1h, b2x, b2y, b2w, b2h)
' x, y represent the box left most x and top most y
' w, h represent the box width and height which is the usual way sprites / tiles / images are described
' such that boxbottom = by + bh
' and boxright = bx + bw

If (b1y + b1h < b2y) Or (b1y > b2y + b2h) Or (b1x > b2x + b2w) Or (b1x + b1w < b2x) Then
BoxCollision% = 0
Else
BoxCollision% = -1
End If
End Function\

Change all those OR statements to _ORELSE statements. A collision routine like this is one place where ORELSE could prove to make a heckuva change in performance.

OR is a mathematical process. It involves doing math on bits and the above will take 3 different math processes to arrive at an answer.

_ORELSE does a binary TRUE/FALSE compare -- **WITH** break logic installed built in it.

IF a = b OR a = c OR a = d THEN .... This will solve it as (a = b) then do the (a = c) then do the (a = d). Then it'll OR the first two values. Then OR the result of that and the last value to get a final result. Multiple processes here.

IF a = b _ORELSE a = c _ORELSE a = d THEN.... This will solve (a=b). If the result is 0, it's done. No need to do anything more.

This statement:

IF a = b _ORELSE a = c _ORELSE a = d THEN

Would translate closer to this code:

IF a = b THEN
IF a = c THEN
IF a = d THEN


The first time it fails to produce a positive result, it's done. No need to do the other parts.

See where that might make quite an improvement for a collision routine, which is being called X number of times per loop?
Reply
#43
Function PixelCollision& (img1 As boxType, img2 As boxType, intx As Long, inty As Long)

Notice the last 2 parameters to the Function, they tell you exactly the pixel the intersect was found. I used that point as the center for the exploding spiders. BTW it finds one point of intersect, its done. So we don't get the whole set of points of intersect if more than one.
  724  855  599  923  575  468  400  206  147  564  878  823  652  556 bxor cross forever
Reply
#44
(09-29-2025, 07:42 PM)SMcNeill Wrote: @bplus you need to update these routines for the newest versions of QB64PE.

Code: (Select All)

Function BoxCollision% (b1x, b1y, b1w, b1h, b2x, b2y, b2w, b2h)
    ' x, y represent the box left most x and top most y
    ' w, h represent the box width and height which is the usual way sprites / tiles / images are described
    ' such that boxbottom = by + bh
    '        and boxright = bx + bw

    If (b1y + b1h < b2y) Or (b1y > b2y + b2h) Or (b1x > b2x + b2w) Or (b1x + b1w < b2x) Then
        BoxCollision% = 0
    Else
        BoxCollision% = -1
    End If
End Function\

Change all those OR statements to _ORELSE statements.  A collision routine like this is one place where ORELSE could prove to make a heckuva change in performance.

OR is a mathematical process.  It involves doing math on bits and the above will take  3 different math processes to arrive at an answer.

_ORELSE does a binary TRUE/FALSE compare -- **WITH** break logic installed built in it.

IF a = b OR a = c OR a = d THEN  ....  This will solve it as (a = b)  then do the (a = c) then do the (a = d).  Then it'll OR the first two values.  Then OR the result of that and the last value to get a final result.  Multiple processes here.

IF a = b _ORELSE a = c _ORELSE a = d THEN....  This will solve (a=b).  If the result is 0, it's done.  No need to do anything more. 

This statement:

IF a = b _ORELSE a = c _ORELSE a = d THEN

Would translate closer to this code:

IF a = b THEN
  IF a = c THEN
      IF a = d THEN


The first time it fails to produce a positive result, it's done.  No need to do the other parts.

See where that might make quite an improvement for a collision routine, which is being called X number of times per loop?

I dont think I actually use that SUB, I like the one that provides the info of where the intersect point, line or box exists exactly.

But thankyou for explaining the advantage of the new _OrElse, that is handy to know and even to be reminded of for this old dog.
  724  855  599  923  575  468  400  206  147  564  878  823  652  556 bxor cross forever
Reply
#45
(09-29-2025, 07:53 PM)bplus Wrote: I dont think I actually use that SUB, I like the one that provides the info of where the intersect point, line or box exists exactly.

But thankyou for explaining the advantage of the new _OrElse, that is handy to know and even to be reminded of for this old dog.

Note that even in the other subs, you can get the same advantage by swapping out AND with _ANDALSO. AndAlso will also short circuit out and exit the process earlier. Since those routines have even more uses of AND in them, the performance improvement might be even better for you.
Reply
#46
I think if only one AND in a statement there is no advantage to swap with _AndAlso.

AND this
Quote:IF a = b _ORELSE a = c _ORELSE a = d THEN

Would translate closer to this code:

IF a = b THEN
  IF a = c THEN
      IF a = d THEN

Applies better to ANDs not ORs which might use ElseIFs ... gantlet.
  724  855  599  923  575  468  400  206  147  564  878  823  652  556 bxor cross forever
Reply
#47
(09-29-2025, 07:42 PM)SMcNeill Wrote: Change all those OR statements to _ORELSE statements.  A collision routine like this is one place where ORELSE could prove to make a heckuva change in performance.

OR is a mathematical process.  It involves doing math on bits and the above will take  3 different math processes to arrive at an answer.

_ORELSE does a binary TRUE/FALSE compare -- **WITH** break logic installed built in it.

Waitaminute! I guess I need to do better at keeping up with new commands (or ones I might have missed) cuz _ORELSE sounds like an absolute game changer for a lot of things!

It makes me wonder what other commands am I missing that could improve performance?

Anyway, I'm grateful you mentioned it, I was not aware of _ORELSE and the performance hit with the regular OR...
Reply
#48
(09-29-2025, 08:21 PM)bplus Wrote: I think if only one AND in a statement there is no advantage to swap with _AndAlso.

IF a + b + c + d + e = f + g + h + i + j   AND k + l + m + n + o = p + q + r + s + t  THEN

This has to perform ALL those math operations on both sides of the process before it does that AND to give you a final result.

Change that to _ANDALSO and you only do *one half* of that process.  ( a + b + c + d + e = f + g + h + i + j).  If that half produces a result that is FALSE, it no longer has to do the other half of the process.

_ORELSE shortcircuits the first time you get a _TRUE match.   

If a _ORELSE b _ORELSE c _ORELSE d _ORELSE e....   IF a is true, then there's no reason to check the rest, the BOOLEAN result is going to be _TRUE.

But lets say:

a = 2
b = 1

IF a OR b....  We're doing math here, and we have to evaluate the solution fully.  
2 OR 1 is 3.  
2 _ORELSE 1 is _TRUE.

OR requires precise mathematical results.
_ORELSE is _TRUE/_FALSE boolean results.  

That difference makes a heckuva change in allowing you to bypass entire segments of your code without ever needing to execute it.



And I was actually wrong with with what I translated above.  That's more how an _ANDELSE block works.  

This isn't completely right:
Quote:IF a = b _ORELSE a = c _ORELSE a = d THEN

Would translate closer to this code:

IF a = b THEN
IF a = c THEN
IF a = d THEN

It would actually translate more to:

IF a = b Then
'do whatever
ELSEIF a = c Then
'do whatever
ELSEIF a = d Then
'do whatever

When the first condition passes, you don't check the others with an _ORELSE process. You only need to keep checking until you either get the first _TRUE result, or you check everything and then get the final _FALSE result.

And for _ANDALSO, it's like how I translated originally.

IF a = b _ANDALSO a = c _ANDALSO a = d THEN

Would translate closer to this code:

IF a = b THEN
....IF a = c THEN
........IF a = d THEN

_ANDALSO bypasses on the _FALSE result. _ORELSE bypasses on the _TRUE result.

Both can allow you to bypass entire large sections of code. If all you need is a boolean _true/_false result, use them. AND/OR is for binary comparisons and precise math figures.
Reply
#49
And hopefully I'm not being too wordy for bplus, but let me explain in detail here:

If b2x >= b1x And b2x <= b1x + b1w And b2y >= b1y And b2y <= b1y + b1h Then 'top left corner in 2nd box

This processes in this order:
b2x >= b1x
b2x <= b1x + b1w
b2y >= b1y
b2y <= b1y + b1h
result from step 1 AND step 2
result from step 5 AND step 3
result form step 6 AND step 4
final result

Change those to _ANDALSO and you have a process like this:
b2x >= b1x
(sees _ANDALSO, if above result is _FALSE skip) b2x <= b1x + b1w
(sees _ANDALSO, if above result is _FALSE skip) b2y >= b1y
(sees _ANDALSO, if above result is _FALSE skip) b2y <= b1y + b1h
final result

See the number of steps that you're bypassing here? All those math operations? The first FALSE allows you to skip all those other operations and math comparisons.
Reply
#50
Yes I got it with this:
Quote:IF a + b + c + d + e = f + g + h + i + j   AND k + l + m + n + o = p + q + r + s + t  THEN

if  a + b + c + d + e = f + g + h + i + j NOT TRUE then  no sense doing the next calculation.

Thanks AndAlso AND never again! Smile
  724  855  599  923  575  468  400  206  147  564  878  823  652  556 bxor cross forever
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Collision Detection NakedApe 12 306 02-26-2026, 01:01 AM
Last Post: NakedApe
  Mac debugger not connecting, a user error! BlameTroi 0 99 02-07-2026, 06:18 PM
Last Post: BlameTroi
  ERROR MESSAGES COLORS ? aurel 5 383 01-02-2026, 11:26 AM
Last Post: aurel
  Using CONST & _RGB used together seem to error... Dav 12 680 12-12-2025, 12:29 AM
Last Post: Dav
Photo from png tile, create symmetrical screen image hsiangch_ong 11 931 08-23-2025, 01:23 AM
Last Post: bplus

Forum Jump:


Users browsing this thread: 1 Guest(s)