Author |
Topic: sprite collisions (Read 972 times) |
|
leslie griffin
Guest
|
 |
sprite collisions
« Thread started on: Dec 30th, 2009, 10:54pm » |
|
is there any collision detction embedded in bbc basic or do i write my own routines..thx...
|
|
Logged
|
|
|
|
admin
Administrator
member is offline


Posts: 1145
|
 |
Re: sprite collisions
« Reply #1 on: Dec 31st, 2009, 08:31am » |
|
Quote:is there any collision detection embedded in bbc basic |
|
SPRITELIB doesn't contain any collision detection code (it has been suggested before, but nobody's implemented it AFAIK). I don't know about GFXLIB; you would need to ask its author.
Richard.
|
|
Logged
|
|
|
|
David Williams
Developer
member is offline

meh

Gender: 
Posts: 452
|
 |
Re: sprite collisions
« Reply #2 on: Dec 31st, 2009, 09:58am » |
|
on Dec 31st, 2009, 08:31am, Richard Russell wrote:SPRITELIB doesn't contain any collision detection code (it has been suggested before, but nobody's implemented it AFAIK). I don't know about GFXLIB; you would need to ask its author.
Richard. |
|
GFXLIB provides quite a few routines intended for bitmap (sprite) collision detection.
http://www.bb4w-games.com/gfxlib/gfxlib.html
Regards, David. --
|
|
Logged
|
|
|
|
admin
Administrator
member is offline


Posts: 1145
|
 |
Re: sprite collisions
« Reply #3 on: Dec 31st, 2009, 10:34am » |
|
Quote:GFXLIB provides quite a few routines intended for bitmap (sprite) collision detection. |
|
I looked on http://www.bb4w-games.com/gfxlib/reference.html, but couldn't see any routine names which immediately suggested a collision-detection function. Which are they?
Richard.
|
|
Logged
|
|
|
|
David Williams
Developer
member is offline

meh

Gender: 
Posts: 452
|
 |
