;==================================================================
;Project Title: CRYSTALIUM
;Author:        Vladislav Borzunov aka ObelardO
;Email:         Obelardos@gmail.com 
;Version:       0.9 Alpha
;Date:          04.03.13
;Notes:         work with game objects
;==================================================================

;Fireballs
;==================================================================

Type TYPE_FIREBALL
	Field Entity
	Field Status$
	Field Plasm[5]
	Field Lightining[1]
     	Field Course
	Field X
	Field Y
	Field Speed
End Type

Function CreateFireBall(x = 0, y = 0)
	FIREBALL.TYPE_FIREBALL = New TYPE_FIREBALL
	
	FIREBALL\Entity = xCreateSphere(4)
	xPositionEntity FIREBALL\Entity, x, y, 0
      xEntityAlpha    FIREBALL\Entity, 0
	xEntityRadius   FIREBALL\Entity, 0.99

	; Animation 
	For i = 0 To 5
		FIREBALL\Plasm[i] = CreateSurface2(1.5 - (i * 0.1))
		xEntityParent     FIREBALL\Plasm[i], FIREBALL\Entity
		xPositionEntity   FIREBALL\Plasm[i], 0, 0, -i * 0.01
		xEntityTexture    FIREBALL\Plasm[i], PLAYER_TEXTURE, 0, 0
		xTurnEntity       FIREBALL\Plasm[i], 0, 180 *(i Mod 2), i * (i Mod 2) * 20
		xEntityFX         FIREBALL\Plasm[i], 1 + 16
		xEntityColor      FIREBALL\Plasm[i], 255, 255 - (6 - i) * 30, 80
	Next

	For i = 0 To 1
		FIREBALL\Lightining[i] = CreateSurface2(2-(i*0.1))
		xEntityParent  	     FIREBALL\Lightining[i], FIREBALL\Entity
		xEntityTexture 	     FIREBALL\Lightining[i], TEXTURE_LIGHT, 0, 0
		xEntityFX              FIREBALL\Lightining[i], 1 + 16
		xTurnEntity            FIREBALL\Lightining[i], 0, 180 *(i Mod 2), 0
		xPositionEntity        FIREBALL\Lightining[i], 0, 0, -i * 0.01
	Next

	FIREBALL\Course = Rand(1,4)
	FIREBALL\Status = "wait"
	FIREBALL\X = x
	FIREBALL\Y = y
	FIREBALL\Speed = 2
End Function

Function UpdateFireBalls()
	For FIREBALL.TYPE_FIREBALL = Each TYPE_FIREBALL
		For i = 0 To 5
			xTurnEntity  FIREBALL\Plasm[i], 0, 0, (i+1)*0.5
		Next
		For i = 0 To 1
			xTurnEntity  FIREBALL\Lightining[i], 0, 0, (i+1)*0.4
			xScaleEntity FIREBALL\Lightining[i], Sin(MilliSecs()*0.2)*0.1+1, Sin(MilliSecs()*0.2)*0.1+1, Sin(MilliSecs()*0.2)*0.1+1
		Next

		Distance# = xEntityDistance (FIREBALL\Entity, PLAYER_ENTITY)
		
		If Distance < 2 
			FIREBALL\Status = "dead"
			PLAYER_LIGHTINING = PLAYER_LIGHTINING - 2
		End If

		LocalX = FIREBALL\X * 0.5
		LocalY = Abs(FIREBALL\Y * 0.5)
		If (LocalX > - 1 And LocalX < 1023) And (LocalY > - 1 And LocalY < 511)

		Select FIREBALL\Status
			Case "wait"
				Select FIREBALL\Course
					Case 1 ; Up
						If MAP_MATRIX(LocalX, LocalY - 1) = ""
							 MAP_MATRIX(LocalX, LocalY) = ""
							 MAP_MATRIX(LocalX, LocalY - 1) = "FB"
							 FIREBALL\Y = FIREBALL\Y + 2
							 FIREBALL\Status = "moving"
						Else
							FIREBALL\Course = Rand(3, 4)
						End If
					Case 2 ; Down
						If MAP_MATRIX(LocalX, LocalY + 1) = ""
							 MAP_MATRIX(LocalX, LocalY) = ""
							 MAP_MATRIX(LocalX, LocalY + 1) = "FB"
							 FIREBALL\Y = FIREBALL\Y - 2
							 FIREBALL\Status = "moving"
						Else
							FIREBALL\Course = Rand(3, 4)
						End If
					Case 3 ; Left
						If MAP_MATRIX(LocalX - 1, LocalY) = ""
							 MAP_MATRIX(LocalX, LocalY) = ""
							 MAP_MATRIX(LocalX - 1, LocalY) = "FB"
							 FIREBALL\X = FIREBALL\X - 2
							 FIREBALL\Status = "moving"
						Else
							FIREBALL\Course = Rand(1, 2)
						End If
					Case 4 ; Right
						If MAP_MATRIX(LocalX + 1, LocalY) = ""
							 MAP_MATRIX(LocalX, LocalY) = ""
							 MAP_MATRIX(LocalX + 1, LocalY) = "FB"
							 FIREBALL\X = FIREBALL\X + 2
							 FIREBALL\Status = "moving"
						Else
							FIREBALL\Course = Rand(1, 2)
						End If
				End Select
			Case "moving"
				If xEntityX(FIREBALL\Entity) > FIREBALL\X xTranslateEntity FIREBALL\Entity,-0.03125 * FIREBALL\Speed, 0, 0
				If xEntityX(FIREBALL\Entity) < FIREBALL\X xTranslateEntity FIREBALL\Entity, 0.03125 * FIREBALL\Speed, 0, 0
				If xEntityY(FIREBALL\Entity) > FIREBALL\Y xTranslateEntity FIREBALL\Entity, 0,-0.03125 * FIREBALL\Speed, 0
				If xEntityY(FIREBALL\Entity) < FIREBALL\Y xTranslateEntity FIREBALL\Entity, 0, 0.03125 * FIREBALL\Speed, 0
				
				If xEntityX(FIREBALL\Entity) = FIREBALL\X And xEntityY(FIREBALL\Entity) = FIREBALL\Y FIREBALL\Status = "wait"
			Case "dead"
				MAP_MATRIX(LocalX, LocalY) = "NC"
				CreateCrystal(FIREBALL\X, FIREBALL\Y)
				Createexplosion(xEntityX(FIREBALL\Entity), xEntityY(FIREBALL\Entity))
				xFreeEntity FIREBALL\Entity
				FIREBALL\Status = ""
				FIREBALL\Course = 0
				FIREBALL\X = 0
				FIREBALL\Y = 0
				FIREBALL\Speed = 0
				Delete FIREBALL
		End Select
		End If
	Next
