remstart
topics:
show use of "SetSpriteCategoryBits" and "SetSpriteCollideBits" and "PhysicsRayCastCategory"
created on: 2015_01_18 (edited on 2015_03_15) - AGK 2
by AFA
[] <- falling blocks with five different colors will
1) pass the ray and then
2) collide with obstacle of the SAME color
_
|_| <- obstacle, red
_
|_| <- obstacle, green
------------- <- this ray filters two colors by category
_
|_| <- obstacle, blue
_
|_| <- obstacle, yellow
remend
// set window properties
SetWindowTitle( "Category Demo" )
Screen_X = 800
Screen_Y = 800
SetWindowSize( Screen_X, Screen_Y, 0 )
SetVirtualResolution( Screen_X, Screen_Y )
SetPrintSize ( Screen_Y / 30 )
// set physics
SetPhysicsWallTop (0) // open top only the red block is affected by this, see SetSpriteCollideBits below
SetPhysicsWallBottom(1) // close bottom only the red block is affected by this, see SetSpriteCollideBits below
SetPhysicsWallLeft (1) // close left wall only the red block is affected by this, see SetSpriteCollideBits below
SetPhysicsWallRight (1) // close right wall only the red block is affected by this, see SetSpriteCollideBits below
SetPhysicsGravity ( 0, 25) // set gravity
// set colors
MaxColor = 4 // 4 colors + white (4 obstacles)
// create an image
Render()
GetImage(100, 0, 0, Screen_X/20, Screen_X/20)
Update(0)
swap()
//Create Sprites - "obstacles"
Dim Obstacle[MaxColor]
For s = 1 to MaxColor // s = 1: no white obstacle
Obstacle[s] = CreateSprite(100)
SetSpriteScale( Obstacle[s], Screen_X, Screen_X)
SetSpriteSize( Obstacle[s], Screen_X/10, Screen_X/10)
SetSpriteOffset( Obstacle[s], Screen_X/10/2, Screen_X/10/2 )
SetSpriteAngle ( Obstacle[s], 45 )
SetSpritePhysicsOn ( Obstacle[s], 1 )// 1=static, 2=dynamic, 3=kinematic
SetSpriteShape ( Obstacle[s], 2 )// 0=no shape, 1=circle, 2=box, 3=polygon
SetSpritePhysicsRestitution ( Obstacle[s], 0.5 )
Next
//Create Sprites - "blocks"
Dim Block[MaxColor]
For s = 0 to MaxColor // all colors
Block[s] = CreateSprite(100)
SetSpriteScale( Block[s], Screen_X, Screen_X)
SetSpriteSize( Block[s], Screen_X/16, Screen_X/16)
SetSpriteOffset( Block[s], Screen_X/32, Screen_X/32 )
SetSpritePhysicsOn ( Block[s], 2 )// 1=static, 2=dynamic, 3=kinematic
SetSpritePhysicsCanRotate ( Block[s], 1) // allow rotating
SetSpriteShape ( Block[s], 2 ) // 0=no shape, 1=circle, 2=box, 3=polygon
SetSpritePhysicsRestitution ( Block[s], 0.5 )
Next
// delete image
If GetImageExists(100) then DeleteImage (100)
// set color of obstacles (no white)
SetSpriteColor ( Obstacle[1], 255, 000, 000, 255 ) // red
SetSpriteColor ( Obstacle[2], 000, 255, 000, 255 ) // green
SetSpriteColor ( Obstacle[3], 000, 000, 255, 255 ) // blue
SetSpriteColor ( Obstacle[4], 255, 255, 000, 255 ) // yellow
// set color of blocks
SetSpriteColor ( Block[0], 255, 255, 255, 255 ) // white
SetSpriteColor ( Block[1], 255, 000, 000, 255 ) // red
SetSpriteColor ( Block[2], 000, 255, 000, 255 ) // green
SetSpriteColor ( Block[3], 000, 000, 255, 255 ) // blue
SetSpriteColor ( Block[4], 255, 255, 000, 255 ) // yellow
// set pile of obstacles with different colors
For i = 1 to MaxColor
SetSpritePositionByOffset( Obstacle[i], Screen_X/2, Screen_Y/(MaxColor+1) * i)
Next
// hide blocks
For i = 0 to MaxColor
SetSpritePositionByOffset( Block[i], -100, 0)
Next
// set category bits for the the obstacles - aim: same colors get same category
For ColorNumber = 1 to MaxColor
Select ColorNumber
// Extract from AGK-help
// "By default all sprites belong to category 1 (0x0001 the 'rightmost bit') and collide with all categories (0xffff)."
// This 'rightmost bit' is the one in the first row below: > 1 <
Case 1 : SetSpriteCategoryBits ( Obstacle[ColorNumber], %0000000000000001) : EndCase // red - one bit at the last digit -> obstacle gets category 1
Case 2 : SetSpriteCategoryBits ( Obstacle[ColorNumber], %0000000000000010) : EndCase // green - one bit at the 2nd last digit -> obstacle gets category 2
Case 3 : SetSpriteCategoryBits ( Obstacle[ColorNumber], %0000000000000100) : EndCase // blue - one bit at the 3rd last digit -> obstacle gets category 3
Case 4 : SetSpriteCategoryBits ( Obstacle[ColorNumber], %0000000000001000) : EndCase // yell - one bit at the 4rd last digit -> obstacle gets category 4
EndSelect
Next
// set collide bits for the blocks - aim: same colors get same colloide bit as category (see above)
For ColorNumber = 0 to MaxColor // (including white)
Select ColorNumber
Case 0 : SetSpriteCollideBits ( Block[ColorNumber], %0000000000000000) : EndCase // white block = no collision with any obstacle
Case 1 : SetSpriteCollideBits ( Block[ColorNumber], %0000000000000001) : EndCase // red - one bit at the last digit -> block collides with sprites of category 1
Case 2 : SetSpriteCollideBits ( Block[ColorNumber], %0000000000000010) : EndCase // green - one bit at the 2nd last digit -> block collides with sprites of category 2
Case 3 : SetSpriteCollideBits ( Block[ColorNumber], %0000000000000100) : EndCase // blue - one bit at the 3rd last digit -> block collides with sprites of category 3
Case 4 : SetSpriteCollideBits ( Block[ColorNumber], %0000000000001000) : EndCase // yell - one bit at the 4th last digit -> block collides with sprites of category 4
EndSelect
Next
// This setup is for the RayCast, it has nothing to do with collision between 'block' and 'obstacle'.
// Category bits for the blocks are set to define colors getting filtered by the ray.
For ColorNumber = 0 to MaxColor // (including white)
Select ColorNumber
Case 0 : SetSpriteCategoryBits ( Block[ColorNumber], %0000000000000000) : EndCase // white block = no category
Case 1 : SetSpriteCategoryBits ( Block[ColorNumber], %1000000000000001) : EndCase // red = category 1 and 16
Case 2 : SetSpriteCategoryBits ( Block[ColorNumber], %0100000000000010) : EndCase // green = category 2 and 15
Case 3 : SetSpriteCategoryBits ( Block[ColorNumber], %0000000000000100) : EndCase // blue = category 3
Case 4 : SetSpriteCategoryBits ( Block[ColorNumber], %0000000000001000) : EndCase // yellow = category 4
EndSelect
Next
remstart
conversion hex - binary - deci:
hex - bit mask - deci
0x0001 - %0000000000000001 - 1
0x0002 - %0000000000000010 - 2
0x0004 - %0000000000000100 - 4
0x0008 - %0000000000001000 - 8
0x0010 - %0000000000010000 - 16
0x0100 - %0000000000100000 - 32
.. - .. - ..
. - . - .
example as hex:
Case 1 : SetSpriteCategoryBits ( Obstacle[ColorNumber], 0x0001) : EndCase
------------------------------------------------------------------------------------------------------------------------
advanced hint:
Seemingly these four commands are affected by category, too.
As 'SetPhysicsWallTop' is set to 1 (= close), the red block will not appear,
it keeps laying on the top of the top-wall - outside the screen.
SetPhysicsWallTop (0/1) // open/close top
SetPhysicsWallBottom (0/1) // open/close bottom
SetPhysicsWallLeft (0/1) // open/close left wall
SetPhysicsWallRight (0/1) // open/close right wall
remend
SetClearColor(255, 255, 215)
ClearScreen()
// set timer
TimeReleaseNewBlock = GetSeconds()
Color = 0
Repeat
// release a new block
If GetSeconds() >= TimeReleaseNewBlock + 4
If Color < MaxColor then Inc Color Else Color = 0
diff = round ( screen_X / 30 )
SetSpritePositionByOffset ( Block[Color], Screen_X/2-diff/2+random(0,diff), -Screen_Y/20)
TimeReleaseNewBlock = GetSeconds()
EndIf
// casts a ray to filter sprites with category 15 and 16
If PhysicsRayCastCategory ( %1100000000000000, 0, Screen_Y/2, Screen_X, Screen_Y/2) = 1
// this way of declaration is really not ideal, enough for this demo - but in real better use an array with user-defined-types...
If GetRayCastSpriteID() = Block[1]
SetPrintColor ( 255, 0, 0)
print("RED BLOCK DETECTED")
ElseIf GetRayCastSpriteID() = Block[2]
SetPrintColor ( 0, 255, 0)
print("GREEN BLOCK DETECTED")
EndIf
EndIf
// line just for visualizing the ray
DrawLine (0, Screen_Y/2, Screen_X, Screen_Y/2, 0, 0, 0)
Sync ()
Until GetRawLastKey() = 27
Help make AGK better by submitting an example for this command! (All examples are subject to approval)