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)
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