End Function

Function DeleteFireBalls()
	For FIREBALL.TYPE_FIREBALL = Each TYPE_FIREBALL
		LocalX = FIREBALL\X * 0.5
		LocalY = Abs(FIREBALL\Y * 0.5)
		MAP_MATRIX(LocalX, LocalY) = ""
		xFreeEntity FIREBALL\Entity
		FIREBALL\Status = ""
		FIREBALL\Course = 0
		FIREBALL\X = 0
		FIREBALL\Y = 0
		FIREBALL\Speed = 0
		Delete FIREBALL
	Next
End Function

;Exit
Type TYPE_TUNNEL
	Field Entity
	Field Status$
End Type

Function CreateTunnel(x = 0, y = 0)
	TUNNEL.TYPE_TUNNEL = New TYPE_TUNNEL
	TUNNEL\Entity = CreateBlock(x, y, "NL", 13)
	TUNNEL\Status = "wait"
End Function

Function UpdateTunnels()
	For TUNNEL.TYPE_TUNNEL = Each TYPE_TUNNEL
		Select TUNNEL\Status
			Case "wait"
				If xEntityDistance(TUNNEL\Entity, PLAYER_ENTITY) < 2
					TUNNEL\Status = "activated"
					If CRYSTAL_COUNT
						If PLAYER_CRYSTALS < CRYSTAL_COUNT
							CreateMenu("tunnel")
						Else
							ConsoleExecute("level "+MAP_NEXT)
						End If
					End If
				End If
			Case "activated"
				If xEntityDistance(TUNNEL\Entity, PLAYER_ENTITY) > 8 TUNNEL\Status = "wait"
		End Select
	Next
End Function

Function DeleteTunnels()
	For TUNNEL.TYPE_TUNNEL = Each TYPE_TUNNEL
		deleteBlock(TUNNEL\Entity)
		TUNNEL\Status = 0
		Delete TUNNEL
	Next
End Function

;Triggers
;==================================================================
Type TYPE_TRIGGER
	Field Entity
	Field Command$
End Type

Type TYPE_COMMAND
	Field Command$
	Field TriggerX
	Field TriggerY
End Type

Function CreateTrigger(x = 0, y = 0)
	TRIGGER.TYPE_TRIGGER = New TYPE_TRIGGER
	TRIGGER\Entity = xCreateCube()
	xPositionEntity  TRIGGER\Entity, x, y, 0
	xEntityAlpha     TRIGGER\Entity, 0;.2
	xEntityColor     TRIGGER\Entity, 0, 255, 0
	LocalX = xEntityX(TRIGGER\Entity) * 0.5
	LocalY = Abs( xEntityY(TRIGGER\Entity)) * 0.5
	For COMMAND.TYPE_COMMAND = Each TYPE_COMMAND
		If COMMAND\TriggerX = LocalX And COMMAND\TriggerY = LocalY
			TRIGGER\Command = COMMAND\Command
			COMMAND\Command$ = ""
			COMMAND\TriggerX = 0
			COMMAND\TriggerY = 0
			Delete COMMAND
		End If
	Next
End Function

Function UpdateTriggers()
	For TRIGGER.TYPE_TRIGGER = Each TYPE_TRIGGER
		If xEntityDistance(PLAYER_ENTITY, TRIGGER\Entity) < 0.8
			InGameCommand(TRIGGER\Command)
			xFreeEntity TRIGGER\Entity
			TRIGGER\Command = ""
			Delete TRIGGER
		End If
	Next
