01-21-2023, 05:40 PM
While making the changes it dawned on me that a mask image is not needed at all! A simple check for two alpha values of 0 works as well. Use the same red oval and green oval images.
Code: (Select All)
'** Pixel Perfect Collision Demo #5
TYPE TypeSPRITE ' sprite definition
image AS LONG ' sprite image
x1 AS INTEGER ' upper left X
y1 AS INTEGER ' upper left Y
x2 AS INTEGER ' lower right X
y2 AS INTEGER ' lower right Y
END TYPE
TYPE TypePOINT ' x,y point definition
x AS INTEGER ' x coordinate
y AS INTEGER ' y coordinate
END TYPE
DIM RedOval AS TypeSPRITE ' red oval image
DIM GreenOval AS TypeSPRITE ' green oval image
DIM Intersect AS TypePOINT ' point of collision
RedOval.image = _LOADIMAGE("redoval.png", 32) ' load red oval image image
GreenOval.image = _LOADIMAGE("greenoval.png", 32) ' load green oval image
'+---------------------------------------------------------------------------------------------+
'| Set image transparent color. This does not need to be done for PNG files with transparency. |
'+---------------------------------------------------------------------------------------------+
_SETALPHA 0, _RGB32(255, 0, 255), RedOval.image ' set image transparent color
_SETALPHA 0, _RGB32(255, 0, 255), GreenOval.image ' set image transparent color
SCREEN _NEWIMAGE(640, 480, 32) ' enter graphics screen
_MOUSEHIDE ' hide the mouse pointer
GreenOval.x1 = 294 ' green oval upper left X
GreenOval.y1 = 165 ' green oval upper left Y
DO ' begin main program loop
_LIMIT 30 ' 30 frames per second
CLS ' clear screen
WHILE _MOUSEINPUT: WEND ' get latest mouse information
_PUTIMAGE (GreenOval.x1, GreenOval.y1), GreenOval.image ' display green oval
_PUTIMAGE (RedOval.x1, RedOval.y1), RedOval.image ' display red oval
RedOval.x1 = _MOUSEX ' record mouse X location
RedOval.y1 = _MOUSEY ' record mouse Y location
IF PixelCollide(GreenOval, RedOval, Intersect) THEN ' pixel collision?
LOCATE 2, 36 ' yes, position text cursor
PRINT "COLLISION!" ' report collision happening
CIRCLE (Intersect.x, Intersect.y), 4, _RGB32(255, 255, 0)
PAINT (Intersect.x, Intersect.y), _RGB32(255, 255, 0), _RGB32(255, 255, 0)
END IF
_DISPLAY ' update screen with changes
LOOP UNTIL _KEYDOWN(27) ' leave when ESC key pressed
SYSTEM ' return to operating system
'------------------------------------------------------------------------------------------------------------
FUNCTION PixelCollide (Obj1 AS TypeSPRITE, Obj2 AS TypeSPRITE, Intersect AS TypePOINT)
'--------------------------------------------------------------------------------------------------------
'- Checks for pixel perfect collision between two rectangular areas. -
'- Returns -1 if in collision -
'- Returns 0 if no collision -
'- -
'- obj1 - rectangle 1 coordinates -
'- obj2 - rectangle 2 coordinates -
'---------------------------------------------------------------------
DIM x1%, y1% ' upper left x,y coordinate of rectangular collision area
DIM x2%, y2% ' lower right x,y coordinate of rectangular collision area
DIM Test1& ' overlap image 1 to test for collision
DIM Test2& ' overlap image 2 to test for collision
DIM Hit% ' -1 (TRUE) if a collision occurs, 0 (FALSE) otherwise
DIM Osource& ' original source image handle
DIM p1~& ' alpha value of pixel on image 1
DIM p2~& ' alpha value of pixel on image 2
Obj1.x2 = Obj1.x1 + _WIDTH(Obj1.image) - 1 ' calculate lower right x,y coordinates of both objects
Obj1.y2 = Obj1.y1 + _HEIGHT(Obj1.image) - 1
Obj2.x2 = Obj2.x1 + _WIDTH(Obj2.image) - 1
Obj2.y2 = Obj2.y1 + _HEIGHT(Obj2.image) - 1
Hit% = 0 ' assume no collision
'+-------------------------------------+
'| perform rectangular collision check |
'+-------------------------------------+
IF Obj1.x2 >= Obj2.x1 THEN ' rect 1 lower right X >= rect 2 upper left X ?
IF Obj1.x1 <= Obj2.x2 THEN ' rect 1 upper left X <= rect 2 lower right X ?
IF Obj1.y2 >= Obj2.y1 THEN ' rect 1 lower right Y >= rect 2 upper left Y ?
IF Obj1.y1 <= Obj2.y2 THEN ' rect 1 upper left Y <= rect 2 lower right Y ?
'+-----------------------------------------------------------------------+
'| rectangular collision detected, perform pixel perfect collision check |
'+-----------------------------------------------------------------------+
IF Obj2.x1 <= Obj1.x1 THEN x1% = Obj1.x1 ELSE x1% = Obj2.x1 ' calculate overlapping coordinates
IF Obj2.y1 <= Obj1.y1 THEN y1% = Obj1.y1 ELSE y1% = Obj2.y1
IF Obj2.x2 <= Obj1.x2 THEN x2% = Obj2.x2 ELSE x2% = Obj1.x2
IF Obj2.y2 <= Obj1.y2 THEN y2% = Obj2.y2 ELSE y2% = Obj1.y2
Test1& = _NEWIMAGE(x2% - x1% + 1, y2% - y1% + 1, 32) ' make overlap image of object 1
Test2& = _NEWIMAGE(x2% - x1% + 1, y2% - y1% + 1, 32) ' make overlap image of object 2
_PUTIMAGE (-(x1% - Obj1.x1), -(y1% - Obj1.y1)), Obj1.image, Test1& ' place overlap area of object 1
_PUTIMAGE (-(x1% - Obj2.x1), -(y1% - Obj2.y1)), Obj2.image, Test2& ' place overlap area of object 2
x% = 0 ' reset overlap area coordinate counters
y% = 0
Osource& = _SOURCE ' remember calling source
DO ' begin pixel collide loop
_SOURCE Test1& ' read from image 1
p1~& = _ALPHA32(POINT(x%, y%)) ' get alpha level of pixel
_SOURCE Test2& ' read from image 2
p2~& = _ALPHA32(POINT(x%, y%)) ' get alpha level of pixel
IF (p1~& <> 0) AND (p2~& <> 0) THEN ' are both pixels transparent?
Hit% = -1 ' no, there must be a collision
Intersect.x = x1% + x% ' return collision coordinates
Intersect.y = y1% + y% '
END IF
x% = x% + 1 ' increment column counter
IF x% > _WIDTH(Test1&) - 1 THEN ' beyond last column?
x% = 0 ' yes, reset x
y% = y% + 1 ' increment row counter
END IF
LOOP UNTIL y% > _HEIGHT(Test1&) - 1 OR Hit% ' leave when last row or collision detected
_SOURCE Osource& ' restore calling source
_FREEIMAGE Test1& ' remove temporary image from RAM
_FREEIMAGE Test2&
END IF
END IF
END IF
END IF
PixelCollide = Hit% ' return result of collision check
END FUNCTION