Posted: 17th Apr 2018 20:38
Collisions between two objects
+ Code Snippet
//EDITED as I noticed I was using x when y and z calculations were needed 
function checkCollision(objID as integer)

local width# as float
local height# as float
local depth# as float
local x# as float
local y# as float
local z# as float
local start_x# as float
local start_y# as float
local start_z# as float
local end_x# as float
local end_y# as float
local end_z# as float 
local object_Hit as integer	

//this checks for colliion between an object with any other object and returns its id
width#=(GetObjectMeshSizeMaxX(objID,1)-GetObjectMeshSizeMinX(objID,1))/2 
height#=(GetObjectMeshSizeMaxY(objID,1)-GetObjectMeshSizeMinY(objID,1))/2 
depth#=(GetObjectMeshSizeMaxZ(objID,1)-GetObjectMeshSizeMinZ(objID,1))/2 
 
x#=getObjectWorldX(objID)
y#=GetObjectWorldY(objID)
z#=getObjectWorldZ(objID)


// calculate the start of the ray cast
start_x# = x#-width#
start_y# = y#+height#
start_z# = z#-depth# 

// calculate the end of the ray cast
end_x# = x#+width#   
end_y# = y#-height#
end_z# = z#+depth#
 
// determine which object has been hit
object_Hit = ObjectRayCast(0,start_x#,start_y#,start_z#,end_x#,end_y#,end_z#)
endfunction object_Hit


Check for collision between a sprite and 3D object
This example assumes you have placed the sprite by offset and the offset is in the center of the sprite
+ Code Snippet
function checkCollisionObjSpr(obj as integer,index as integer,spr as integer,camID as integer)
	local collision as integer
	
    //this checks for collision between a sprite with a 3d mesh and returns 1 if there would be a collision
    width=Ceil(GetSpriteWidth(Spr)/2.0)     
    height=Ceil(GetSpriteHeight(Spr)/2.0)  //because the calculations should take place from its centre
 
	check_x = GetSpriteXByOffset(spr)-width
	check_y = GetSpriteYByOffset(spr)+height
	// get the x, y and z unit vectors based on the sprite position
	start_x = Get3DVectorXFromScreen(check_x,check_y)
	start_y = Get3DVectorYFromScreen(check_x,check_y)
	start_z = Get3DVectorZFromScreen(check_x,check_y)

	check_x2 = GetSpriteXByOffset(spr)+width
	check_y2 = GetSpriteYByOffset(spr)-height
 
	end_x = Get3DVectorXFromScreen(check_x2,check_y2)
	end_y = Get3DVectorYFromScreen(check_x2,check_y2)
	end_z = Get3DVectorZFromScreen(check_x2,check_y2)
  
    objStart_x = GetObjectX(obj)+GetObjectMeshSizeMinX(obj,index) 
    objStart_y = GetObjectY(obj)-GetObjectMeshSizeMinY(obj,index)
    objStart_z = GetObjectZ(obj)-GetObjectMeshSizeMinY(obj,index)
    
    objEnd_x = GetObjectX(obj)-GetObjectMeshSizeMaxX(obj,index) 
    objEnd_y = GetObjectY(obj)+GetObjectMeshSizeMaxY(obj,index)
    objEnd_z = GetObjectZ(obj)+GetObjectMeshSizeMaxY(obj,index)
    
    for check=start_x to end_x
		if check>objStart_x and check>objEnd_x then coll1=1
	next check
	
	for check=start_y to end_y
		if check>objStart_y and check>objEnd_y then coll2=1
	next check
	//if start_z<objStart_z and start_z<objEnd_z then coll3=1
	coll3=1
	if coll1=1 and coll2=1 and coll3=1
		collision=1
    else 
		collision=0
	endif	
endfunction collision
Posted: 19th Apr 2018 14:09
Thanks for all this stuff. Its great!
I'm digging into the path editor now.
Posted: 2nd May 2018 4:38
3D Night Driving Original full source no media required makes for a great template
Now includes car headlights and a possibility of cows on road and stereoscopic options
arrow keys to steer and space to brake
+ Code Snippet
//questions and comments https://forum.thegamecreators.com/thread/222010
#constant KEY_LEFT  = 37  //the left arrow key scancode
#constant KEY_UP    = 38  //the up arrow key scancode
#constant KEY_RIGHT = 39  //the right arrow key scancode
#constant KEY_DOWN  = 40  //the down arrow key scancode
#constant KEY_A     = 65  //the scan code for the "a" key	
#constant KEY_Z     = 90  //the scan code for the "z" key
#constant KEY_SPACE	= 32  //the space bar
#constant mapX=20 	//maximum blocks on x plane CHANGE THIS TO MAKE ROAD NARROWER IE 20 WHICH WILL SPEED IT UP
#constant mapY=1  	//maximum blocks on y plane
#constant mapZ=100 	//maximum blocks on z plane
#constant xMaxResolution=1024
#constant yMaxResolution=768
#constant acceleration#=.05 //used to calclate the carSpeed#
#constant maxCarSpeed#=2.5 //The Maximum speed the carBlock will move 
#constant minCarSpeed#=0.01   //The Minimum speed the carBlock will move 
#constant textTitle=1 //the title text id
#constant textSpeed=2 //the speed text id
#constant textScore=3 //the score text id
#constant textLives=4 //the lives text id
#constant textFPS=5   // the fps text id
#constant textGameOver=6  //the game over text id
#constant textPlayAgain=7 //the Click to play again text id
#constant textHighScore=8 //the highscore text id
#constant textTopSpeed=9  //the top speed text id
#constant textHowFar=10   //the text how far can you go text id
#constant textCredit=11   //My Credit text id
#constant textLevel=12    //current level text id
#constant wireFrameTextureID    =1 //the image thats used for all cows and cars
#constant gridTextureID         =2
#constant speedoTextureID       =3 
#constant speedoNeedleTextureID =4 //the speedo texture image this is rotated to show speed 
#constant sound1 =1
#constant sound2 =2
#constant camLeftOffsetX=-.250 //the camera offsets for Anaglyph Stereoscopic view
#constant camLeftOffsetY=-.05
#constant camLeftOffsetZ=-.125
#constant camRightOffsetX=.250
#constant camRightOffsetY=.04
#constant camRightOffsetZ=.125
#constant spriteLeftOffsetX=2 //the sprite offsets for Anaglyph Stereoscopic view
#constant spriteLeftOffsetY=-2
#constant spriteRightOffsetX=-2
#constant spriteRightOffsetY=2
#constant stereoButton=1 		//the button on the load screen selecting stereoscopic mode
#constant normalButton=2 		//the button on the load screen selecting normal mode
#constant cowStart=8000 		//the cows id start at 8000
#constant AccelerationFactor#=.025 //the speed your car accelerates at
#constant DecelerationFactor#=.025 //the braking factor 
#constant carLightObj=4000 		//need to have a car light object to set the point lights off this is the id there are two
#constant otherCarLightObj=4003 //This is the id of the other cars light object
#constant carLight=1  		//this is your left car light 2 is right 
#constant otherCarLight=3 	//other cars light starter Id 
#constant myGround=5000 	//need a ground object for the lights to work this is the object ID
#constant Bg=1000 			// for the rubout sprite gets deleted once text sprites created
#constant startText =100    //textid spriteids for text and imageid starters they all get deleted once game starts playing


global speed#  = 2.0 //the following for a sine curve to repesent hils on the yplane
global carSpeed#
global blockCount 
global carBlock=10000      //carblock and carMem have the same referrence
global carMem=10000        //the carBlocks memblock id
global otherCarBlock=10006 //the otherCarblock and otherCarMem have the same referrence 
global otherCarMem=10006   //the other carBlocks memblock id
global timeCount#
global closestBlock   //the closest post to the front
global closestBlock2  //the other closest post to the front as there are two one left one right	 

global Quad			  //stores the id of the quad object used for sterescopic 	
global Stereo		  //stores the id of the shader used for stereoscopic 	
global leftRenderImage  //left render image used when stereoscopic is selected
global rightRenderImage //Right render image used when stereoscopic is selected
global stereoFlag       //used to hold the value of 1 if stereoscopic select otherwise 0
global strlen		  //holds the length of the string that the scrolling credits use	
global lives=3        //The actual lives of a player   
global score=0        //holds the player score whiched is based on progression  
global highScore=0    //holds the total high score for the day
global topSpeed#=0    //the maximun speed you have reached today 	 
global level=1		  //players current level 	
global levelCounter=0 //levelcounter is a count of how many times the last post has been passed its used to calculate the level once youve passed the last post 5 times
time#=timer()		  //holds the startTime for calculations of the sineCurve with the movements and used in calculating an acceleration curve 
global offsetx as float //offsets the other car from the posta
dim blocksChanged[mapX*mapY*mapZ] as block

// show all errors
SetErrorMode(2)

// set window properties
SetWindowTitle( "Night Driving" )
SetWindowSize( xMaxResolution, yMaxResolution, 0 )
SetWindowAllowResize( 1 ) // allow the user to resize the window

// set display properties
SetVirtualResolution( xMaxResolution, yMaxResolution ) // doesn't have to match the window
SetOrientationAllowed( 0, 0, 1, 1 ) // allow only landscape on mobile devices
SetSyncRate( 30, 0 ) // 30fps instead of 60 to save battery
SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts

rem for Credits
type myText
	id as integer		//rem id of sprite
	x as integer  		//rem x axis
	y as integer		//rem y-axis
	img as integer		//rem holds the image number for the sprite
endtype

rem used for pulling the object apart by the vertices
type vertex
	xDirection as integer 	//used to send the a vertice in x direction
	yDirection as integer	//used to send the a vertice in y direction
	zDirection as integer	//used to send the a vertice in z direction
endtype

type block
	id as integer 		//the id of the object
	randX as integer 	//the random x offset only applied to cows on road 
	randZ as integer 	//the random z offset only applied to cows on road
	xPosStart as integer//the x starting location of posts and cows
	yPosStart as integer//the y starting location of posts and cows
	zPosStart as integer//the z starting location of posts and cows
	level as integer 	//
	//the following used for my particle effect
    xDirection as float //used for sending objects into orbit when there is a crash
    yDirection as float	//used for sending objects into orbit when there is a crash
    zDirection as float //used for sending objects into orbit when there is a crash
endtype
CreateSpeedoTexture(speedoTextureID)
CreateSprite(1,speedoTextureID)
SetSpritePosition(1,10,yMaxResolution-GetSpriteHeight(1))
CreateSpeedoNeedle(speedoNeedleTextureID)
CreateSprite(2,speedoNeedleTextureID)
SetSpritePosition(2,10,yMaxResolution-GetSpriteHeight(2))
createWireFrameTexture(wireFrameTextureID,32,32, makecolor(255,255,255))
createGridTexture(gridTextureID,32,32,4,4,makecolor(255,255,255))
strlen=setupCredits() //used to set up the scrolling credits
num=1
for y = 1 to mapY 	
for x = 1 to mapX step mapX-1
for z = 1 to mapZ step 10
	if num=1 
		CreateObjectBox(num,.5,2,.5)
	else	
		InstanceObject(num,1)
	endif
	c=255:SetObjectColor(num,c,c,c,255)
	SetObjectCollisionMode( num, 1 ) //On is needed for raycasting
    CreateMemblockFromObjectMesh(num,num,1) //there is exactly the same number of blocks as memblocks and each id is equal
	blocksChanged[num].id=num
	//the directions are only used for the particle effect when you crash
	blocksChanged[num].xDirection=Random2(-100,100)/50.0
	blocksChanged[num].yDirection=Random2(-100,100)/50.0
	blocksChanged[num].zDirection=Random2(-100,100)/50.0
	blocksChanged[num].xPosStart=x
	blocksChanged[num].yPosStart=y
	blocksChanged[num].zPosStart=z
	blocksChanged[num].level=1	
	SetObjectPosition(num,x,y,z)
	createCow(cowStart+(num-1)*7)
	if x>10
		SetObjectPosition(cowStart+(num-1)*7,blocksChanged[num].xPosStart+random(2,20),blocksChanged[num].yPosStart,blocksChanged[num].zPosStart) 
	else
		SetObjectPosition(cowStart+(num-1)*7,blocksChanged[num].xPosStart-random(2,20),blocksChanged[num].yPosStart,blocksChanged[num].zPosStart) 
		//RotateObjectLocalY(cowStart+(num-1)*7,180)
	endif
	RotateObjectGlobalY(cowStart+(num-1)*7,random(1,360))

	inc num
next z
next x
next y
blockCount=num-1

//There is a maximum of cows on the road at a time
//to make it simpler there are always four cows on the road at any time
//i use a random number to determine if they are visible or not and switch the collisions
//and visibility at any one time
for num=blockCount+1 to blockCount+4   
	//sheep collision object
	blocksChanged[num].id=num
	//the directions are only used for the particle effect when you crash
	blocksChanged[num].xDirection=Random2(-100,100)/50.0
	blocksChanged[num].yDirection=Random2(-100,100)/50.0
	blocksChanged[num].zDirection=Random2(-100,100)/50.0
	blocksChanged[num].xPosStart=10
	blocksChanged[num].yPosStart=1 //4 for cow
	blocksChanged[num].zPosStart=50	
	blocksChanged[num].level=1
	createCow(num+((num-blockCount-1)*7))
	RotateObjectGlobalY(num+((num-blockCount-1)*7),random(1,360))

	blocksChanged[num].randX=random(5,15)
	blocksChanged[num].randZ=random(5,15)
	SetObjectPosition(num+((num-blockCount-1)*7),getObjectX(10)+blocksChanged[num].randX,getObjectY(10),getObjectZ(10)+blocksChanged[num].randZ)
	ranRange=trunc((log(level)*5.0)+2.0) //this gives it an exponential randomness (basically the higher the level the greater the chance of a cow) 
    if ranRange>8 then ranRange=8
    if Random(1,10)<ranRange
		//there are seven parts to a cow  set collisions on for each part
		SetObjectCollisionMode(num+((num-blockCount-1)*7),1)
		SetObjectCollisionMode(num+((num-blockCount-1)*7)+1,1)
		SetObjectCollisionMode(num+((num-blockCount-1)*7)+2,1)
		SetObjectCollisionMode(num+((num-blockCount-1)*7)+3,1)
		SetObjectCollisionMode(num+((num-blockCount-1)*7)+4,1)
		SetObjectCollisionMode(num+((num-blockCount-1)*7)+5,1)
		SetObjectCollisionMode(num+((num-blockCount-1)*7)+6,1)
		//set all parts of a cow to visible
		SetObjectVisible(num+((num-blockCount-1)*7),1)
		SetObjectVisible(num+((num-blockCount-1)*7)+1,1)
		SetObjectVisible(num+((num-blockCount-1)*7)+2,1)
		SetObjectVisible(num+((num-blockCount-1)*7)+3,1)
		SetObjectVisible(num+((num-blockCount-1)*7)+4,1)
		SetObjectVisible(num+((num-blockCount-1)*7)+5,1)
		SetObjectVisible(num+((num-blockCount-1)*7)+6,1)
	else
		//there are seven parts to a cow i set collisions off for each part
		SetObjectCollisionMode(num+((num-blockCount-1)*7),0)
		SetObjectCollisionMode(num+((num-blockCount-1)*7)+1,0)
		SetObjectCollisionMode(num+((num-blockCount-1)*7)+2,0)
		SetObjectCollisionMode(num+((num-blockCount-1)*7)+3,0)
		SetObjectCollisionMode(num+((num-blockCount-1)*7)+4,0)
		SetObjectCollisionMode(num+((num-blockCount-1)*7)+5,0)
		SetObjectCollisionMode(num+((num-blockCount-1)*7)+6,0)
		//set all parts of a cow to invisible
		SetObjectVisible(num+((num-blockCount-1)*7),0)
		SetObjectVisible(num+((num-blockCount-1)*7)+1,0)
		SetObjectVisible(num+((num-blockCount-1)*7)+2,0)
		SetObjectVisible(num+((num-blockCount-1)*7)+3,0)
		SetObjectVisible(num+((num-blockCount-1)*7)+4,0)
		SetObjectVisible(num+((num-blockCount-1)*7)+5,0)
		SetObjectVisible(num+((num-blockCount-1)*7)+6,0)
	endif
next num

createCar(carBlock,carMem)
createCar(otherCarBlock,otherCarMem)
createHeadlights()
createSound(sound1,1) //creates a base rumble
createSound(sound2,2) //creates white noise
//SetFogMode( 1 ) 
//SetFogColor(20,20,20)
//SetFogRange(10,100)
//CreatePointLight(1, getObjectX(carBlock),getObjectY(carBlock),getObjectZ(carBlock), 120, 255, 255,255 ) 
setCameraPosition(1,mapX/2,10,0)

AddVirtualButton(stereoButton,xMaxResolution/2-72,yMaxResolution/2-50,100)
AddVirtualButton(normalButton,xMaxResolution/2+72,yMaxResolution/2-50,100)
SetVirtualButtonSize(stereoButton,140,100 )
SetVirtualButtonSize(normalButton,140,100 )
SetVirtualButtonText(stereoButton,"Stereoscopic"+chr(10)+"Play")
SetVirtualButtonText(normalButton,"Normal"+chr(10)+"Play")
SetVirtualButtonColor(stereoButton,100,100,100)
SetVirtualButtonColor(normalButton,50,50,50)

CreateShader()
Quad = CreateObjectQuad()
Stereo = LoadShader( "Anaglyph.vs", "Anaglyph.ps" )
leftRenderImage=CreateRenderImage(xMaxResolution,yMaxResolution, 0, 0 )
rightRenderImage=CreateRenderImage(xMaxResolution,yMaxResolution, 0, 0 )
setupText():stereoFlag=0:playMode=0

//SetPointlights to the headlight object positions set by create headlights
//Each cat has two headlights
SetPointLightPosition( carLight, GetObjectWorldX (carLightObj), getObjectWorldY (carLightObj), getObjectWorldZ (carLightObj)) 
SetPointLightPosition( carLight+1, GetObjectWorldX (carLightObj+1), getObjectWorldY (carLightObj+1), getObjectWorldZ (carLightObj+1)) 
SetPointLightPosition( otherCarLight, GetObjectWorldX (otherCarLightObj), getObjectWorldY (otherCarLightObj), getObjectWorldZ (otherCarLightObj)) 
SetPointLightPosition( otherCarLight+1, GetObjectWorldX (otherCarLightObj+1), getObjectWorldY (otherCarLightObj+1), getObjectWorldZ (otherCarLightObj+1)) 
repeat 
	if stereoFlag=1 //stereoscopic mode selected
		Update(0)
		// left render for 3D Analglyp Stereoscopic
		SetRenderToImage(leftRenderImage, -1 )
		ClearScreen()
		setCameraPosition(1,mapX/2+camLeftOffsetX,10+camLeftOffsetY,camLeftOffsetZ)
		//setCameraPosition(1,camLeftOffsetX,camLeftOffsetY,camLeftOffsetZ)
		SetSpritePosition(1,10+spriteLeftOffSetX,yMaxResolution-GetSpriteHeight(1)+spriteLeftOffSetY)
		SetSpritePosition(2,10+spriteLeftOffSetX,yMaxResolution-GetSpriteHeight(2)+spriteLeftOffSetY)
	endif
	
	//Change the color of the buttons once pressed
	if GetVirtualButtonPressed(stereoButton)=1
		stereoFlag=1:playMode=1
		SetVirtualButtonColor(stereoButton,50,50,50)
		SetVirtualButtonColor(normalButton,100,100,100)
	endif
	if GetVirtualButtonPressed(normalButton)=1
		stereoFlag=0:playMode=2
		SetVirtualButtonColor(stereoButton,100,100,100)
		SetVirtualButtonColor(normalButton,50,50,50)
		setCameraPosition(1,mapX/2,10,0)
		SetRenderToScreen()
	endif
	
	//if you touch the screen or press the spacebar play game
	If GetPointerPressed()  or GetRawKeyPressed(32) or playMode>0
		//deleteTextScroll(strLen)
		setTextVisible(textLevel,1)
		SetTextVisible(textGameOver,0):SetTextVisible(textPlayAgain,0):SetTextVisible(textHowFar,0)
		SetVirtualButtonVisible(stereoButton,0):SetVirtualButtonVisible(normalButton,0)
		lives=3:score=0:playGame()
		if score>highScore 
			highScore=score
			SetTextString(textHighScore,"High="+Str(highScore))
		endif
		if carSpeed#>topSpeed#
			topSpeed#=carSpeed#
			SetTextString(textTopSpeed,"Top Speed="+Str(Round(topSpeed#/maxCarSpeed#*100))+"%")
		endif
		SetVirtualButtonVisible(stereoButton,1):SetVirtualButtonVisible(normalButton,1):playMode=0
	endif
	fubarpkTextScroll(strLen) //used to make the scrolling text scroll
	if stereoFlag=1  //stereoscopic has been selected 
		drawAllObjects()
	
		// right render
		SetRenderToImage(rightRenderImage, -1 )
		ClearScreen()
		setCameraPosition(1,(mapX/2)+camRightOffsetX,10+camRightOffsetY,camRightOffsetZ)
		
		SetSpritePosition(1,10+spriteRightOffSetX,yMaxResolution-GetSpriteHeight(1)+spriteRightOffSetY)
		SetSpritePosition(2,10+spriteRightOffSetX,yMaxResolution-GetSpriteHeight(2)+spriteRightOffSetY)
		Render3D()
		// post process
		SetRenderToScreen()
		SetObjectImage( Quad, leftRenderImage, 0 )
		SetObjectImage( Quad, rightRenderImage, 1 )
		SetObjectShader( Quad, Stereo)
		DrawObject( Quad )
		Render2DFront() 
		Swap()
	else
		sync() //normal mode selected
	endif
until GetRawKeyPressed(27) 
end //exitprogram

function playGame()
speed#=0:level=1:levelCounter=0:restoreBlocks()
carSpeed#=minCarSpeed#    //car speed used for acceleration with timerResetTimer():time#=timer():starttime#=timer()
x=xMaxResolution/2:yAngle=0:offsetx=4.25:timeCount#=0
ResetTimer():time#=timer():starttime#=timer()
x1#=GetObjectAngleX(carBlock+2) //car wheels
y1#=GetObjectAngleY(carBlock+2) //get the angle of wheels so rotation can be applied
z1#=GetObjectAngleZ(carBlock+2)
x2#=GetObjectAngleX(otherCarBlock+2)
y2#=GetObjectAngleY(otherCarBlock+2)
z2#=GetObjectAngleZ(otherCarBlock+2)
SetTextString(textLevel,"Level "+str(Level) )
SetTextVisible(textLevel,1):iAlpha=255
SetTextColorAlpha(textLevel, iAlpha )
otherCarSpeed#=random(2,10)/10.0:timeCount#=0
carSpeed#=minCarSpeed# 		
repeat
	//Used for the cars headlights
	SetPointLightPosition( carLight, GetObjectWorldX (carLightObj), getObjectWorldY (carLightObj), getObjectWorldZ (carLightObj)) 
	SetPointLightPosition( carLight+1, GetObjectWorldX (carLightObj+1), getObjectWorldY (carLightObj+1), getObjectWorldZ (carLightObj+1)) 
	
	SetPointLightPosition( otherCarLight, GetObjectWorldX (otherCarLightObj), getObjectWorldY (otherCarLightObj), getObjectWorldZ (otherCarLightObj)) 
	SetPointLightPosition( otherCarLight+1, GetObjectWorldX (otherCarLightObj+1), getObjectWorldY (otherCarLightObj+1), getObjectWorldZ (otherCarLightObj+1)) 
	
	if stereoFlag=1 //sterescopic selected from start
		Update(0)

		// left render
		SetRenderToImage(leftRenderImage, -1 )
		ClearScreen()
		setCameraPosition(1,mapX/2+camLeftOffsetX,10+camLeftOffsetY,camLeftOffsetZ)
		SetSpritePosition(1,10+spriteLeftOffSetX,yMaxResolution-GetSpriteHeight(1)+spriteLeftOffSetY)
		SetSpritePosition(2,10+spriteLeftOffSetX,yMaxResolution-GetSpriteHeight(2)+spriteLeftOffSetY)
	endif
	
	yAngle=abs(GetDirectionX()*25) //get an angle based on the gyroscope
	if GetDirectionX()<=0  //-.15 //uses gyroscope for movement
		moveBlocks(abs(GetDirectionX()*2.5),0,carSpeed#) 
		yAngle=-abs(GetDirectionX()*25) //get gyroscope angle
		SetObjectRotation( carBlock,0,yAngle,0 ) //rotate your car based on gyroscope
		SetObjectRotation(carBlock+2,x1#,yAngle*2,z1#) //yAngle used to turn the left front wheel left 
		SetObjectRotation(carBlock+3,x1#,yAngle*2,z1#) //yAngle used to turn the right front wheel	right
		SetObjectRotation(carBlock+4,x1#,y1#,z1#)
		SetObjectRotation(carBlock+5,x1#,y1#,z1#)	
	else  
		moveBlocks(-abs(GetDirectionX()*2.5),0,carSpeed#)
		yAngle=abs(GetDirectionX()*25) //get gyroscope angle
		SetObjectRotation( carBlock,0,yAngle,0 ) //rotate your car based on gyroscope
		SetObjectRotation(carBlock+2,x1#,yangle*2,z1#)  //yAngle used to turn the left front wheel left
		SetObjectRotation(carBlock+3,x1#,yangle*2,z1#)	//yAngle used to turn the right front wheel right	
		SetObjectRotation(carBlock+4,x1#,y1#,z1#)
		SetObjectRotation(carBlock+5,x1#,y1#,z1#)	
	endif
	SetObjectRotation(otherCarBlock+2,x2#,y2#,z2#) //sets the rotation of the oncoimng car
	SetObjectRotation(otherCarBlock+3,x2#,y2#,z2#)
	SetObjectRotation(otherCarBlock+4,x2#,y2#,z2#)
	SetObjectRotation(otherCarBlock+5,x2#,y2#,z2#)
	x1#=x1#+carSpeed#:x2#=x2#-carSpeed#	
	otherCarSpeed#=moveOtherCarBlock(carSpeed#,otherCarSpeed#)	
	
	//the second raycasting is used for crashes
	x#=getObjectX(carBlock) 
	y#=GetObjectY(carBlock) 
	z#=getObjectZ(carBlock) 
	
	// calculate the start of the ray cast
	// a car is 2,2,4
	start_x# = x#  
	start_y# = y# 
	start_z# = z# 
    // calculate the end of the ray cast
	end_x# = x#+2.0
	end_y# = y# 
	end_z# = z#+4.0 + carSpeed#  
	hit=ObjectRayCast(0,start_x#,start_y#,start_z#,end_x#,end_y#,end_z#)
	if hit>0 or getObjectx(carBlock)<getObjectx(closestBlock) or getObjectx(carBlock)>getObjectx(closestBlock2) //player crashed 
		dec lives
		PlaySound(sound1,100,0)
		PlaySound(sound2,50,0)
		timeCount#=0
		blocksExplode()
		restoreBlocks()
		carSpeed#=minCarSpeed#  //Set the speed back to its default as you crashed
		yAngle=0:speed#=0
		levelCounter=0 
		SetTextString(textLevel,"Level "+str(Level) )
		SetTextVisible(textLevel,1):iAlpha=255
		SetTextColorAlpha(textLevel, iAlpha )
		time#=timer():starttime#=timer()  
	endif
	if GetRawKeyState ( KEY_SPACE ) or GetPointerPressed()
	if timer()>time#+.05	
		carSpeed#=carSpeed#-((maxCarSpeed#-carSpeed#)*DecelerationFactor#+.01) //+.01 otherwise it doesnt decelerate if top speed reached
		if carSpeed#<minCarSpeed# then carSpeed#=minCarSpeed#
		time#=timer()
	endif	 
	else
		
	if timer()>time# +.125
		if timer()>starttime#+2 then speed#=speed#+.125
		carSpeed#=carSpeed#+((maxCarSpeed#-carSpeed#)*AccelerationFactor#) //increase the car speed every 1 second
		timeCount#=timeCount#+(carSpeed#*.5)  //.50
		if carSpeed#>maxCarSpeed# then carSpeed#=maxCarSpeed#
		time#=timer()
		//endif
	endif	
	endif
	if timer()>time#+.125
		carSpeed#=carSpeed#+((maxCarSpeed#-carSpeed#)*AccelerationFactor#) 
		timeCount#=timeCount#+(carSpeed#*.5)
		time#=timer()
	endif
	if carSpeed#>maxCarSpeed# then carSpeed#=maxCarSpeed#
	SetSpriteAngle(2,carSpeed#*100.0) //sets the speedo needle to indicate speed
	SetTextString(textScore,"Score="+Str(score))
	SetTextString(textLives,"Cars="+Str(lives))
	if score>highScore 
		highScore=score
		SetTextString(textHighScore,"High="+Str(highScore))
	endif
	if carSpeed#>topSpeed#
		topSpeed#=carSpeed#
	endif
	fubarpkTextScroll(strLen) //the scolling text at bottom it can be commented out
	if stereoFlag=1 //stereoscopic selected from main menu
		drawAllObjects()
	
		// right render
		SetRenderToImage(rightRenderImage, -1 )
		ClearScreen()
		setCameraPosition(1,(mapX/2)+camRightOffsetX,10+camRightOffsetY,camRightOffsetZ)
		
		SetSpritePosition(1,10+spriteRightOffSetX,yMaxResolution-GetSpriteHeight(1)+spriteRightOffSetY)
		SetSpritePosition(2,10+spriteRightOffSetX,yMaxResolution-GetSpriteHeight(2)+spriteRightOffSetY)
		Render3D()
		// post process
		SetRenderToScreen()
		SetObjectImage( Quad, leftRenderImage, 0 )
		SetObjectImage( Quad, rightRenderImage, 1 )
		SetObjectShader( Quad, Stereo)
		DrawObject( Quad )
		Render2DFront() 
		Swap()
	else
		sync()
	endif
	
	if iAlpha>1 then iAlpha=iAlpha-5
	SetTextColorAlpha(textLevel, iAlpha )
	
	if levelCounter > 5 //go to next level
		inc level
		levelCounter=0 
		SetTextString(textLevel,"Level "+str(Level) )
		SetTextVisible(textLevel,1):iAlpha=255
		SetTextColorAlpha(textLevel, iAlpha )
	endif
until GetRawKeyPressed(27) or lives <1
SetTextVisible(textGameOver,1)
SetTextVisible(textPlayAgain,1)
SetTextVisible(textHowFar,1)

endfunction

function setupText()
x=xMaxResolution/2
CreateText(textTitle,"Night Driving")
SetTextSize(textTitle,50)
SetTextPosition(textTitle,x-120,5)
SetTextColor(textTitle,255,255,255,255)

CreateText(textScore,"Score=")
SetTextSize(textScore,35)
SetTextPosition(textScore,13,5)
SetTextColor(textScore,255,255,255,255)

CreateText(textLives,"Cars=")
SetTextSize(textLives,35)
SetTextPosition(textLives,26,35)
SetTextColor(textLives,255,255,255,255)

CreateText(textGameOver,"GameOver")
SetTextSize(textGameOver,55)
SetTextPosition(textGameOver,x-112,yMaxResolution/2-18)
SetTextColor(textGameOver,255,255,255,255)
SetTextVisible(textGameOver,0)	

CreateText(textPlayAgain,"How far can you go?")
SetTextSize(textPlayAgain,55)
SetTextPosition(textPlayAgain,x-200,yMaxResolution/2+20)
SetTextColor(textPlayAgain,255,255,255,255)
SetTextVisible(textPlayAgain,1)	

CreateText(textHowFar,"Click to Play")
SetTextSize(textHowFar,55)
SetTextPosition(textHowFar,x-126,yMaxResolution/2+58)
SetTextColor(textHowFar,255,255,255,255)
SetTextVisible(textHowFar,1)	

CreateText(textHighScore,"High=0")
SetTextSize(textHighScore,35)
SetTextPosition(textHighScore,xMaxResolution-150,5)
SetTextColor(textHighScore,255,255,255,255)

//CreateText(textCredit,"Programmed by fubarpk using AGK")
//SetTextSize(textCredit,35)
//SetTextPosition(textCredit,5,yMaxResolution-32)
//SetTextColor(textCredit,255,255,255,255)

CreateText(textLevel,"Level ")
SetTextSize(textLevel,50)
SetTextPosition(textLevel,x-75,300)
SetTextColor(textLevel,255,255,255,255)
SetTextVisible(textLevel,0)

endfunction

function fubarpkCreateTextImage (myString as string,imgNum as integer)
	//this function creates a sprite from a text letter used for the fubarpktextscroll function
	CreateSprite(bg,0)
	SetSpriteSize(bg,150,150)
	SetSpriteColor(bg,0,0,0,255)
	clearscreen()
	CreateText(startText,myString)
	SetTextSize(startText,50)
	SetTextPosition(startText,0,0)
	Render():If GetImageExists(imgNum) then DeleteImage(imgNum)
	GetImage(imgNum,0,0,50,50):ClearScreen()
	SetImageTransparentColor( imgNum,0,0,0 )
	DrawSprite(bg)
	ClearScreen()
	DeleteText(startText):deleteSprite(bg)
endfunction

function fubarpkTextScroll(strlen as integer)
//scrolls the credit text
for num = 1 to strlen
	textSpr[num].x=textSpr[num].x-1
	if GetSpriteExists(textSpr[num].id) then SetSpritePosition(textSpr[num].id,textSpr[num].x,textSpr[num].y)
	if textSpr[num].x <-10 then textSpr[num].x=xMaxResolution +100
next num
endfunction 

function deleteTextScroll(strlen)
//can be used to clean up and delete all the sprites created for the textscroller	
for num = 1 to strlen
	DeleteSprite(textSpr[num].id)
	DeleteImage(textSpr[num].img)
next num
endfunction 

function setupCredits()
rem Create a heap of sprites so they can be scrolled and have other effects that text dont allow
text$=("Programmed by fubarpk in AGK"):strLen=len(text$)
global dim textSpr[strLen] as myText
for num=1 to strLen 
	textSpr[num].id=num+startText+(num-1)
	textSpr[num].img=num+startText+(num-1)
	textSpr[num].x=(num-1)*15
	textSpr[num].y=yMaxResolution-33
	fubarpkCreateTextImage(Mid(text$,num,1),textSpr[num].img)
	createSprite(textSpr[num].id,textSpr[num].img)
	SetSpriteSize(textSpr[num].id,24,28)
	SetSpriteColor(textSpr[num].id,255,255,255,255) 
	SetSpriteTransparency(textSpr[num].id,1)
	SetSpriteDepth(textSpr[num].id,10)
	SetSpriteGroup(textSpr[num].id,1)
next num 
endfunction strlen

function modifyBlock(block as integer,  ammount as integer)
	rem This function is used to modify the car roof block so as it is angled
	rem there are the following 8 vertexs that we need to modify to extend in the ydirection [0,2,4,6,8,9,10,11]
	vertex as integer[7] = [0,2,4,6,8,9,10,11]
	maxVertex=GetMemblockInt(block,0)-1
	for index = 0 to 7
		if index<=maxVertex  
    		SetMeshMemblockVertexPosition(block,vertex[index],GetMeshMemblockVertexX(block,vertex[index]),GetMeshMemblockVertexY(block,vertex[index])+ammount,GetMeshMemblockVertexZ(block,vertex[index]))
		endif
    next index
    SetObjectMeshFromMemblock(block,1,block)
endfunction	

function moveBlocks(x as float,y as float,z as float)
	rem this function moves all the posts and cows
	
	rem These define the maximum and minimum an object may be placed in this example all objects
	rem are 1,1,1 so defing these locations was done as following but could be calculated for 
	rem other objects of different dimmensions
	xNum=mapX-1 //number of objects placed accross the xplane-1
	yNum=mapY-1 //number of objects placed accross the yplane-1
	zNum=mapZ-1 //number of objects placed accross the zplane-1
	rem defing the 3d window workspace
	xMin#=x:xMax#=mapX+x //the minimum and maximum xlocations for wrapping blocks on x plane 
	yMin=1:yMax=mapY //the minimum and maximum ylocation for wrapping blocks on the y plane 
	zMin#=0:zMax#=mapZ //the minimum and maximum zlocations for wrapping blocks on z plane 
	//time#=timer()
	//myRed=random(0,255):myGreen=random(0,255):myBlue=random(0,255)
	multiplier#=timer()*5:if multiplier#>150 then multiplier# =150
	for num=1 to blockCount //move posts and collision cows on road blocks 
		SetObjectPosition(num,getObjectX(num)+x,getObjectY(num),getObjectZ(num))
		if z>0 //move blocks toward screen
			if GetObjectWorldZ(num)<zMin#
				x# = sin(timeCount#)*34 //this is used to adjust the xposition of the posts so as we get curves in the road
				SetObjectPosition(num,x#+getObjectX(num),getObjectY(num),getObjectZ(num)+zNum) //reset position as post has gone off screen  
			else
				SetObjectPosition(num,getObjectX(num),getObjectY(num),getObjectZ(num)-z) 
				 
			endif   
		endif
		
	next num
	num=1
	for cows = 0 to 19 //move cows
		SetObjectPosition(cowStart+(cows*7),getObjectX(cowStart+(cows*7))+x,getObjectY(cowStart+(cows*7)),getObjectZ(cowStart+(cows*7)))
		if z>0 
			if GetObjectWorldZ(cowStart+(cows*7))<zMin#
				x# = sin(timeCount#)*34 //this is used to adjust the xposition of the cows so as they move on the same curve as the road
				SetObjectPosition(cowStart+(cows*7),getObjectX(cowStart+(cows*7))+x#,getObjectY(cowStart+(cows*7)),getObjectZ(cowStart+(cows*7))+zNum)		
			else
				SetObjectPosition(cowStart+(cows*7),getObjectX(cowStart+(cows*7)),getObjectY(cowStart+(cows*7)),getObjectZ(cowStart+(cows*7))-z) //reset position as cow has gone off screen	
			endif
		endif

	next cows
	
	for num=blockCount+1 to blockCount+4
		//this is the four cows that may or may not appear on the road
		if GetObjectWorldZ(num+((num-blockCount-1)*7))<zMin#
			//cows are coming forward and they are set relative to the post at object 10
			RotateObjectGlobalY(num+((num-blockCount-1)*7),random(1,360))
			blocksChanged[num].randX=random(5,15)
			blocksChanged[num].randZ=random(5,15)
			SetObjectPosition(num+((num-blockCount-1)*7),getObjectX(10)+blocksChanged[num].randX,getObjectY(10),getObjectZ(10)+zNum+blocksChanged[num].randZ)
			ranRange=trunc((log(level)*5.0)+2.0) //used to make it exponentially have more cars depending on level		
			if ranRange>8 then ranRange=8
			if Random(1,10)<ranRange //max difficulty 80 percent
				//Set Collision for all cow parts to on
				SetObjectCollisionMode(num+((num-blockCount-1)*7),1)
				SetObjectCollisionMode(num+((num-blockCount-1)*7)+1,1)
				SetObjectCollisionMode(num+((num-blockCount-1)*7)+2,1)
				SetObjectCollisionMode(num+((num-blockCount-1)*7)+3,1)
				SetObjectCollisionMode(num+((num-blockCount-1)*7)+4,1)
				SetObjectCollisionMode(num+((num-blockCount-1)*7)+5,1)
				SetObjectCollisionMode(num+((num-blockCount-1)*7)+6,1)
				//set all cow parts to visible	
				SetObjectVisible(num+((num-blockCount-1)*7),1)
				SetObjectVisible(num+((num-blockCount-1)*7)+1,1)
				SetObjectVisible(num+((num-blockCount-1)*7)+2,1)
				SetObjectVisible(num+((num-blockCount-1)*7)+3,1)
				SetObjectVisible(num+((num-blockCount-1)*7)+4,1)
				SetObjectVisible(num+((num-blockCount-1)*7)+5,1)
				SetObjectVisible(num+((num-blockCount-1)*7)+6,1)
					
			else
				//Set Collision for all cow parts to off
				SetObjectCollisionMode(num+((num-blockCount-1)*7),0)
				SetObjectCollisionMode(num+((num-blockCount-1)*7)+1,0)
				SetObjectCollisionMode(num+((num-blockCount-1)*7)+2,0)
				SetObjectCollisionMode(num+((num-blockCount-1)*7)+3,0)
				SetObjectCollisionMode(num+((num-blockCount-1)*7)+4,0)
				SetObjectCollisionMode(num+((num-blockCount-1)*7)+5,0)
				SetObjectCollisionMode(num+((num-blockCount-1)*7)+6,0)
				//set all cow parts to invisible		
				SetObjectVisible(num+((num-blockCount-1)*7),0)
				SetObjectVisible(num+((num-blockCount-1)*7)+1,0)
				SetObjectVisible(num+((num-blockCount-1)*7)+2,0)
				SetObjectVisible(num+((num-blockCount-1)*7)+3,0)
				SetObjectVisible(num+((num-blockCount-1)*7)+4,0)
				SetObjectVisible(num+((num-blockCount-1)*7)+5,0)
				SetObjectVisible(num+((num-blockCount-1)*7)+6,0)
					
			endif
		else
			SetObjectPosition(num+((num-blockCount-1)*7),getObjectX(10)+blocksChanged[num].randX,getObjectY(num+((num-blockCount-1)*7)),getObjectZ(num+((num-blockCount-1)*7))-z)	//reset cows back to start position
		endif
		
			
	
	next num
	//once the last post block has moved off screen increase score and the levelcounter
	if getObjectZ(blockCount)<zMin# //num=10 
		score=score+(((100*level)*carSpeed#)/2)
		inc levelCounter
	endif

endfunction	

function moveOtherCarBlock(spd as float, otherSpd as float)
	zMin#=0
	zNum=mapZ-1 //number of objects placed accross the zplane-1
	closestBlock=1:closestBlock2=1:furthestBlock=1:rem closestBlockToCar=1:lastBlockToCar=1
	//used to calculate a vector to point the oncoming car
	for num=2 to blockCount
		tempZ#=getObjectZ(num)
		if getObjectZ(closestBlock)>tempZ# then closestBlock=num
		if getObjectZ(closestBlock2)>=tempZ# then closestBlock2=num
		if getObjectZ(furthestBlock)<tempZ# then furthestBlock=num
	next num
    spd=spd+otherSpd
	x#=getObjectX(otherCarBlock)
	y#=getObjectY(otherCarBlock)
	z#=getObjectZ(otherCarBlock)
	if GetObjectWorldZ(otherCarBlock)<zMin#
		SetObjectPosition(otherCarBlock,getObjectX(furthestBlock)+offsetx,y#,z#+zNum)
		otherSpd=random(2,10)/10.0 //sets a random speed for oncoming car
	else
		xx#=getObjectX(closestBlock)+10
		zz#=getObjectZ(closestBlock)	
		
		ang# = GetAngle(x#,z#,xx#,zz#)
		
		SetObjectPosition(otherCarBlock,x#-sin(ang#)*spd,y#,z#-spd)
		angle# = GetAngle(getObjectX(blockCount),getObjectZ(blockCount),getObjectX(blockCount-2),getObjectZ(blockCount-2))
		SetObjectRotation(otherCarBlock,0,0,0)
		RotateObjectGlobalY(otherCarBlock,angle#)

	endif    
endfunction otherSpd

function blocksExplode()
	//Set Pointlightmode to vertex mode (the lights wont work doing this but it slows down too much)
	SetPointLightMode(carLight,0) 
	SetPointLightMode(carLight+1,0) 
	SetPointLightMode(otherCarLight,0) 
	SetPointLightMode(otherCarLight+1,0) 
	SetSpriteAngle(2,0)
	maxVertex=GetMemblockInt(carBlock,0)-1
	Dim CarVertex[maxVertex] as vertex	//get all the vertices of bottom car block and give them directions
	For index=0 to maxVertex
		//set each vertex a random direction
		CarVertex[index].xDirection=random2(-100,100)/50.0
		CarVertex[index].yDirection=Random2(-100,100)/50.0
		CarVertex[index].zDirection=Random2(-100,0)/50.0
	next index	
	
	maxVertex=GetMemblockInt(carBlock+1,0)-1
	Dim CarTopVertex[maxVertex] as vertex	//get all the vertices of top car block and give them directions
	For index=0 to maxVertex
		//set each vertex a random direction
		CarTopVertex[index].xDirection=random2(-100,100)/50.0
		CarTopVertex[index].yDirection=Random2(-100,100)/50.0
		CarTopVertex[index].zDirection=Random2(-100,0)/50.0
	next index	
	
	maxVertex=GetMemblockInt(otherCarBlock,0)-1
	Dim OtherCarVertex[maxVertex] as vertex	//get all the vertices of bottom other car block and give them directions
	For index=0 to maxVertex
		//set each vertex a random direction
		OtherCarVertex[index].xDirection=random2(-100,100)/50.0
		OtherCarVertex[index].yDirection=Random2(-100,100)/50.0
		OtherCarVertex[index].zDirection=Random2(-100,0)/50.0
	next index	
	
	maxVertex=GetMemblockInt(otherCarBlock+1,0)-1
	Dim OtherCarTopVertex[maxVertex] as vertex	
	For index=0 to maxVertex
		//set each vertex a random direction
		OtherCarTopVertex[index].xDirection=random2(-100,100)/50.0
		OtherCarTopVertex[index].yDirection=Random2(-100,100)/50.0
		OtherCarTopVertex[index].zDirection=Random2(-100,0)/50.0
	next index	
	
	dim wheels[7] as vertex //get all the wheels and send them into orbit
	for wheel = 0 to 7 //8 wheels with both cars
		wheels[wheel].xDirection=random2(-100,100)/50.0
		wheels[wheel].yDirection=random2(-100,100)/50.0
		wheels[wheel].zDirection=random2(-100,100)/50.0
	next wheel	

	dim cowsDirection[blockCount+3] as vertex
	for cows=0 to blockCount+2 //send all the cows that are positioned off the road into orbit
		cowsDirection[cows].xDirection=random2(-100,100)/50.0
		cowsDirection[cows].yDirection=random2(-100,100)/50.0
		cowsDirection[cows].zDirection=random2(-100,100)/50.0
	next cows
	
	
	startTime#=Timer()
	repeat
		if stereoFlag=1 //stereoscopic has been selected
			Update(0)

			// left render
			SetRenderToImage(leftRenderImage, -1 )
			ClearScreen()
			setCameraPosition(1,mapX/2+camLeftOffsetX,10+camLeftOffsetY,camLeftOffsetZ)
			SetSpritePosition(1,10+spriteLeftOffSetX,yMaxResolution-GetSpriteHeight(1)+spriteLeftOffSetY)
			SetSpritePosition(2,10+spriteLeftOffSetX,yMaxResolution-GetSpriteHeight(2)+spriteLeftOffSetY)
		endif
	
		for num=1 to blockCount 
			//move the ground blocks in their set random directions 
			SetObjectPosition(num,getObjectX(num)+blocksChanged[num].xDirection,getObjectY(num)+blocksChanged[num].yDirection,getObjectZ(num)+blocksChanged[num].zDirection)
		next num
		
		for num=blockCount+1 to blockCount+4  //move the sheep on road in random directions
			SetObjectPosition(num+((num-blockCount-1)*7),getObjectX(num)+blocksChanged[num].xDirection,getObjectY(num)+blocksChanged[num].yDirection,getObjectZ(num)+blocksChanged[num].zDirection)
		next num 

		//just send wheels into orbit		
		for wheel = 0 to 3 //your car wheels
			SetObjectPosition(carBlock+2+wheel,getObjectX(carBlock+2+wheel)+wheels[wheel].xDirection,getObjectY(carBlock+2+wheel)+wheels[wheel].yDirection,getObjectZ(carBlock+2+wheel)+wheels[wheel].zDirection)
		next wheel 	
		for wheel = 4 to 7 //other car wheels
			SetObjectPosition(otherCarBlock-2+wheel,getObjectX(otherCarBlock-2+wheel)+wheels[wheel].xDirection,getObjectY(otherCarBlock-2+wheel)+wheels[wheel].yDirection,getObjectZ(otherCarBlock-2+wheel)+wheels[wheel].zDirection)
		next wheel 	
		for cows=0 to blockCount-1  //there are 20 sheep +3 on road =+2
			SetObjectPosition((cowStart+(cows*7)),getObjectX(cowStart+(cows*7))+cowsDirection[cows].xDirection,getObjectY(cowStart+(cows*7))+cowsDirection[cows].yDirection,getObjectZ(cowStart+(cows*7))+cowsDirection[cows].zDirection) 	
		next cows
		
		for index = 0 to maxVertex
			//Tear the cars vertexs apart as set by there random direction
			SetMeshMemblockVertexPosition(carMem,index,GetMeshMemblockVertexX(carMem,index)+CarVertex[index].xDirection,GetMeshMemblockVertexY(carMem,index)+CarVertex[index].yDirection,GetMeshMemblockVertexZ(carMem,index)+CarVertex[index].zDirection)
			SetMeshMemblockVertexPosition(otherCarMem,index,GetMeshMemblockVertexX(OtherCarMem,index)+otherCarVertex[index].xDirection,GetMeshMemblockVertexY(otherCarMem,index)+OtherCarVertex[index].yDirection,GetMeshMemblockVertexZ(otherCarMem,index)+otherCarVertex[index].zDirection)
			SetMeshMemblockVertexPosition(carMem+1,index,GetMeshMemblockVertexX(carMem+1,index)+CarTopVertex[index].xDirection,GetMeshMemblockVertexY(carMem+1,index)+CarTopVertex[index].yDirection,GetMeshMemblockVertexZ(carMem+1,index)+CarTopVertex[index].zDirection)
			SetMeshMemblockVertexPosition(otherCarMem+1,index,GetMeshMemblockVertexX(OtherCarMem+1,index)+otherCarTopVertex[index].xDirection,GetMeshMemblockVertexY(otherCarMem+1,index)+OtherCarTopVertex[index].yDirection,GetMeshMemblockVertexZ(otherCarMem+1,index)+otherCarTopVertex[index].zDirection)
		next index
		
		
		SetObjectMeshFromMemblock(carBlock,1,carMem)
		SetObjectMeshFromMemblock(carBlock+1,1,carMem+1)
		SetObjectMeshFromMemblock(otherCarBlock,1,otherCarMem)
		SetObjectMeshFromMemblock(otherCarBlock+1,1,otherCarMem+1)
		
		//sets the position of the lights in relation to carblock positions
		SetPointLightPosition( carLight, GetObjectWorldX (carBlock+2), getObjectWorldY (carBlock+2), getObjectWorldZ (carBlock+2)) 
		SetPointLightPosition( carLight+1, GetObjectWorldX (carBlock+3), getObjectWorldY (carBlock+3), getObjectWorldZ (carBlock+3)) 
		SetPointLightPosition( otherCarLight, GetObjectWorldX (otherCarBlock+2), getObjectWorldY (otherCarBlock+2), getObjectWorldZ (otherCarBlock+2)) 
		SetPointLightPosition( otherCarLight+1, GetObjectWorldX (otherCarBlock+3), getObjectWorldY (otherCarBlock+3), getObjectWorldZ (otherCarBlock+3)) 
		
		if stereoFlag=1 //stereoscopic has been set
			drawAllObjects()
	
			// right render
			SetRenderToImage(rightRenderImage, -1 )
			ClearScreen()
			setCameraPosition(1,(mapX/2)+camRightOffsetX,10+camRightOffsetY,camRightOffsetZ)
			SetSpritePosition(1,10+spriteRightOffSetX,yMaxResolution-GetSpriteHeight(1)+spriteRightOffSetY)
			SetSpritePosition(2,10+spriteRightOffSetX,yMaxResolution-GetSpriteHeight(2)+spriteRightOffSetY)
			//
			Render3D()
			// post process
			SetRenderToScreen()
			SetObjectImage( Quad, leftRenderImage, 0 )
			SetObjectImage( Quad, rightRenderImage, 1 )
			SetObjectShader( Quad, Stereo)
			DrawObject( Quad )
			Render2DFront() 
			Swap()
		else
			sync()
		endif
	until timer()>StartTime#+3
	//sets poitlights back to pixel mode as it is the only way to show the light appearing on the road
	SetPointLightMode(carLight,1) 
	SetPointLightMode(carLight+1,1) 
	SetPointLightMode(otherCarLight,1) 
	SetPointLightMode(otherCarLight+1,1) 
endfunction	

function restoreBlocks()
	//restore all the block properties after a collision
	for num=1 to blockCount
		//restore blocks to the starting positions
		SetObjectPosition(blocksChanged[num].id,blocksChanged[num].xPosStart,blocksChanged[num].yPosStart,blocksChanged[num].zPosStart)
		createCow(cowStart+(num-1)*7)
		if blocksChanged[num].xPosStart>10
			SetObjectPosition(cowStart+(num-1)*7,blocksChanged[num].xPosStart+random(2,20),blocksChanged[num].yPosStart,blocksChanged[num].zPosStart) 
		else
			SetObjectPosition(cowStart+(num-1)*7,blocksChanged[num].xPosStart-random(2,20),blocksChanged[num].yPosStart,blocksChanged[num].zPosStart) 
		endif
		RotateObjectGlobalY(cowStart+(num-1)*7,random(1,360)) //randomly rotate a cow so they dont all face same direction
	next num
	
	
for num=blockCount+1 to blockCount+4  //create the four cows that may appear on the road 
	//sheep collision object
	blocksChanged[num].id=num
	//the directions are only used for the particle effect when you crash
	blocksChanged[num].xDirection=Random2(-100,100)/50.0
	blocksChanged[num].yDirection=Random2(-100,100)/50.0
	blocksChanged[num].zDirection=Random2(-100,100)/50.0
	blocksChanged[num].xPosStart=10
	blocksChanged[num].yPosStart=1 //4 for cow
	blocksChanged[num].zPosStart=50	
	blocksChanged[num].level=1
	createCow(num+((num-blockCount-1)*7))
	RotateObjectGlobalY(num+((num-blockCount-1)*7),random(1,360))

	blocksChanged[num].randX=random(5,15)
	blocksChanged[num].randZ=random(5,15)
	SetObjectPosition(num+((num-blockCount-1)*7),getObjectX(10)+blocksChanged[num].randX,getObjectY(10),getObjectZ(10)+blocksChanged[num].randZ)
	ranRange=trunc((log(level)*5.0)+2.0) 
    if ranRange>8 then ranRange=8
    if Random(1,10)<ranRange
		SetObjectCollisionMode(num+((num-blockCount-1)*7),1)
		SetObjectCollisionMode(num+((num-blockCount-1)*7)+1,1)
		SetObjectCollisionMode(num+((num-blockCount-1)*7)+2,1)
		SetObjectCollisionMode(num+((num-blockCount-1)*7)+3,1)
		SetObjectCollisionMode(num+((num-blockCount-1)*7)+4,1)
		SetObjectCollisionMode(num+((num-blockCount-1)*7)+5,1)
		SetObjectCollisionMode(num+((num-blockCount-1)*7)+6,1)
		SetObjectVisible(num+((num-blockCount-1)*7),1)
		SetObjectVisible(num+((num-blockCount-1)*7)+1,1)
		SetObjectVisible(num+((num-blockCount-1)*7)+2,1)
		SetObjectVisible(num+((num-blockCount-1)*7)+3,1)
		SetObjectVisible(num+((num-blockCount-1)*7)+4,1)
		SetObjectVisible(num+((num-blockCount-1)*7)+5,1)
		SetObjectVisible(num+((num-blockCount-1)*7)+6,1)
	else
		SetObjectCollisionMode(num+((num-blockCount-1)*7),0)
		SetObjectCollisionMode(num+((num-blockCount-1)*7)+1,0)
		SetObjectCollisionMode(num+((num-blockCount-1)*7)+2,0)
		SetObjectCollisionMode(num+((num-blockCount-1)*7)+3,0)
		SetObjectCollisionMode(num+((num-blockCount-1)*7)+4,0)
		SetObjectCollisionMode(num+((num-blockCount-1)*7)+5,0)
		SetObjectCollisionMode(num+((num-blockCount-1)*7)+6,0)
		SetObjectVisible(num+((num-blockCount-1)*7),0)
		SetObjectVisible(num+((num-blockCount-1)*7)+1,0)
		SetObjectVisible(num+((num-blockCount-1)*7)+2,0)
		SetObjectVisible(num+((num-blockCount-1)*7)+3,0)
		SetObjectVisible(num+((num-blockCount-1)*7)+4,0)
		SetObjectVisible(num+((num-blockCount-1)*7)+5,0)
		SetObjectVisible(num+((num-blockCount-1)*7)+6,0)
	endif
next num
//as the cars vertics and faces have all been destroyed iy is just easier to recreate them which dont take long
createCar(carBlock,carMem)
createCar(otherCarBlock,otherCarMem)
createHeadlights()
speed#  = 0

resetTimer() //need to reset time for the road curves
endfunction

function createSound(SoundId as integer,num as integer)
//create sound wave in memory
local sound as integer
local frames as integer
local data as integer 
local size as integer
local mem as integer
local sec as float

sec = .4
data = sec * (44100 * (2*2)) // 176400 bytes per second
frames = data / 4
size = 2+2+4+4 + data
mem = CreateMemblock(size)
 
SetMemblockByte(mem,0, 2) //The first 2 bytes of the memlbock store the number of channels (1 or 2 supported)
SetMemblockByte(mem,1, 0)
SetMemblockByte(mem,2,16) //the next 2 bytes store the bits per sample (8 (1 byte) or 16 (2 byte) supported)
SetMemblockByte(mem,3, 0)
SetMemblockint(mem,4,44100) // the next 4 bytes store the samples per second, for example 44100
SetMemblockint(mem,8,frames) // The next 4 bytes are the number of frames in the sound data, the size of the sound data in bytes can be calculated from this with the formula numFrames*(bitsPerSample/8)*channels.

local i as integer
local value as integer
local Hz as float // the hertz of the sound
local w as float

value=0
w=0
local randomize as integer[8]=[80,53,-25,73,44,0,24,80] //deep base rumble
maxW=360:if num=2 then maxW=32768 //360 is normal
for i=0 to data -1 step 4
	Hz=randomize[random2(1,8)] //deep base rumble
	w=w+(maxW / 44100.0) * Hz
	if w > maxW then w = w -maxW
	value = sin(w)*(32767.0) //Max ?32768 through 32767
	SetMemblockShort(mem,12+i+0 ,value) // short 2 bytes ?32768 through 32767
	SetMemblockShort(mem,12+i+2 ,value) // short 2 bytes ?32768 through 32767
next i
CreateSoundFromMemblock(SoundId,mem)
DeleteMemblock(mem)
endFunction //sound

function createWireFrameTexture(ImgId as integer,sizex as integer, sizey as integer, color)
    SetClearColor(0,0,0)
    ClearScreen()
    Render()
    drawbox(0,0,sizex-1, sizey-1, color, color,color,color, 0)
    Render()
    //img = getimage(0,0,sizex, sizey)
    getimage(ImgId,0,0,sizex, sizey)
    Swap()
 endfunction //img

function createGridTexture(ImgId as integer,sizex as integer, sizey as integer,stepx as integer,stepy as integer, color)
    SetClearColor(0,0,0)
    ClearScreen()
    Render()
    for y=0 to sizey-1 step stepy
		DrawLine(0,y,sizex,y,color,color)
	next y
	for x=0 to sizex-1 step stepx
		DrawLine(x,0,x,sizey,color,color)
	next x
    Render(): 
    //img = getimage(0,0,sizex, sizey)
    getimage(ImgId,0,0,sizex, sizey)
    Swap()
 endfunction //img
 
function CreateSpeedoTexture(imgId as integer)
	SetClearColor(0,0,0)
	ClearScreen()
	text1=createText("10"):SetTextSize(text1,20):SetTextPosition(text1,15,167):DrawText(text1)
	text2=createText("20"):SetTextSize(text2,20):SetTextPosition(text2,0,130):DrawText(text2) 
	text3=createText("30"):SetTextSize(text3,20):SetTextPosition(text3,1,87):DrawText(text3) 
	text4=createText("40"):SetTextSize(text4,20):SetTextPosition(text4,18,46):DrawText(text4) 
	text5=createText("50"):SetTextSize(text5,20):SetTextPosition(text5,50,17):DrawText(text5) 
	text6=createText("60"):SetTextSize(text6,20):SetTextPosition(text6,90,1):DrawText(text6) 
	text7=createText("70"):SetTextSize(text7,20):SetTextPosition(text7,134,1):DrawText(text7) 
	text8=createText("80"):SetTextSize(text8,20):SetTextPosition(text8,177,17):DrawText(text8) 
	text9=createText("90"):SetTextSize(text9,20):SetTextPosition(text9,209,46):DrawText(text9) 
	text10=createText("100"):SetTextSize(text10,20):SetTextPosition(text10,226,87):DrawText(text10) 
	text11=createText("110"):SetTextSize(text11,20):SetTextPosition(text11,228,130):DrawText(text11) 
	text12=createText("120"):SetTextSize(text12,20):SetTextPosition(text12,220,167):DrawText(text12) 
	Render()
	//img = getimage(0,0,255,255)
	getimage(ImgId,0,0,255,255)
	Swap()
	DeleteText(text1):DeleteText(text2):DeleteText(text3):DeleteText(text4):DeleteText(text5):DeleteText(text6)
	DeleteText(text7):DeleteText(text8):DeleteText(text9):DeleteText(text10):DeleteText(text11):DeleteText(text12)
endfunction //img  
 
function CreateSpeedoNeedle(imgId as integer)
	ClearScreen()
	DrawLine( 125, 126, 58, 194,255,255,255 )
	DrawLine( 126, 126, 59, 194,255,255,255 )
	DrawLine( 127, 126, 60, 194,255,255,255 )
	DrawEllipse(126,126,4,4,makecolor(255,255,255),makecolor(255,255,255),1) 
	Render()
	//img = getimage(0,0,255,255)
	getimage(ImgId,0,0,255,255)
	Swap() 
 endfunction //img

function getAngle(x1#, y1#, x2#, y2#)
    
    result# = ATan2(x1# - x2#,y1# - y2#)
endfunction result#

function drawAllObjects()
	DrawObject(carBlock)                 //draw your car
	DrawObject(otherCarBlock)            //draw other car
	for wheel = 2 to 5 //your car wheels
		drawObject(carBlock+wheel)       //draw your cars wheels  
		drawObject(otherCarBlock+wheel)  //draw other cars wheels
	next wheel 	
	
	for num=1 to blockCount 
		DrawObject(num)                  //draw posts
		DrawObject(cowStart+(num-1)*7) //draw sheep 
	next num
	for num=blockCount+1 to blockCount+3
		DrawObject(num+3) //draw road sheep
	next num
	DrawSprite(1):DrawSprite(2)
endfunction

function createCar(carId as integer,carMemId as integer)
	DeleteObject(carId):DeleteObject(CarId+1)
	DeleteObject(carId+2):DeleteObject(CarId+3)
	DeleteObject(carId+4):DeleteObject(CarId+5)
	
	
	DeleteMemBlock(carMemId):DeleteMemblock(carMemId+1)	
	vertex as integer[7] = [17,15,7,13, 1,19,3,5]
	
	CreateObjectBox(carId,2,2,4)
	CreateMemblockFromObjectMesh(carId,carMemId,1)
	setObjectPosition(carId,mapX/2,mapY,10)
	SetObjectImage(carId,wireFrameTextureID,0)
	//SetObjectColor(carId,200,0,0,255) //red cars go faster 
	SetObjectColor(carId,255,255,255,255)  
	
	SetObjectTransparency(carId,1)
	SetObjectCollisionMode(carId,1) //on is set or raycasting wont work
	CreateObjectBox(carId+1,2,1,1) //the car top
	SetObjectImage(carId+1,wireFrameTextureID,0)
	SetObjectTransparency(carId+1,1)

	setObjectPosition(carId+1,getObjectX(carId)-(mapX/2),getObjectY(carId)-mapY+1.5,getObjectZ(carId)-10)
	CreateMemblockFromObjectMesh(carId+1,carMemId+1,1)
	for i = 0 to 7
		SetMeshMemblockVertexPosition(carMemId+1,vertex[i],GetMeshMemblockVertexX(carMemId,vertex[i]),GetMeshMemblockVertexY(carMemId,vertex[i])+.5,GetMeshMemblockVertexZ(carMemId,vertex[i])*.5)
	next i
	//SetMeshMemblockVertexPosition(carMemId+1,vertexBottom[2],GetMeshMemblockVertexX(carMemId,vertexBottom[2]),GetMeshMemblockVertexY(carMem,vertexBottom[2]),GetMeshMemblockVertexZ(carMem,vertexBottom[2])-1)
	
	SetObjectMeshFromMemblock(carId+1,1,carMemId+1)
    
	SetObjectColor(carId+1,255,255,255,255) //red cars go faster 
	SetObjectCollisionMode(carId+1,1) //on is set or raycasting wont work
	FixObjectToObject(carId+1,carId) 
	
	//now for four wheels
	CreateObjectCylinder(carId+2,.5,1,10) //front left
	SetObjectImage(carId+2,gridTextureID,0)
	SetObjectTransparency(carId+2,1)
	SetObjectRotation(carId+2,0,0,90)
	SetObjectPOsition(carId+2,-.75,-1,1.25)
	SetObjectColor(carId+2,255,255,255,255)
	FixObjectToObject(carId+2,carId)
	//SetObjectCollisionMode(carId+2,1) 
	
	CreateObjectCylinder(carId+3,.5,1,10) //front right
	SetObjectImage(carId+3,gridTextureID,0)
	SetObjectTransparency(carId+3,1)
	SetObjectRotation(carId+3,0,0,90)
	SetObjectPOsition(carId+3,.75,-1,1.25)
	SetObjectColor(carId+3,255,255,255,255)
	FixObjectToObject(carId+3,carId)
	//SetObjectCollisionMode(carId+3,1) 
	
	CreateObjectCylinder(carId+4,.5,1,10) //back left
	SetObjectImage(carId+4,gridTextureID,0)
	SetObjectTransparency(carId+4,1)
	SetObjectRotation(carId+4,0,0,90)
	SetObjectPOsition(carId+4,-.75,-1,-1.15)
	SetObjectColor(carId+4,255,255,255,255)
	FixObjectToObject(carId+4,carId)
	//SetObjectCollisionMode(carId+4,1) 
	
	CreateObjectCylinder(carId+5,.5,1,10) //back right
	SetObjectImage(carId+5,gridTextureID,0)
	SetObjectTransparency(carId+5,1)
	SetObjectRotation(carId+5,0,0,90)
	SetObjectPOsition(carId+5,.75,-1,-1.15)
	SetObjectColor(carId+5,255,255,255,255)
	FixObjectToObject(carId+5,carId)
	//SetObjectCollisionMode(carId+5,1) 
endfunction

function createCow(cowId as integer)
	//cows are made up of 7 objects
	DeleteObject(cowId):DeleteObject(cowId+1):DeleteObject(cowId+2):DeleteObject(cowId+3)
	DeleteObject(cowId+4):DeleteObject(cowId+5):DeleteObject(cowId+6)
	//cow body
	CreateObjectBox(cowId,2.0,1.0,1) 
	SetObjectImage(cowId,wireFrameTextureID,0)
	setObjectPosition(cowId,mapX/2,mapY+4,10)
	SetObjectTransparency(cowId,1)
	SetObjectCollisionMode(cowId,1) //on is set or raycasting wont work
	//cow head
	CreateObjectBox(cowId+1,0.65,0.25,.5) //head
	SetObjectImage(cowId+1,wireFrameTextureID,0)
	setObjectPosition(cowId+1,getObjectX(cowId)-(mapX/2)-1,getObjectY(cowId)-mapY-3.5,getObjectZ(cowId)-10)
	SetObjectRotation(cowId+1,0,0,20)
	SetObjectTransparency(cowId+1,1)
	//SetObjectCollisionMode(cowId+1,1) //on is set or raycasting wont work
	FixObjectToObject(cowId+1,cowId) 
    //cow tail
	CreateObjectBox(cowId+2,.1,1.0,.25) 
	SetObjectImage(cowId+2,wireFrameTextureID,0)
	setObjectPosition(cowId+2,getObjectX(cowId)-(mapX/2)+1.15,getObjectY(cowId)-mapY-4,getObjectZ(cowId)-10)
	SetObjectRotation(cowId+2,0,0,20)
	SetObjectTransparency(cowId+2,1)
	//SetObjectCollisionMode(cowId+2,1) //on is set or raycasting wont work
	FixObjectToObject(cowId+2,cowId) 
	//leg left front
	CreateObjectBox(cowId+3,.1,.50,.25) 
	SetObjectImage(cowId+3,wireFrameTextureID,0)
	setObjectPosition(cowId+3,getObjectX(cowId)-(mapX/2)-1.0,getObjectY(cowId)-mapY-4.75,getObjectZ(cowId)-10.25)
	SetObjectRotation(cowId+3,0,0,0)
	SetObjectTransparency(cowId+3,1)
	//SetObjectCollisionMode(cowId+3,1) //on is set or raycasting wont work
	FixObjectToObject(cowId+3,cowId) 
	//leg right front
	CreateObjectBox(cowId+4,.1,.50,.25) 
	SetObjectImage(cowId+4,wireFrameTextureID,0)
	setObjectPosition(cowId+4,getObjectX(cowId)-(mapX/2)+1.0,getObjectY(cowId)-mapY-4.75,getObjectZ(cowId)-10.25)
	SetObjectRotation(cowId+4,0,0,0)
	SetObjectTransparency(cowId+4,1)
	//SetObjectCollisionMode(cowId+4,1) //on is set or raycasting wont work
	FixObjectToObject(cowId+4,cowId) 
	//leg left back
	CreateObjectBox(cowId+5,.1,.50,.25) 
	SetObjectImage(cowId+5,wireFrameTextureID,0)
	setObjectPosition(cowId+5,getObjectX(cowId)-(mapX/2)-1.0,getObjectY(cowId)-mapY-4.75,getObjectZ(cowId)-9.75)
	SetObjectRotation(cowId+5,0,0,0)
	SetObjectTransparency(cowId+5,1)
	//SetObjectCollisionMode(cowId+5,1) //on is set or raycasting wont work
	FixObjectToObject(cowId+5,cowId) 
	//leg right back
	CreateObjectBox(cowId+6,.1,.50,.25) 
	SetObjectImage(cowId+6,wireFrameTextureID,0)
	setObjectPosition(cowId+6,getObjectX(cowId)-(mapX/2)+1.0,getObjectY(cowId)-mapY-4.75,getObjectZ(cowId)-9.75)
	SetObjectRotation(cowId+6,0,0,0)
	SetObjectTransparency(cowId+6,1)
	//SetObjectCollisionMode(cowId+6,1) //on is set or raycasting wont work
	FixObjectToObject(cowId+6,cowId) 
endfunction

function createHeadlights()
	SetAmbientColor( 0, 0, 0 )
	SetSunActive (0)
	
	If GetObjectExists(myGround) then DeleteObject(myGround)
	CreateObjectPlane(myGround, 250, 250 )
	SetObjectPosition (myGround, 0, 0, 0) 
	SetObjectRotation (myGround, 90, 0, 0)
	setObjectColor (myGround, 255, 255,225,255)	

	if GetObjectExists(carLightObj) then DeleteObject(carLightObj)
	if GetObjectExists(carLightObj+1) then DeleteObject(carLightObj+1)
	
	CreateObjectBox (carLightObj,1.0, 1.0, 1.0)
	SetObjectPosition (carLightObj,-2.0, 0, 10)
	CreateObjectBox (carLightObj+1,1.0, 1.0, 1.0)
	SetObjectPosition (carLightObj+1,2.0, 0, 10)
	SetObjectVisible(carLightObj,0)
	SetObjectCollisionMode(carLightObj,0)
	SetObjectVisible(carLightObj+1,0)
	SetObjectCollisionMode(carLightObj+1,0)

	if GetObjectExists(otherCarLightObj) then DeleteObject(otherCarLightObj)
	if GetObjectExists(otherCarLightObj+1) then DeleteObject(otherCarLightObj+1)

	CreateObjectBox (otherCarLightObj,1.0, 1.0, 1.0)
	SetObjectPosition (otherCarLightObj,-2.0, 0, -10)
	CreateObjectBox (otherCarLightObj+1,1.0, 1.0, 1.0)
	SetObjectPosition (otherCarLightObj+1,2.0, 0, -10)
	SetObjectVisible(otherCarLightObj,0)
	SetObjectCollisionMode(otherCarLightObj,0)
	SetObjectVisible(otherCarLightObj+1,0)
	SetObjectCollisionMode(otherCarLightObj+1,0)
	
	if GetPointLightExists(carLight) then DeletePointLight(carLight)
	if GetPointLightExists(carLight+1) then DeletePointLight(carLight+1)
	
	CreatePointLight( carLight, getObjectX (carLightObj), getObjectY (carLightObj), getObjectZ (carLightObj), 200.0, 255, 255, 255 ) 
	SetPointLightMode(carLight, 1 )
	CreatePointLight( carLight+1, getObjectX (carLightObj+1), getObjectY (carLightObj+1), getObjectZ (carLightObj+1), 200.0, 255, 255, 255 ) 
	SetPointLightMode(carLight+1, 1 )

	if GetPointLightExists(otherCarLight) then DeletePointLight(otherCarLight)
	if GetPointLightExists(otherCarLight+1) then DeletePointLight(otherCarLight+1)

	CreatePointLight( otherCarLight, getObjectX (otherCarBlock+1), getObjectY (otherCarBlock+1), getObjectZ (otherCarBlock+1), 200.0, 255, 255, 255 ) 
	SetPointLightMode(otherCarLight, 1 ) 
	CreatePointLight( otherCarLight+1, getObjectX (otherCarBlock+1), getObjectY (otherCarBlock+1), getObjectZ (otherCarBlock+1), 200.0, 255, 255, 255 ) 
	SetPointLightMode(otherCarLight+1, 1 ) 

	FixObjectToObject( carLightObj, carBlock ) 
	FixObjectToObject( carLightObj+1, carBlock )
	FixObjectToObject( otherCarLightObj, otherCarBlock ) 
	FixObjectToObject( otherCarLightObj+1, otherCarBlock )
	
	SetPointLightPosition( carLight, GetObjectWorldX (carLightObj), getObjectWorldY (carLightObj), getObjectWorldZ (carLightObj)) 
	SetPointLightPosition( carLight+1, GetObjectWorldX (carLightObj+1), getObjectWorldY (carLightObj+1), getObjectWorldZ (carLightObj+1)) 
	SetPointLightPosition( otherCarLight, GetObjectWorldX (otherCarLightObj), getObjectWorldY (otherCarLightObj), getObjectWorldZ (otherCarLightObj)) 
	SetPointLightPosition( otherCarLight+1, GetObjectWorldX (otherCarLightObj+1), getObjectWorldY (otherCarLightObj+1), getObjectWorldZ (otherCarLightObj+1)) 
	
endfunction 

function createShader()
file = OpenToWrite("Anaglyph.vs")
WriteLine(file,"attribute vec3 position;")
WriteLine(file,"varying vec2 uvVarying;")
WriteLine(file,"uniform vec4 uvBounds0;")
WriteLine(file,"uniform float agk_invert;")
WriteLine(file,"void main()")
WriteLine(file,"{")
WriteLine(file,"gl_Position = vec4(position.xy * vec2(1, agk_invert), 0.5, 1.0);")
WriteLine(file,"uvVarying = (position.xy * vec2(0.5, -0.5) + 0.5) * uvBounds0.xy + uvBounds0.zw;") 
WriteLine(file,"}")
CloseFile(file)


file = OpenToWrite("Anaglyph.ps")
WriteLine(file,"uniform sampler2D texture0;")
WriteLine(file,"uniform sampler2D texture1;")
WriteLine(file,"varying mediump vec2 uvVarying;")
WriteLine(file,"void main()")
WriteLine(file,"{")
WriteLine(file,"vec3 LColor = texture2D(texture0, uvVarying).xyz;")
WriteLine(file,"vec3 RColor = texture2D(texture1, uvVarying).xyz;") 
WriteLine(file,"vec4 Color;") 
WriteLine(file,"Color.r = 0.299 * LColor.r + 0.587 * LColor.g + 0.114 * LColor.b;")
WriteLine(file,"Color.g = RColor.g;")
WriteLine(file,"Color.b = RColor.b;")
WriteLine(file,"Color = clamp(Color,0.0,1.0);") //restricts color range
WriteLine(file,"gl_FragColor = Color;")
WriteLine(file,"}")
CloseFile(file)
endfunction


The Explosion in the above uses a combination of sending blocks into orbit and sending the vertexs
of objects in all directions. Here is an easier explode function that should work on any mesh.
Vertex Explosion
+ Code Snippet
type vertex
    xDirection as integer
    yDirection as integer
    zDirection as integer
endtype

type object 
	objMesh as integer
	objMem as integer
	maxVertex as integer
	myVertex as vertex[1000] //need to be able to set this to maxVertex as integer
endtype

Setvirtualresolution(1024,600)
//setCameraPosition(1,100,10,0)
createGridTexture(1,32,32,4,4,makecolor(255,255,255))
Sphere=CreateObjectSphere(2,5,5)
Box=CreateObjectBox( 2, 2, 2 )
Cylinder=CreateObjectCylinder(4,2,10)
Cone=CreateObjectCone(4,2,10) 
SetObjectPosition(Sphere,getObjectX(Sphere)-4,getObjectY(Sphere),getObjectZ(Sphere))
SetObjectPosition(Cylinder,getObjectX(Cylinder)+4,getObjectY(Cylinder),getObjectZ(Cylinder))
SetObjectPosition(Cone,getObjectX(Cone)+8,getObjectY(Cone),getObjectZ(Cone))

SetObjectImage(Sphere,1,0)
SetObjectImage(Box,1,0)
SetObjectImage(Cylinder,1,0)
SetObjectImage(Cone,1,0)
SetObjectTransparency(Sphere,1)
SetObjectTransparency(Box,1)
SetObjectTransparency(Cylinder,1)
SetObjectTransparency(Cone,1)

SetObjectColor(Sphere,255,0,0,255)
SetObjectColor(Box,0,255,0,255)
SetObjectColor(Cylinder,0,0,255,255)
SetObjectColor(Cone,255,255,0,255)
do
 if GetRawKeyPressed(49) 
	 objectExplode(Sphere,2)
	 deleteObject(Sphere)
	 Sphere=CreateObjectSphere(2,5,5)
	 SetObjectPosition(Sphere,getObjectX(Sphere)-4,getObjectY(Sphere),getObjectZ(Sphere))
	 SetObjectImage(Sphere,1,0)
	 SetObjectColor(Sphere,255,0,0,255)
	 SetObjectTransparency(Sphere,1)
 endif
 if GetRawKeyPressed(50) 
	 objectExplode(Box,2)
	 deleteObject(Box)
	 Box=CreateObjectBox( 2, 2, 2 )
	 SetObjectImage(Box,1,0)
	 SetObjectColor(Box,0,255,0,255)
	 SetObjectTransparency(Box,1)	 
 endif  
 if GetRawKeyPressed(51) 
	 objectExplode(Cylinder,2)
	 DeleteObject(Cylinder)
	 Cylinder=CreateObjectCylinder(4,2,10)
	 SetObjectPosition(Cylinder,getObjectX(Cylinder)+4,getObjectY(Cylinder),getObjectZ(Cylinder))
	 SetObjectImage(Cylinder,1,0)
	 SetObjectColor(Cylinder,0,0,255,255)
	 SetObjectTransparency(Cylinder,1)
  endif	
  if GetRawKeyPressed(52) 
	objectExplode(Cone,2)
	DeleteObject(Cone)
	Cone=CreateObjectCone(4,2,10) 
	SetObjectPosition(Cone,getObjectX(Cone)+8,getObjectY(Cone),getObjectZ(Cone))
	SetObjectImage(Cone,1,0)
	SetObjectColor(Cone,255,255,0,255)
	SetObjectTransparency(Cone,1)
  endif	
  Print("Vertex destruct") 
  Print("Press 1 to destroy sphere.")
  Print("Press 2 to destroy box.")
  Print("Press 3 to destroy cylinder.")
  Print("Press 4 to destroy cone.")
  RotateObjectLocalY( Box, 2 )
 Sync()
loop

function objectExplode(obj as integer, time as float)
	numMeshes=GetObjectNumMeshes(obj)
	dim myObject[numMeshes] as object
	for mesh=1 to numMeshes
		myObject[mesh].objMesh=mesh
		myObject[mesh].objMem=CreateMemblockFromObjectMesh(obj,mesh)
		myObject[mesh].maxVertex=GetMemblockInt(myObject[mesh].objMem,0)-1
		//myObject[mesh].myVertex[myObject[mesh].maxVertex]   
		//dim myObject[mesh].myVertex[myObject[mesh].maxVertex]
		For index=0 to myObject[mesh].maxVertex
			
			//set each vertex a random direction
			myObject[mesh].myVertex[index].xDirection=random2(-100,100)/50.0
			myObject[mesh].myVertex[index].yDirection=Random2(-100,100)/50.0
			myObject[mesh].myVertex[index].zDirection=Random2(-100,100)/50.0
		next index  
	next mesh
	
      
    startTime#=Timer()
    repeat
		for mesh=1 to numMeshes 
			for index = 0 to myObject[mesh].maxVertex
				//Tear the object vertexs apart as set by there random direction
				SetMeshMemblockVertexPosition(myObject[mesh].objMem,index,GetMeshMemblockVertexX(myObject[mesh].objMem,index)+myObject[mesh].myVertex[index].xDirection,GetMeshMemblockVertexY(myObject[mesh].objMem,index)+myObject[mesh].myVertex[index].yDirection,GetMeshMemblockVertexZ(myObject[mesh].objMem,index)+myObject[mesh].myVertex[index].zDirection)
			next index
			SetObjectMeshFromMemblock(obj,mesh,myObject[mesh].objMem)
		next mesh
        sync()
    until timer()>StartTime#+time 
    //housekeeping
    for mesh=1 to numMeshes
		DeleteMemblock(myObject[mesh].objMem)
	next mesh
endfunction

function createGridTexture(ImgId as integer,sizex as integer, sizey as integer,stepx as integer,stepy as integer, color)
    SetClearColor(0,0,0)
    ClearScreen()
    Render()
    for y=0 to sizey-1 step stepy
		DrawLine(0,y,sizex,y,color,color)
	next y
	for x=0 to sizex-1 step stepx
		DrawLine(x,0,x,sizey,color,color)
	next x
    Render(): 
    //img = getimage(0,0,sizex, sizey)
    getimage(ImgId,0,0,sizex, sizey)
    Swap()
 endfunction //img
Posted: 2nd May 2018 6:12
There's also the Useful Functions Community Project (which I've added this thread to)
And the Community Toolkit
Posted: 10th May 2018 22:38
A Speedometer created with code
+ Code Snippet
SetWindowTitle( "Speedometer" )
SetWindowSize( 1024, 768 , 0 )
SetWindowAllowResize( 1 ) // allow the user to resize the window
 
// set display properties
SetVirtualResolution( 1024, 768 ) // doesn't have to match the window
SetOrientationAllowed( 0, 0, 1, 1 ) // allow only landscape on mobile devices
SetSyncRate( 30, 0 ) // 30fps instead of 60 to save battery
SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts
#constant speedoTextureID       =3
#constant speedoNeedleTextureID =4

CreateSpeedoTexture(speedoTextureID)
CreateSprite(1,speedoTextureID)
SetSpritePosition(1,10,768-GetSpriteHeight(1))
CreateSpeedoNeedle(speedoNeedleTextureID)
CreateSprite(2,speedoNeedleTextureID)
SetSpritePosition(2,10,768-GetSpriteHeight(2))
angle#=0
repeat 
	angle#=angle#+1
	SetSpriteAngle(2,angle#)
sync()
until GetRawKeyPressed(27)

function CreateSpeedoTexture(imgId as integer)
	SetClearColor(0,0,0)
	ClearScreen()
	text1=createText("10"):SetTextSize(text1,20):SetTextPosition(text1,15,167):DrawText(text1)
	text2=createText("20"):SetTextSize(text2,20):SetTextPosition(text2,0,130):DrawText(text2) 
	text3=createText("30"):SetTextSize(text3,20):SetTextPosition(text3,1,87):DrawText(text3) 
	text4=createText("40"):SetTextSize(text4,20):SetTextPosition(text4,18,46):DrawText(text4) 
	text5=createText("50"):SetTextSize(text5,20):SetTextPosition(text5,50,17):DrawText(text5) 
	text6=createText("60"):SetTextSize(text6,20):SetTextPosition(text6,90,1):DrawText(text6) 
	text7=createText("70"):SetTextSize(text7,20):SetTextPosition(text7,134,1):DrawText(text7) 
	text8=createText("80"):SetTextSize(text8,20):SetTextPosition(text8,177,17):DrawText(text8) 
	text9=createText("90"):SetTextSize(text9,20):SetTextPosition(text9,209,46):DrawText(text9) 
	text10=createText("100"):SetTextSize(text10,20):SetTextPosition(text10,226,87):DrawText(text10) 
	text11=createText("110"):SetTextSize(text11,20):SetTextPosition(text11,228,130):DrawText(text11) 
	text12=createText("120"):SetTextSize(text12,20):SetTextPosition(text12,220,167):DrawText(text12) 
	Render()
	//img = getimage(0,0,255,255)
	getimage(ImgId,0,0,255,255)
	Swap()
	DeleteText(text1):DeleteText(text2):DeleteText(text3):DeleteText(text4):DeleteText(text5):DeleteText(text6)
	DeleteText(text7):DeleteText(text8):DeleteText(text9):DeleteText(text10):DeleteText(text11):DeleteText(text12)
endfunction //img  
 
function CreateSpeedoNeedle(imgId as integer)
	ClearScreen()
	DrawLine( 125, 126, 58, 194,255,255,255 )
	DrawLine( 126, 126, 59, 194,255,255,255 )
	DrawLine( 127, 126, 60, 194,255,255,255 )
	DrawEllipse(126,126,4,4,makecolor(255,255,255),makecolor(255,255,255),1) 
	Render()
	//img = getimage(0,0,255,255)
	getimage(ImgId,0,0,255,255)
	Swap() 
 endfunction //img


A Vertical Health Bar
in this example width is set to 20 and height is set to 200 (easily changed)
+ Code Snippet
SetWindowTitle( "Progress Bar" )
SetWindowSize( 1024, 768 , 0 )
SetWindowAllowResize( 1 ) // allow the user to resize the window
  
// set display properties
SetVirtualResolution( 1024, 768 ) // doesn't have to match the window
SetOrientationAllowed( 0, 0, 1, 1 ) // allow only landscape on mobile devices
SetSyncRate( 30, 0 ) // 30fps instead of 60 to save battery
SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts
 
img=createTexture(MakeColor(0,255,0))  //this could replaced with a healthy image of your sprite you want to use
img3=createTexture(MakeColor(255,0,0)) //this could be replaced with the total dead image

CreateSprite(1,img)
CreateSprite(2,img3)
SetSpriteSize(1,20,200)
SetSpriteSize(2,20,200)


SetSpritePosition(1,0,0)
SetSpritePosition(2,0,0)
ammount=0
repeat
    ammount=ammount+1
    if ammount<=getSpriteHeight(1)
		//DeleteImage(img2)
		img2=progress(2,img3)
		SetSpriteimage(2,img2)
		SetSpriteSize(2,20,ammount)
	else
		ammount=0
	endif
    sync()
until GetRawKeyPressed(27)
 
function progress(image as integer,ammount as integer)
    newimg=CopyImage(image,0,0,20,ammount ) 
 endfunction newimg

function createTexture(color)
	SetClearColor(0,0,0)
    ClearScreen()
	DrawBox( 0, 0, 20, 200, color,color ,color, color, 1 ) 
    
    Render()
    img = getimage(0,0,20,200)
	SetImageTransparentColor( img,0,0,0 )
    Swap() 
 endfunction img

Modifications could be made easy enough so as it uses a percentage system I left that out for simplicity.
A Horizontal Health Bar in this example width is set to 200 and height is set to 20 (easily changed)
+ Code Snippet
SetWindowTitle( "Progress Bar" )
SetWindowSize( 1024, 768 , 0 )
SetWindowAllowResize( 1 ) // allow the user to resize the window
  
// set display properties
SetVirtualResolution( 1024, 768 ) // doesn't have to match the window
SetOrientationAllowed( 0, 0, 1, 1 ) // allow only landscape on mobile devices
SetSyncRate( 30, 0 ) // 30fps instead of 60 to save battery
SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts
 
img=createTexture(MakeColor(0,255,0))  //this could replaced with a healthy image of your sprite you want to use
img3=createTexture(MakeColor(255,0,0)) //this could be replaced with the total dead image

CreateSprite(1,img)
CreateSprite(2,img3)
SetSpriteSize(1,200,20)
SetSpriteSize(2,200,20)


SetSpritePosition(1,0,0)
SetSpritePosition(2,0,0)
ammount=0
repeat
    ammount=ammount+1
    if ammount<=getSpriteWidth(1)
		//DeleteImage(img2)
		img2=progress(2,img3)
		SetSpriteimage(2,img2)
		SetSpriteSize(2,ammount,20)
	else
		ammount=0
	endif
    sync()
until GetRawKeyPressed(27)
 
function progress(image as integer,ammount as integer)
    newimg=CopyImage(image,0,0,ammount,20 ) 
 endfunction newimg

function createTexture(color)
	SetClearColor(0,0,0)
    ClearScreen()
	DrawBox( 0, 0, 200, 20, color,color ,color, color, 1 ) 
    
    Render()
    img = getimage(0,0,200,20)
	SetImageTransparentColor( img,0,0,0 )
    Swap() 
 endfunction img

Both of these health bars were written this way so as you could gradually change the health of a player using an image like a picture of a person etc
that you have previously loaded (ie Img and img3 with the two different images you plan to use). They both use 2 sprites to do this and 3 images
Because Sprite 1 is created before Sprite 2 it works otherwise you would have to use the SetSpriteDepth command to place Sprite 2 in front of Sprite 1.

A Radial Health Bar could be done similar to this gradually hiding the sprite beneath. This isn't a perfected method and there
are better radial ones on the forum including the use of shaders, its just a quick example to show how it could be done.
+ Code Snippet
SetWindowTitle( "Radial Health Bar" )
SetWindowSize( 1024, 768 , 0 )
SetWindowAllowResize( 1 ) // allow the user to resize the window
 
// set display properties
SetVirtualResolution( 1024, 768 ) // doesn't have to match the window
SetOrientationAllowed( 0, 0, 1, 1 ) // allow only landscape on mobile devices
SetSyncRate( 30, 0 ) // 30fps instead of 60 to save battery
SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts
#constant progressStartX=768
#constant progressStartY=0
#constant progressEndX=1024:rem this should be progressStartX+width of sprites my width and height is 256
#constant progressEndY=255:rem this should be progressStartY+height of sprites

radialTextureID=CreateProgressRadial()
radialTextureID2=clearProgressRadial()
//SetImageTransparentColor(radialTextureID,0,0,0 )
//SetImageTransparentColor(radialTextureID2,0,0,0 )

CreateSprite(3,0) //this could use any image you have loaded that you wish to hide with your radial progress bar
SetSpriteSize(3,255,255)
SetSpriteColor(3,0,255,0,255)
CreateSprite(1,radialTextureID)
CreateSprite(2,radialTextureID2)
SetSpritePosition(1,progressStartX,progressStartY)
SetSpritePosition(2,progressStartX,progressStartY)
SetSpritePosition(3,progressStartX,progressStartY)
SetSpriteDepth(1,1)
SetSpriteDepth(2,2)
SetSpriteDepth(3,5)
SetSpriteVisible(1,0)
SetSpriteVisible(2,0)

SetClearColor(0,0,0)
angle#=0:ammount=0
repeat 
	if angle#<ammount
		SetSpriteVisible(1,1):SetSpriteVisible(2,1)
		angle#=angle#+1
		SetSpriteAngle(1,angle#)
		tempImg=progressRadial()
		DeleteImage(radialTextureID2)
		CopyImage(radialTextureID2,tempImg,0,0,255,255) 
		SetSpriteimage(2,radialTextureID2)
	else
		if angle#>=360
			angle#=0:ammount=0
			SetSpriteVisible(1,0)
			tempImg=clearProgressRadial()
			DeleteImage(radialTextureID2)
			CopyImage(radialTextureID2,tempImg,0,0,255,255)
			SetSpriteimage(2,radialTextureID2)
			SetSpriteVisible(2,0)
		endif
	endif
	if GetRawKeyPressed(32) then ammount = ammount +45
	if Ammount>360 then ammount=0
	Print("Press Space bar to take some health")
sync()
until GetRawKeyPressed(27)

function clearProgressRadial()
	SetClearColor(0,0,0)
    ClearScreen()
	DrawBox (progressStartX,progressStartY,progressEndX,progressEndY,MakeColor(0,0,0),MakeColor(0,0,0),MakeColor(0,0,0),MakeColor(0,0,0),1)
    Render()
    img = getimage(progressStartX,progressStartY,255,255)
	SetImageTransparentColor(img,0,0,0 )
    Swap() 
endfunction img

function createProgressRadial()
    SetClearColor(0,0,0)
    ClearScreen()
	//DrawBox (124,0,130,128,MakeColor(255,255,255),MakeColor(255,255,255),MakeColor(255,255,255),MakeColor(255,255,255),1)
    DrawBox (progressStartX+124,progressStartY+0,progressStartX+130,progressStartY+128,MakeColor(1,1,1),MakeColor(1,1,1),MakeColor(1,1,1),MakeColor(1,1,1),1)
    Render()
    img = getimage(progressStartX,progressStartY,255,255)
	SetImageTransparentColor(img,0,0,0 )
    Swap() 
 endfunction img
 

function progressRadial()
	SetClearColor(0,0,0)
    ClearScreen()
    DrawSprite(1)
    Render()
    img = getimage(progressStartX,progressStartY,255,255)
    //Swap()  	
 endfunction img

In the above the most distant back ground might be an animated sprite ie a heart pumping blood etc

A Simpler Horizontal Health Bar If you don't have a sprite youd like to hide or show as a background sprite its much easier to have a progress bar
+ Code Snippet
SetWindowTitle( "Progress Bar" )
SetWindowSize( 1024, 768 , 0 )
SetWindowAllowResize( 1 ) // allow the user to resize the window
  
// set display properties
SetVirtualResolution( 1024, 768 ) // doesn't have to match the window
SetOrientationAllowed( 0, 0, 1, 1 ) // allow only landscape on mobile devices
SetSyncRate( 30, 0 ) // 30fps instead of 60 to save battery
SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts
 
img=createTexture(MakeColor(0,255,0))  //this could replaced with a healthy image of your sprite you want to use
img3=createTexture(MakeColor(255,0,0)) //this could be replaced with the total dead image

CreateSprite(1,0)
CreateSprite(2,0)
SetSpriteSize(1,200,20)
SetSpriteSize(2,200,20)
SetSpriteColor(1,0,255,0,255)
SetSpriteColor(2,255,0,0,255)
SetSpritePosition(1,0,0)
SetSpritePosition(2,0,0)
ammount=0:time#=0
repeat
    elapsedTime#=timer()-time#
    if ammount<=getSpriteWidth(1) and elapsedTime#>=.25
		inc ammount
		SetSpriteSize(2,ammount,20)
	else
		if ammount>=GetSpriteWidth(1)
			ammount=0
			SetSpriteSize(2,ammount,20)
		endif
	endif
	sync()
until GetRawKeyPressed(27)
Posted: 2nd Jun 2018 3:39
Retrieve the color at x,y location on screen
+ Code Snippet
Function pickColor(X,Y)
	rem prepare image grab area
	clearScreen()
	setScissor(X,Y,X+1,Y+1)
	render()

	rem get image
	img = getImage(X,Y,X+1,Y+1)

	rem create memblock
	mem = createMemblockfromImage(img)

	rem get memblock data
	r = getMemblockbyte(mem,12):rem gets red channel data
	g = getMemblockbyte(mem,13):rem gets green channel data
	b = getMemblockbyte(mem,14):rem gets blue channel data
	s$ = str(r)+","+str(g)+","+str(b)

	rem tidy up
	deletememblock(mem)
	deleteimage(img)
	setScissor(0,0,getDeviceWidth(),getDeviceHeight())
	clearScreen()
endfunction s$

Some string handling routine can be used to get the red or green or blue values individiualy

or if you just want the color for use with drawing commands
+ Code Snippet
Function pickColor(X,Y)
 
    //color as integer
    rem prepare image grab area
    clearScreen()
    setScissor(X,Y,X+1,Y+1)
    render()
  
    img = getImage(X,Y,X+1,Y+1)
  
    rem create memblock
     
    mem = createMemblockfromImage(img)
  
    rem get memblock data
    r = getMemblockbyte(mem,12):rem gets red channel data
    g = getMemblockbyte(mem,13):rem gets green channel data
    b = getMemblockbyte(mem,14):rem gets blue channel data
  
     
    rem tidy up
    deletememblock(mem)
    deleteimage(img)
    setScissor(0,0,getDeviceWidth(),getDeviceHeight())
    clearScreen()
    color = makeColor(r,g,b)
    //color=0
endfunction color
Posted: 2nd Jun 2018 15:27
why are you returning the color value as a string and not dword/integer?
Posted: 2nd Jun 2018 16:50
why are you returning the color value as a string and not dword/integer?

at the time when I created that routine I wanted to output the red green blue values as a string
but it has been handy doing it that way for other effects and I am not sure if I return as a Dword
how I would address individual values doing it with a Dword. When I came across someone with
a problem on the forums I dug that routine up out of my code snippets and thought I would share
here
Posted: 4th Jun 2018 14:34
To extract the colors:

alpha = (color && 0xFF000000) >> 24
red = (color && 0x00FF0000) >> 16
green = (color && 0x0000FF00) >> 8
blue = color && 0x000000FF


To put them back together:
color = (alpha*16777216)+(red*65536)+(green*256)+blue


Technically, you wouldn't need the bitwise AND to extract the alpha but I put it in there to help demonstrate the pattern of how it's working. First, we mask the component we want, then we shift over to the first byte in the integer leaving everything else in the last 3 bytes empty.
Posted: 20th Jun 2018 3:41
A growing tree using draw commands and a Fractal formula demonstrating recursion

+ Code Snippet
// set window properties
SetWindowTitle( "Fractal Math" )
SetWindowSize( 1024, 768, 0 )
SetSyncRate(30,0) ` 

// set display properties
SetVirtualResolution( 1024, 768 )
length#=1
do
if length#<250 then length#=length#+.25	//grows at the rate of.25 increase the number to grow faster
cantor2(512,768,length#,270) //draws a growing tree
Sync()
loop

function cantor2(x as float,y as float,length as float,ang as integer)
local x2 as float
local y2 as float
if length>1	
  x2= length * cos(ang) + x //calculate endx point given length and angle 
  y2= length * sin(ang) + y //calculate endy point given length and angle
  DrawLine(x,y,x2,y2,MakeColor(255,255,255),MakeColor(255,255,255))
  cantor2(x2,y2,length/1.5,ang+15)
  cantor2(x2,y2,length/1.5,ang-15)
  
  //if you change the above to this it will add some randomness but if you 
  //try to draw gradually with the draw command it will appear as if there is wind
  //cantor2(x2,y2,length/1.5,ang+random(10,15))
  //cantor2(x2,y2,length/1.5,ang-random(10,15))
endif
endfunction



Adding some randomness to produce 3 prettier trees with varying thickness

+ Code Snippet
// set window properties
SetWindowTitle( "Fractal Math" )
SetWindowSize( 1024, 768, 0 )
SetSyncRate(30,0) ` 

// set display properties
SetVirtualResolution( 1024, 768 )
spr=CreateSprite(0)
SetSpriteSize(spr,100,1)
SetSpriteOffset(spr,0,0)
Render()
cantor2(512,768,250,40,270) //draws a tree
cantor2(266,768,200,40,270) //produces another smaller tree
cantor2(778,768,200,40,270) //produces yet another smaller tree
Swap()
img = getimage(0,0,1024,768)
sprite=CreateSprite(img)
length#=1
do
 
Sync()
loop

function cantor2(x as float,y as float,length as float,thickness as float,ang as integer)
local x2 as float
local y2 as float
if length>1	
  x2= length * cos(ang) + x //calculate endx point given length and angle 
  y2= length * sin(ang) + y //calculate endy point given length and angle
  for thick=-thickness/2 to thickness/2 step 1
	DrawLine(x+thick,y,x2+thick,y2,MakeColor(255,255,255),MakeColor(255,255,255))
  next thick
  cantor2(x2,y2,length/1.5,thickness/1.5,ang+random(20,45))
  cantor2(x2,y2,length/1.5,thickness/1.5,ang-random(20,45))
endif
endfunction

The next step to the above is to try varying thickness with the use of a sprite pasting it to an image
0110 The sprite being designed something like it is to the left with 1 being white black being 0
1111 That would allow the branches to get smaller but without the previous branches last thickness showing (best to try the above if you aren't sure what I mean)
Replacing the drawline command and loop in the cantor function to something like
+ Code Snippet
   SetSpriteAngle(sprDraw,ang)
  SetSpriteSize(sprDraw,thickness,length)
  SetSpritePosition(sprDraw,x,y)
  DrawSprite(sprDraw)
This could be used with the render to image capabilities of AppGameKit or using getimage to make even better trees (something to try)

If you change the cantor function to below you can control how many recursions
+ Code Snippet
function cantor2(x as float,y as float,length as float,recursions as integer,maxRecursions as integer,ang as integer)
local x2 as float
local y2 as float
if length>1	and recursions<maxRecursions
  x2= length * cos(ang) + x //calculate endx point given length and angle 
  y2= length * sin(ang) + y //calculate endy point given length and angle
  DrawLine(x,y,x2,y2,MakeColor(255,255,255),MakeColor(255,255,255))
  cantor2(x2,y2,length/1.5,recursions+1,maxRecursions,ang+random(10,15))
  cantor2(x2,y2,length/1.5,recursions+1,maxRecursions,ang-random(10,15))
  
  //if you change the above to this it will add some randomness but if you 
  //try to draw gradually with the draw command it will appear as if there is wind
  //cantor2(x2,y2,length/1.5,ang+random(10,15))
  //cantor2(x2,y2,length/1.5,ang-random(10,15))
endif
endfunction


an example of controlling the recursion can be done with the following
+ Code Snippet
cantor2(512,100,200,0,3,80) //3recursions
cantor2(266,100,200,0,2,80) //2 recursions
cantor2(778,100,200,0,1,80) //1 recursion
Posted: 20th Jun 2018 6:56
I cant see what these look like as of now cause at work, but will certainly take a look later. Maybe very good to go onto a 3D Plane with transparency for the air spaces... interesting...

Well done.

Posted: 20th Jun 2018 7:10
Thanks @Puzzler
I really was curious how a lightning effect could be produced, I wasn't even sure AppGameKit would support recursion.
It sure does support recursion and the tree effect kinda produces a line drawn tree with branches. If I can get a
lightning design im happy with I just might try a shader to produces 2d lightning
Posted: 29th Jun 2018 17:55
For those interested in the above tree fractal may like this
Fern Fractal
Converted to AppGameKit from Phaelax's Darkbasic code found here https://forum.thegamecreators.com/thread/80144
+ Code Snippet
//https://forum.thegamecreators.com/thread/80144
SetWindowTitle( "Fractal Math" )
SetWindowSize( 1024, 768, 0 )
SetSyncRate(30,0) ` 
 
// set display properties
SetVirtualResolution( 1024, 768 )
createShader() //only needed the first time program is run
LoadSpriteShader(1,"blurr.ps") 
Render()
fern(512,668,7,90,7,50,150)
fern(511,668,7,90,7,50,150)
fern(513,668,7,90,7,50,150)
fern(510,668,7,90,7,50,150)
fern(514,668,7,90,7,50,150)
DrawLine(512,668,512,768,MakeColor(55,255,55),MakeColor(55,255,55))
DrawBox (510,668,514,768,MakeColor(55,255,55),MakeColor(55,255,55),MakeColor(55,255,55),MakeColor(55,255,55),1)

Swap()
img = getimage(0,0,1024,768)
sprite=CreateSprite(img)
SetSpriteShader(sprite,1)
SetShaderConstantByName(1,"size",1024.0,768.0,4.0,0.0) //if you don't want it blurred comment out this line works as follows //x sprite size, y sprite size, blur ammout ,0.0 needed
repeat
   Sync()
until GetRawKeyPressed(32) //spacebar

end


REM ====== FERN FRACTAL =======
REM X,Y         - starting position for fern, root of first stem
REM passes      - number of iterations
REM startAngle  - angle to start drawing on this pass
REM bendAngle   - overall bending angle of the whole leaf
REM branchAngle - angle to branch off each stem at
REM height      - starting height
function fern(x as float, y as float, passes as integer, startAngle as float, bendAngle as float, branchAngle as float, height as float)
   rootAngle# = wrapvalue(startAngle - bendAngle)

   x2 = x + cos(rootAngle#)*height
   y2 = y - sin(rootAngle#)*height
   DrawLine(x,y,x2,y2,MakeColor(55,255,55),MakeColor(55,255,55))

   height = height*0.5

   x3 = x + cos(wrapvalue(rootAngle#+branchAngle))*height
   y3 = y - sin(wrapvalue(rootAngle#+branchAngle))*height
   DrawLine(x,y,x3,y3,MakeColor(55,255,55),MakeColor(55,255,55))

   x4 = x + cos(wrapvalue(rootAngle#-branchAngle))*height
   y4 = y - sin(wrapvalue(rootAngle#-branchAngle))*height
   DrawLine(x,y,x4,y4,MakeColor(55,255,55),MakeColor(55,255,55))

   if passes > 1
      fern(x2,y2,passes-1, rootAngle#, bendAngle, branchAngle, height)
      fern(x3,y3,passes-1, wrapvalue(rootAngle#+branchAngle), bendAngle, branchAngle, height)
      fern(x4,y4,passes-1, wrapvalue(rootAngle#-branchAngle), bendAngle, branchAngle, height)
   endif

endfunction

function wrapvalue(num as float)
	while num>360
		num=num-360
	endwhile
endfunction num

function createShader()

file = OpenToWrite("blurr.ps")
WriteLine(file,"uniform sampler2D texture0;")
WriteLine(file,"varying mediump vec2 uvVarying;")
WriteLine(file,"varying mediump vec4 colorVarying;")
WriteLine(file,"uniform vec4 size; // ")
WriteLine(file,"mediump vec2 uOff = vec2(1.0/size.x,0.0); // these can be changed to match the size of the texture/pixel size")
WriteLine(file,"mediump vec2 vOff = vec2(0.0,1.0/size.y);")
WriteLine(file,"//float size = 1.0; // 5 gives 100 samples used to get ONE pixel!   (2x5x2x5 = 100)")
WriteLine(file,"float x;")
WriteLine(file,"float y;")
WriteLine(file,"float mult= 1.0/4.0/size.z/size.z; //scale factor")
WriteLine(file,"void main()")
WriteLine(file,"{")
WriteLine(file,"	for (y = -size.z; y<size.z; y++)  // a range of 2*size on y")
WriteLine(file,"	{")
WriteLine(file,"		for (x = -size.z; x<size.z; x++)  // a range of 2*size on x")
WriteLine(file,"		{")
WriteLine(file,"			gl_FragColor += texture2D(texture0, uvVarying+(x*uOff)+(y*vOff)); ")
WriteLine(file,"		}")
WriteLine(file,"	}")
WriteLine(file,"	gl_FragColor *= mult; // scale the colour down by 1/100th as we have added up 100 pxels worth!")
WriteLine(file,"}")
CloseFile(file)
endfunction


Using the Fern code to create a 3D Shrub with planes
+ Code Snippet
//https://forum.thegamecreators.com/thread/80144
SetWindowTitle( "Fractal Math" )
SetWindowSize( 1024, 768, 0 )
SetSyncRate(30,0) ` 
 
// set display properties
SetVirtualResolution( 1024, 768 )
SetClearColor(0,0,0)

SetCameraPosition(1,0,0,-150)
SetCameraLookAt(1,0,0,0,0)
CreateShrub(1,100,100)  //there are 4 objects that make up a shrub therefore the second must start at 5
CreateShrub(5,100,100)
SetObjectPosition(1,-40,0,0)
SetObjectPosition(5,40,0,0)
repeat
	RotateObjectGlobalY(1,.2)  //rotate the two shrubs differently so you can check them out 
	RotateObjectGlobalX(5,.2)
	
    Sync()
until GetRawKeyPressed(32) //spacebar

end


function createShrub(objectNum as integer, xSize as float,ySize as float)
ClearScreen()
Render()
fern(256,668,7,90,7,50,150)
fern(255,668,7,90,7,50,150)
fern(257,668,7,90,7,50,150)
fern(254,668,7,90,7,50,150)
fern(258,668,7,90,7,50,150)
DrawLine(256,668,256,768,MakeColor(55,255,55),MakeColor(55,255,55))
DrawBox (254,668,258,768,MakeColor(55,255,55),MakeColor(55,255,55),MakeColor(55,255,55),MakeColor(55,255,55),1)

Swap()
img = getimage(0,320,512,768)

CreateObjectPlane(objectNum,xSize,ySize)
InstanceObject(objectNum+1,objectNum)
InstanceObject(objectNum+2,objectNum)
InstanceObject(objectNum+3,objectNum)
SetObjectPosition(objectNum,0,0,0)
SetObjectPosition(objectNum+1,0,0,0)
SetObjectPosition(objectNum+2,0,0,0)
SetObjectPosition(objectNum+3,0,0,0)
SetObjectRotation(objectNum,0,0,0)
SetObjectRotation(objectNum+1,0,45,0)
SetObjectRotation(objectNum+2,0,90,0)
SetObjectRotation(objectNum+3,0,135,0)
SetObjectImage(objectNum,img,0)
SetObjectImage(objectNum+1,img,0)
SetObjectImage(objectNum+2,img,0)
SetObjectImage(objectNum+3,img,0)
SetObjectTransparency(objectNum,1)
SetObjectTransparency(objectNum+1,1)
SetObjectTransparency(objectNum+2,1)
SetObjectTransparency(objectNum+3,1)
FixObjectToObject(objectNum+1,objectNum)
FixObjectToObject(objectNum+2,objectNum)
FixObjectToObject(objectNum+3,objectNum)
	
endfunction

REM ====== FERN FRACTAL =======
REM X,Y         - starting position for fern, root of first stem
REM passes      - number of iterations
REM startAngle  - angle to start drawing on this pass
REM bendAngle   - overall bending angle of the whole leaf
REM branchAngle - angle to branch off each stem at
REM height      - starting height
function fern(x as float, y as float, passes as integer, startAngle as float, bendAngle as float, branchAngle as float, height as float)
   rootAngle# = wrapvalue(startAngle - bendAngle)

   x2 = x + cos(rootAngle#)*height
   y2 = y - sin(rootAngle#)*height
   DrawLine(x,y,x2,y2,MakeColor(55,255,55),MakeColor(55,255,55))

   height = height*0.5

   x3 = x + cos(wrapvalue(rootAngle#+branchAngle))*height
   y3 = y - sin(wrapvalue(rootAngle#+branchAngle))*height
   DrawLine(x,y,x3,y3,MakeColor(55,255,55),MakeColor(55,255,55))

   x4 = x + cos(wrapvalue(rootAngle#-branchAngle))*height
   y4 = y - sin(wrapvalue(rootAngle#-branchAngle))*height
   DrawLine(x,y,x4,y4,MakeColor(55,255,55),MakeColor(55,255,55))

   if passes > 1
      fern(x2,y2,passes-1, rootAngle#, bendAngle, branchAngle, height)
      fern(x3,y3,passes-1, wrapvalue(rootAngle#+branchAngle), bendAngle, branchAngle, height)
      fern(x4,y4,passes-1, wrapvalue(rootAngle#-branchAngle), bendAngle, branchAngle, height)
   endif

endfunction

function wrapvalue(num as float)
	while num>360
		num=num-360
	endwhile
endfunction num


Using my Fractal Tree algorithm to create a dead looking 3D Tree with planes
+ Code Snippet
//https://forum.thegamecreators.com/thread/80144
SetWindowTitle( "Fractal Math" )
SetWindowSize( 1024, 768, 0 )
SetSyncRate(30,0) ` 
 
// set display properties
SetVirtualResolution( 1024, 768 )
SetClearColor(0,0,0)

SetCameraPosition(1,0,0,-150)
SetCameraLookAt(1,0,0,0,0)
CreateTree(1,100,100)  //there are 4 objects that make up a tree therefore the second must start at 5
CreateTree(5,100,100)
SetObjectPosition(1,-40,0,0)
SetObjectPosition(5,40,0,0)
repeat
	RotateObjectGlobalY(1,.2)  //rotate the two trees differently so you can check them out 
	RotateObjectGlobalX(5,.2)
	
    Sync()
until GetRawKeyPressed(32) //spacebar

end


function createTree(objectNum as integer, xSize as float,ySize as float)
ClearScreen()
Render()
cantor2(512,768,250,40,270) //draws a tree
Swap()
img = getimage(0,0,1024,768)

CreateObjectPlane(objectNum,xSize,ySize)
InstanceObject(objectNum+1,objectNum)
InstanceObject(objectNum+2,objectNum)
InstanceObject(objectNum+3,objectNum)
SetObjectPosition(objectNum,0,0,0)
SetObjectPosition(objectNum+1,0,0,0)
SetObjectPosition(objectNum+2,0,0,0)
SetObjectPosition(objectNum+3,0,0,0)
SetObjectRotation(objectNum,0,0,0)
SetObjectRotation(objectNum+1,0,45,0)
SetObjectRotation(objectNum+2,0,90,0)
SetObjectRotation(objectNum+3,0,135,0)
SetObjectImage(objectNum,img,0)
SetObjectImage(objectNum+1,img,0)
SetObjectImage(objectNum+2,img,0)
SetObjectImage(objectNum+3,img,0)
SetObjectTransparency(objectNum,1)
SetObjectTransparency(objectNum+1,1)
SetObjectTransparency(objectNum+2,1)
SetObjectTransparency(objectNum+3,1)
FixObjectToObject(objectNum+1,objectNum)
FixObjectToObject(objectNum+2,objectNum)
FixObjectToObject(objectNum+3,objectNum)
	
endfunction

function cantor2(x as float,y as float,length as float,thickness as float,ang as integer)
local x2 as float
local y2 as float
if length>1  
  x2= length * cos(ang) + x //calculate endx point given length and angle 
  y2= length * sin(ang) + y //calculate endy point given length and angle
  for thick=-thickness/2 to thickness/2 step 1
    DrawLine(x+thick,y,x2+thick,y2,MakeColor(71,25,0),MakeColor(71,35,0))
  next thick
  cantor2(x2,y2,length/1.5,thickness/1.5,ang+random(20,45))
  cantor2(x2,y2,length/1.5,thickness/1.5,ang-random(20,45))
endif
endfunction
Posted: 29th Jun 2018 18:36
Thats cool

Here is a Barnsley Fern if you like me to add stuff here too

+ Code Snippet
// Project: BarnsleyFern 
// Created: 2018-06-29

// show all errors
SetErrorMode(2)

// set window properties
SetWindowTitle( "BarnsleyFern" )
SetWindowSize( 1024, 768, 0 )
SetWindowAllowResize( 1 ) // allow the user to resize the window

// set display properties
SetVirtualResolution( 1024, 768 ) // doesn't have to match the window
SetOrientationAllowed( 1, 1, 1, 1 ) // allow both portrait and landscape on mobile devices
SetSyncRate( 30, 0 ) // 30fps instead of 60 to save battery
SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts


x# as float
y# as float
nextX# as float
nextY# as float
rand as float
size# = 50

for loops=1 to 100000

	DrawLine(1024/2+x#*size#,768/2-y#*size#,1024/2+x#*size#,768/2-y#*size#,MakeColor(0,random(100,250),0),MakeColor(random(100,250),random(100,250),0))

rand = random(1,100)

//1
if rand < 10
	nextX# = 0
	nextY# = 0.16 * y#
else
	//2
	if rand < 86 
		
		nextX# = 0.85 * x# + 0.04 * y#
		nextY# = -0.04 * x# + 0.85 * y# + 1.6
	else
		//3
		if rand<93 
			nextX# = 0.20 * x# + -0.26 * y#
			nextY# = 0.23 * x# + 0.22 * y# + 1.6
		else

			//4 
			nextX# = -0.15 * x# + 0.28 * y#
			nextY# = 0.26 * x# + 0.24  * y# +0.44
		endif
	endif
endif


x# = NextX#

y# = NextY#


next
print("Done")
sync()
sleep(10000)



do
    

    Print( ScreenFPS() )
    Sync()
loop


Posted: 29th Jun 2018 19:24
Thanks Puzzler your most welcome to post code and comment etc

The Barnsley fern looks very good

Think the Barnsley Fern algorithm could be used to create a fern garden with a mixture of plane objects scattered about perhaps
with some tiling of the texture similarly to the way I created the 3D tree and 3D shrub above. I think that would be allot easier to
do with modelling software which kinda defeats the purpose with what I am trying to achieve here, That is create models, textures
etc with code. As a fractal example its fantastic tho and appreciate the sharing of the code.

I may use the tree and shrub in something lol not sure what yet. Maybe a code challenge as they usually require everything to be
created with code
Posted: 30th Jun 2018 14:53
2D Water Ripple

+ Code Snippet

// Project: 2D water 
// Created: 2018-06-30

// show all errors
SetErrorMode(2)

// set window properties
SetWindowTitle( "2D water" )
SetWindowSize( 1024, 768, 0 )
SetWindowAllowResize( 1 ) // allow the user to resize the window

// set display properties
SetVirtualResolution( 1024, 768 ) // doesn't have to match the window
SetOrientationAllowed( 1, 1, 1, 1 ) // allow both portrait and landscape on mobile devices
SetSyncRate( 30, 0 ) // 30fps instead of 60 to save battery
SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts

#constant cols = 200
#constant rows = 200

global current as float [rows,cols]
global previous as float [rows,cols]
global temp as float [rows,cols]
global dampening#, spread# as float 

// change these values for effect changes
dampening# = 0.9
spread# = 2


// position a starting pixel
current[rows/2,cols/2] = 255


time# = timer()
do
    updateripple()
    
    if timer()-time# > 1 
		time#= timer()
		current[random(1,rows),random(1,rows)] = 255
	endif

   // Print( ScreenFPS() )
    Sync()
loop


function updateripple()
	for x = 1 to cols-1
		for y=1 to rows-1
			current[x,y] = ( previous[x-1,y] + previous [ x + 1, y] + previous [ x , y - 1 ] + previous [ x, y + 1 ] ) / 2  - current[x,y]
			
			current[x,y] = current[x,y] * dampening#
			
			DrawLine(x*spread#,y*spread#,x*spread#,y*spread#,MakeColor(0,current[x,y],0),MakeColor(0,current[x,y],0))
				
		next
	next

	temp = previous
	previous = current
	current = temp
	
endfunction


Change the dampening and spread for other effects

eg
dampening# = 0.9
spread# = 2
Posted: 30th Jun 2018 18:52
Love the water Ripple @Puzzler

Using Pixel or Fragment Shaders
https://steamcommunity.com/sharedfiles/filedetails/?id=370165947

I converted that pixel shader to show on a 3D Plane
You can now have a transparency texture added to the second texture and it will not draw where there is transparency
+ Code Snippet
#constant screenWidth=1024
#constant screenHeight=768

SetWindowSize(screenWidth,screenHeight,0)
Setvirtualresolution(screenWidth,screenHeight)
// set variables for camera's starting position
pos_x# = 0
pos_y# = 50
pos_z# = 0
createEllipseForPortals(2)

// orientate camera
SetCameraRotation(1,30,0,0)
SetCameraPosition(1,pos_x#,pos_y#,pos_z#)
CreateObjectPlane(2,500,500)
SetObjectRotation(2,90,0,0)
SetObjectPosition(2,0,-17,250)
//dont set a second image if you dont want to have transparency layer added where any color that isnt transparent makes use of the Kali
SetObjectImage(2,2,1) 
SetObjectTransparency(2,1) //needed or the transparency will show as black on the object
createShader()
Shader=LoadShader( "Kaliset.vs","Kaliset.ps" )
SetObjectShader(2,Shader)
SetShaderConstantByName( Shader,"iResolution",500,500,0,0 )
do

    SetShaderConstantByName( Shader,"iGlobalTime",Timer()*.5,0,0,0 ) `tell the shader what time it is - so it can update its animations
    print(ScreenFPS())
    sync()
loop
function createEllipseForPortals(img as integer)
	rem create an ellipse that can be used as a sprite 
	SetClearColor(0,0,0)
	ClearScreen()
    Render()
    DrawBox(0,0,100,100,MakeColor(0,0,0),MakeColor(0,0,0),MakeColor(0,0,0),MakeColor(0,0,0),1)
    DrawEllipse(50,50,50,50,MakeColor(255,255,255),MakeColor(255,255,255),1)
    DrawEllipse(50,50,20,20,MakeColor(0,0,0),MakeColor(0,0,0),1) //comment out this line if you dont like donuts lol
    
    Swap()
    getimage(img,0,0,100,100)
    SetImageTransparentColor(img,0,0,0)
    sync()
endfunction 

function createShader()
//create the shader used for the port holes	
if GetFileExists("Kaliset.vs") then DeleteFile("Kaliset.vs")		
file = OpenToWrite("Kaliset.vs")
WriteLine(file,"attribute highp vec3 position;")
WriteLine(file,"attribute mediump vec3 normal;")
WriteLine(file,"attribute mediump vec2 uv;")
WriteLine(file,"varying highp vec3 posVarying;")
WriteLine(file,"varying mediump vec3 normalVarying;")
WriteLine(file,"varying mediump vec2 uv0Varying;")
WriteLine(file,"varying mediump vec2 uv1Varying;")
WriteLine(file,"varying mediump vec3 lightVarying;")
WriteLine(file,"uniform vec3 iResolution; // viewport resolution (in pixels)")
WriteLine(file,"uniform float iGlobalTime; // shader playback time (in seconds)")
WriteLine(file,"uniform float iChannelTime[10]; // channel playback time (in seconds)")
WriteLine(file,"uniform vec3 iChannelResolution[10]; // channel resolution (in pixels)")
WriteLine(file,"//uniform vec4 iMouse; // mouse pixel coords. xy: current (if MLB down)")
WriteLine(file,"uniform sampler2D texture0; // input channel")
WriteLine(file,"uniform vec4 iDate; // (year, month, day, time in seconds)")
WriteLine(file,"uniform highp mat3 agk_WorldNormal;")
WriteLine(file,"uniform highp mat4 agk_World;")
WriteLine(file,"uniform highp mat4 agk_ViewProj;")
WriteLine(file,"uniform mediump vec4 uvBounds0;")
WriteLine(file,"uniform mediump vec4 uvBounds1;")
WriteLine(file,"mediump vec3 GetVSLighting( mediump vec3 normal, highp vec3 pos );")
WriteLine(file,"void main()")
WriteLine(file,"{") 
WriteLine(file,"    uv0Varying = uv * uvBounds0.xy + uvBounds0.zw;")
WriteLine(file,"    uv1Varying = uv * uvBounds1.xy + uvBounds1.zw;")
WriteLine(file,"    highp vec4 pos = agk_World * vec4(position,1.0);")
WriteLine(file,"    gl_Position = agk_ViewProj * pos;")
WriteLine(file,"    mediump vec3 norm = normalize(agk_WorldNormal * normal);")
WriteLine(file,"    posVarying = pos.xyz;")
WriteLine(file,"    normalVarying = norm;")
WriteLine(file,"    lightVarying = GetVSLighting( norm, posVarying );")
WriteLine(file,"}") 
CloseFile(file)

if GetFileExists("Kaliset.ps") then DeleteFile("Kaliset.ps")	
file = OpenToWrite("Kaliset.ps")
WriteLine(file,"uniform vec3 iResolution; // viewport resolution (in pixels)")
WriteLine(file,"uniform float iGlobalTime; // shader playback time (in seconds)")
WriteLine(file,"uniform float iChannelTime[10]; // channel playback time (in seconds)")
WriteLine(file,"")
WriteLine(file,"//uniform vec4 iMouse; // mouse pixel coords. xy: current (if MLB down)")
WriteLine(file,"uniform sampler2D texture0; // input channel ")
WriteLine(file,"uniform sampler2D texture1; // input channel ")
WriteLine(file,"uniform vec4 iDate; // (year, month, day, time in seconds)")
WriteLine(file,"varying mediump vec2 uv0Varying;")
WriteLine(file,"varying mediump vec2 uv1Varying;")
WriteLine(file,"const int iterations=12;")
WriteLine(file,"void main(void)")
WriteLine(file,"{")
WriteLine(file,"//this takes the pixel we are working with to determine where it is on the screen")
//WriteLine(file,"vec2 z = gl_FragCoord.xy/iResolution.xy;")
WriteLine(file,"vec2 z = uv0Varying;")
WriteLine(file,"//fixes aspect ratio in favor of symmety. comment it and see what it looks like")
WriteLine(file,"//z.y*=iResolution.y/iResolution.x;")
WriteLine(file,"//gloobywavez")
WriteLine(file,"z.x += sin(z.y*2.0+iGlobalTime * .2)/10.0;")
WriteLine(file,"//zooom")
WriteLine(file,"//z*= 1.2 + sin(iGlobalTime*.15);")
WriteLine(file,"//pan")
WriteLine(file,"//z+=vec2(sin(iGlobalTime*.2),cos(iGlobalTime*.01));")
WriteLine(file,"//rotate")
WriteLine(file,"//z=vec2(z.x*cos(iGlobalTime*.2)- z.y*sin(iGlobalTime*.2),z.y*cos(iGlobalTime*.2));")
WriteLine(file,"vec2 c=vec2(0.5, 1.1);")
WriteLine(file,"")
WriteLine(file,"float average=0.;")
WriteLine(file,"float l=length(z);")
WriteLine(file,"float prevl;")
WriteLine(file,"for (int i=0; i<iterations; i++)")
WriteLine(file,"{")
WriteLine(file,"//kaliset base form")
WriteLine(file,"z=abs(z)/dot(z,z) -c;")
WriteLine(file,"//this is another function that can be iterated to produce some different fractals")
WriteLine(file,"//comment out the previous kaliset and experiment with values with this one!!")
WriteLine(file,"//z = abs(z)/(z.x*z.y)-c;")
WriteLine(file,"prevl=l;")
WriteLine(file,"l=length(z);")
WriteLine(file,"average+=abs(l-prevl);")
WriteLine(file,"}")
WriteLine(file,"//get the average length based upon the amount of iterations elapsed. multiply it to adjust definition")
WriteLine(file,"average/=float(iterations) * 15.;")
WriteLine(file,"//color fluctuation")
WriteLine(file,"average+=iGlobalTime*0.08;")
WriteLine(file,"vec3 myColor=vec3(0.2,0.21,.62);")
WriteLine(file,"vec3 finalColor;")
WriteLine(file,"//set the colors!")
WriteLine(file,"finalColor.r = (fract(float(average)/myColor.r));")
WriteLine(file,"finalColor.g = (fract(float(average)/myColor.g));")
WriteLine(file,"finalColor.b = (fract(float(average)/myColor.b));")
WriteLine(file,"vec4 colorResult1  = texture2D(texture1, uv1Varying);") 
WriteLine(file,"gl_FragColor = mix(colorResult1,vec4(finalColor,1.0), colorResult1.a);")
WriteLine(file,"}") 
CloseFile(file)
endfunction
Posted: 1st Jul 2018 1:45
A small random 3D world of fractals and Kaleidoscopes

What started as a test is turning out to be a minigame
Using a character Controller and physics, spawns enemies that can be shot
and these are shown on a radar and uses particle effects on enemy shot

At the moment levels increase every 5 Kills
Which increases the movement speed of the enemy exponentially with log
and decreases the spawn time. There is a bonus level once you reach level 5

+ Code Snippet
//Definition of a porthole
//A porthole consists of at least two structural components and is, in its simplest form, 
//similar to any other type of window in design and purpose. The porthole is primarily a 
//circular glass disk, known as a 'portlight', encased in a metal frame that is bolted 
//securely into the side of a ship's hull.
//by definition  a porthole is a tunnel for light
//The word "portal" in science fiction and fantasy generally refers to a technological or 
//magical doorway that connects two distant locations separated by spacetime. It usually 
//consists of two or more gateways, with an object entering one gateway leaving via the 
//other instantaneously.

#constant screenWidth =1024 //The screemwidth 
#constant screenHeight=768  //the screen height
#constant KEY_LEFT    = 37  //the left arrow key scancode
#constant KEY_UP      = 38  //the up arrow key scancode
#constant KEY_RIGHT   = 39  //the right arrow key scancode
#constant KEY_DOWN    = 40  //the down arrow key scancode
#constant KEY_A       = 65  //the scan code for the "a" key	
#constant KEY_D       = 68	//the scan code for the "d" key	
#constant KEY_S       = 83	//the scan code for the "s" key	
#constant KEY_W       = 87	//the scan code for the "w" key	
#constant KEY_Z       = 90  //the scan code for the "z" key
#constant KEY_SPACE	  = 32  //the space bar
#constant KEY_ENTER	  = 13  //the enter key
#constant KEY_ESCAPE  = 27  //the escape key used to exit program
#constant KEY_T       = 84
#constant leftWall	  = 1   //object ID of left wall   
#constant rightWall   = 2   //object ID of right wall
#constant ground      = 3	//object ID of ground
#constant backWall	  = 4 	//object ID of back wall
#constant frontWall   = 5	//object ID of front wall
#constant portal 	  = 6   //start objects id there are 4 in total
#constant bonusLeftWall = 10   //object ID of the bonus level left wall   
#constant bonusRightWall= 11   //object ID of the bonus level right wall
#constant bonusGround   = 12   //object ID of the bonus level ground
#constant bonusPortal   = 13   //object ID of the bonus level ground
#constant fruitStart    = 600 //Where bonus fruit IDs start 
#constant obstacleStart = 700 //where the obstacle IDs on the bonus level start
#constant shrubStart    = 14  //where shrub object ids start
#constant shrubCount   = 40  //how many shrubs there are
#constant treeStart	   = 216 //where tree object ids start NOTE starts 1 greater than (shrubcount*5)+shrubstart 
#constant treeCount    = 20  //how many tree objects there are
#constant playerObj    = 500 //object ID of player
#constant crossHair	   = 1	//The Cross Hair mouse sprite ID
#constant radarSpr	   = 2	//the square white box used for radar
#constant playerSpr    = 3	//Player sprite on the radar ID
#constant bookFront	   = 400//object ID of the book front cover	
#constant bookCoverImg = 400//the image Id of the book front cover
#constant bookPages1   = 401//object ID of book page 1
#constant bookPages1Img= 401//The image ID of book page 1
#constant bookPages2   = 402//object ID of the book page 2
#constant bookPages2Img= 402//The image ID of the book page 2
#constant bookPages3   = 403//object ID of the book page 3
#constant bookPages3Img= 403//The image Id of the book page 3
#constant bookPages4   = 404//object ID of the book page 4
#constant bookPages4Img= 404//The image Id of the book page 4
#constant bookBack     = 405//object ID of the back cover of the book
#constant bookBackImg  = 405//the image ID of the back cover of book
#constant playerGunObj = 501//The player gun object ID its invisible but location is used to shooy from
#constant bulletLife   = 3  //time to keep bullets alive
#constant Shader	   = 1  //the shader ID
#constant textLevel	   = 1  //current level text id
#Constant helpMessage  = 2  //help messages starter iD there are 3
#constant camOff_y#    =15  //Camera y offset
#constant spawnStartTime=5.0//The start time to wait for spawning enemies
#constant spawnMinTime=1.0  //the minimum enemies have to wait before spawning
#constant killsToLevel=5    //ammount of kills needed for level increase
#constant texture1		=500//ground texture ID
#constant texture2		=501//the brick texture ID
#constant texture3		=502//the particles texture ID
#constant texture4		=503//an ellipse surrounded by transparency imageID used for portals (texture1 of the shader masking layer)
#constant texture5		=504//Just a texture ID used with the shader used for portals (texture2 of the shader is used to replaced transparent part in texture1)

SetWindowTitle( "The Splendid Book of Portals" ) 
SetScreenResolution(screenWidth,screenHeight)
Setvirtualresolution(screenWidth,screenHeight)
create3DPhysicsWorld()

//the type used for bonus fruit
type object 
    objMesh as integer
    objMem as integer
    maxVertex as integer
endtype

//used for the moving obstacles in the bonus tunnel
type obstacle
	ID as integer
	direction as integer
endtype 

// the type used for bullets  
type bullet
    ID as integer
    time as float // a time used because bullets die over time
endtype

//the type used for enemy
type enemy
    ID as integer 		//the ID of the spawned enemy
    sprID as integer	//the sprite ID so as its location on radar can be shown
endtype	

global myBullet as bullet[0] //we start with no bullets but use an array that we can insert more
global myEnemy as enemy[0]	 //we start with no enemy but use an array that we can insert more
global myObstacles as obstacle[0]		

global bulletCount=0 //keeps track of the ammount of bullets currently alive used for processing
global enemyCount=0  //keeps track of the ammount of enemy currently alive used for processing
//used for camera angle on the yAxis
global camAngle_x#   //the x angle of the camera
global camAngle_y#   //the y angle of the camera
camAngle_x#=wrapvalue(GetPointerY()) //get the pointer y location and wrap in a 360 degree range
camAngle_y#=wrapvalue(GetPointerX()) //get the pointer x location and wrap in a 360 degree range
createShader() //used to create the shader
LoadShader(Shader, "Kaliset.vs","Kaliset.ps" ) //shaders need to be loaded
startStory():SetPrintColor(255,255,255) //display book and set print color back to white
createtexture(texture1,512,512, makecolor(55,155,55),256) //creates the ground texture
createWallTexture(texture2)   //creates a brick texture 
createEllipse(texture3)       //creates particle explosion texture
createEllipseForPortals(texture4)
CreateWindow(texture5) //creates the texture for around the edge of portals in arena 
createArena() //creates play game arena 
CreateCharacterController(200):Step3DPhysicsWorld()  

//Set the shader to all of the porthole objects there are 4
for num = 0 to 3
	SetObjectShader(portal+num,Shader)
next num
SetShaderConstantByName( Shader,"iResolution",100,100,0,0 ) //set the dimentions of the shader
SetObjectShader(bonusPortal,Shader)
//create some shrubs and randomly position then in play arena
for num = shrubStart to (shrubCount*5)+shrubStart step 5
	CreateShrub(num,30,30)  //there are 4 objects that make up a tree therefore the second must start at 5
	SetObjectPosition(num,random2(-200,200),-15,random2(100,500))
	SetObjectCollisionMode(num,0)
	SetObjectCollisionMode(num+1,0)
	SetObjectCollisionMode(num+2,0)
	SetObjectCollisionMode(num+3,0)
next num

//create some trees and position them randomly in the arena
for num = treeStart to (treeCount*5)+treeStart step 5
	CreateTree(num,60,80)  //there are 4 objects that make up a tree therefore the second must start at 5
	SetObjectPosition(num,random2(-200,200),0,random2(100,500))
	SetObjectCollisionMode(num,0)
	SetObjectCollisionMode(num+1,0)
	SetObjectCollisionMode(num+2,0)
	SetObjectCollisionMode(num+3,0)
	
	//Create a collision object
	//CreateObjectCylinder(num+1+(treeCount*5),20,4,20)
	//SetObjectPosition(num+1+(treeCount*5),GetObjectX(num),GetObjectY(num)-10,GetObjectZ(num))
	//SetObjectVisible(num+1+(treeCount*5),0)
	//SetObjectCollisionMode(num+1+(treeCount*5),1)
	//Create3DPhysicsStaticBody(num+1+(treeCount*5)) 
	//SetObject3DPhysicsRestitution(num+1+(treeCount*5),10)
next num

SetRawMousePosition(screenWidth*.5,screenheight*.5) //position the pointer at the centre of screen		
global messagesFlag=1 //the variable used for displaying the messages in game set to zero for no messages

repeat
	if getpointerpressed() 
		If GetSpriteExists(radarSpr) then SetSpriteVisible(radarSpr,1)
		If GetSpriteExists(playerSpr) then SetSpriteVisible(playerSpr,1)
		playGame()
	endif
	sync()
until GetRawKeyState(KEY_ESCAPE)

end 

function playGame()
radarImg=radar()
createSprite(radarSpr,radarImg)
SetSpritePosition(radarSpr,screenWidth-101,1)
CreateSprite(playerSpr,0):SetSpriteImage(playerSpr,createPlayerSprImage()):SetSpriteSize(playerSpr,5,5):SetSpriteColor(playerSpr,0,255,0,255):SetSpriteTransparency(playerSpr,1)	
	
SetRawMouseVisible(0) //hide the mouse pointer
SetCameraRotation(1,0,0,0)	//set the camera locations so as we can see the book
SetCameraPosition(1,0,0,-20)
teleport(-1) //teleport =1 for clockwise =-1 for anticlockwise
DeleteSprite(crossHair):CreateSprite(crossHair,createCrossHair())
SetSpritePositionByOffset(crossHair,screenWidth*.5,ScreenHeight*.5)
for num3=1 to enemyCount //make sure there are no enemies left from previous game
	DeleteObject(myEnemy[num3].ID)
	DeleteSprite(myEnemy[num3].sprID)
	myEnemy.remove(num3)
	dec enemyCount
next num3
for num=1 to bulletCount  //delete any left over bullets from previous game
	DeleteObject(myBullet[num].ID)
	myBullet.remove(num)
	dec bulletCount
next num

//create a fading level text
CreateText(textLevel,"Level ")
SetTextSize(textLevel,50)
SetTextPosition(textLevel,(screenWidth*.5)-75,300)
SetTextColor(textLevel,255,255,255,255)
SetTextVisible(textLevel,0)
SetTextString(textLevel,"Level "+str(Level) )
SetTextVisible(textLevel,1):iAlpha=255
SetTextColorAlpha(textLevel, iAlpha )
//the messages that are used in game 
if messagesFlag=1
	CreateText(helpMessage,"")
	CreateText(helpMessage+1,"")
	CreateText(helpMessage+2,"")
	SetTextSize(helpMessage,50)
	SetTextSize(helpMessage+1,50)
	SetTextSize(helpMessage+2,50)
	SetTextPosition(helpMessage,(screenWidth*.5)-220,100)
	SetTextPosition(helpMessage+1,(screenWidth*.5)-220,150)
	SetTextPosition(helpMessage+2,(screenWidth*.5)-220,200)
endif
//set camera rotation to where the arena is location
SetCameraRotation(1,camangle_x#,GetObjectWorldAngleY(playerObj),GetObjectWorldAngleZ(playerObj) ) 
SetCameraPosition(1,GetObjectWorldX(playerObj),GetObjectWorldY(playerObj)+camOff_y#,GetObjectWorldZ(playerObj))
sync():time#=timer():messageTime#=timer():global lives=5:global kills=0:global level=1:Global enemySpeed#=.5:global iAlpha:alpha=255:flag=1
global spawnTime#=spawnStartTime:global ranSpeed#:ranSpeed#=((log(level))+0.50):global fruit=0 //calculate an exponential speed increase for the enemy
repeat
	updatePlayerMovement(50)
	updateEnemy()

	for num=1 to enemyCount
		//check if any ebenmy has collided with the player
		collID=checkCollision(myEnemy[num].ID) 
		if collID=playerObj
			DeleteObject(myEnemy[num].ID)
			DeleteSprite(myEnemy[num].sprID)
			myEnemy.remove(num)
			dec enemyCount
			dec lives
			exit
		endif
	next num
	if GetRawKeyPressed(KEY_T) then playBonusLevel() 
	
	//There is no limit to bullets but a timer of bulletlife for how long they live
	for num=1 to bulletCount
		if (myBullet[num].time)+bulletLife<timer() 
			DeleteObject(myBullet[num].ID)
			myBullet.remove(num)
			dec bulletCount
		endif
	next num

	//spawn a new enemy every spawntime
	if timer()>(time#+spawnTime#)
		spawnEnemy(random(portal,portal+3))
		time#=timer()
	endif
	
	if messagesFlag=1
	if alpha>1
		dec alpha
		SetTextColorAlpha(helpMessage,alpha)
		SetTextColorAlpha(helpMessage+1,alpha)
		SetTextColorAlpha(helpMessage+2,alpha)
	elseif flag=1 and timer()>messageTime#+5
			SetTextString(helpMessage,"I already want to go")
			SetTextString(helpMessage+1,"home there is nothing")
			SetTextString(helpMessage+2,"here.")
			alpha=255:flag=2:messageTime#=timer()		
	elseif flag=2 and timer()>messageTime#+6
			SetTextString(helpMessage,"There seems to be")
			SetTextString(helpMessage+1,"4 Portals which")
			SetTextString(helpMessage+2,"one is the way home")
			alpha=255:flag=3:messageTime#=timer()
	elseif flag=3 and timer()>messageTime#+4
			SetTextString(helpMessage,"What are these box")
			SetTextString(helpMessage+1,"things coming from")
			SetTextString(helpMessage+2,"the Portals")
			alpha=255:flag=4:messageTime#=timer()
	elseif flag=4 and timer()>messageTime#+5
			SetTextString(helpMessage,"This is some kind of")
			SetTextString(helpMessage+1,"robot battle arena.")
			SetTextString(helpMessage+2,"Get me out of here")
			alpha=255:flag=5:messageTime#=timer()	
	elseif flag=5 and timer()>messageTime#+6
			SetTextString(helpMessage,"There has to be some ")
			SetTextString(helpMessage+1,"end to the ammount of")
			SetTextString(helpMessage+2,"Robots coming")
			alpha=255:flag=6:messageTime#=timer()
	elseif flag=6 and timer()>messageTime#+6
			SetTextString(helpMessage,"That dam scientist ")
			SetTextString(helpMessage+1,"tricked me. When I ")
			SetTextString(helpMessage+2,"I find him %&&^%%.")
			alpha=255:flag=7:messageTime#=timer()			
	elseif flag=7 and timer()>messageTime#+6
			SetTextString(helpMessage,"These portals seem ")
			SetTextString(helpMessage+1,"to be one way only. ")
			SetTextString(helpMessage+2,"There must be way out.")
			alpha=255:flag=8:messageTime#=timer()			
	elseif flag=8 and timer()>messageTime#+10
			SetTextString(helpMessage,"Im getting tired and ")
			SetTextString(helpMessage+1,"still no way out.")
			SetTextString(helpMessage+2,"")
			alpha=255:flag=9:messageTime#=timer()			
	endif
	endif	
 	
 	if iAlpha>2 then iAlpha=iAlpha-2
	SetTextColorAlpha(textLevel, iAlpha )
	
	//set camera and its offsets in relation to the players position
	SetCameraRotation(1,camangle_x#,GetObjectWorldAngleY(playerObj),GetObjectWorldAngleZ(playerObj) ) 
    SetCameraPosition(1,GetObjectWorldX(playerObj),GetObjectWorldY(playerObj)+camOff_y#,GetObjectWorldZ(playerObj))
    SetShaderConstantByName( Shader,"iGlobalTime",Timer()*.5,0,0,0 ) `tell the shader what time it is - so it can update its animations
	print(ScreenFPS())
	print("Level="+str(level))
	print("Lives="+str(lives))
	print("Kills="+str(kills))
	sync()
until GetRawKeyState(KEY_ESCAPE) or lives <=1

DeleteSprite(radarSpr):
DeleteText(textLevel):DeleteText(helpMessage):DeleteText(helpMessage+1):DeleteText(helpMessage+2)	
//set camera back to the locations where book is visible
SetCameraRotation(1,0,0,0)	
SetCameraPosition(1,0,0,-20)
teleport(1):gameOver():messagesFlag=0
SetRawMouseVisible(1) //the mouse is now visible this makes more sence when clicking playgame
endfunction

function updateEnemy()
	//update all enemy locations and check for collisions with player bullets
	for num=1 to enemyCount
		//gets the angle between you and the enemy 
		ang# = GetAngle(getObjectX(myEnemy[num].ID),getObjectZ(myEnemy[num].ID),getObjectX(playerObj),getObjectZ(playerObj))
		//points the enemy toward you which is the difference between your location and the above angle
		SetObjectRotation(myEnemy[num].ID,0,0,0)	
		RotateObjectGlobalY(myEnemy[num].ID,difference(ang#,GetObjectWorldAngleY(myEnemy[num].ID)) ) 
		MoveObjectLocalZ( myEnemy[num].ID, -enemySpeed# )
		if GetObject3DPhysicsFirstContact(myEnemy[num].ID) //check if the enemy has had contact 
            while GetObject3DPhysicsNextContact() 
            contactObjB  = GetObject3DPhysicsContactObjectB()
			     
            for num2=1 to bulletCount
				if contactObjB=myBullet[num2].ID   //enemy has been shot destroy them and bullet
					partID=Create3DParticles( getObjectX(myBullet[num2].ID),getObjectY(myBullet[num2].ID),getObjectZ(myBullet[num2].ID) ) 
					Set3DParticlesDirection( partID, 0,2, 0, 0 ) 
					Set3DParticlesDirectionRange( partID,275,45  ) 
					Set3DParticlesImage(partID,texture3)
					Set3DParticlesSize(partID,6)
					Set3DParticlesLife(partID,5.5)
					Set3DParticlesVelocityRange(partID,1,10)
					Set3DParticlesMax(partID,50)
					DeleteObject(myBullet[num2].ID)
					myBullet.remove(num2)
					dec bulletCount
					DeleteObject(myEnemy[num].ID)
					DeleteSprite(myEnemy[num].sprID)
					myEnemy.remove(num)
					dec enemyCount
					inc kills
					Update3DParticles( partID,0 ) 
					if mod(kills,killsToLevel) =0
						inc level
						if mod(level,5)=0 then playBonusLevel() 
						ranSpeed#=((log(level))+0.50) //calculate an exponential speed increase for the enemy
						if ranSpeed#>2.5 then ranSpeed#=2.5
						SetTextString(textLevel,"Level "+str(Level) )
						SetTextVisible(textLevel,1):iAlpha=255
						SetTextColorAlpha(textLevel, iAlpha )
						for num3=1 to enemyCount
							DeleteObject(myEnemy[num3].ID)
							DeleteSprite(myEnemy[num3].sprID)
							myEnemy.remove(num3)
							dec enemyCount
						next num3
						spawnTime#=SpawnTime#-.5
						if spawnTime#<spawnMinTime then spawnTime#=spawnMinTime
					endif
					exitfunction
				endif
			next num2
			endwhile
		endif
		//position the enemy sprite on radar
		x#=GetObjectX(myEnemy[num].ID)+250:x#=(x#/500)*100:x#=100-x#:x#=screenWidth-x#
		y#=(GetObjectZ(myEnemy[num].ID)-50):y#=(y#/500)*100:y#=100-y#:
		SetSpritePosition(myEnemy[num].sprID,x#,y#)
				
	next num
endfunction
function checkCollision(object)
//this checks for colliion between an object with any other object and returns its id
width#=50
height#=20 
depth#=50 
 
x#=getObjectWorldX(object)
y#=GetObjectWorldY(object)
z#=getObjectWorldZ(object)
// calculate the start of the ray cast
start_x# = x#-width#
start_y# = y#+height#
start_z# = z#-depth# 
// calculate the end of the ray cast
end_x# = x#+width#   
end_y# = y#-height#
end_z# = z#+depth# 
// determine which object has been hit
object_hit = ObjectRayCast(0,start_x#,start_y#,start_z#,end_x#,end_y#,end_z#)
endfunction object_hit 	

//used to calculate a direction angle to point objects to an object
function getAngle(x1#, y1#, x2#, y2#)
    //result# = ATanFull(x1# - x2#, y1# - y2#)
	result# = ATan2(x1# - x2#,y1# - y2#)
endfunction result#

function updatePlayerMovement(velocity as float)
	//update the player movement in the direction of the following keys
	local old as integer
	
	camAngle_x#=GetPointerY()
	camAngle_y#=GetPointerX()
	
	//rotate the player object in relation to pointer x if pointerx <10 then add 360 if pointerx too far right yake 360
	if camAngle_y#>=10 and camAngle_y#<=(screenWidth-10)
		Rotate3DPhysicsCharacterController(playerObj,camAngle_y#) 
	elseif camAngle_y#<10 
		camAngle_y#=camAngle_y#+360
		SetRawMousePosition(camAngle_y#,camAngle_x#) 
		Rotate3DPhysicsCharacterController(playerObj,camAngle_y#) 
	elseif camAngle_y#>(screenWidth-10) 
		camAngle_y#=camAngle_y#-360
		SetRawMousePosition(camAngle_y#,camAngle_x#) 		
		Rotate3DPhysicsCharacterController(playerObj,camAngle_y#) 
	endif
	
	if GetRawKeyState(KEY_LEFT)  //strafe left
		Move3DPhysicsCharacterController(playerObj,3,velocity)
		old=3
	endif
	if GetRawKeyState(KEY_RIGHT)  //strafe right
		Move3DPhysicsCharacterController(playerObj,4,velocity)
		old=4
	endif
	
	if GetRawKeyState(KEY_UP) //move forward
		Move3DPhysicsCharacterController(playerObj,1,velocity)
		old=1
	endif
	
	if GetRawKeyState(KEY_DOWN) //move backwards
		Move3DPhysicsCharacterController(playerObj,2,velocity)
		old=2
	endif
	
	if GetrawkeyPressed(KEY_SPACE) or GetRawMouseRightPressed() //jump
		Jump3DPhysicsCharacterController(playerObj)
	endif
	
	if GetrawkeyPressed(KEY_ENTER) or GetPointerPressed() //shoot
		ThrowBall( 1000.0, 10.0)
	endif
	Step3DPhysicsWorld() //needs to be called prior to below and any camera adjustments
	
	select old //the following is used to reset the movement back to zero if player moved this turn otherwise it continuely moves
		case 1
			Move3DPhysicsCharacterController(playerObj,1,0)
		endcase
		case 2
			Move3DPhysicsCharacterController(playerObj,2,0)
		endcase 
		case 3
			Move3DPhysicsCharacterController(playerObj,3,0)
		endcase 
		case 4
			Move3DPhysicsCharacterController(playerObj,4,0)
		endcase 
    endselect
	x#=GetObjectX(playerObj)+250:x#=(x#/500)*100:x#=100-x#:x#=screenWidth-x#
	y#=(GetObjectZ(playerObj)-50):y#=(y#/500)*100:y#=100-y#
	SetSpriteAngle(playerSpr,GetObjectAngleY(playerObj)) 
	SetSpritePosition(playerSpr,x#,y#)
endfunction 

function difference(x as float ,y as float)
diff as float
diff = (x-y)
endfunction diff

function CreateCharacterController(z as integer)
	//create the character controller of the player its invisible but needed for physics
	DeleteObject(playerObj)
	CreateObjectBox(playerObj,20,20,20)
	SetObjectPosition(playerObj,0,-10,z)
		
	SetObjectVisible(playerObj,0) 
    characterOffsetVec = CreateVector3( 0.0, 2.5, 0.0 )
    objectOrientationVec = CreateVector3( 0.0, 0.0, 0.0 )
    Delete3DPhysicsCharacterController(playerObj)
	Create3DPhysicsCharacterController(playerObj, 1, characterOffsetVec, objectOrientationVec, .90 )
    DeleteVector3( characterOffsetVec )
    DeleteVector3( objectOrientationVec )
    
    CreateObjectBox(playerGunObj,20,20,20)
	SetObjectPosition(playerGunObj,GetObjectWorldX(playerObj),GetObjectWorldY(playerObj)+camOff_y#,GetObjectWorldZ(playerObj))
	SetObjectVisible(playerGunObj,0) 
endfunction

function createArena()
//create the game world arena
CreateObjectBox(leftWall,2,502,502 ) 
SetObjectImage(leftWall,texture2,0)
SetObjectPosition(leftWall,-250,232,300)
Create3DPhysicsStaticBody(leftWall) 
 
CreateObjectBox(rightWall,2,502, 502 ) 
SetObjectImage(rightWall,texture2,0)
SetObjectPosition(rightWall,250,232,300)
Create3DPhysicsStaticBody(rightWall) 
 
CreateObjectBox(ground,502,1, 502 ) 
SetObjectImage(ground,texture1,0)
SetObjectPosition(ground,0,-18,300)
Create3DPhysicsStaticBody(ground) 
 
CreateObjectBox(backWall,502, 502,2 ) 
SetObjectImage(backWall,texture2,0)
SetObjectPosition(backWall,0,232,550)
Create3DPhysicsStaticBody(backWall) 

CreateObjectBox(frontWall,502, 502,2 ) 
SetObjectImage(frontWall,texture2,0)
SetObjectPosition(frontWall,0,232,50)
Create3DPhysicsStaticBody(frontWall) 

CreateObjectBox(bonusLeftWall,2,502,1500 ) 
SetObjectImage(bonusLeftWall,texture2,0)
SetObjectPosition(bonusLeftWall,-50,232,1300)
Create3DPhysicsStaticBody(bonusLeftWall) 

CreateObjectBox(bonusRightWall,2,502,1500 ) 
SetObjectImage(bonusRightWall,texture2,0)
SetObjectPosition(bonusRightWall,50,232,1300)
Create3DPhysicsStaticBody(bonusRightWall) 

CreateObjectBox(bonusGround,502,1, 1500 ) 
SetObjectImage(bonusGround,texture1,0)
SetObjectPosition(bonusGround,0,-18,1300)
Create3DPhysicsStaticBody(bonusGround) 

CreateObjectBox(bonusPortal,100,100,2 ) 
SetObjectImage(bonusPortal,texture1,0)
SetObjectPosition(bonusPortal,0,32,2000)
SetObjectImage(bonusPortal,texture4,1)
SetObjectImage(bonusPortal,texture5,2)

Create3DPhysicsStaticBody(bonusPortal) 

CreateObjectPlane(portal,100,100)
SetObjectImage(portal,texture1,0)
SetObjectImage(portal,texture4,1) //the second texture used for masking out bits
SetObjectImage(portal,texture5,2) 
//SetObjectTransparency(portal,1)   //used so as the transparent bits with the above part dont show
SetObjectRotation(portal,0,-90,0)
SetObjectPosition(portal,-248,50,300)
SetObjectCollisionMode(portal,0)

InstanceObject(portal+1,portal)
SetObjectImage(portal+1,texture1,0)
SetObjectImage(portal+1,texture4,1) //the second texture used for masking out bits
SetObjectImage(portal+1,texture5,2) 
//SetObjectTransparency(portal+1,1)   //used so as the transparent bits with the above part dont show
SetObjectRotation(portal+1,0,-90,0)
SetObjectPosition(portal+1,248,50,300)
SetObjectCollisionMode(portal+1,0)

InstanceObject(portal+2,portal)
SetObjectImage(portal+2,texture1,0)
SetObjectImage(portal+2,texture4,1) //the second texture used for masking out bits
SetObjectImage(portal+2,texture5,2) 
//SetObjectTransparency(portal,1)   //used so as the transparent bits with the above part dont show
SetObjectRotation(portal+2,0,0,0)
SetObjectPosition(portal+2,0,50,548)
SetObjectCollisionMode(portal+2,0)

InstanceObject(portal+3,portal)
SetObjectImage(portal+3,texture1,0)
SetObjectImage(portal+3,texture4,1) //the second texture used for masking out bits
SetObjectImage(portal+3,texture5,2) 
//SetObjectTransparency(portal+3,1)   //used so as the transparent bits with the above part dont show
SetObjectRotation(portal+3,0,0,0)
SetObjectPosition(portal+3,0,50,52)
SetObjectCollisionMode(portal+3,0)

endfunction

function createShrub(objectNum as integer, xSize as float,ySize as float)
ClearScreen()
Render()
fern(256,668,7,90,7,50,150)
fern(255,668,7,90,7,50,150)
fern(257,668,7,90,7,50,150)
fern(254,668,7,90,7,50,150)
fern(258,668,7,90,7,50,150)
DrawLine(256,668,256,768,MakeColor(55,255,55),MakeColor(55,255,55))
DrawBox (254,668,258,768,MakeColor(55,255,55),MakeColor(55,255,55),MakeColor(55,255,55),MakeColor(55,255,55),1)
Swap()
img = getimage(0,320,512,768)

//a Shrub is made up of 4 planeobjects 
CreateObjectPlane(objectNum,xSize,ySize)
InstanceObject(objectNum+1,objectNum)
InstanceObject(objectNum+2,objectNum)
InstanceObject(objectNum+3,objectNum)
SetObjectPosition(objectNum,0,0,0)
SetObjectPosition(objectNum+1,0,0,0)
SetObjectPosition(objectNum+2,0,0,0)
SetObjectPosition(objectNum+3,0,0,0)
SetObjectRotation(objectNum,0,0,0)
SetObjectRotation(objectNum+1,0,45,0)
SetObjectRotation(objectNum+2,0,90,0)
SetObjectRotation(objectNum+3,0,135,0)
SetObjectImage(objectNum,img,0)
SetObjectImage(objectNum+1,img,0)
SetObjectImage(objectNum+2,img,0)
SetObjectImage(objectNum+3,img,0)
SetObjectTransparency(objectNum,1)
SetObjectTransparency(objectNum+1,1)
SetObjectTransparency(objectNum+2,1)
SetObjectTransparency(objectNum+3,1)
FixObjectToObject(objectNum+1,objectNum)
FixObjectToObject(objectNum+2,objectNum)
FixObjectToObject(objectNum+3,objectNum)
     
endfunction

REM ====== FERN FRACTAL =======
REM X,Y         - starting position for fern, root of first stem
REM passes      - number of iterations
REM startAngle  - angle to start drawing on this pass
REM bendAngle   - overall bending angle of the whole leaf
REM branchAngle - angle to branch off each stem at
REM height      - starting height
function fern(x as float, y as float, passes as integer, startAngle as float, bendAngle as float, branchAngle as float, height as float)
   rootAngle# = wrapvalue(startAngle - bendAngle)
 
   x2 = x + cos(rootAngle#)*height
   y2 = y - sin(rootAngle#)*height
   DrawLine(x,y,x2,y2,MakeColor(255,255,5),MakeColor(255,255,5))
 
   height = height*0.5
 
   x3 = x + cos(wrapvalue(rootAngle#+branchAngle))*height
   y3 = y - sin(wrapvalue(rootAngle#+branchAngle))*height
   DrawLine(x,y,x3,y3,MakeColor(55,255,55),MakeColor(55,255,55))
 
   x4 = x + cos(wrapvalue(rootAngle#-branchAngle))*height
   y4 = y - sin(wrapvalue(rootAngle#-branchAngle))*height
   DrawLine(x,y,x4,y4,MakeColor(55,255,55),MakeColor(55,255,55))
 
   if passes > 1
      fern(x2,y2,passes-1, rootAngle#, bendAngle, branchAngle, height)
      fern(x3,y3,passes-1, wrapvalue(rootAngle#+branchAngle), bendAngle, branchAngle, height)
      fern(x4,y4,passes-1, wrapvalue(rootAngle#-branchAngle), bendAngle, branchAngle, height)
   endif
 
endfunction
 
function createTree(objectNum as integer, xSize as float,ySize as float)
ClearScreen()
Render()
cantor2(512,768,250,40,270) //draws a tree
Swap()
img = getimage(0,0,1024,768)

// a tree is made up of four planeobjects  
CreateObjectPlane(objectNum,xSize,ySize)
InstanceObject(objectNum+1,objectNum)
InstanceObject(objectNum+2,objectNum)
InstanceObject(objectNum+3,objectNum)
SetObjectPosition(objectNum,0,0,0)
SetObjectPosition(objectNum+1,0,0,0)
SetObjectPosition(objectNum+2,0,0,0)
SetObjectPosition(objectNum+3,0,0,0)
SetObjectRotation(objectNum,0,0,0)
SetObjectRotation(objectNum+1,0,45,0)
SetObjectRotation(objectNum+2,0,90,0)
SetObjectRotation(objectNum+3,0,135,0)
SetObjectImage(objectNum,img,0)
SetObjectImage(objectNum+1,img,0)
SetObjectImage(objectNum+2,img,0)
SetObjectImage(objectNum+3,img,0)
SetObjectTransparency(objectNum,1)
SetObjectTransparency(objectNum+1,1)
SetObjectTransparency(objectNum+2,1)
SetObjectTransparency(objectNum+3,1)
FixObjectToObject(objectNum+1,objectNum)
FixObjectToObject(objectNum+2,objectNum)
FixObjectToObject(objectNum+3,objectNum)   
endfunction

//the cantor function used for creating a tree texture 
function cantor2(x as float,y as float,length as float,thickness as float,ang as integer)
local x2 as float
local y2 as float
if length>1  
  x2= length * cos(ang) + x //calculate endx point given length and angle 
  y2= length * sin(ang) + y //calculate endy point given length and angle
  for thick=-thickness/2 to thickness/2 step 1
    DrawLine(x+thick,y,x2+thick,y2,MakeColor(71,25,0),MakeColor(71,35,0))
  next thick
  cantor2(x2,y2,length/1.5,thickness/1.5,ang+random(20,45))
  cantor2(x2,y2,length/1.5,thickness/1.5,ang-random(20,45))
endif
endfunction

//wraps the value passed into a 360 degree range and returns thye new value  
function wrapvalue(num as float)
    while num>360
        num=num-360
    endwhile
endfunction num

//used to create grass texture
function createtexture(imgID as integer,sizex# as float, sizey# as float, color, density as integer)
    swap()
    drawbox(0,0,sizex#, sizey#, color, color,color,color, 1)
    render()
    img = getimage(0,0,sizex#, sizey#)
        
    memblockid = CreateMemblockFromImage (img)
    imgwidth = GetMemblockInt(memblockid, 0)
    imgheight = GetMemblockInt(memblockid, 4)
        
    size=GetMemblockSize(memblockid)
    for offset=12 to size-4 step 4
          
        r=GetMemblockByte(memblockid, offset)
        g=GetMemblockByte(memblockid, offset+1)
        b=GetMemblockByte(memblockid, offset+2)
        a=GetMemblockByte(memblockid, offset+3)
                
            
        strength=random(1,density)
    
        SetMemblockByte (memblockid, offset, r-strength)
        SetMemblockByte (memblockid, offset+1, g-strength)
        SetMemblockByte (memblockid, offset+2, b-strength )
        SetMemblockByte (memblockid, offset+3, a-strength)
    next
    deleteimage (img)
    CreateImageFromMemblock(imgID,memblockid)
    DeleteMemblock(memblockid)
endfunction 

//creates the border around the radar
function radar()
	SetClearColor(0,0,0)
	ClearScreen()
    Render()
    DrawBox(0,0,100,100,MakeColor(255,255,255),MakeColor(255,255,255),MakeColor(255,255,255),MakeColor(255,255,255),0) 
    Swap()
    img = getimage(0,0,102,102)
    sync()
endfunction img

function createEllipse(img as integer)
	rem create an ellipse that can be used as a sprite 
	SetClearColor(0,0,0)
	ClearScreen()
    Render()
    //DrawBox(0,0,100,100,MakeColor(255,255,255),MakeColor(255,255,255),MakeColor(255,255,255),MakeColor(255,255,255),1)
    DrawEllipse(75,75,25,25,MakeColor(55,55,55),MakeColor(55,55,55),1)
    Swap()
    getimage(img,0,0,100,100)
    sync()
endfunction 

function createEllipseForPortals(img as integer)
	SetClearColor(0,0,0)
	ClearScreen()
    Render()
    DrawBox(0,0,512,512,MakeColor(0,0,0),MakeColor(0,0,0),MakeColor(0,0,0),MakeColor(0,0,0),1)
    DrawEllipse(256,256,248,248,MakeColor(255,255,255),MakeColor(255,255,255),1)
    //DrawEllipse(256,256,64,64,MakeColor(0,0,0),MakeColor(0,0,0),1)
    Swap()
    getimage(img,0,0,512,512)
    SetImageTransparentColor(img,0,0,0)
    sync()
endfunction 

function CreateWindow(img as integer)
	SetClearColor(0,0,0)
	ClearScreen()
    Render()
    DrawBox(0,0,512,512,MakeColor(102,178,255),MakeColor(102,178,255),MakeColor(102,178,255),MakeColor(102,178,255),1)
    
    DrawBox(0,0,512,6,MakeColor(102,51,0),MakeColor(102,51,0),MakeColor(102,51,0),MakeColor(102,51,0),1)
    DrawBox(0,0,6,512,MakeColor(102,51,0),MakeColor(102,51,0),MakeColor(102,51,0),MakeColor(102,51,0),1)
    DrawBox(0,496,512,512,MakeColor(102,51,0),MakeColor(102,51,0),MakeColor(102,51,0),MakeColor(102,51,0),1)
    DrawBox(496,0,512,512,MakeColor(102,51,0),MakeColor(102,51,0),MakeColor(102,51,0),MakeColor(102,51,0),1)
    
    DrawBox(0,124,512,130,MakeColor(102,51,0),MakeColor(102,51,0),MakeColor(102,51,0),MakeColor(102,51,0),1)
    DrawBox(0,252,512,258,MakeColor(102,51,0),MakeColor(102,51,0),MakeColor(102,51,0),MakeColor(102,51,0),1)
    DrawBox(0,380,512,387,MakeColor(102,51,0),MakeColor(102,51,0),MakeColor(102,51,0),MakeColor(102,51,0),1)
    
    DrawBox(124,0,131,512,MakeColor(102,51,0),MakeColor(102,51,0),MakeColor(102,51,0),MakeColor(102,51,0),1)
    DrawBox(252,0,258,512,MakeColor(102,51,0),MakeColor(102,51,0),MakeColor(102,51,0),MakeColor(102,51,0),1)
    DrawBox(380,0,387,512,MakeColor(102,51,0),MakeColor(102,51,0),MakeColor(102,51,0),MakeColor(102,51,0),1)  
 
    Swap()
    getimage(img,0,0,512,512)
    //SetImageTransparentColor(img,0,0,0)
    sync()
endfunction	

function createPlayerSprImage()
	rem draw a triangle image used for the player sprite on radar
	SetClearColor(0,0,0)
	ClearScreen()
    Render()
    //DrawBox(0,0,10,10,MakeColor(0,0,0),MakeColor(0,0,0),MakeColor(0,0,0),MakeColor(0,0,0),1)
    DrawLine(5,0,9,9,makeColor(255,255,255),makeColor(255,255,255))
	DrawLine(0,9,9,9,makeColor(255,255,255),makeColor(255,255,255))
	DrawLine(0,9,5,0,makeColor(255,255,255),makeColor(255,255,255))
    swap()
    img = getimage(0,0,10,10)
    SetImageTransparentColor(img,0,0,0)
endfunction img
	

function createCrossHair()
	rem draw an ellipse that can be used as a sprite and returns the value of the image
	SetClearColor(0,0,0)
	ClearScreen()
    Render()
    DrawEllipse(50,50,25,25,MakeColor(200,0,0),MakeColor(200,0,0),0)
    DrawLine(25,50,75,50,200,0,0)
	DrawLine(50,25,50,75,200,0,0)

    Swap()
    img = getimage(0,0,100,100)
endfunction img

//creates wall texture
function createWallTexture(img as integer)
	ClearScreen()
    Render()
    DrawBox(0,0,512,512,MakeColor(155,155,155),MakeColor(155,155,155),MakeColor(155,155,155),MakeColor(155,155,155),1)
    x=-5:y=0:oldX=0
    repeat
		repeat
			DrawBox(x,y,x+5,y+1,MakeColor(155,5,5),MakeColor(155,5,5),MakeColor(155,5,5),MakeColor(155,5,5),1)
			x=x+6
		until x>512+5
		if oldx=-5
			x=-2:oldx=-2
		else
			x=-5:oldx=-5
		endif	
		y=y+3
	until y>512+2
    Swap()
    getimage(img,0,0,512,512)
    sync()
endfunction

function spawnEnemy(spawnLoc as integer) //the spawn location is at the portal location
	//offset Locations depending on which spawn location 
	local xOff as integer
	local yOff as integer
	local zOff as integer
	select spawnLoc
		case portal :
			xOff=0:yOff=-60:zOff=40
		endcase
		case (portal+1) :
			xOff=-40:yOff=-60:zOff=0
		endcase
		case (portal+2) :
			xOff=0:yOff=-60:zOff=-40
		endcase
		case (portal+3) :
			xOff=40:yOff=-60:zOff=0
		endcase
	endSelect
	
    enemy = CreateObjectBox(16,20,16)
    enemySpr=CreateSprite(0):SetSpriteSize(enemySpr,2,2):SetSpriteColor(enemySpr,255,0,0,255)
    setobjectrotation(enemy,0,0,0)
    SetObjectPosition( enemy, GetObjectX(spawnLoc)+xOff,GetObjectY(spawnLoc)+yOff,GetObjectZ(spawnLoc)+zOff )
    SetObjectColor(enemy,random(50,255),random(50,255),random(50,255),255)
    //SetObjectShader(enemy,Shader)
    SetObjectCollisionMode(enemy,1)
    //3D Physics code
    Create3DPhysicsDynamicBody( enemy )
    SetObjectShapeBox( enemy )
    myItem as enemy
    myItem.ID = enemy //the object id of the enemy
    myItem.sprID=enemySpr
	myEnemy.insert(myItem) //update bullet arrow as there is unlimeted bullets 
	inc enemyCount //used for a enemy counter to check if theyve timed out or not 
endfunction

function ThrowBall( initialSpeed as float, mass as float)
	//To move dynamic physics bodies we need to apply velocity to the physics body.
	gunPositionVec= CreateVector3(GetObjectWorldX(playerObj),GetObjectWorldY(playerObj)+camOff_y#,GetObjectWorldZ(playerObj)) //im using the camera position as the gun position 
    //Create a tempory projectile block to calculate movement vectors of bullets
    projectileDirBox as integer
    projectileDirBox = CreateObjectBox( 1.0, 1.0, 1.0 )
    SetObjectPosition( projectileDirBox, GetVector3X( gunPositionVec ), GetVector3Y( gunPositionVec ), GetVector3Z( gunPositionVec ) )
    setobjectrotation(projectiledirbox,camangle_x#,GetObjectWorldAngleY(playerObj),GetObjectWorldAngleZ(playerObj))
        
    MoveObjectLocalZ( projectileDirBox, 1.0 )
    projectileDirVec = CreateVector3( GetobjectWorldX( projectileDirBox )-GetVector3X( gunPositionVec ), GetobjectWorldY( projectileDirBox )-GetVector3Y( gunPositionVec ), GetobjectWorldZ( projectileDirBox )-GetVector3Z( gunPositionVec ) )
    DeleteObject( projectileDirBox )
    throwBall as integer    
    throwBall = CreateObjectSphere( 10, 16, 32 )
    SetObjectColor( throwBall, 255, 0,0,255 )
    SetObjectPosition( throwBall, GetVector3X( gunPositionVec ), GetVector3Y( gunPositionVec ), GetVector3Z( gunPositionVec ) )
    //3D Physics code
    Create3DPhysicsDynamicBody( throwBall )
    SetObjectShapeSphere( throwBall )
    SetObject3DPhysicsMass( throwBall, mass )
    SetObject3DPhysicsLinearVelocity( throwBall, projectileDirVec, initialSpeed )
    
    //SetObject3DPhysicsFriction( throwBall, 0.8 )
    //SetObject3DPhysicsRollingFriction( throwBall, 0.7 )
    //SetObject3DPhysicsCanSleep(throwBall,0)
    myItem as bullet
    myItem.ID = throwBall //the object id of the bullet
	myItem.time = timer()  //timer is used to set there life time as bullets will die off after so long
	myBullet.insert(myItem) //update bullet arrow as there is unlimeted bullets 
	inc bulletCount //used for a bullet counter to check if theyve timed out or not 
    deletevector3(projectileDirVec)
    deletevector3(gunPositionVec)
endfunction

function startStory()
local flag:flag=1	
//begin the story book by creating the cover and pages
CreateObjectBox(bookFront,10, 20, 0.1 )
createBookCover(bookCoverImg)
SetObjectImage(bookFront,bookCoverImg,0)
SetObjectPosition(bookFront,-5,10.0,.05)
FixObjectPivot(bookFront)
SetObjectPosition(bookFront,-5.0,-10.0,0)
SetObjectRotation(bookFront,0,180,0)
SetObjectCollisionMode(bookFront,0)

CreateObjectBox(bookPages1,10, 20,0.1 )
createBookPages1(bookPages1Img)
SetObjectImage(bookPages1,bookPages1Img,0)
SetObjectPosition(bookPages1,-5.0,10.0,.05)
FixObjectPivot(bookPages1)
SetObjectPosition(bookPages1,-5.0,-10.0,0)
SetObjectRotation(bookPages1,0,180,0)
SetObjectCollisionMode(bookPages1,0)

CreateObjectBox(bookPages2,10, 20,0.1 )
createBookPages2(bookPages2Img)
SetObjectImage(bookPages2,bookPages2Img,0)
SetObjectPosition(bookPages2,-5.0,10.0,.05)
FixObjectPivot(bookPages2)
SetObjectPosition(bookPages2,-5.0,-10.0,0.0)
SetObjectRotation(bookPages2,0,180,0)
SetObjectCollisionMode(bookPages2,0)

CreateObjectBox(bookPages3, 10, 20,0.1 )
createBookPages3(bookPages3Img)
SetObjectImage(bookPages3,bookPages3Img,0)
SetObjectPosition(bookPages3,-5.0,10.0,.05)
FixObjectPivot(bookPages3)
SetObjectPosition(bookPages3,-5.0,-10.0,0.0)
SetObjectRotation(bookPages3,0,180,0)
SetObjectCollisionMode(bookPages3,0)

CreateObjectBox(bookPages4, 10, 20,0.1 )
createBookPages4(bookPages4Img)
SetObjectImage(bookPages4,bookPages4Img,0)
SetObjectPosition(bookPages4,-5.0,10.0,.05)
FixObjectPivot(bookPages4)
SetObjectPosition(bookPages4,-5.0,-10.0,0.0)
SetObjectRotation(bookPages4,0,180,0)
SetObjectCollisionMode(bookPages4,0)
SetObJectVisible(bookPages4,0)

CreateObjectBox(bookBack,10, 20,0.1 )
createBookBack(bookBackImg)
SetObjectImage(bookBack,bookBackImg,0)
SetObjectPosition(bookBack,-5.0,10.0,.05)
FixObjectPivot(bookBack)
SetObjectPosition(bookBack,-5.0,-10.0,0.0)
SetObjectRotation(bookBack,0,180,0)
SetObjectCollisionMode(bookBack,0)
 while	GetObjectAngleY(bookFront)<360 and flag=1
	 RotateObjectLocalY( bookFront, .25 )
	 if GetPointerPressed() then flag=0
	 sync()
 endwhile
 SetObjectRotation(bookFront,0,360,0):flag=1
 while GetObjectAngleY(bookPages1)<360 and flag=1
	if GetObjectAngleY(bookPages1)>300 then SetObjectVisible(bookFront,0) 
	RotateObjectLocalY( bookPages1, .25 )
	 if GetPointerPressed() then flag=0
	sync()
 endwhile
 SetObjectVisible(bookFront,0)
 SetObjectRotation(bookPages1,0,360,0):flag=1
 while GetObjectAngleY(bookPages2)<360 and flag=1
	if GetObjectAngleY(bookPages2)>300 then SetObjectVisible(bookPages1,0) 
	RotateObjectLocalY( bookPages2, .25 )		
	if GetPointerPressed() then flag=0
	sync()
 endwhile
 SetObjectVisible(bookPages1,0)
 SetObjectRotation(bookPages2,0,360,0):flag=1
 
 //DeleteObject(bookFront):DeleteImage(bookcoverImg)
 //DeleteObject(bookPages1):DeleteImage(bookPages1Img)
 //DeleteObject(bookPages2):DeleteImage(bookPages2Img)
 //DeleteObject(bookPages3):DeleteImage(bookPages3Img) 
endfunction

function teleport(direction as integer)
 blankImage=createBlankImage()
 teleport=CreateObjectCylinder(1,1,100)
 SetObjectRotation(teleport,90,0,0)
 SetObjectImage(teleport,blankImage,0)
 SetObjectShader(teleport,Shader)
 SetShaderConstantByName(teleport,"iResolution",100,100,0,0 )

 blackCyl=CreateObjectCylinder(1,1,100)
 SetObjectRotation(blackCyl,90,0,0)
 SetObjectPosition(blackCyl,0,0,-1)
 SetObjectColor(BlackCyl,0,0,0,255)
 SetObjectVisible(blackCyl,0)
 Local x#:local z#:local x2#:local y2#:local time#:local flag	
 x#=.25:z#=.25:x2#=2:z2#=2:flag=1:time#=timer()
 repeat

	 if x#<140.0
		inc x#:inc z#
	 endif
	 SetObjectScale(teleport,x#,.25,z#)
	 RotateObjectLocalY(teleport,direction)
	 SetShaderConstantByName( Shader,"iGlobalTime",Timer(),0,0,0 ) `tell the shader what time it is - so it can update its animations
	 
	 if timer()>time#+2.0
		 SetObjectVisible(blackCyl,1)
		 SetObjectScale(blackCyl,x2#,.25,z2#)
		 inc x2#:inc z2#
	 endif
	 if GetPointerPressed() then flag=0
	 sync()
 until timer()>time#+4.0 or flag=0
 DeleteObject(teleport)
 DeleteObject(blackCyl)
 DeleteImage(blankImage)
endfunction 


function createBlankImage()
	rem create an ellipse that can be used as a sprite and returns the value of the image
	SetClearColor(0,0,0)
	ClearScreen()
    Render()
    DrawBox(0,0,100,100,MakeColor(255,255,255),MakeColor(255,255,255),MakeColor(255,255,255),MakeColor(255,255,255),1)
    Swap()
    img = getimage(0,0,100,100)
    SetImageTransparentColor( img, 0, 0, 0 ) 
endfunction img

function createBookCover(img as integer)
SetClearColor(10,0,0)
ClearScreen()
DrawBox(0,0,256,256,makeColor(87,65,47),makeColor(87,65,47),makeColor(87,65,47),makeColor(87,65,47),1)
print("    ")
print("    The")
print("  Splendid")
print("   Book")
print("    of")
print("  Portals")

Render()
getimage(img,0,0,256,256)
Swap()

endfuncTion 

function createBookBack(img as integer)
SetClearColor(10,0,0)
ClearScreen()
DrawBox(0,0,256,256,makeColor(87,65,47),makeColor(87,65,47),makeColor(87,65,47),makeColor(87,65,47),1)
print("   ")
print("   ")
print("    The")
print("    End")
Render()
getimage(img,0,0,256,256)
Swap()

endfuncTion 

function createBookPages1(img as integer)
SetClearColor(10,0,0)
ClearScreen()
DrawBox(0,0,512,512,makeColor(255,255,255),makeColor(255,255,255),makeColor(255,255,255),makeColor(255,255,255),1)
SetPrintColor(1,1,1)
SetPrintSize(20)
print("")
print("   The Splendid Book of Portals ")
SetPrintSize(16)
print("")
print("")
print("   A fictional game programmed and published by")
print("  fubarpk. All media has been created with code")
print("  and all code has been produced by fubarpk, with")
print("  the exception some examples have been found on ")
print("  the TGC forums and modified to suit this Game.")
print("")
print("")
print("  Credits") 
print("  The Game Creators for making it possible.")
print("  And a special thanks to lots of wonderful people")
print("  on the forums that make it easy to learn AGK.")
print("")
print("")
print("")
print("  The game is dedicated basicFanatics keyword game") 
print("  jam July 9th - 16th 2018 with my key words being")
print("  book splendid and tunnel.")
Render()
getimage(img,0,0,512,512)
Swap()
SetPrintSize(30)
endfuncTion 

function createBookPages2(img as integer)
SetClearColor(10,0,0)
ClearScreen()
DrawBox(0,0,512,512,makeColor(255,255,255),makeColor(255,255,255),makeColor(255,255,255),makeColor(255,255,255),1)
SetPrintColor(1,1,1)
SetPrintSize(20)
print("")
print("   The Splendid Book of Portals ")
SetPrintSize(16)
print("")
print("")
print("    The date is 2040 and your planets sun is on a ")
print("  collision course with the largest asteroid man")
print("  has ever known. It will surely destroy the sun")
print("  and its orbiting planets will float off into ")
print("  the galaxy somewhere.")
print("")
print("")
print("  A scientist has created a portal to another") 
print("  universe but it is unknown what is on the ")
print("  other side")
print("")
print("")
print("  Armed with your trusty gun you begin your") 
print("  journey by entering the portal with the warning")
print("  that the portal back will close after 1 hour and")
print("  after that there will be no way back.")
Render()
getimage(img,0,0,512,512)
Swap()
SetPrintSize(30)
endfuncTion 

function createBookPages3(img)
SetClearColor(10,0,0)
ClearScreen()
DrawBox(0,0,512,512,makeColor(255,255,255),makeColor(255,255,255),makeColor(255,255,255),makeColor(255,255,255),1)
SetPrintColor(1,1,1)
SetPrintSize(20)
print("")
print("   The Splendid Book of Portals ")
SetPrintSize(16)
print("")
print("")
print("  Controls")
print("  Left mouse button to shoot.")
print("  Right mouse button to jump.")
print("  Use the mouse curser to aim.")
print("  Up arrow to move forward.")
print("  Down Arrow to move back.")
print("  Left Arrow strafe left.")
print("  Right Arrow strafe right.")
print("  Esc Exits")
print("")
print("")
print("  Click screen to take Portal")
print("  ")
print("  PS:Clicking advances pages and teleports")
print("  ")

Render()
getimage(img,0,0,512,512)
Swap()
SetPrintSize(30)
endfunction img

function createBookPages4(img)
SetClearColor(10,0,0)
ClearScreen()
DrawBox(0,0,512,512,makeColor(255,255,255),makeColor(255,255,255),makeColor(255,255,255),makeColor(255,255,255),1)
SetPrintColor(1,1,1)
SetPrintSize(20)
print("")
print("   The Splendid Book of Portals ")
SetPrintSize(16)
print("")
print("")
print("  Stumbling through another portal you find")
print("  yourself in a tunnel with moving walls and")
print("  fruit scattered on the ground.")
print("  ")
print("  Looking for a way back to finding that")
print("  Scientist responsible for you being here.")
print("  ")
print("  ")

Render()
getimage(img,0,0,512,512)
Swap()
SetPrintSize(30)
endfunction img


function gameOver()
If GetSpriteExists(radarSpr) then SetSpriteVisible(radarSpr,0)
If GetSpriteExists(playerSpr) then SetSpriteVisible(playerSpr,0)	
local y#:local flag	
SetObjectVisible(bookBack,1)	
y#=180:flag=1
while y#<360 and flag=1
	y#=y#+.25
	if GetObjectAngleY(bookPages3)>300 then SetObjectVisible(bookPages2,0) 
	SetObjectRotation( bookPages3,0,y#,0 )
	if getpointerpressed() then flag=0
	if GetRawKeyState(KEY_ESCAPE) then end 		
	sync()
endwhile
SetObjectRotation( bookPages3,0,360,0 ):SetObjectVisible(bookPages2,1) //incase the user clicked the screen
y#=360
while y#>180 and flag=1
	y#=y#-.25
	if y#<200 then SetObjectVisible(bookBack,0) 
	SetObjectRotation(bookPages3,0,y#,0)
	if getpointerpressed() then flag=0
	if GetRawKeyState(KEY_ESCAPE) then end 		
	sync()
endwhile
SetObjectRotation(bookPages3,0,180,0) //incase the user clicked the screen

endfunction

function bonusLevel()
local flag:flag=1
SetObjectVisible(bookPages4,1)	
If GetSpriteExists(radarSpr) then SetSpriteVisible(radarSpr,0)
If GetSpriteExists(playerSpr) then SetSpriteVisible(playerSpr,0)
while GetObjectAngleY(bookPages3)<360 and flag=1
	if GetObjectAngleY(bookPages3)>300 then SetObjectVisible(bookPages2,0) 
	RotateObjectLocalY( bookPages3,.25 )
	if getpointerpressed() then flag=0
	if GetRawKeyState(KEY_ESCAPE) then end 		
	sync()
endwhile
SetObjectRotation(bookPages3,0,360,0) //incase the user clicked the screen
teleport(-1)
CreateCharacterController(600):
SetObjectVisible(bookPages4,0)
SetObjectVisible(bookPages2,1)
SetObjectRotation(bookPages3,0,180,0)
endfunction	

function playBonusLevel()
	local obstacleCount:local alpha:local flag:local messageTime#:local z
	obstacleCount=0:alpha=255:flag=1:messageTime#=timer()
	for num=1 to bulletCount
		DeleteObject(myBullet[num].ID)
		myBullet.remove(num)
		dec bulletCount
	next num
	for num=1 to enemyCount
		DeleteObject(myEnemy[num].ID)
		DeleteSprite(myEnemy[num].sprID)
		myEnemy.remove(num)
		dec enemyCount
	next num
	SetTextColorAlpha(helpMessage,0)
	SetTextColorAlpha(helpMessage+1,0)
	SetTextColorAlpha(helpMessage+2,0)
	SetCameraRotation(1,0,0,0):SetCameraPosition(1,0,0,-20)
	teleport(1):bonusLevel()
	SetCameraRotation(1,camangle_x#,GetObjectWorldAngleY(playerObj),GetObjectWorldAngleZ(playerObj) ) 
	SetCameraPosition(1,GetObjectWorldX(playerObj),GetObjectWorldY(playerObj)+camOff_y#,GetObjectWorldZ(playerObj))
	SetRawMousePosition(screenWidth*.5,screenheight*.5)
	z=650
	for num = fruitStart to (24*2)+fruitStart step 2
		DeleteObject(num)
		createFruit(num)
		SetObjectColor(num,random(1,255),random(1,255),random(1,255),255)
		SetObjectPosition(num,0,-14,z)
		SetObjectRotation(num,0,random(1,360),0)
		SetObjectCollisionMode(num,1)
		SetObjectCollisionMode(num+1,0)
		z=z+50
	next num
	z=700
	for num =1 to 10
		ID=CreateObjectBox(100,100,2 ) 
		//SetObjectImage(ID,texture2,0)
		SetObjectColor(ID,random(1,255),random(1,255),random(1,255),255)
		direction=random(1,4)
		if direction=1 or direction =2
			SetObjectPosition(ID,0,random(75,150),z)
		elseif direction =3
			SetObjectPosition(ID,150,32,z)
		elseif direction =4
			SetObjectPosition(ID,-150,32,z)
		endif
		Delete3DPhysicsBody(ID)
		Create3DPhysicsStaticBody(ID)
		SetObjectShapeBox(ID) 
		myItem as obstacle
		myItem.ID = ID //the object id of the obstacle
        myItem.direction=direction
		myObstacles.insert(myItem) //update myObstacles 
	    inc obstacleCount //used for a obstacle counter 
		z=z+100
	next num
	
	repeat
		updatePlayerMovement(50)
		for num=fruitStart to (26*2)+fruitStart step 2
			collID=checkCollision(num) 
			if collID=playerObj
				Delete3DPhysicsBody(num):DeleteObject(num):DeleteObject(num+1):inc fruit
			endif
		next num
		
		//move the obstacles 
		for num =1 to obstacleCount
			if myObstacles[num].direction=1 
				if getObjectY(myObstacles[num].ID)<150
					SetObjectPosition(myObstacles[num].ID,getObjectX(myObstacles[num].ID),getObjectY(myObstacles[num].ID)+1,getObjectZ(myObstacles[num].ID))
				else
					myObstacles[num].direction=2
				endif
			elseif myObstacles[num].direction=2 
				if getObjectY(myObstacles[num].ID)>32
					SetObjectPosition(myObstacles[num].ID,getObjectX(myObstacles[num].ID),getObjectY(myObstacles[num].ID)-1,getObjectZ(myObstacles[num].ID))
				else
					myObstacles[num].direction=1
				endif
			endif		
			if myObstacles[num].direction=3 
				if getObjectX(myObstacles[num].ID)<150
					SetObjectPosition(myObstacles[num].ID,getObjectX(myObstacles[num].ID)+1,getObjectY(myObstacles[num].ID),getObjectZ(myObstacles[num].ID))
				else
					myObstacles[num].direction=4
				endif
			elseif myObstacles[num].direction=4 
				if getObjectX(myObstacles[num].ID)>-150
					SetObjectPosition(myObstacles[num].ID,getObjectX(myObstacles[num].ID)-1,getObjectY(myObstacles[num].ID),getObjectZ(myObstacles[num].ID))
				else
					myObstacles[num].direction=3
				endif
			endif		
			
			SetObjectRotation(myObstacles[num].ID,0,0,0)
		next num

	if messagesFlag=1
	if alpha>1
		dec alpha
		SetTextColorAlpha(helpMessage,alpha)
		SetTextColorAlpha(helpMessage+1,alpha)
		SetTextColorAlpha(helpMessage+2,alpha)
	elseif flag=1 and timer()>messageTime#+5
			SetTextString(helpMessage,"That portal just")
			SetTextString(helpMessage+1,"led me to some")
			SetTextString(helpMessage+2,"kind of tunnel.")
			alpha=255:flag=2:messageTime#=timer()		
	elseif flag=2 and timer()>messageTime#+6
			SetTextString(helpMessage,"The moving walls")
			SetTextString(helpMessage+1,"look dangerous")
			SetTextString(helpMessage+2,"I better take care")
			alpha=255:flag=3:messageTime#=timer()
	elseif flag=3 and timer()>messageTime#+4
			SetTextString(helpMessage,"This place reminds ")
			SetTextString(helpMessage+1,"me of something I")
			SetTextString(helpMessage+2,"saw at the Movies.")
			alpha=255:flag=4:messageTime#=timer()
	elseif flag=4 and timer()>messageTime#+5
			SetTextString(helpMessage,"I wonder if i can eat")
			SetTextString(helpMessage+1,"this fruit. Some of")
			SetTextString(helpMessage+2,"it looks tasty.")
			alpha=255:flag=5:messageTime#=timer()	
	elseif flag=5 and timer()>messageTime#+4
			SetTextString(helpMessage,"I see a portal at the ")
			SetTextString(helpMessage+1,"other end. I am best ")
			SetTextString(helpMessage+2,"to take it. ")
			alpha=255:flag=6:messageTime#=timer()
	elseif flag=6 and timer()>messageTime#+4
			SetTextString(helpMessage,"How do these portals  ")
			SetTextString(helpMessage+1,"work. Perhaps by ")
			SetTextString(helpMessage+2,"walking through it.")
			alpha=255:flag=7:messageTime#=timer()			
	endif
	endif
	
	print("Level="+str(level))
	print("Lives="+str(lives))
	print("Fruit="+str(fruit))
		//set camera and its offsets in relation to the players position
	SetCameraRotation(1,camangle_x#,GetObjectWorldAngleY(playerObj),GetObjectWorldAngleZ(playerObj) ) 
	SetCameraPosition(1,GetObjectWorldX(playerObj),GetObjectWorldY(playerObj)+camOff_y#,GetObjectWorldZ(playerObj))
	SetShaderConstantByName( Shader,"iGlobalTime",Timer()*.5,0,0,0 ) `tell the shader what time it is - so it can update its animations
	sync()
	until getObjectZ(playerObj)> 1975 or GetRawKeyState(KEY_ESCAPE)
	
	//do housekeeping remove any fired bullets
	for num=1 to bulletCount
		DeleteObject(myBullet[num].ID)
		myBullet.remove(num)
		dec bulletCount
	next num
	//remove all obstacles we no longer need them
	for num =obstacleCount to 1 step -1
		DeleteObject(myObstacles[num].ID)
		myObstacles.remove(num)
	next num
	obstacleCount=0
	SetCameraRotation(1,0,0,0):SetCameraPosition(1,0,0,-20)
	If GetSpriteExists(radarSpr) then SetSpriteVisible(radarSpr,1)
	If GetSpriteExists(playerSpr) then SetSpriteVisible(playerSpr,1)
	teleport(-1):CreateCharacterController(200):
	SetCameraRotation(1,camangle_x#,GetObjectWorldAngleY(playerObj),GetObjectWorldAngleZ(playerObj) ) 
	SetCameraPosition(1,GetObjectWorldX(playerObj),GetObjectWorldY(playerObj)+camOff_y#,GetObjectWorldZ(playerObj))
	SetRawMousePosition(screenWidth*.5,screenheight*.5)
endfunction	

function createFruit(fruitID as integer)
CreateObjectSphere(fruitID,5,10,10)
SetObjectPosition(fruitID,25,0,0)
 
numMeshes=GetObjectNumMeshes(fruitID)
myObject as object
myObject.objMem=CreateMemblockFromObjectMesh(fruitID,1)
myObject.maxVertex=GetMemblockInt(myObject.objMem,0)-1
 
for index = 0 to 21//myObject.maxVertex
    if index <=9 
        SetMeshMemblockVertexPosition(myObject.objMem,index,GetMeshMemblockVertexX(myObject.objMem,index),GetMeshMemblockVertexY(myObject.objMem,index)-2,GetMeshMemblockVertexZ(myObject.objMem,index))
    else
        SetMeshMemblockVertexPosition(myObject.objMem,index,GetMeshMemblockVertexX(myObject.objMem,index),GetMeshMemblockVertexY(myObject.objMem,index)-1,GetMeshMemblockVertexZ(myObject.objMem,index))
    endif  
next index
SetObjectMeshFromMemblock(fruitID,1,myObject.objMem)
DeleteMemblock(myObject.objMem)
SetObjectColor(fruitID,200,0,0,255)
Create3DPhysicsStaticBody(fruitID)
SetObjectShapeSphere(fruitID ) 

CreateObjectBox(fruitID+1,.5,2,.5)
vertex as integer[7] = [17,15,7,13, 1,19,3,5]
numMeshes=GetObjectNumMeshes(fruitID+1)
myObject.objMem=CreateMemblockFromObjectMesh(fruitID+1,1)
myObject.maxVertex=GetMemblockInt(myObject.objMem,0)-1
for i = 0 to 7
    SetMeshMemblockVertexPosition(myObject.objMem,vertex[i],GetMeshMemblockVertexX(myObject.objMem,vertex[i])+1,GetMeshMemblockVertexY(myObject.objMem,vertex[i]),GetMeshMemblockVertexZ(myObject.objMem,vertex[i]))
next i   
SetObjectMeshFromMemblock(fruitID+1,1,myObject.objMem)
DeleteMemblock(myObject.objMem)
SetObjectColor(fruitID+1,160,80,45,255)
SetObjectPosition(fruitID+1,-1,2,0)
FixObjectToObject(fruitID+1,fruitID)
endfunction	
function createShader()
//create the shader used for the port holes 
//Texture0 is where the kaleidosope is drawn
//Texture1 is a masking layer, anything on this layer that isn't transparent is used for drawing the Kali in texture0
//Texture2 is the texture you want to replace the transparent parts in texture1
//If no textures are set to an object the whole object will be a kaleidoscope
//if texture1 and setobjecttransparency is used then the transparent parts in texture1 will be transparent
//If texture2 is used with or without setobjecttransparency the parts visible on this texture will be drawn on the invisible bits in texture1
if GetFileExists("Kaliset.vs") then DeleteFile("Kaliset.vs")        
file = OpenToWrite("Kaliset.vs")
WriteLine(file,"attribute highp vec3 position;")
WriteLine(file,"attribute mediump vec3 normal;")
WriteLine(file,"attribute mediump vec2 uv;")
WriteLine(file,"varying highp vec3 posVarying;")
WriteLine(file,"varying mediump vec3 normalVarying;")
WriteLine(file,"varying mediump vec2 uv0Varying;")
WriteLine(file,"varying mediump vec2 uv1Varying;")
WriteLine(file,"varying mediump vec2 uv2Varying;")
WriteLine(file,"varying mediump vec3 lightVarying;")
WriteLine(file,"uniform vec3 iResolution; // viewport resolution (in pixels)")
WriteLine(file,"uniform float iGlobalTime; // shader playback time (in seconds)")
WriteLine(file,"uniform float iChannelTime[10]; // channel playback time (in seconds)")
WriteLine(file,"uniform vec3 iChannelResolution[10]; // channel resolution (in pixels)")
WriteLine(file,"//uniform vec4 iMouse; // mouse pixel coords. xy: current (if MLB down)")
WriteLine(file,"uniform sampler2D texture0; // input channel")
WriteLine(file,"uniform vec4 iDate; // (year, month, day, time in seconds)")
WriteLine(file,"uniform highp mat3 agk_WorldNormal;")
WriteLine(file,"uniform highp mat4 agk_World;")
WriteLine(file,"uniform highp mat4 agk_ViewProj;")
WriteLine(file,"uniform mediump vec4 uvBounds0;")
WriteLine(file,"uniform mediump vec4 uvBounds1;")
WriteLine(file,"uniform mediump vec4 uvBounds2;")
WriteLine(file,"mediump vec3 GetVSLighting( mediump vec3 normal, highp vec3 pos );")
WriteLine(file,"void main()")
WriteLine(file,"{") 
WriteLine(file,"    uv0Varying = uv * uvBounds0.xy + uvBounds0.zw;")
WriteLine(file,"    uv1Varying = uv * uvBounds1.xy + uvBounds1.zw;")
WriteLine(file,"    uv2Varying = uv * uvBounds2.xy + uvBounds2.zw;")
WriteLine(file,"    highp vec4 pos = agk_World * vec4(position,1.0);")
WriteLine(file,"    gl_Position = agk_ViewProj * pos;")
WriteLine(file,"    mediump vec3 norm = normalize(agk_WorldNormal * normal);")
WriteLine(file,"    posVarying = pos.xyz;")
WriteLine(file,"    normalVarying = norm;")
WriteLine(file,"    lightVarying = GetVSLighting( norm, posVarying );")
WriteLine(file,"}") 
CloseFile(file)
 
if GetFileExists("Kaliset.ps") then DeleteFile("Kaliset.ps")    
file = OpenToWrite("Kaliset.ps")
WriteLine(file,"uniform vec3 iResolution; // viewport resolution (in pixels)")
WriteLine(file,"uniform float iGlobalTime; // shader playback time (in seconds)")
WriteLine(file,"uniform float iChannelTime[10]; // channel playback time (in seconds)")
WriteLine(file,"")
WriteLine(file,"//uniform vec4 iMouse; // mouse pixel coords. xy: current (if MLB down)")
WriteLine(file,"uniform sampler2D texture0; // input channel ")
WriteLine(file,"uniform sampler2D texture1; // input channel ")
WriteLine(file,"uniform sampler2D texture2; // input channel ")
WriteLine(file,"uniform vec4 iDate; // (year, month, day, time in seconds)")
WriteLine(file,"varying mediump vec2 uv0Varying;")
WriteLine(file,"varying mediump vec2 uv1Varying;")
WriteLine(file,"varying mediump vec2 uv2Varying;")
WriteLine(file,"const int iterations=12;")
WriteLine(file,"void main(void)")
WriteLine(file,"{")
WriteLine(file,"//this takes the pixel we are working with to determine where it is on the screen")
//WriteLine(file,"vec2 z = gl_FragCoord.xy/iResolution.xy;")
WriteLine(file,"vec2 z = uv0Varying;")
WriteLine(file,"//fixes aspect ratio in favor of symmety. comment it and see what it looks like")
WriteLine(file,"//z.y*=iResolution.y/iResolution.x;")
WriteLine(file,"//gloobywavez")
WriteLine(file,"z.x += sin(z.y*2.0+iGlobalTime * .2)/10.0;")
WriteLine(file,"//zooom")
WriteLine(file,"//z*= 1.2 + sin(iGlobalTime*.15);")
WriteLine(file,"//pan")
WriteLine(file,"//z+=vec2(sin(iGlobalTime*.2),cos(iGlobalTime*.01));")
WriteLine(file,"//rotate")
WriteLine(file,"//z=vec2(z.x*cos(iGlobalTime*.2)- z.y*sin(iGlobalTime*.2),z.y*cos(iGlobalTime*.2));")
WriteLine(file,"vec2 c=vec2(0.5, 1.1);")
WriteLine(file,"")
WriteLine(file,"float average=0.;")
WriteLine(file,"float l=length(z);")
WriteLine(file,"float prevl;")
WriteLine(file,"for (int i=0; i<iterations; i++)")
WriteLine(file,"{")
WriteLine(file,"//kaliset base form")
WriteLine(file,"z=abs(z)/dot(z,z) -c;")
WriteLine(file,"//this is another function that can be iterated to produce some different fractals")
WriteLine(file,"//comment out the previous kaliset and experiment with values with this one!!")
WriteLine(file,"//z = abs(z)/(z.x*z.y)-c;")
WriteLine(file,"prevl=l;")
WriteLine(file,"l=length(z);")
WriteLine(file,"average+=abs(l-prevl);")
WriteLine(file,"}")
WriteLine(file,"//get the average length based upon the amount of iterations elapsed. multiply it to adjust definition")
WriteLine(file,"average/=float(iterations) * 15.;")
WriteLine(file,"//color fluctuation")
WriteLine(file,"average+=iGlobalTime*0.08;")
WriteLine(file,"vec3 myColor=vec3(0.2,0.21,.62);")
WriteLine(file,"vec3 finalColor;")
WriteLine(file,"//set the colors!")
WriteLine(file,"finalColor.r = (fract(float(average)/myColor.r));")
WriteLine(file,"finalColor.g = (fract(float(average)/myColor.g));")
WriteLine(file,"finalColor.b = (fract(float(average)/myColor.b));")
WriteLine(file,"vec4 colorResult1  = texture2D(texture1, uv1Varying);")
WriteLine(file,"vec4 colorResult2  = mix(colorResult1,vec4(finalColor,1.0), colorResult1.a);")
//WriteLine(file,"vec4 colorResult3  = texture2D(texture2, uv2Varying);")
WriteLine(file,"vec4 colorResult3  = mix(texture2D(texture2,uv2Varying),colorResult2,colorResult1.a);")
//WriteLine(file,"gl_FragColor = mix(colorResult3,colorResult1,colorResult2);")
WriteLine(file,"gl_FragColor = colorResult3;")
WriteLine(file,"}") 
CloseFile(file)
endfunction


Controls
mouse sets direction and aims
up arrow move forward
down arrow move backward
left arrow strafe left
right arrow strafe right
mouse left button shoots
mouse right button jumps
Posted: 1st Jul 2018 22:09
Wow, Thanks for sharing all this mate!
Posted: 1st Jul 2018 22:14
Thats really great effects with Shaders too great stuff- keep the snippets coming

I been working on a Maze Generator for the Coding Train one, well my interperations of how this guy codes - nearly finished just a bit of backtracking to do

This can then be used for 3D maze apps