End Function

Function CommandTrigger(InputString$)
	COMMAND.TYPE_COMMAND = New TYPE_COMMAND
	COMMAND\TriggerX = StrToInt(StrCut(InputString,1,","))
	COMMAND\TriggerY = StrToInt(StrCut(InputString,2,","))
	COMMAND\Command$ = StrCut(InputString,3,",")
End Function

Function DeleteTriggers()
	For TRIGGER.TYPE_TRIGGER = Each TYPE_TRIGGER
		xFreeEntity TRIGGER\Entity
		TRIGGER\Command = ""
		Delete TRIGGER
	Next
End Function

Function InGameCommand(Command$)
	If Not Command = ""
		command = Replace(command, "'", quotes)
		If Left(command,1) <> "/" command = "/"+Command 
		While Not Instr(Command,"/") = 0
			command = Right(command,Len(command) - Instr(command,"/"))
			Select Strcut(Command, 1, "(")
				Case "con"      :ConsoleExecute(Strcut(Command, 2, "()"))
				Case "menu"     :CreateMenu(Strcut(Command, 2, "()"))
				Case "crystals" :CRYSTAL_COUNT = StrToInt(Strcut(Command, 2, "()"))
				Case "trig"     :CommandTrigger(Replace(Command,"trig(", ""))
				Case "light"    :PLAYER_LIGHTINING = StrToInt(Strcut(Command, 2, "()"))
				Case "next"     :MAP_NEXT = Strcut(Command, 2, "()")
				Case "time"     :MAP_TIME = StrToInt(Strcut(Command, 2, "()"))
			End Select
		Wend
	End If
End Function

;Stone
;==================================================================
Const STONE_COLLISION = 4

Type TYPE_STONE
	Field Entity
	Field Status$
	Field X
	Field Y
	Field Speed#
	Field impact
	Field Hover 
End Type

Function CreateStone(x = 0, y = 0)
	STONE.TYPE_STONE = New TYPE_STONE

	STONE\X = x: STONE\Y = y
	STONE\Status = "wait"
	STONE\Speed = 1.0
	
	STONE\Entity =		 xCreateSphere(6)
	xEntityParent            STONE\Entity, MAP_ENTITY
	xTurnEntity 		 STONE\Entity, 0, 0, Rand(0,360)
	xNameEntity              STONE\Entity, "MS"
	xPositionEntity          STONE\Entity, x, y, 0
	xEntityType              STONE\Entity, STONE_COLLISION
	xEntityTexture           STONE\Entity, TEXTURE_GENERAL,        0, 0
	xEntityTexture           STONE\Entity, TEXTURE_GENERAL_NORMAL, 0, 1
	xSetEntityEffect 		 STONE\Entity, EFFECT_BUMP
	xSetEffectTechnique 	 STONE\Entity, "Bump"
	xSetEffectTechnique 	 STONE\Entity, "PointDistance"
	xSetEffectMatrixSemantic STONE\Entity, "MatWorldViewProj", WORLDVIEWPROJ
	xSetEffectMatrixSemantic STONE\Entity, "MatWorld", STONE\Entity
	xSetEffectVector         STONE\Entity, "AmbientClr", 0, 0, 0;"AmbientClr",.12,.18,.24
	xSetEffectVector 		 STONE\Entity, "LightClr", 1, 0.8, 0.6
	xSetEffectFloat   	 STONE\Entity, "LightInt", 2.5
	xSetEffectFloat   	 STONE\Entity, "RngLight", 20
	xSetEffectTexture	       STONE\Entity, "tDiffuse", TEXTURE_GENERAL,        0
	xSetEffectTexture        STONE\Entity, "tNormal",  TEXTURE_GENERAL_NORMAL, 0

	xEmitSound SOUND_STONE_FELL, STONE\Entity
End Function