Re: sprite collisions
« Reply #4 on: Dec 31st, 2009, 6:56pm » |
|
on Dec 31st, 2009, 10:34am, Richard Russell wrote:
The GFXLIB routines intended for, or oriented towards, collision detection, rely on reading the alpha byte of certain 32-bpp (RGBA) background pixels, or testing if a specified bit is set in the alpha byte. The current publicly available version of GFXLIB (version 1.1.00) provides the following routines for setting or reading alpha values or testing single alpha bits:
ReadAlphaChannel -- Reads alpha value at specified (X,Y) test position PlotTestACBit -- Plots a bitmap *and* tests if a specified alpha bit is set PlotScaleSetACBit -- Plots a scaled bitmap at the same time as setting a specified bit in the alpha byte of overwritten background pixels PlotPScaleSetACBit -- Practically identical to previous, except remaining alpha bits are preserved (this routine's probably superfluous) PlotScaleTestACBit -- Plots a scaled bitmap and tests if a specified bit is set in the alpha byte of at least one overwritten background pixel TestPixelACBit -- Tests if a specified alpha bit is set in a pixel at position (X,Y) ShapeTestACBit -- Uses non-zero-valued pixels of a bitmap as a collision mask, similar to PlotTestACBit except nothing actually plotted ScaleShapeTestACBit -- Similar to previous, but for scaled collision masks
The forthcoming version 1.3 will include these additional related routines:
PlotSetACBit -- Plots a bitmap and sets specified bit in alpha byte of any overwritten background pixels PlotSetACBit2 -- Doesn't plot 'visible' pixels, but sets specified alpha bit based on non-zero-valued pixels of an 8-bpp mask bitmap PlotSetACBit3 -- Similar as previous, except uses a 32-bpp mask PlotScaleSetACValue -- Plots a scaled bitmap, setting alpha bytes of overwritten pixels to some specified value PlotRotateSetACValue -- Similar, but for rotated bitmaps PlotRotateSetACBit -- ...for rotated bitmaps
There are a few more to come.
Correct use of these routines allows for fast, pixel-perfect (or at least sufficiently accurate) collision detection.
Here's a program which demonstrates the basic use of the routine ReadAlphaChannel (this should run if GFXLIB v1.1.00 is installed):
Code: REM. Demonstrate use of ReadAlphaChannel
REM. Should be compatible with GFXLIB version 1.1.0
M% = 3 : HIMEM = LOMEM+M%*&100000
MODE 8 : OFF
INSTALL @lib$+"GFXLIB" : PROCAutoInit32
REM. Set bit 0 in the alpha byte of every non-zero pixel in
REM. the pre-defined 64x64 32-bpp 'demo' bitmap
REM. (This rather tedious preparatory step isn't necessary in
REM. GFXLIB v1.3 or later)
dispVars.bmBuffAddr% = demoBm32%
dispVars.bmBuffW% = 64
dispVars.bmBuffH% = 64
SYS GFXLIB_PlotOR, dispVars{}, demoBm32%, 64, 64, 0, 0, 1<<24
SYS GFXLIB_QuickSetDispVars, dispVars{}, dibSectionAddr%
REM. Set up structured array of sprite object params
numObjs% = 100
DIM obj{( numObjs%-1 ) active%, x%, y%, xv%, yv%}
REM. Define initial sprite positions and velocities
FOR I% = 0 TO numObjs%-1
obj{( I% )}.active% = TRUE
obj{( I% )}.x% = RND(640 - 64)
obj{( I% )}.y% = RND(512 - 64)
obj{( I% )}.xv% = RND(3)-2
obj{( I% )}.yv% = RND(3)-2
NEXT I%
*REFRESH OFF
REPEAT
SYS GFXLIB_Clr, dispVars{}, &000040
MOUSE X%, Y%, B%
X% DIV= 2 : Y% DIV= 2
REM. Draw active objects and update their positions
FOR I% = 0 TO numObjs%-1
IF obj{( I% )}.active% THEN
SYS GFXLIB_Plot, dispVars{}, demoBm32%, 64, 64, obj{(I%)}.x%, obj{(I%)}.y%
obj{(I%)}.x% += obj{( I% )}.xv%
obj{(I%)}.y% += obj{( I% )}.yv%
IF obj{(I%)}.x% < 0 OR obj{(I%)}.x% > 640-64 THEN obj{( I% )}.xv% *= -1
IF obj{(I%)}.y% < 0 OR obj{(I%)}.y% > 512-64 THEN obj{( I% )}.yv% *= -1
ENDIF
NEXT I%
REM. If left mouse button pressed, then read the alpha channel value
REM. at the mouse position (X%,Y%)
IF B% = 4 THEN
SYS GFXLIB_ReadAlphaChannel, dispVars{}, X%, Y% TO V%
REM. If V%<>0 then there's a 'collision', so which object is it?
IF V% <> 0 THEN
FOR I% = 0 TO numObjs%-1
IF obj{( I% )}.active% THEN
IF X% >= obj{(I%)}.x% THEN
IF Y% >= obj{(I%)}.y% THEN
IF X% < obj{(I%)}.x%+64 THEN
IF Y% < obj{(I%)}.y%+64 THEN
REM. de-activate object
obj{( I% )}.active% = FALSE
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
NEXT I%
ENDIF
ENDIF
REM. Update screen / program window
SYS "InvalidateRect", @hwnd%, 0, 0
PROCWait(4)
*REFRESH
UNTIL FALSE
And here's one to demonstrate PlotTestACBit:
Code: REM. Demonstrate use of PlotTestACBit
REM. Should be compatible with GFXLIB version 1.1.0
M% = 3 : HIMEM = LOMEM+M%*&100000
MODE 8 : OFF
INSTALL @lib$+"GFXLIB" : PROCAutoInit32
REM. Set bit 0 in the alpha byte of every non-zero pixel in
REM. the pre-defined 64x64 32-bpp 'demo' bitmap
REM. (This rather tedious preparatory step isn't necessary in
REM. GFXLIB v1.3 or later)
dispVars.bmBuffAddr% = demoBm32%
dispVars.bmBuffW% = 64
dispVars.bmBuffH% = 64
SYS GFXLIB_PlotOR, dispVars{}, demoBm32%, 64, 64, 0, 0, 1<<24
SYS GFXLIB_QuickSetDispVars, dispVars{}, dibSectionAddr%
REM. Set up structured array of sprite object params
numObjs% = 100
DIM obj{( numObjs%-1 ) active%, x%, y%, xv%, yv%}
REM. Define initial sprite positions and velocities
FOR I% = 0 TO numObjs%-1
obj{( I% )}.active% = TRUE
obj{( I% )}.x% = RND(640 - 64)
obj{( I% )}.y% = RND(512 - 64)
obj{( I% )}.xv% = RND(3)-2
obj{( I% )}.yv% = RND(3)-2
NEXT I%
*REFRESH OFF
REPEAT
SYS GFXLIB_Clr, dispVars{}, &000040
MOUSE X%, Y%, B%
X% DIV= 2 : Y% DIV= 2
REM. Draw active objects and update their positions
FOR I% = 0 TO numObjs%-1
IF obj{( I% )}.active% THEN
SYS GFXLIB_Plot, dispVars{}, demoBm32%, 64, 64, obj{(I%)}.x%, obj{(I%)}.y%
obj{(I%)}.x% += obj{( I% )}.xv%
obj{(I%)}.y% += obj{( I% )}.yv%
IF obj{(I%)}.x% < 0 OR obj{(I%)}.x% > 640-64 THEN obj{( I% )}.xv% *= -1
IF obj{(I%)}.y% < 0 OR obj{(I%)}.y% > 512-64 THEN obj{( I% )}.yv% *= -1
ENDIF
NEXT I%
REM. Draw collision test bitmap, checking if alpha bit 0 is set in
REM. any overwritten background pixels
SYS GFXLIB_PlotTestACBit, dispVars{}, demoBm32%, 64, 64, X%, Y%, 0 TO V%
REM. If V%<>0 then there's a collision
IF V% <> 0 THEN
FOR I% = 0 TO numObjs%-1
IF obj{( I% )}.active% THEN
IF X% >= obj{(I%)}.x%-64 THEN
IF Y% >= obj{(I%)}.y%-64 THEN
IF X% < obj{(I%)}.x%+64 THEN
IF Y% < obj{(I%)}.y%+64 THEN
REM. de-activate object
obj{( I% )}.active% = FALSE
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
NEXT I%
ENDIF
REM. Update screen / program window
SYS "InvalidateRect", @hwnd%, 0, 0
PROCWait(4)
*REFRESH
UNTIL FALSE
The compiled executables can be downloaded from here:
http://www.bb4w-games.com/bb4wprogs/collisiondetection.zip
For what it's worth, much of the (generally accurate) bitmap collision detection in my recent game "Crystal Hunter II" was achieved using some of the above-mentioned routines, so they do actually work!
Regards,
David. --
|
|
Logged
|
|
|
|
David Williams
Developer
member is offline

meh

Gender: 
Posts: 452
|
 |
Re: sprite collisions
« Reply #5 on: Dec 31st, 2009, 10:22pm » |
|
Another example:
http://www.bb4w-games.com/bb4wprogs/plottestalphabit_example.zip
The GFXLIB routine PlotSetAlphaBit is used to draw the 480x128 "GFXLIB" graphic, at the same time setting (quite arbitrarily) bit 5 in the alpha byte of any overwritten background pixel.
Then PlotTestAlphaBit is used to draw the colourful 48x48 disc sprite, whilst also checking if bit 5 is set in the alpha byte of any background pixel overwritten by the disc. If bit 5 is found to be set at least once, then the red border appears.
Source program below (unfortunately, it requires the as-yet unavailable GFXLIB v1.3 to run it).
Regards, David. --
Code: REM. PlotTestAlphaBit // Example
REM.
REM. Demonstrate use of PlotTestAlphaBit
REM.
REM. Parameters: dispVars{}, bmAddr, bmW, bmH, x, y
REM.
REM. PlotTestAlphaBit is an external GFXLIB module
REM. Make 3MB of RAM available for this program
M% = 3
HIMEM = LOMEM + M%*&100000
REM. Invoke display mode 8 (dimensions: 640x512)
MODE 8 : OFF
REM. Install and initialise GFXLIB core library
INSTALL @lib$ + "GFXLIB13"
PROCInitGFXLIB
REM. Install and initialise required modules
INSTALL @lib$ + "GFXLIB_modules\PlotTestAlphaBit" : PROCInitModule
INSTALL @lib$ + "GFXLIB_modules\RGBSwap" : PROCInitModule
INSTALL @lib$ + "GFXLIB_modules\PlotSetAlphaBit" : PROCInitModule
INSTALL @lib$ + "GFXLIB_modules\RectangleOR" : PROCInitModule
REM. Load the graphics
REM. (they'll be converted to the required 32bpp format by PROCLoadBMP)
PROCLoadBMP( @lib$ + "GFXLIB_media\bg2_640x512x24.BMP", bg%, 0 )
PROCLoadBMP( @lib$ + "GFXLIB_media\gfxlib_480x128x8.BMP", gfxlib%, 0 )
PROCLoadBMP( @lib$ + "GFXLIB_media\disc1_48x48x32.BMP", disc%, 0 )
SYS GFXLIB_RGBSwap%, gfxlib%, 480, 128, 2
REPEAT
MOUSE X%, Y%, B%
X% DIV= 2
Y% DIV= 2
SYS GFXLIB_BPlot%, dispVars{}, bg%, 640, 512, 0, 0
SYS GFXLIB_PlotSetAlphaBit%, dispVars{}, gfxlib%, 480, 128, (640-480)DIV2, (512-128)DIV2, 5
SYS GFXLIB_PlotTestAlphaBit%, dispVars{}, disc%, 48, 48, X%-24, Y%-24, 5 TO R%
IF R% <> 0 THEN
SYS GFXLIB_RectangleOR%, dispVars{}, 0, 0, 640, 16, &FF0000
SYS GFXLIB_RectangleOR%, dispVars{}, 0, 512-16, 640, 16, &FF0000
SYS GFXLIB_RectangleOR%, dispVars{}, 0, 0, 16, 512, &FF0000
SYS GFXLIB_RectangleOR%, dispVars{}, 640-16, 0, 16, 512, &FF0000
ENDIF
REM. Update the screen / program window
PROCdisplay
UNTIL FALSE
|
|
Logged
|
|
|
|
David Williams
Developer
member is offline

meh

Gender: 
Posts: 452
|
 |
Re: sprite collisions
« Reply #6 on: Jan 3rd, 2010, 9:42pm » |
|
We haven't heard back from the OP yet, so perhaps this means I've done a pretty good job at confusing the heck out of him? 
Anyway...
The demo program linked-to below shows one idea for implementing collision detection that may work under certain circumstances.
In the demo, when a 'baddy' sprite is plotted, the array index for that baddy is stored in the alpha byte of all background pixels overwritten by the baddy sprite. So, if the array index is 44, then 44 gets stored in the alpha byte of overwritten background pixels. Then when it's time to do some collision detection, reading the alpha value (using, say, GFXLIB_ReadAlphaValue) of a background pixel at some position (X,Y) will give either zero (no collision), or the array index of a baddy. So this is a fast, direct and accurate way of doing collision detection.
http://www.bb4w-games.com/bb4wprogs/invaders.zip -- (91 Kb)
Use the Z and X keys to move left and right respectively, and press Enter to fire fireballs at the descending aliens.
This will probably be my last word on this matter, unless someone wishes to discuss it further.
David.
|
|
Logged
|
|
|
|
|