(AGK version: 108.24)
Submitted: 2015-03-15 12:30:01
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)
Login to post an example of your own.