Function UpdateStones()
	While decision = 0
		decision = Rand(-1, 1)
	Wend
	
	For STONE.TYPE_STONE = Each TYPE_STONE
		LocalX = STONE\X * 0.5
		LocalY = Abs(STONE\Y*0.5)
		If (LocalX > - 1 And LocalX < 1023) And (LocalY > - 1 And LocalY < 511)

			If STONE\Status = "moving" And xEntityDistance(STONE\Entity, PLAYER_ENTITY) < 1 PLAYER_LIGHTINING = PLAYER_LIGHTINING - 0.1
		
			Select STONE\Status
				Case "wait"
					Select MAP_MATRIX(LocalX, LocalY + 1)
						Case ""
							If xEntityDistance(STONE\Entity, PLAYER_ENTITY) < 6 And STONE\Hover = 0 STONE\Hover = 30
							If STONE\Hover > 0 STONE\Hover = STONE\Hover - 1
							If STONE\Hover = 0
								MAP_MATRIX(LocalX, LocalY) = ""
								MAP_MATRIX(LocalX, LocalY + 1) = "MS" 
								STONE\Y = STONE\Y - 2
								STONE\Status = "moving"
								STONE\Speed = 4
							End If
						Case "DN"
							DetonateDynamite(STONE\X, STONE\Y - 2)
							STONE\Status = "dead"
						Case "FB"
							CreateExplosion(STONE\X, STONE\Y - 2)
							STONE\Status = "dead"
						Default
							If MAP_MATRIX(LocalX + decision, LocalY + 1) = "" And MAP_MATRIX(LocalX + decision, LocalY ) = ""
								MAP_MATRIX(LocalX, LocalY) = ""
								MAP_MATRIX(LocalX + decision, LocalY) = "MS" 
								STONE\X = STONE\X + decision * 2
								STONE\Status = "moving"
								STONE\Speed = 2
							End If
					End Select
					If STONE\Entity = xEntityCollided(PLAYER_ENTITY, STONE_COLLISION) 
						If STONE\Impact > 10 STONE\Impact = 0
						If (xKeyDown(32) Or xKeyDown(KEY_RIGHT)) And Abs(PLAYER_ACTIVE_Y-xEntityY(STONE\Entity)) < 0.9 And PLAYER_ACTIVE_X < STONE\X
							If STONE\Impact = 10 And MAP_MATRIX(LocalX + 1, Abs(STONE\Y) * 0.5) = ""
								MAP_MATRIX(LocalX, LocalY) = ""
								MAP_MATRIX(LocalX + 1, LocalY) = "MS" 
								STONE\X = STONE\X + 2
								STONE\Status = "moving"
								STONE\Speed = 1
							End If
							Keypressed = True
						End If
						If (xKeyDown(30) Or xKeyDown(KEY_LEFT)) And Abs(PLAYER_ACTIVE_Y-xEntityY(STONE\Entity)) < 0.9 And PLAYER_ACTIVE_X > STONE\X
							If STONE\Impact = 10 And MAP_MATRIX(LocalX - 1, Abs(STONE\Y) * 0.5) = ""
								MAP_MATRIX(LocalX, LocalY) = ""
								MAP_MATRIX(LocalX - 1, LocalY) = "MS" 
								STONE\X = STONE\X - 2
								STONE\Status = "moving"
								STONE\Speed = 1
							End If
							Keypressed = True
						End If
						If Keypressed STONE\Impact = STONE\Impact + 1				
					End If
				Case "moving"
					If xEntityX(STONE\Entity) > STONE\X xTranslateEntity STONE\Entity,-0.03125 * STONE\Speed, 0, 0
					If xEntityX(STONE\Entity) < STONE\X xTranslateEntity STONE\Entity, 0.03125 * STONE\Speed, 0, 0
					If xEntityY(STONE\Entity) > STONE\Y xTranslateEntity STONE\Entity, 0,-0.03125 * STONE\Speed, 0
					If xEntityY(STONE\Entity) < STONE\Y xTranslateEntity STONE\Entity, 0, 0.03125 * STONE\Speed, 0
					
					xTurnEntity STONE\Entity, 0, 0, (xEntityX(STONE\Entity) - STONE\X) * 2
	
					If xEntityX(STONE\Entity) = STONE\X And xEntityY(STONE\Entity) = STONE\Y
						If MAP_MATRIX(LocalX, LocalY + 1) = ""
							MAP_MATRIX(LocalX, LocalY) = ""
							MAP_MATRIX(LocalX, LocalY + 1) = "MS" 
							STONE\Y = STONE\Y - 2
							STONE\Speed = 4
						Else
							STONE\Status = "wait"
							xPlaySound SOUND_STONE_FELL 
						End If
					End If
				Case "dead"
					MAP_MATRIX(LocalX, LocalY) = ""
					xFreeEntity STONE\Entity
					STONE\Status = ""
					STONE\X = 0: STONE\Y = 0: STONE\Speed = 0: STONE\Impact = 0
					Delete STONE
			End Select
		End If
	Next
End Function

Function DeleteStones()
	For STONE.TYPE_STONE = Each TYPE_STONE
		xFreeEntity STONE\Entity
		STONE\Status = ""
		STONE\X = 0: STONE\Y = 0: STONE\Speed = 0: STONE\Impact = 0
		Delete STONE
	Next
End Function

;explosion
;==================================================================
Type TYPE_EXPLOSION
	Field Entity
	Field Range
	Field SoundPoint
End Type

Function CreateExplosion(x = 0, y = 0)
	EXPLOSION.TYPE_EXPLOSION = New TYPE_EXPLOSION
	
	EXPLOSION\Entity = CreateSurface2(4)
	xEntityTexture EXPLOSION\Entity, TEXTURE_EXPLOSION, 0
	xPositionEntity EXPLOSION\Entity, x, y, -2
	xEntityFX EXPLOSION\Entity, 1

	EXPLOSION\SoundPoint = xCreateCube(EXPLOSION\Entity)
	xEntityAlpha 	EXPLOSION\SoundPoint, 0
	xPositionEntity   EXPLOSION\SoundPoint, 0, 0, -6
	
	Sound = Rand(1, 2)
	Select Sound
		Case 1: xEmitSound SOUND_EXPLOSION_A, EXPLOSION\SoundPoint: xPlaySound SOUND_EXPLOSION_A
		Case 2: xEmitSound SOUND_EXPLOSION_B, EXPLOSION\SoundPoint: xPlaySound SOUND_EXPLOSION_B
	End Select
End Function

Function UpdateExplosions()
	For EXPLOSION.TYPE_EXPLOSION = Each TYPE_EXPLOSION
		xEntityTexture EXPLOSION\Entity, TEXTURE_EXPLOSION, Int(EXPLOSION\Range)
		xTurnEntity EXPLOSION\Entity, 0, 0, 1

		EXPLOSION\Range = EXPLOSION\Range + 1
		
			For BLOCK.TYPE_BLOCK = Each TYPE_BLOCK

				If xEntityDistance ( EXPLOSION\Entity, BLOCK\Entity) < EXPLOSION\Range * 0.2
					xSetEffectFloat  BLOCK\Entity, "LightInt", (4 - (EXPLOSION\Range * 0.1)) + 2.5
				End If

				If EXPLOSION\Range < 20
					If xEntityDistance ( EXPLOSION\Entity, BLOCK\Entity) < EXPLOSION\Range * 0.2
						Select xEntityName(BLOCK\Entity)
							Case "03": DeleteBlock(BLOCK\Entity)
							Case "04": DeleteBlock(BLOCK\Entity)
							Case "05": DeleteBlock(BLOCK\Entity)
							Case "06": DeleteBlock(BLOCK\Entity)
							Case "10": DeleteBlock(BLOCK\Entity)
							Case "12": DeleteBlock(BLOCK\Entity)
							Case "WC": DeleteBlock(BLOCK\Entity)
							Case "DN"
							x = xEntityX(BLOCK\Entity): y = xEntityY(BLOCK\Entity)
							DeleteBlock(BLOCK\Entity)
							CreateExplosion(x, y)
						End Select
					End If
				End If
			Next
		
		If EXPLOSION\Range = 20
			For FIREBALL.TYPE_FIREBALL = Each TYPE_FIREBALL
				If xEntityDistance ( EXPLOSION\Entity, FIREBALL\Entity) < EXPLOSION\Range * 0.2
					FIREBALL\Status = "dead"
				End If
			Next
		End If
	
		If EXPLOSION\Range = 40
			xFreeEntity EXPLOSION\SoundPoint
			xFreeEntity EXPLOSION\Entity
			EXPLOSION\Range = 0
			Delete EXPLOSION
		End If
	Next
End Function

Function deleteExplosions()
	For EXPLOSION.TYPE_EXPLOSION = Each TYPE_EXPLOSION
		xFreeEntity EXPLOSION\SoundPoint
		xFreeEntity EXPLOSION\Entity
		EXPLOSION\Range = 0
		Delete EXPLOSION
	Next
End Function

;Dynamite
;==================================================================
Type TYPE_DYNAMITE
	Field Entity
	Field Status$
	Field X#
	Field Y#
	Field TNT
	Field impact
End Type

Function CreateDynamite(x = 0, y = 0, Name$ = "DN", TNT = True)
	DYNAMITE.TYPE_DYNAMITE = New TYPE_DYNAMITE
	DYNAMITE\Entity = CreateBlock(x, y, Name, 7 + TNT); = If DYNAMITE\TNT DYNAMITE\Entity=CreateBlock(x,y,"DN",8) Else DYNAMITE\Entity=CreateBlock(x,y,"DN",7)
	DYNAMITE\X = x: DYNAMITE\Y = y
	DYNAMITE\Status = "wait"
	DYNAMITE\TNT = TNT
End Function

Function UpdateDynamites()
	For DYNAMITE.TYPE_DYNAMITE = Each TYPE_DYNAMITE
		LocalX = DYNAMITE\X * 0.5:       If LocalX > 1023 LocalX = 1023:  If LocalX < 1 LocalX = 1
		LocalY = Abs(DYNAMITE\Y * 0.5):  If LocalY >  511 LocalY =  511:  If LocalY < 1 LocalY = 1

		Select DYNAMITE\Status
			Case "wait"
				If DYNAMITE\Entity = xEntityCollided(PLAYER_ENTITY, MAP_COLLISION)
					If DYNAMITE\Impact > 5 DYNAMITE\Impact = 0
					If (xKeyDown(32) Or xKeyDown(KEY_RIGHT)) And Abs(PLAYER_ACTIVE_Y-xEntityY(DYNAMITE\Entity)) < 0.9 And PLAYER_ACTIVE_X < DYNAMITE\X
						If DYNAMITE\Impact = 5 And MAP_MATRIX(LocalX + 1, LocalY) = ""
							MAP_MATRIX(LocalX, LocalY) = ""
							MAP_MATRIX(LocalX + 1, LocalY) = xEntityName(DYNAMITE\Entity)
							DYNAMITE\X = DYNAMITE\X + 2
							DYNAMITE\Status = "moving"
						End If
						Keypressed = True
					End If
					If (xKeyDown(30) Or xKeyDown(KEY_LEFT)) And Abs(PLAYER_ACTIVE_Y-xEntityY(DYNAMITE\Entity)) < 0.9 And PLAYER_ACTIVE_X > DYNAMITE\X
						If DYNAMITE\Impact = 5 And MAP_MATRIX(LocalX - 1, LocalY) = ""
							MAP_MATRIX(LocalX, LocalY) = ""
							MAP_MATRIX(LocalX - 1, LocalY) = xEntityName(DYNAMITE\Entity)
							DYNAMITE\X = DYNAMITE\X - 2
							DYNAMITE\Status = "moving"
						End If
						Keypressed = True
					End If
					If (xKeyDown(17) Or xKeyDown(KEY_UP)) And Abs(PLAYER_ACTIVE_X-xEntityX(DYNAMITE\Entity)) < 0.9 And PLAYER_ACTIVE_Y < DYNAMITE\Y
						If DYNAMITE\Impact = 5 And MAP_MATRIX(LocalX, LocalY - 1) = ""
							MAP_MATRIX(LocalX, LocalY) = ""
							MAP_MATRIX(Localx, LocalY - 1) = xEntityName(DYNAMITE\Entity)
							DYNAMITE\Y = DYNAMITE\Y + 2
							DYNAMITE\Status = "moving"
						End If
						Keypressed = True
					End If
					If (xKeyDown(31) Or xKeyDown(KEY_DOWN)) And Abs(PLAYER_ACTIVE_X-xEntityX(DYNAMITE\Entity)) < 0.9 And PLAYER_ACTIVE_Y > DYNAMITE\Y
						If DYNAMITE\Impact = 5 And MAP_MATRIX(LocalX, LocalY + 1) = ""
							MAP_MATRIX(LocalX, LocalY) = ""
							MAP_MATRIX(Localx, LocalY + 1) = xEntityName(DYNAMITE\Entity)
							DYNAMITE\Y = DYNAMITE\Y - 2
							DYNAMITE\Status = "moving"
						End If
						Keypressed = True
					End If
					If Keypressed DYNAMITE\Impact = DYNAMITE\Impact + 1
					If xEntityX(DYNAMITE\Entity) <> DYNAMITE\X Or xEntityY(DYNAMITE\Entity) <> DYNAMITE\Y xPlaySound SOUND_DYNAMITE_MOVE
				End If
			Case "moving"
				If xEntityX(DYNAMITE\Entity) > DYNAMITE\X xMoveEntity DYNAMITE\Entity,-0.0625, 0, 0
				If xEntityX(DYNAMITE\Entity) < DYNAMITE\X xMoveEntity DYNAMITE\Entity, 0.0625, 0, 0
				If xEntityY(DYNAMITE\Entity) > DYNAMITE\Y xMoveEntity DYNAMITE\Entity, 0,-0.0625, 0
				If xEntityY(DYNAMITE\Entity) < DYNAMITE\Y xMoveEntity DYNAMITE\Entity, 0, 0.0625, 0
				
				If xEntityX(DYNAMITE\Entity) = DYNAMITE\X And xEntityY(DYNAMITE\Entity) = DYNAMITE\Y
					DYNAMITE\Status = "wait"
				End If
		End Select
	Next
End Function

Function DeleteDynamite(Entity)
	For DYNAMITE.TYPE_DYNAMITE = Each TYPE_DYNAMITE
		If DYNAMITE\Entity = Entity
			deleteblock(DYNAMITE\Entity)
			DYNAMITE\Status$ = 0
			DYNAMITE\X#      = 0
			DYNAMITE\Y#      = 0
			DYNAMITE\TNT     = 0
			DYNAMITE\impact  = 0
			Delete DYNAMITE
		End If
	Next
End Function

Function DetonateDynamite(x, y)
	For DYNAMITE.TYPE_DYNAMITE = Each TYPE_DYNAMITE
		 If DYNAMITE\X = x And DYNAMITE\Y = y
			DeleteDynamite(DYNAMITE\Entity)
			CreateExplosion(x, y)
		 End If
	Next
End Function

Function DeleteDynamites()
	For DYNAMITE.TYPE_DYNAMITE = Each TYPE_DYNAMITE
		deleteblock(DYNAMITE\Entity)
		DYNAMITE\Status$ = 0
		DYNAMITE\X#      = 0
		DYNAMITE\Y#      = 0
		DYNAMITE\TNT     = 0
		DYNAMITE\impact  = 0
		Delete DYNAMITE
	Next
End Function

;Background
;==================================================================
Function CreateBackground()
	MAP_BACKGROUND = xLoadMesh("data\models\background.b3d")
	xPositionEntity 		 MAP_BACKGROUND, 0, 0, 2
	xScaleEntity    	   	 MAP_BACKGROUND, 0.2, 0.2, 0.2
	xEntityParent            MAP_BACKGROUND, MAP_ENTITY
	xEntityTexture           MAP_BACKGROUND, TEXTURE_GENERAL,        3, 0
	xEntityTexture           MAP_BACKGROUND, TEXTURE_GENERAL_NORMAL, 3, 1
	xSetEntityEffect 		 MAP_BACKGROUND, EFFECT_BUMP
	xSetEffectTechnique 	 MAP_BACKGROUND, "Bump"
	xSetEffectTechnique 	 MAP_BACKGROUND, "PointDistance"
	xSetEffectMatrixSemantic MAP_BACKGROUND, "MatWorldViewProj", WORLDVIEWPROJ
	xSetEffectMatrixSemantic MAP_BACKGROUND, "MatWorld", MAP_BACKGROUND
	xSetEffectVector         MAP_BACKGROUND, "AmbientClr", 0, 0, 0
	xSetEffectVector 		 MAP_BACKGROUND, "LightClr", 0.5, 0.4, 0.3
	xSetEffectFloat   	 MAP_BACKGROUND, "LightInt", 1.5
	xSetEffectFloat   	 MAP_BACKGROUND, "RngLight", 25
	xSetEffectTexture	       MAP_BACKGROUND, "tDiffuse", TEXTURE_GENERAL,        3
	xSetEffectTexture        MAP_BACKGROUND, "tNormal",  TEXTURE_GENERAL_NORMAL, 3
End Function

Function DeleteBackGround()
	FreeEntity MAP_BACKGROUND
End Function

Function UpdateBackGround()
	PLAYER_ROUNDED_X = Int(PLAYER_CAMERA_X)
	PLAYER_ROUNDED_Y = Int(PLAYER_CAMERA_Y)
	xPositionEntity MAP_BACKGROUND, PLAYER_ROUNDED_X - (PLAYER_ROUNDED_X Mod 2) + 1, PLAYER_ROUNDED_Y - (PLAYER_ROUNDED_Y Mod 2) - 1, 2
End Function

;Blocks
;==================================================================
Type TYPE_BLOCK
	Field Entity
	Field light#
End Type

Function CreateBlock(x = 0, y = 0, Name$ = "", id = 0, collision = MAP_COLLISION)
	BLOCK.TYPE_BLOCK = New TYPE_BLOCK
	If Not id Id = Int(name) - 1
	BLOCK\Light = 1.0
	
	BLOCK\Entity =		 xCreateCube()
	xEntityParent            BLOCK\Entity, MAP_ENTITY
	xNameEntity              BLOCK\Entity, Name
	xPositionEntity          BLOCK\Entity, x, y, 0
	xEntityType              BLOCK\Entity, collision
	xEntityTexture           BLOCK\Entity, TEXTURE_GENERAL,        id, 0
	xEntityTexture           BLOCK\Entity, TEXTURE_GENERAL_NORMAL, id, 1
	xSetEntityEffect 		 BLOCK\Entity, EFFECT_BUMP
	xSetEffectTechnique 	 BLOCK\Entity, "Bump"
	xSetEffectTechnique 	 BLOCK\Entity, "PointDistance"
	xSetEffectMatrixSemantic BLOCK\Entity, "MatWorldViewProj", WORLDVIEWPROJ
	xSetEffectMatrixSemantic BLOCK\Entity, "MatWorld", BLOCK\Entity
	xSetEffectVector         BLOCK\Entity, "AmbientClr", 0, 0, 0;"AmbientClr",.12,.18,.24
	xSetEffectVector 		 BLOCK\Entity, "LightClr", 1, 0.8, 0.6
	xSetEffectFloat   	 BLOCK\Entity, "LightInt", 2.5
	xSetEffectFloat   	 BLOCK\Entity, "RngLight", 25
	xSetEffectTexture	       BLOCK\Entity, "tDiffuse", TEXTURE_GENERAL,        id
	xSetEffectTexture        BLOCK\Entity, "tNormal",  TEXTURE_GENERAL_NORMAL, id
	Return BLOCK\Entity
End Function

Function DeleteBlock(Entity)
	For BLOCK.TYPE_BLOCK = Each TYPE_BLOCK
		If BLOCK\Entity = Entity
			MAP_MATRIX(Int(xEntityX(Entity)*0.5),Abs(Int(xEntityY(Entity)*0.5))) = ""
			xFreeEntity BLOCK\Entity
			Delete BLOCK
		End If
	Next
End Function

Function DeleteBlocks()
	For BLOCK.TYPE_BLOCK = Each TYPE_BLOCK
		xFreeEntity BLOCK\Entity
		Delete BLOCK
	Next
End Function

;Crystals
;==================================================================
Global TEXTURE_CRYSTAL
Global TEXTURE_CRYSTAL_NORMAL
Global CRYSTAL_ENTITY
Global CRYSTAL_PLAYERPIVOT
Global CRYSTAL_COUNT

Type TYPE_CRYSTAL
	Field Entity
	Field Glow
	Field GlowPower#
	Field Status$
	Field Y
	Field Super
End Type

Function CreateCrystal(x = 0, y = 0, Super = 0)
	CRYSTAL.TYPE_CRYSTAL = New TYPE_CRYSTAL
	
	CRYSTAL\Entity = xLoadMesh("data\models\crystal.b3d")
	xEntityParent       CRYSTAL\Entity, CRYSTAL_ENTITY
	xEntityTexture      CRYSTAL\Entity, TEXTURE_CRYSTAL       , 0, 0
	xEntityTexture      CRYSTAL\Entity, TEXTURE_CRYSTAL_NORMAL, 0, 1
	xSetEntityEffect    CRYSTAL\Entity, EFFECT_BUMP_SPECULAR
	xSetEffectTechnique CRYSTAL\Entity, "Bump"
	xPositionEntity     CRYSTAL\Entity, x, y, z
	xTurnEntity         CRYSTAL\Entity, 0, Rand(10,120)*4, 0
	
	CRYSTAL\Glow =  CreateSurface2(3)
	xPositionEntity CRYSTAL\Glow, x, y, 0
     ;xEntityParent   CRYSTAL\Glow, CRYSTAL\Entity
	xEntityTexture  CRYSTAL\Glow, TEXTURE_LIGHT , 0, 0
	xEntityColor    CRYSTAL\Glow, 30, 255, 30
	xEntityFX       CRYSTAL\Glow, 1

	CRYSTAL\Status = "wait"
	CRYSTAL\GlowPower = 1
	CRYSTAL\Super = Super
	CRYSTAL\Y = y

	If CRYSTAL\Super xEntityColor CRYSTAL\Glow,   100, 100, 255
	
End Function

Function UpdateCrystals()
	xPositionEntity CRYSTAL_PLAYERPIVOT, PLAYER_ACTIVE_X, PLAYER_ACTIVE_Y, PLAYER_ACTIVE_Z
	For CRYSTAL.TYPE_CRYSTAL = Each TYPE_CRYSTAL
		xTurnEntity     CRYSTAL\Glow, 0, 0, -0.5
		xEntityAlpha    CRYSTAL\Glow, (PLAYER_CAMERA_ZOOM - xEntityDistance(CRYSTAL\Glow, CRYSTAL_PLAYERPIVOT)) * 0.1 + CRYSTAL\Super
		xScaleEntity    CRYSTAL\Glow, Sin(MilliSecs()*0.2)*0.1+1, Sin(MilliSecs()*0.2)*0.1+1, Sin(MilliSecs()*0.2)*0.1+1
		xPositionEntity CRYSTAL\Glow, xEntityX(CRYSTAL\Entity), xEntityY(CRYSTAL\Entity) - 0.65 , 0
		
		LocalX = xEntityX(CRYSTAL\ENTITY) * 0.5
		LocalY = Abs(xEntityY(CRYSTAL\ENTITY)) * 0.5
		If (LocalX > - 1 And LocalX < 1023) And (LocalY > - 1 And LocalY < 511)
			Select CRYSTAL\Status
				Case "wait"
					If MAP_MATRIX(LocalX,LocalY + 1) = ""
						MAP_MATRIX(LocalX,LocalY + 1) = "NC" 
						MAP_MATRIX(LocalX, LocalY) = ""
						CRYSTAL\Status = "moving"
						CRYSTAL\Y = CRYSTAL\Y - 2
						Return False
					End If
					If xEntityDistance (CRYSTAL\Entity, PLAYER_ENTITY) < 1.8
						CRYSTAL\Status = "activated"
						xPlaySound(SOUND_CRYSTAL_PICKUP)
						xHideEntity CRYSTAL\Entity
					End If
				Case "moving"
					If xEntityY(CRYSTAL\Entity) > CRYSTAL\Y xMoveEntity CRYSTAL\Entity, 0,-0.125, 0
					If xEntityY(CRYSTAL\Entity) = CRYSTAL\Y CRYSTAL\Status = "wait"
				Case "activated"
					If CRYSTAL\GlowPower < 2 CRYSTAL\GlowPower = CRYSTAL\GlowPower + (CRYSTAL\GlowPower * 0.05) Else CRYSTAL\Status = "dead"
					xScaleEntity CRYSTAL\Glow, CRYSTAL\GlowPower  ,CRYSTAL\GlowPower  ,CRYSTAL\GlowPower
					xEntityAlpha CRYSTAL\Glow, (2 - CRYSTAL\GlowPower)
				Case "dead"
					If CRYSTAL\Super PLAYER_LIGHTINING = 22 Else PLAYER_LIGHTINING = PLAYER_LIGHTINING + 1
					PLAYER_CRYSTALS = PLAYER_CRYSTALS + 1
					PLAYER_SCORE = PLAYER_SCORE + 100 + 900 * CRYSTAL\Super
					xFreeEntity CRYSTAL\Entity
					xFreeEntity CRYSTAL\Glow
					MAP_MATRIX(LocalX,LocalY) = ""
					CRYSTAL\Status = ""
					CRYSTAL\GlowPower = ""
					CRYSTAL\Y = 0
					Delete CRYSTAL
			End Select
		End If
	Next
End Function

Function DeleteCrystals()
	For CRYSTAL.TYPE_CRYSTAL = Each TYPE_CRYSTAL
		xFreeEntity CRYSTAL\Entity
		xFreeEntity CRYSTAL\Glow
		CRYSTAL\Glowpower = 0
		CRYSTAL\Status   = 0
		CRYSTAL\Super    = 0
		CRYSTAL\Y = 0
		Delete CRYSTAL
	Next
End Function