From f788403f8c76d4d7baaac6fd9e9d5756bb5fd997 Mon Sep 17 00:00:00 2001
From: Ian C <ianc@noddybox.co.uk>
Date: Sun, 8 May 2005 23:37:33 +0000
Subject: *** empty log message ***

---
 .cvsignore   |    3 +-
 shockwave.bb | 3810 +++++++++++++++++++++++++++++-----------------------------
 2 files changed, 1909 insertions(+), 1904 deletions(-)

diff --git a/.cvsignore b/.cvsignore
index fcd12be..2105426 100644
--- a/.cvsignore
+++ b/.cvsignore
@@ -1 +1,2 @@
-hiscore.dat
\ No newline at end of file
+hiscore.dat
+shockwave.exe
\ No newline at end of file
diff --git a/shockwave.bb b/shockwave.bb
index 1d9031d..78bce99 100644
--- a/shockwave.bb
+++ b/shockwave.bb
@@ -1,1903 +1,1907 @@
-;
-; SHOCKWAVE (c) COPYRIGHT Ian Cowburn 2004
-;
-; $Id: shockwave.bb,v 1.9 2005-03-12 00:33:54 ianc Exp $
-;
-
-Include "gfx/font.bb"
-
-; ============================================
-; TYPES
-; ============================================
-;
-Type Particle
-	Field	id
-	Field	a#
-	Field	ai#
-	Field	spin#
-	Field	dx#,dy#,dz#
-	Field	life
-End Type
-
-Type SpriteText
-	Field	id
-	Field	txt
-	Field	a#
-	Field	ai#
-	Field	xi#
-	Field	yi#
-	Field	zi#
-	Field	life
-End Type
-	
-Type Shockwave
-	Field	id
-	Field	length
-	Field	z#
-End Type
-
-Type SWLine
-	Field	x1#,y1#
-	Field	r1,g1,b1
-	Field	x2#,y2#
-	Field	r2,g2,b2
-End Type
-
-Type Asteroid
-	Field	id
-	Field	size
-	Field	colcnt
-	Field	speed#
-	Field	dx#,dy#
-	Field	power
-	Field	split
-End Type
-
-Type PowerUp
-	Field	id
-	Field	chance
-	Field	max
-	Field	count
-End Type
-
-Type QSound
-	Field	snd
-	Field	time
-	Field	obj
-End Type
-
-; ============================================
-; CONSTS
-; ============================================
-;
-Const DEBUGMODE=False
-
-Const MAPSIZE=256
-Const FIELDSIZE=246
-
-Const RADSCALE=16
-Const RADSIZE=(MAPSIZE*2)/RADSCALE
-Const RADMID=RADSIZE/2
-
-Const TXTSIZE=256
-
-Const SPRTXTSIZE=128
-
-Const SHIPZ#=149
-Const WAVEZ#=150
-Const SHIPSZ#=2
-
-Const ASTLARGE=20
-Const ASTMEDIUM=10
-Const ASTSMALL=5
-Const ASTMAXSPEED#=0.5
-Const ASTMINSPEED#=0.4
-Const ASTSHIELD=200
-
-Const MAXSHIELD=100
-
-Const SHIPTYPE=1
-Const SWTYPE=2
-Const ASTTYPE=3
-
-Const POWNONE=0
-Const POWSPLIT=1
-Const POWTURBOTURN=2
-Const POWSHIELD=3
-Const POWFPS=4
-
-Const TURN_NORMAL#=3
-Const TURN_TURBO#=2
-Const MAXSPEED_NORMAL#=1
-Const MAXSPEED_TURBO#=2
-
-Const CAMERA_NORMAL=1
-Const CAMERA_FPS=2
-
-; ============================================
-; GLOBLS
-; ============================================
-;
-Global WINW=800
-Global WINH=600
-
-Global sw.Shockwave=Null
-
-
-; ============================================
-; MAIN
-; ============================================
-;
-Graphics3D WINW,WINH,32;,2
-
-SetBuffer BackBuffer()
-
-Global camera=CreateCamera()
-Global listener=CreateListener(camera,0.001)
-
-Dim snd_emitter(7)
-
-For f=0 To 7
-	snd_emitter(f)=CreatePivot(camera)
-Next
-
-PositionEntity snd_emitter(0),0,0,2
-PositionEntity snd_emitter(1),1,0,1
-PositionEntity snd_emitter(2),2,0,0
-PositionEntity snd_emitter(3),1,0,-1
-PositionEntity snd_emitter(4),0,0,-2
-PositionEntity snd_emitter(5),-1,0,-1
-PositionEntity snd_emitter(6),-2,0,0
-PositionEntity snd_emitter(7),-1,0,1
-
-CameraRange camera,0.1,10000
-CameraFogMode camera,0
-
-AmbientLight 255,255,255
-
-Global vectex=CreateVectex()
-Global asttex=CreateAsttex()
-Global powertex=CreatePowertex()
-Global shieldtex=CreateShieldtex()
-Global maptex=CreateMaptex()
-Global radar=CreateTexture(RADSIZE,RADSIZE,1+2+16+32+256)
-Global hud=CreateTexture(TXTSIZE,TXTSIZE,1+2+16+32+256)
-
-Global ship=CreateShip()
-Global particle=CreateParticle()
-Global large_asteroid=CreateAsteroid(ASTLARGE)
-Global medium_asteroid=CreateAsteroid(ASTMEDIUM)
-Global small_asteroid=CreateAsteroid(ASTSMALL)
-Global map=CreateMap()
-Global radar_spr=CreateSprite(camera)
-Global hud_spr=CreateSprite(camera)
-
-Global start_sfx=Load3DSound("sfx/start.wav")
-Global bonus_level_sfx=Load3DSound("sfx/bonus_level.wav")
-Global laugh_sfx=Load3DSound("sfx/laugh.wav")
-Global explode_sfx=Load3DSound("sfx/explode.wav")
-Global pop_sfx=Load3DSound("sfx/pop.wav")
-Global turbostart_sfx=Load3DSound("sfx/powerstart.wav")
-Global turbostop_sfx=Load3DSound("sfx/powerstop.wav")
-Global turnstart_sfx=Load3DSound("sfx/powerstart.wav")
-Global turnstop_sfx=Load3DSound("sfx/powerstop.wav")
-Global smartbomb_sfx=Load3DSound("sfx/smartbomb.wav")
-
-HideEntity particle
-HideEntity large_asteroid
-HideEntity medium_asteroid
-HideEntity small_asteroid
-
-EntityType ship,SHIPTYPE
-EntityRadius large_asteroid,ASTLARGE/2
-EntityRadius medium_asteroid,ASTMEDIUM/2
-EntityRadius small_asteroid,ASTSMALL/2
-EntityRadius ship,SHIPSZ
-
-;Collisions ASTTYPE,SWTYPE,2,1
-;Collisions ASTTYPE,SHIPTYPE,2,0
-Collisions ASTTYPE,ASTTYPE,1,1
-
-PositionEntity radar_spr,7,5,15
-EntityTexture radar_spr,radar
-PositionEntity hud_spr,0,0,2
-EntityTexture hud_spr,hud
-ScaleSprite hud_spr,1.15,0.85
-
-Global fps_camera=CreateCamera(ship)
-Global fps_radar_spr=CreateSprite(fps_camera)
-Global fps_hud_spr=CreateSprite(fps_camera)
-PositionEntity fps_radar_spr,7.4,5.3,9
-EntityTexture fps_radar_spr,radar
-PositionEntity fps_hud_spr,0,0,2
-EntityTexture fps_hud_spr,hud
-ScaleSprite fps_hud_spr,1.85,1.45
-TurnEntity fps_camera,-70,0,0
-MoveEntity fps_camera,0,5,-15
-CameraProjMode camera,0
-
-Global current_camera=camera
-
-Global globang=0
-Global start_level=1
-Global start_bonus=0
-Global quit=False
-Global MAX_SPEED#=MAXSPEED_NORMAL
-Global turn#=TURN_NORMAL
-Global speed#=0
-Global score=0
-Global shield=0
-Global dead=False
-Global highscore=0
-Global highlostchain=0
-Global new_highscore=False
-Global new_highlostchain=False
-Global hit_count=0
-Global hit_timer=0
-Global turbo_count=0
-Global turn_count=0
-Global fps_count=0
-Global is_bonus_level=False
-
-LoadHighScore()
-
-CreatePowerUp(POWSPLIT,99,1)
-CreatePowerUp(POWSHIELD,97,0)
-CreatePowerUp(POWTURBOTURN,95,10)
-CreatePowerUp(POWFPS,98,2)
-
-SetCamera(CAMERA_NORMAL)
-
-Global timer=CreateTimer(100)
-
-Restore InstructionData
-Read a$
-Global instruction$
-
-While a$<>"END"
-	instruction$=instruction$+a$
-	Read a$
-Wend
-
-Repeat
-
-	SetCameraFOV(60)
-
-	Menu()
-	
-	If quit
-		Exit
-	EndIf
-
-	speed=0
-	MAX_SPEED#=MAXSPEED_NORMAL
-	turn#=TURN_NORMAL
-	
-	ClearText()
-	
-	PositionEntity ship,0,0,SHIPZ
-	RotateMesh ship,0,0,0
-	
-	ClearParticles()
-	ClearSpriteText()
-	InitShockwave(180,WAVEZ)
-	InitAsteroids()
-	
-	score=0
-	shield=MAXSHIELD
-	dead=False
-	done=False
-	level=start_level
-	total_chain=0
-	hit_timer=0
-	hit_count=0
-	
-	new_level=True
-	end_level=False
-	
-	FlushKeys
-	Delete Each QSound
-	
-	While (Not dead) And (Not done) And (Not KeyHit(1))
-	
-		If new_level
-		
-			If (level Mod 5)=0
-				is_bonus_level=True
-			Else
-				is_bonus_level=False
-			EndIf
-			
-			ClearText()
-			
-			ResetPowerUps()
-			
-			AddScore(0)
-			SubShield(0)
-			
-			noast=5+2*level
-			
-			If noast>100
-				noast=100
-			EndIf
-	
-			For f=1 To noast
-				NewAsteroid(ASTLARGE,Rand(-FIELDSIZE,FIELDSIZE),Rand(-FIELDSIZE,FIELDSIZE))
-			Next
-			
-			If is_bonus_level
-				For f=30 To 50 Step 4
-					NewCameraSpriteText("BONUS LEVEL "+Str$(level),$ffffff,0,0,EntityZ(camera)+f,-0.4,1,0.01)
-				Next
-				
-				EmitSound(bonus_level_sfx,camera)
-			Else
-				For f=30 To 50 Step 4
-					NewCameraSpriteText("LEVEL "+Str$(level),$ffffff,0,0,EntityZ(camera)+f,-0.4,1,0.01)
-				Next
-				
-				EmitSound(start_sfx,camera)
-			EndIf
-			
-			total_chain=0
-			hit_count=0
-			turn_count=0
-			turbo_count=0
-			new_level=False
-		EndIf
-	
-		If (First Asteroid)=Null And (Not end_level)
-			If hit_timer>0
-				hit_timer=0
-				
-				If hit_count>5
-					bonus=hit_count*50
-					NewCameraSpriteText("CHAIN BONUS",$ff0000,0,5,EntityZ(camera)+50,-0.2,1,0.005)
-					NewCameraSpriteText(Str$(bonus),$ffff00,0,3,EntityZ(camera)+50,-0.2,1,0.005)
-					AddScore(bonus)
-					total_chain=total_chain+hit_count
-				EndIf
-			EndIf
-
-			end_level=True
-			end_levelc=500
-			
-			HudTextCentre(50,"LEVEL COMPLETE!",$ffffff)
-
-			If start_bonus>0
-				HudTextCentre(100,"START BONUS",$ff0000)
-				HudTextCentre(110,Str$(start_bonus),$ffff00)
-				AddScore(start_bonus)
-				start_bonus=0
-			EndIf
-			
-			If total_chain>0
-				bonus=total_chain*17
-				HudTextCentre(160,"CHAIN BONUS",$ff0000)
-				HudTextCentre(170,Str$(bonus),$ffff00)
-				AddScore(bonus)
-			EndIf
-				
-			If shield=0
-				HudTextCentre(190,"SECRET ZERO SHIELD BONUS",$ff0000)
-				HudTextCentre(200,"99999",$ffff00)
-				AddScore(99999)
-				SubShield(-MAXSHIELD)
-			ElseIf shield=MAXSHIELD
-				HudTextCentre(190,"PERFECT SHIELD BONUS",$ff0000)
-				HudTextCentre(200,"20000",$ffff00)
-				AddScore(20000)
-			ElseIf total_chain>0
-				bonus=total_chain
-				
-				If (shield+bonus)>MAXSHIELD
-					bonus=MAXSHIELD-shield
-				EndIf
-				
-				HudTextCentre(190,"NEW SHIELDS WON",$ff0000)
-				HudTextCentre(200,Str$(bonus),$ffff00)
-				SubShield(-bonus)
-			EndIf
-
-			level=level+1
-		EndIf
-		
-		If end_level
-			end_levelc=end_levelc-1
-			
-			If end_levelc<200
-				HudTextCentre(128,"GET READY!",$ffffff)
-			EndIf
-			
-			If end_levelc=0
-				end_level=False
-				new_level=True
-			EndIf
-		EndIf
-		
-		If turn_count>0
-			turn_count=turn_count-1
-			
-			If turn_count=0
-				CircleQSound(turnstop_sfx,1)
-				turn=TURN_NORMAL
-			EndIf
-		EndIf
-	
-		If turbo_count>0
-			turbo_count=turbo_count-1
-			
-			If turbo_count=0
-				CircleQSound(turbostop_sfx,1)
-				MAX_SPEED=MAXSPEED_NORMAL
-			EndIf
-		EndIf
-	
-		If fps_count>0
-			fps_count=fps_count-1
-			
-			If fps_count=0
-				CircleQSound(turbostop_sfx,1)
-				SetCamera(CAMERA_NORMAL)
-			EndIf
-		EndIf
-	
-		If KeyDown(203)
-			TurnEntity ship,0,0,turn
-		EndIf
-		
-		If KeyDown(205)
-			TurnEntity ship,0,0,-turn
-		EndIf
-		
-		If KeyHit(25)
-			FlushKeys
-			c=$ffff00
-			ci=-$111100
-			While (Not KeyHit(25)) And (Not KeyHit(1))
-				HudTextCentre(124,"P A U S E D",c)
-				c=c+ci
-				If c=0 Or c=$ffff00 Then ci=-ci
-				RenderWorld
-				Flip
-			Wend
-			HudTextCentre(124,"           ",$ffff00)
-		EndIf
-		
-		If speed<MAX_SPEED
-			speed=speed+0.02
-			If speed>MAX_SPEED Then speed=MAX_SPEED
-		ElseIf speed>MAX_SPEED
-			speed=speed-0.02
-			If speed<MAX_SPEED Then speed=MAX_SPEED
-		EndIf
-		
-		If hit_timer>0
-			hit_timer=hit_timer-1
-			
-			If hit_timer=0
-				If hit_count>5
-					bonus=hit_count*50
-					NewCameraSpriteText("CHAIN BONUS",$ff0000,0,5,EntityZ(camera)+50,-0.2,1,0.005)
-					NewCameraSpriteText(Str$(bonus),$ff0000,0,3,EntityZ(camera)+50,-0.2,1,0.005)
-					AddScore(bonus)
-					total_chain=total_chain+hit_count
-				EndIf
-				
-				hit_count=0
-			EndIf
-		EndIf
-		
-		MoveEntity ship,0,speed,0
-		
-		PositionEntity camera,EntityX(ship),EntityY(ship),0
-		;PointEntity camera,ship
-		
-		UpdateParticles()
-		UpdateSpriteText()
-	
-		UpdateWorld
-		
-		RenderWorld
-		
-		UpdateAsteroids()
-	
-		AddShockwave(ship)
-		
-		DrawRadar()
-		
-		ex=EntityX(ship)
-		ey=EntityY(ship)
-		
-		If ex<-MAPSIZE Or ex>MAPSIZE
-			RotateEntity ship,0,0,-EntityRoll(ship)
-			MoveEntity ship,0,speed,0
-		EndIf
-		
-		If ey<-MAPSIZE Or ey>MAPSIZE
-			RotateEntity ship,0,0,180-EntityRoll(ship)
-			MoveEntity ship,0,speed,0
-		EndIf
-
-		ProcessQSounds()
-		Flip
-		
-		WaitTimer(timer)
-		
-		globang=(globang+10) Mod 360
-		
-		If DEBUGMODE
-			If KeyHit(200)
-				MAX_SPEED=MAX_SPEED+0.1
-				NewCameraSpriteText(Str$(MAX_SPEED),$ff0000,0,5,EntityZ(camera)+50,-0.2,1,0.005)
-			EndIf
-			If KeyHit(208)
-				MAX_SPEED=MAX_SPEED-0.1
-				NewCameraSpriteText(Str$(MAX_SPEED),$ff0000,0,5,EntityZ(camera)+50,-0.2,1,0.005)
-			EndIf
-			If KeyHit(64)
-				For ast.Asteroid=Each Asteroid
-					FreeEntity ast\id
-					Delete ast
-				Next
-				NewCameraSpriteText("DELALL",$ff0000,0,5,EntityZ(camera)+50,-0.2,1,0.005)
-			EndIf
-			If KeyHit(65)
-				SubShield(shield)
-				NewCameraSpriteText("NOSHLD",$ff0000,0,5,EntityZ(camera)+50,-0.2,1,0.005)
-			EndIf
-			If KeyHit(66)
-				SubShield(-MAXSHIELD)
-				NewCameraSpriteText("FULLSHLD",$ff0000,0,5,EntityZ(camera)+50,-0.2,1,0.005)
-			EndIf
-		EndIf
-		
-	Wend
-	
-	SetCamera(CAMERA_NORMAL)
-	
-	new_highscore=False
-	new_highlostchain=False
-	
-	If dead
-	
-		CircleQSound(explode_sfx,25)
-	
-		fov#=60
-		
-		NewCameraSpriteText("GAME OVER!",$ffffff,0,0,EntityZ(camera)+0.5,0,0.1,-0.005)
-		
-		If hit_count>5
-			NewCameraSpriteText("LOST A",$800000,0,-2,EntityZ(camera)+0.5,0,0.1,-0.005)
-			NewCameraSpriteText("CHAIN OF",$800000,0,-4,EntityZ(camera)+0.5,0,0.1,-0.005)
-			NewCameraSpriteText(Str$(hit_count)+"!",$800000,0,-6,EntityZ(camera)+0.5,0,0.1,-0.005)
-		EndIf
-		
-		If score>highscore
-			new_highscore=True
-			highscore=score
-		EndIf
-		
-		If hit_count>5 And hit_count>highlostchain
-			new_highlostchain=True
-			highlostchain=hit_count
-		EndIf
-		
-		If new_highscore Or new_highlostchain
-			SaveHighScore()
-		EndIf
-		
-		f=0
-	
-		While (f<700) And (Not (KeyDown(57) Or KeyDown(1)))
-			ProcessQSounds()
-			SetCameraFOV(fov)
-			If fov<175
-				fov=fov+1
-			EndIf
-			UpdateAsteroids()
-			DrawRadar()
-			UpdateParticles()
-			UpdateSpriteText()
-			UpdateWorld
-			RenderWorld
-			Flip
-			f=f+1
-		Wend
-		
-		While fov>60
-			ProcessQSounds()
-			SetCameraFOV(fov)
-			fov=fov-5
-			UpdateAsteroids()
-			DrawRadar()
-			UpdateParticles()
-			UpdateSpriteText()
-			UpdateWorld
-			RenderWorld
-			Flip
-		Wend
-		
-		SetCameraFOV(60)
-		
-	EndIf
-	
-Forever
-
-End
-
-; ============================================
-; Utils
-; ============================================
-;
-.Utils
-
-Function SetCamera(cam)
-	Select cam
-		Case CAMERA_NORMAL
-			CameraProjMode camera,1
-			CameraProjMode fps_camera,0
-			ShowEntity hud_spr
-			ShowEntity radar_spr
-			HideEntity fps_hud_spr
-			HideEntity fps_radar_spr
-			current_camera=camera
-		Case CAMERA_FPS
-			CameraProjMode camera,0
-			CameraProjMode fps_camera,1
-			HideEntity hud_spr
-			HideEntity radar_spr
-			ShowEntity fps_hud_spr
-			ShowEntity fps_radar_spr
-			current_camera=fps_camera
-	End Select
-End Function
-
-Function SetCameraFOV(FOV#)
-   CameraZoom camera, 1.0 / Tan(FOV#/2.0)
-End Function
-
-Function Info()
-	Color 255,255,255
-	Text 0,0,"M:"+MeshWidth(ship)+","+MeshHeight(ship)+","+MeshDepth(ship)
-	Text 0,10,"S:"+MeshWidth(sw\id)+","+MeshHeight(sw\id)+","+MeshDepth(sw\id)
-End Function
-
-Function AddScore(s)
-	score=score+s
-	HudText(0,0,"SCORE")
-	HudTextCol(48,0,score,$ff0000)
-End Function
-
-Function SubShield(s)
-	orig=shield
-	shield=shield-s
-	If shield<0 And (Not dead) Then shield=0:dead=True:EmitSound(laugh_sfx,snd_emitter(Rand(0,7)))
-	If shield>300 Then shield=300
-	If orig=>50 And shield<50 Then EmitSound(laugh_sfx,snd_emitter(Rand(0,7)))
-	If orig=>20 And shield<20 Then EmitSound(laugh_sfx,snd_emitter(Rand(0,7)))
-	HudText(150,0,"SHEILD")
-	HudTextCol(206,0,shield+" ",$ff0000)
-End Function
-
-Function ClearTexture(t)
-	w=TextureWidth(t)-1
-	h=TextureHeight(t)-1
-	b=TextureBuffer(t)
-	LockBuffer b
-	For x=0 To w
-		For y=0 To h
-			WritePixelFast x,y,0,b
-		Next
-	Next
-	UnlockBuffer b
-End Function
-
-Function RectTexture(t,x,y,w,h,c)
-	tw=TextureWidth(t)-1
-	th=TextureHeight(t)-1
-	b=TextureBuffer(t)
-	LockBuffer b
-	For xc=x To x+w-1
-		For yc=y To y+h-1
-			If xc>=0 And xc<tw And yc>=0 And yc<th
-				WritePixelFast xc,yc,c,b
-			EndIf
-		Next
-	Next
-	UnlockBuffer b
-End Function
-
-; ============================================
-; Collisions
-; ============================================
-;
-.Collisions
-
-Function HitSW(e,size)
-	size=size/2
-	ex=EntityX(e)
-	ey=EntityY(e)
-	
-	eminx=ex-size
-	emaxx=ex+size
-	
-	eminy=ey-size
-	emaxy=ey+size
-	
-	Return MeshesIntersect(e,sw\id)
-End Function
-
-
-; ============================================
-; Sprite Text
-; ============================================
-;
-.SpriteTextRoutines
-
-Function ClearSpriteText()
-	For s.SpriteText=Each SpriteText
-		FreeEntity s\id
-		FreeTexture s\txt
-		Delete s
-	Next
-End Function
-
-Function UpdateSpriteText()
-	For s.SpriteText=Each SpriteText
-	
-		If s\life=0
-			s\a=s\a-s\ai
-
-			If s\a<0.05
-				FreeEntity s\id
-				FreeTexture s\txt
-				Delete s
-			Else
-				EntityAlpha s\id,s\a
-				MoveEntity s\id,0,0,s\zi
-			EndIf
-		Else
-			s\life=s\life-1
-			
-			If s\life=0
-				FreeEntity s\id
-				FreeTexture s\txt
-				Delete s
-			Else
-				MoveEntity s\id,s\xi,s\yi,s\zi
-			EndIf
-		EndIf
-		
-	Next
-End Function
-
-Function NewSpriteText(a$,col,x#,y#,z#,zi#,al#,ai#)
-	s.SpriteText=New SpriteText
-	s\txt=CreateTexture(SPRTXTSIZE,SPRTXTSIZE,1+2+16+32)
-	s\id=CreateSprite()
-	s\a=al
-	s\ai=ai
-	s\zi=zi
-	s\xi=0
-	s\yi=0
-	s\life=0
-
-	ScaleSprite s\id,20,20	
-	EntityTexture s\id,s\txt
-	PositionEntity s\id,x,y,z
-	EntityAlpha s\id,al
-	
-	ClearTexture(s\txt)
-	TextureText(s\txt,a$,col)
-End Function
-
-Function NewCameraSpriteText(a$,col,x#,y#,z#,zi#,al#,ai#)
-	s.SpriteText=New SpriteText
-	s\txt=CreateTexture(SPRTXTSIZE,SPRTXTSIZE,1+2+16+32)
-	s\id=CreateSprite(current_camera)
-	s\a=al
-	s\ai=ai
-	s\zi=zi
-	s\xi=0
-	s\yi=0
-	s\life=0
-
-	ScaleSprite s\id,10,10	
-	EntityTexture s\id,s\txt
-	PositionEntity s\id,x,y,z
-	EntityAlpha s\id,al
-	
-	ClearTexture(s\txt)
-	TextureText(s\txt,a$,col)
-End Function
-
-Function NewCameraSpriteTextScroll(a$,col,x#,y#,z#,xi#,yi#,zi#,life)
-	s.SpriteText=New SpriteText
-	s\txt=CreateTexture(SPRTXTSIZE,SPRTXTSIZE,1+2+16+32)
-	s\id=CreateSprite(camera)
-	s\a=al
-	s\ai=ai
-	s\zi=zi
-	s\xi=xi
-	s\yi=yi
-	s\life=life
-
-	ScaleSprite s\id,1,1
-	EntityTexture s\id,s\txt
-	PositionEntity s\id,x,y,z
-	EntityAlpha s\id,1
-	
-	ClearTexture(s\txt)
-	TextureText(s\txt,a$,col)
-End Function
-
-; ============================================
-; Text
-; ============================================
-;
-.TextRoutines
-
-Function ClearText()
-	b=TextureBuffer(hud)
-	LockBuffer b
-	For x=0 To TXTSIZE-1
-		For y=0 To TXTSIZE-1
-			WritePixelFast x,y,0,b
-		Next
-	Next
-	UnlockBuffer b
-End Function
-
-Function HudText(tx,ty,a$)
-	b=TextureBuffer(hud)
-	LockBuffer b
-	
-	For f=1 To Len(a$)
-		c=Asc(Mid$(a$,f,1))-32
-		For x=0 To 7
-			For y=0 To 7
-				WritePixelFast tx+x,ty+y,font_data(c,x,y),b
-			Next
-		Next
-		tx=tx+8
-	Next
-	UnlockBuffer b
-End Function
-
-
-Function HudTextCol(tx,ty,a$,col)
-	b=TextureBuffer(hud)
-	LockBuffer b
-	
-	For f=1 To Len(a$)
-		c=Asc(Mid$(a$,f,1))-32
-		For x=0 To 7
-			For y=0 To 7
-				WritePixelFast tx+x,ty+y,(font_data(c,x,y) And $ff000000) Or (font_data(c,x,y) And col),b
-			Next
-		Next
-		tx=tx+8
-	Next
-	UnlockBuffer b
-End Function
-
-
-Function HudTextCentre(ty,a$,col)
-	tx=TXTSIZE/2-Len(a$)*4
-	b=TextureBuffer(hud)
-	LockBuffer b
-	
-	For f=1 To Len(a$)
-		c=Asc(Mid$(a$,f,1))-32
-		For x=0 To 7
-			For y=0 To 7
-				WritePixelFast tx+x,ty+y,(font_data(c,x,y) And $ff000000) Or (font_data(c,x,y) And col),b
-			Next
-		Next
-		tx=tx+8
-	Next
-	UnlockBuffer b
-End Function
-
-
-Function TextureText(t,a$,col)
-	ty=TextureHeight(t)/2-4
-	tx=TextureWidth(t)/2-Len(a$)*4
-	b=TextureBuffer(t)
-	LockBuffer b
-	
-	For f=1 To Len(a$)
-		c=Asc(Mid$(a$,f,1))-32
-		For x=0 To 7
-			For y=0 To 7
-				WritePixelFast tx+x,ty+y,(font_data(c,x,y) And $ff000000) Or (font_data(c,x,y) And col),b
-			Next
-		Next
-		tx=tx+8
-	Next
-	UnlockBuffer b
-End Function
-
-
-; ============================================
-; Radar
-; ============================================
-;
-.Radar
-
-Function DrawRadar()
-	b=TextureBuffer(radar)
-	LockBuffer b
-	For x=0 To RADSIZE-1
-		For y=0 To RADSIZE-1
-			WritePixelFast x,y,$20ffffff,b
-		Next
-	Next
-
-	x=RADMID+EntityX(ship)/RADSCALE
-
-	If x<0
-		x=0
-	EndIf
-
-	If x>=RADSIZE
-		x=RADSIZE-1
-	EndIf
-	
-	For y=0 To RADSIZE-1
-		WritePixelFast x,y,$7fffffff,b
-	Next
-	
-	y=RADMID-EntityY(ship)/RADSCALE
-
-	If y<0
-		y=0
-	EndIf
-
-	If y>=RADSIZE
-		y=RADSIZE-1
-	EndIf
-	
-	For x=0 To RADSIZE-1
-		WritePixelFast x,y,$7fffffff,b
-	Next
-	
-	For a.Asteroid=Each Asteroid
-		If a\size=ASTLARGE
-			c=$ffffff00
-		ElseIf a\size=ASTMEDIUM
-			c=$ffc8c8c8
-		Else
-			c=$ffa0a0a0
-		EndIf
-		x=RADMID+EntityX(a\id)/RADSCALE
-		y=RADMID-EntityY(a\id)/RADSCALE
-		
-		If x>-1 And x<RADSIZE And y>-1 And y<RADSIZE
-			WritePixelFast x,y,c,b
-		EndIf
-	Next
-	UnlockBuffer b
-End Function
-
-
-; ============================================
-; Asteroids
-; ============================================
-;
-.Asteroids
-
-Function InitAsteroids()
-	For a.Asteroid=Each Asteroid
-		FreeEntity a\id
-		Delete a
-	Next
-End Function
-
-
-Function NewAsteroid(size,x#,y#)
-	a.Asteroid=New Asteroid
-	
-	If size=ASTLARGE
-		a\id=CopyEntity(large_asteroid)
-	ElseIf size=ASTMEDIUM
-		a\id=CopyEntity(medium_asteroid)
-	Else
-		a\id=CopyEntity(small_asteroid)
-	EndIf
-	
-	a\size=size
-	
-	EntityTexture a\id,shieldtex
-	PositionEntity a\id,x,y,WAVEZ
-	
-	a\colcnt=ASTSHIELD
-	
-	a\speed#=Rnd(ASTMINSPEED,ASTMAXSPEED)
-	ang=Rand(360)
-	
-	a\dx=Sin(ang)*a\speed
-	a\dy=Cos(ang)*a\speed
-	
-	a\power=PowerUp()
-	a\split=False
-	
-End Function
-
-
-Function UpdateAsteroids()
-
-	If False
-		sz=32
-		i=CreateImage(sz,sz)
-		CopyRect 0,0,sz,sz-1,0,1,TextureBuffer(shieldtex),ImageBuffer(i)
-		CopyRect 0,sz-1,sz,1,0,0,TextureBuffer(shieldtex),ImageBuffer(i)
-		CopyRect 0,0,sz,sz,0,0,ImageBuffer(i),TextureBuffer(shieldtex)
-		FreeImage i
-		RotateTexture shieldtex,globang
-	EndIf
-	
-	do_split=False
-	
-	For a.Asteroid=Each Asteroid
-	
-		upd=True
-		
-		If a\colcnt>0
-			a\colcnt=a\colcnt-1
-			
-			If a\colcnt=0
-				If a\power=POWNONE
-					EntityTexture a\id,asttex
-				Else
-					EntityTexture a\id,powertex
-				EndIf
-				EntityType a\id,ASTTYPE
-			EndIf
-			
-			hit_ship=False
-			hit_sw=False
-		Else
-			hit_ship=EntityDistance(a\id,ship)<(a\size/2+SHIPSZ)
-			hit_sw=HitSW(a\id,a\size)
-		EndIf
-		
-		If hit_ship
-			SubShield(1)
-			NewParticleMove(particle,EntityX(ship),EntityY(ship),EntityZ(ship)-1,10,2,Rnd(-2,2),Rnd(-2,2),0)
-		ElseIf hit_sw Or a\split
-		
-			If Not dead
-				AddScore(a\size)
-				
-				hit_timer=200
-				hit_count=hit_count+1
-				
-				If Not a\split
-					EmitSound(pop_sfx,a\id)
-					dz#=0.1
-					For f=10 To 100 Step 10
-						NewAlphaParticleMove(particle,EntityX(a\id),EntityY(a\id),EntityZ(a\id)-f,1.0,-0.01,f/10,0,0,dz)
-						dz=dz+0.1
-					Next
-				EndIf
-	
-				If a\size>ASTSMALL
-					x#=EntityX(a\id)
-					y#=EntityY(a\id)
-					
-					NewAsteroid(a\size/2,x,y)
-					NewAsteroid(a\size/2,x,y)
-				EndIf
-				
-				If a\power<>POWNONE
-					If a\split
-						ReturnPowerUp(a\power)
-					Else
-						Select a\power
-							Case POWSPLIT
-								NewCameraSpriteText("SMART BOMB!",$ff0000,0,0,EntityZ(camera)+30,-0.4,1,0.01)
-								do_split=True
-								CircleQSound(smartbomb_sfx,2)
-							
-							Case POWSHIELD
-								NewCameraSpriteText("SHEILD UP!",$ff0000,0,0,EntityZ(camera)+31,-0.4,1,0.01)
-								SubShield(-10)
-								
-							Case POWTURBOTURN
-								If Rand(100)>50
-									NewCameraSpriteText("TURBO NUTTER!",$ff0000,0,0,EntityZ(camera)+32,-0.4,1,0.01)
-									CircleQSOund(turbostart_sfx,1)
-									turbo_count=turbo_count+500
-									MAX_SPEED=MAXSPEED_TURBO
-								Else
-									NewCameraSpriteText("TURN LOSS!",$ff0000,0,0,EntityZ(camera)+33,-0.4,1,0.01)
-									CircleQSound(turnstart_sfx,1)
-									turn_count=turn_count+500
-									turn=TURN_TURBO
-								EndIf
-							Case POWFPS
-								SetCamera(CAMERA_FPS)
-								NewCameraSpriteText("FPS MODE!",$ff0000,0,0,EntityZ(camera)+33,-0.4,1,0.01)
-								CircleQSOund(laugh_sfx,4)
-								fps_count=fps_count+1000
-						End Select
-					EndIf
-				EndIf
-		
-				FreeEntity a\id
-				Delete a
-				upd=False
-			EndIf
-		EndIf
-		
-		If upd
-			If CountCollisions(a\id)>0
-				a\dx=CollisionNX(a\id,1)*a\speed
-				a\dy=CollisionNY(a\id,1)*a\speed
-			EndIf
-			
-			TurnEntity a\id,0,a\dx*2,0
-			TranslateEntity a\id,a\dx,a\dy,0
-			
-			ex=EntityX(a\id)
-			ey=EntityY(a\id)
-			
-			If ex<-MAPSIZE Or ex>MAPSIZE
-				s=Sgn(ex)
-				PositionEntity a\id,s*MAPSIZE,ey,WAVEZ
-				a\dx=-a\dx
-			EndIf
-
-			If ey<-MAPSIZE Or ey>MAPSIZE
-				s=Sgn(ey)
-				PositionEntity a\id,ex,s*MAPSIZE,WAVEZ
-				a\dy=-a\dy
-			EndIf
-		EndIf
-	Next
-	
-	If do_split
-		For a=Each Asteroid
-			a\split=True
-		Next
-	EndIf
-
-End Function
-
-
-; ============================================
-; Shockwave
-; ============================================
-;
-.Shochwave
-
-Function InitShockwave(length,z#)
-	If sw<>Null
-		FreeEntity sw\id
-	Else
-		sw=New Shockwave
-	EndIf
-	
-	Delete Each SWLine
-	CreateSWLine(0,0,0)
-	
-	sw\length=length
-	sw\id=CreateMesh()
-	PositionEntity sw\id,0,0,z
-	EntityType sw\id,SWTYPE
-	EntityRadius sw\id,1
-	CreateSurface(sw\id)
-	sw\z=z
-	
-	EntityFX sw\id,1+2+16+32
-End Function
-
-
-Function CreateSWLine.SWLine(x#,y#,roll#)
-	s.SWLine=New SWLine
-	sz#=0.5
-	
-	s\x1=x-sz*Cos(roll)
-	s\x2=x+sz*Cos(roll)
-	s\y1=y-sz*Sin(roll)
-	s\y2=y+sz*Sin(roll)
-	
-	s\r1=Rand(100,255)
-	s\g1=Rand(0,100)
-	s\b1=Rand(0,100)
-	s\r2=Rand(100,255)
-	s\g2=Rand(0,100)
-	s\b2=Rand(0,100)
-End Function
-
-
-Function AddShockwave(base)
-
-	x#=EntityX(base)
-	y#=EntityY(base)
-	roll#=EntityRoll(base)
-	
-	CreateSWLine(x,y,roll)
-	
-	If sw\length>0
-		sw\length=sw\length-1
-	Else
-		Delete First SWLine
-	EndIf
-		
-	s=GetSurface(sw\id,1)
-	ClearSurface s,True,True
-	
-	al#=0.1
-	
-	prev.SWLine=Null
-	
-	For sl.SWLine=Each SWLine
-		If prev<>Null
-			If True
-				v0=AddVertex(s,sl\x1,sl\y1,0)
-				v1=AddVertex(s,sl\x2,sl\y2,0)
-				v2=AddVertex(s,prev\x1,prev\y1,0)
-				v3=AddVertex(s,prev\x2,prev\y2,0)
-				
-				VertexColor s,v0,sl\r1,sl\g1,sl\b1,al
-				VertexColor s,v1,sl\r2,sl\g2,sl\b2,al
-				VertexColor s,v2,prev\r1,prev\g1,prev\b1,al
-				VertexColor s,v3,prev\r2,prev\g2,prev\b2,al
-	
-				AddTriangle(s,v0,v1,v2)
-				AddTriangle(s,v1,v3,v2)
-			EndIf
-			
-			If False
-				v0=AddVertex(s,sl\x1,sl\y1,-1)
-				v1=AddVertex(s,sl\x2,sl\y2,-1)
-				v2=AddVertex(s,prev\x1,prev\y1,-1)
-				v3=AddVertex(s,prev\x2,prev\y2,-1)
-				v4=AddVertex(s,sl\x1,sl\y1,1)
-				v5=AddVertex(s,sl\x2,sl\y2,1)
-				v6=AddVertex(s,prev\x1,prev\y1,1)
-				v7=AddVertex(s,prev\x2,prev\y2,1)
-				
-				VertexColor s,v0,sl\r1,sl\g1,sl\b1,al
-				VertexColor s,v1,sl\r2,sl\g2,sl\b2,al
-				VertexColor s,v2,prev\r1,prev\g1,prev\b1,al
-				VertexColor s,v3,prev\r2,prev\g2,prev\b2,al
-	
-				AddTriangle(s,v0,v1,v2)
-				AddTriangle(s,v1,v3,v2)
-				AddTriangle(s,v4,v6,v5)
-				AddTriangle(s,v4,v6,v7)
-			EndIf
-
-			If al<1.0
-				al=al+0.05
-			EndIf
-		EndIf
-		
-		prev=sl
-	Next
-End Function
-
-
-; ============================================
-; Particles
-; ============================================
-;
-.Particles
-
-Function ClearParticles()
-	For p.Particle=Each Particle
-		FreeEntity p\id
-		Delete p
-	Next
-End Function
-
-Function UpdateParticles()
-	For p.Particle=Each Particle
-		If p\life=0 Or p\a<=0
-			FreeEntity p\id
-			Delete p
-		Else
-			p\life=p\life-1
-			p\a=p\a+p\ai
-			EntityAlpha p\id,p\a
-			TurnEntity p\id,0,0,p\spin
-			MoveEntity p\id,p\dx,p\dy,p\dz
-		EndIf
-	Next
-End Function
-
-Function NewParticle(base,x#,y#,z#,life,spin#)
-	NewParticleMove(base,x,y,z,life,spin,0,0,0)
-End Function
-
-Function NewParticleMove(base,x#,y#,z#,life,spin#,dx#,dy#,dz#)
-	p.Particle=New Particle
-	p\id=CopyEntity(base)
-	ShowEntity p\id
-	PositionEntity p\id,x,y,z
-	p\life=life
-	p\a=1.0
-	p\dx=dx
-	p\dy=dy
-	p\dz=dz
-	p\spin=spin
-End Function
-
-Function NewAlphaParticle(base,x#,y#,z#,a#,ai#,spin#)
-	NewAlphaParticleMove(base,x,y,z,a,ai,spin,0,0,0)
-End Function
-
-Function NewAlphaParticleMove(base,x#,y#,z#,a#,ai#,spin#,dx#,dy#,dz#)
-	p.Particle=New Particle
-	p\id=CopyEntity(base)
-	ShowEntity p\id
-	EntityAlpha p\id,a
-	PositionEntity p\id,x,y,z
-	p\life=9999999
-	p\a=a
-	p\ai=ai
-	p\dx=dx
-	p\dy=dy
-	p\dz=dz
-	p\spin=spin
-End Function
-
-
-; ============================================
-; Mesh and Texture
-; ============================================
-;
-.MeshAndTexture
-
-Function CreateVectex()
-	s=256
-	t=CreateTexture(s,s,1+4+8+256)
-	i=CreateImage(s,s)
-	b=BackBuffer()
-	SetBuffer ImageBuffer(i)
-	Color 128,128,128
-	Rect 0,0,s,s,True
-	For f=0 To 128
-		Color 255-f,255-f,255-f
-		Rect f,f,s-f*2,s-f*2,False
-	Next
-	SetBuffer b
-	CopyRect 0,0,s,s,0,0,ImageBuffer(i),TextureBuffer(t)
-	FreeImage i
-	Return t
-End Function
-
-Function CreateParticle()
-	m=CreateMesh()
-	b=CreateBrush(255,0,0)
-	s=CreateSurface(m,b)
-	
-	sz#=2
-
-	v0=AddVertex(s,0,sz,0)
-	v1=AddVertex(s,-sz,-0,0)
-	v2=AddVertex(s,0,-sz,0)
-	v3=AddVertex(s,sz,0,0)
-	
-	AddTriangle(s,v0,v2,v1)
-	AddTriangle(s,v0,v3,v2)
-	
-	UpdateNormals m
-	
-	Return m
-End Function
-
-Function CreateShip()
-
-	m=CreateMesh()
-	b=CreateBrush(255,255,255)
-	BrushTexture b,vectex
-	s=CreateSurface(m,b)
-	
-	sz#=SHIPSZ
-
-	v0=AddVertex(s,0,sz,0,0,0)
-	v1=AddVertex(s,-sz,-sz,0,0,1)
-	v2=AddVertex(s,0,-sz/2,1,0,1)
-	v3=AddVertex(s,sz,-sz,0,1,0)
-	
-	AddTriangle(s,v0,v2,v1)
-	AddTriangle(s,v0,v3,v2)
-	
-	UpdateNormals m
-	
-	Return m
-
-End Function
-
-Function CreateAsttex()
-	s=256
-	t=CreateTexture(s,s,1+4+8+256)
-	i=CreateImage(s,s)
-	b=BackBuffer()
-	SetBuffer ImageBuffer(i)
-	Color 0,0,128
-	Rect 0,0,s,s,True
-	Color 64,64,255
-	For f=0 To 256 Step 32
-		Rect f,0,4,256,True
-		Rect 0,f,256,4,True
-	Next
-	SetBuffer b
-	CopyRect 0,0,s,s,0,0,ImageBuffer(i),TextureBuffer(t)
-	FreeImage i
-	Return t
-End Function
-
-Function TRANS_CreateAsttex()
-	s=256
-	t=CreateTexture(s,s,1+4+8+256)
-	ClearTexture(t)
-	For f=0 To 256 Step 32
-		RectTexture(t,f,0,4,256,$ffffffff)
-		RectTexture(t,0,f,256,4,$ffffffff)
-	Next
-	Return t
-End Function
-
-Function CreatePowertex()
-	s=256
-	t=CreateTexture(s,s,1+4+8+256)
-	i=CreateImage(s,s)
-	b=BackBuffer()
-	SetBuffer ImageBuffer(i)
-	Color 128,128,0
-	Rect 0,0,s,s,True
-	Color 255,255,0
-	For f=0 To 256 Step 32
-		Rect f,0,4,256,True
-		Rect 0,f,256,4,True
-	Next
-	SetBuffer b
-	CopyRect 0,0,s,s,0,0,ImageBuffer(i),TextureBuffer(t)
-	FreeImage i
-	Return t
-End Function
-
-Function TRANS_CreatePowertex()
-	s=256
-	t=CreateTexture(s,s,1+4+8+256)
-	ClearTexture(t)
-	For f=0 To 256 Step 32
-		RectTexture(t,f,0,4,256,$ffffff00)
-		RectTexture(t,0,f,256,4,$ffffff00)
-	Next
-	Return t
-End Function
-
-Function OLD_CreateShieldtex()
-	sz=32
-	t=CreateTexture(sz,sz,1+4+8+256)
-	i=CreateImage(sz,sz)
-	b=BackBuffer()
-	SetBuffer ImageBuffer(i)
-	For f=0 To sz-1
-		Color Rand(255),Rand(255),Rand(255)
-		Line 0,f,sz-1,f
-	Next
-	SetBuffer b
-	CopyRect 0,0,sz,sz,0,0,ImageBuffer(i),TextureBuffer(t)
-	FreeImage i
-	Return t
-End Function
-
-Function CreateShieldtex()
-	s=32
-	t=CreateTexture(s,s,1+4+8+256)
-	ClearTexture(t)
-	For x=0 To s Step 2
-		For y=0 To s Step 2
-			RectTexture(t,x+(y Mod 2),y,1,1,$ffffffff)
-			;RectTexture(t,x,y,1,1,$ffffffff)
-		Next
-	Next
-	Return t
-End Function
-
-Function CreateAsteroid(size#)
-
-	size=size/2
-
-	m=CreateSphere()
-	ScaleEntity m,size,size,size
-	Return m
-
-	m=CreateMesh()
-	s=CreateSurface(m)
-	
-	pt#=16.0
-	ai#=360.0/pt
-	
-	AddVertex(s,0,0,0,0.5,0.5)
-	
-	For f=0 To pt-1
-		a#=f*ai
-		x#=Sin(a)*size
-		y#=Cos(a)*size
-		AddVertex(s,x,y,z,Abs(Sin(a)),Abs(Cos(a)))
-	Next
-	
-	For f=1 To pt-1
-		AddTriangle(s,0,f,f+1)
-	Next
-	
-	AddTriangle(s,0,pt,1)
-	
-	UpdateNormals m
-	
-	Return m
-
-End Function
-
-Function CreateMaptex()
-	s=256
-	t=CreateTexture(s,s,1+4+8+256)
-	i=CreateImage(s,s)
-	b=BackBuffer()
-	SetBuffer ImageBuffer(i)
-	Color 0,0,64
-	Rect 0,0,s,s,True
-	For f=0 To 128
-		rd=Rand(128,255)
-		gn=Rand(128,255)
-		bl=Rand(128,255)
-		
-		x=Rand(1,s-1)
-		y=Rand(1,s-1)
-		Color rd/2,gn/2,bl/2
-		Plot x-1,y
-		Plot x+1,y
-		Plot x,y-1
-		Plot x,y+1
-		Color rd,gn,bl
-		Plot x,y
-	Next
-	Color 0,0,128
-	Rect 0,0,s,s,False
-	SetBuffer b
-	CopyRect 0,0,s,s,0,0,ImageBuffer(i),TextureBuffer(t)
-	FreeImage i
-	Return t
-End Function
-
-Function MapSurface(m,b,x1,y1,z1,x2,y2,z2,x3,y3,z3,x4,y4,z4)
-	s=CreateSurface(m,b)
-	
-	v0=AddVertex(s,x1,y1,z1,0,0)
-	v1=AddVertex(s,x2,y2,z2,1,0)
-	v2=AddVertex(s,x3,y3,z3,0,1)
-	v3=AddVertex(s,x4,y4,z4,1,1)
-	
-	AddTriangle(s,v0,v1,v2)
-	AddTriangle(s,v1,v3,v2)
-End Function
-
-Function CreateMap()
-
-	m=CreateMesh()
-	b=CreateBrush(255,255,255)
-	BrushTexture b,maptex
-	
-	sz=MAPSIZE+10
-	
-	MapSurface(m,b,	-sz,sz,sz,		sz,sz,sz,		-sz,-sz,sz,		sz,-sz,sz)
-	MapSurface(m,b,	-sz,sz,-sz,		sz,sz,-sz,		-sz,sz,sz,		sz,sz,sz)
-	MapSurface(m,b,	-sz,-sz,-sz,	-sz,sz,-sz,		-sz,-sz,sz,		-sz,sz,sz)
-	MapSurface(m,b,	sz,sz,-sz,		sz,-sz,-sz,		sz,sz,sz,		sz,-sz,sz)
-	MapSurface(m,b,	sz,-sz,-sz,		-sz,-sz,-sz,	sz,-sz,sz,		-sz,-sz,sz)
-		
-	UpdateNormals m
-	
-	Return m
-
-End Function
-
-
-; ============================================
-; Menu
-; ============================================
-;
-.TitleRoutines
-
-Function Menu()
-
-	FlushKeys
-	
-	InitAsteroids()
-
-	ClearText()
-	
-	PositionEntity ship,0,0,SHIPZ
-	RotateMesh ship,0,0,0
-	
-	ClearParticles()
-	ClearSpriteText()
-	InitShockwave(180,WAVEZ)
-	
-	done=False
-	turn=0
-	count=100
-	speed=0
-	r=0
-	g=0
-	b=0
-	i=1
-	tl$="abcdefgh"
-	ic=1
-	icl=Len(instruction$)
-	icp=1
-
-	HudTextCentre(20,"SHOCKWAVE",$ffffff)
-	HudTextCentre(30,"(C) 2004 IAN C",$ffffff)
-	
-	If DEBUGMODE
-		HudTextCentre(150,"**** DEBUG KEYS ENABLED ****",$ff0000)
-	EndIf
-	
-	HudTextCentre(50,"PRESS F1 FOR LEVEL",$ffff00)
-	HudTextCentre(60,"PRESS SPACE TO PLAY",$ffff00)
-	HudTextCentre(80,"PRESS ESC TO QUIT",$ffff00)
-	
-	HudTextCentre(170,"HIGH SCORE",$ffffff)
-	HudTextCentre(200,"LARGEST LOST CHAIN",$ffffff)
-	
-	AddScore(0)
-	start_bonus=(start_level-1)^2*1000
-	
-	ti=MilliSecs()
-	
-	While Not done
-	
-		HudText(245,0,Mid$(tl$,i,1))
-		
-		If (MilliSecs()-ti)>200
-			i=(i Mod Len(tl$))+1
-			ti=MilliSecs()
-		EndIf
-		
-		HudTextCentre(100,"   START LEVEL " + start_level+"   ",$00ffff)
-		HudTextCentre(110,"   BONUS " + start_bonus+"   ",$00ffff)
-		
-		If new_highscore
-			HudTextCentre(170,"NEW HIGH SCORE",(g Shl 16) Or (b Shl 8) Or r)
-		EndIf
-		
-		If new_highlostchain
-			HudTextCentre(200,"NEW LARGEST LOST CHAIN",(g Shl 16) Or (b Shl 8) Or r)
-		EndIf
-		
-		HudTextCentre(180,Str$(highscore),(r Shl 16) Or (g Shl 8) Or b)
-		HudTextCentre(210,Str$(highlostchain),(r Shl 16) Or (g Shl 8) Or b)
-		
-		r=(r+7) And 255
-		g=(g+5) And 255
-		b=(b+3) And 255
-		
-		ic=ic-1
-		
-		If ic=0
-			NewCameraSpriteTextScroll(Mid$(instruction$,icp,1),$ffffff,5,-2,EntityZ(camera)+5,-0.02,0,0,500)
-			ic=6
-			icp=icp+1
-			If icp>icl
-				icp=1
-			EndIf
-		EndIf
-	
-		If KeyHit(1)
-			done=True
-			quit=True
-		EndIf
-		
-		If KeyHit(57)
-			done=True
-		EndIf
-		
-		If KeyHit(59)
-			start_level=start_level+5
-			If start_level>30
-				start_level=1
-			EndIf
-			start_bonus=(start_level-1)^2*1000
-		EndIf
-		
-		count=count-1
-		
-		If count=0
-			turn=Rand(-1,1)
-			
-			If turn=0
-				count=Rand(1,200)
-			Else
-				count=Rand(10,200)
-			EndIf			
-		EndIf
-	
-		If turn=-1
-			TurnEntity ship,0,0,TURN_NORMAL
-		EndIf
-		
-		If turn=1
-			TurnEntity ship,0,0,-TURN_NORMAL
-		EndIf
-		
-		If speed<MAX_SPEED
-			speed=speed+0.002
-		EndIf
-	
-		MoveEntity ship,0,speed,0
-		
-		PositionEntity camera,EntityX(ship),EntityY(ship),0
-		;PositionEntity camera,0,0,0
-		;PointEntity camera,ship
-		
-		UpdateParticles()
-		UpdateSpriteText()
-	
-		UpdateWorld
-		
-		RenderWorld
-		
-		AddShockwave(ship)
-		
-		DrawRadar()
-		
-		ex=EntityX(ship)
-		ey=EntityY(ship)
-		
-		If ex<-MAPSIZE Or ex>MAPSIZE
-			RotateEntity ship,0,0,-EntityRoll(ship)
-			MoveEntity ship,0,speed,0
-		EndIf
-		
-		If ey<-MAPSIZE Or ey>MAPSIZE
-			RotateEntity ship,0,0,180-EntityRoll(ship)
-			MoveEntity ship,0,speed,0
-		EndIf
-		
-		Flip
-		
-		globang=(globang+10) Mod 360
-		
-	Wend
-
-End Function
-
-
-; ============================================
-; Highscore Routines
-; ============================================
-;
-.HiScoreRoutines
-
-Function LoadHighScore()
-	fp=ReadFile("hiscore.dat")
-
-	If fp=0
-		Return
-	EndIf
-
-	highscore=ReadInt(fp)
-	highlostchain=ReadInt(fp)
-	CloseFile fp
-End Function
-
-Function SaveHighScore()
-	fp=WriteFile("hiscore.dat")
-	
-	If fp=0
-		Return
-	EndIf
-	
-	WriteInt fp,highscore
-	WriteInt fp,highlostchain
-	CloseFile fp
-End Function
-
-
-; ============================================
-; Power Up Routines
-; ============================================
-;
-.PowerUpRoutines
-
-Function CreatePowerUp(id,chance,max)
-	p.PowerUp=New PowerUp
-	p\id=id
-	p\chance=chance
-	p\max=max
-End Function
-
-Function ResetPowerUps()
-	For p.PowerUp=Each PowerUp
-		p\count=0
-	Next
-End Function
-
-Function PowerUp()
-	If is_bonus_level
-		Return POWSPLIT
-	EndIf
-	
-	i=Rand(100)
-	
-	For p.PowerUp=Each PowerUp
-		If i>p\chance And p\count<p\max
-			p\count=p\count+1
-			Return p\id
-		EndIf
-	Next
-	
-	Return POWNONE
-End Function
-
-Function ReturnPowerUp(id)
-	For p.PowerUp=Each PowerUp
-		If p\id=id
-			p\count=p\count-1
-			Return
-		EndIf
-	Next
-End Function
-
-
-; ============================================
-; Queued Sound Routines
-; ============================================
-;
-.QSoundRoutines
-
-Function ProcessQSounds()
-	For s.QSound=Each QSound
-		If s\time=0
-			EmitSound(s\snd,s\obj)
-			Delete s
-		Else
-			s\time=s\time-1
-		EndIf
-	Next
-End Function
-
-
-Function QueueQSound(snd,time,source)
-	s.QSound=New QSound
-	s\snd=snd
-	s\time=time
-	s\obj=source
-End Function
-
-
-Function CircleQSound(snd,del)
-	For f=0 To 7
-		QueueQSound(snd,del*f,snd_emitter(f))
-	Next
-End Function
-
-
-
-; ============================================
-; Instruction Data
-; ============================================
-;
-.InstructionData
-Data "THE ALIENS HAVE SELECTED YOU TO REPRESENT THE HUMAN RACE "
-Data "IN SHOCKWAVE.  "
-Data "IF YOU FAIL 3 BILLION SOULS WILL BE LOST. MOST IMPORTANTLY, YOURS....   "
-Data "THERE IS A SPANNER IN THE WORKS THOUGH - YOUR SHIP IS BUST.  "
-Data "THERE IS NO CONTROL OVER ITS "
-Data "SPEED.  ONLY STEERING WORKS AND YOU CAN ONLY DESTROY THE SPHERES WITH YOUR SHOCKWAVE EXHAUST.  "
-Data "THE DESTROYED SPHERES MAY ALSO HAVE "
-Data "UNDESIRED EFFECTS ON THE SHIP...   OR EVEN GOOD ONES.  "
-Data "TO STEER USE THE LEFT AND RIGHT CURSOR KEYS.  PRESS P TO PAUSE.  PRESS ESCAPE TO QUIT.   "
-Data "    "
-Data "GOOD LUCK!                                       "
-Data "END"
+;
+; SHOCKWAVE (c) COPYRIGHT Ian Cowburn 2004
+;
+; $Id: shockwave.bb,v 1.10 2005-05-08 23:37:33 ianc Exp $
+;
+
+Include "gfx/font.bb"
+
+; ============================================
+; TYPES
+; ============================================
+;
+Type Particle
+	Field	id
+	Field	a#
+	Field	ai#
+	Field	spin#
+	Field	dx#,dy#,dz#
+	Field	life
+End Type
+
+Type SpriteText
+	Field	id
+	Field	txt
+	Field	a#
+	Field	ai#
+	Field	xi#
+	Field	yi#
+	Field	zi#
+	Field	life
+End Type
+	
+Type Shockwave
+	Field	id
+	Field	length
+	Field	z#
+End Type
+
+Type SWLine
+	Field	x1#,y1#
+	Field	r1,g1,b1
+	Field	x2#,y2#
+	Field	r2,g2,b2
+End Type
+
+Type Asteroid
+	Field	id
+	Field	size
+	Field	colcnt
+	Field	speed#
+	Field	dx#,dy#
+	Field	power
+	Field	split
+End Type
+
+Type PowerUp
+	Field	id
+	Field	chance
+	Field	max
+	Field	count
+End Type
+
+Type QSound
+	Field	snd
+	Field	time
+	Field	obj
+End Type
+
+; ============================================
+; CONSTS
+; ============================================
+;
+Const DEBUGMODE=False
+
+Const MAPSIZE=256
+Const FIELDSIZE=246
+
+Const RADSCALE=16
+Const RADSIZE=(MAPSIZE*2)/RADSCALE
+Const RADMID=RADSIZE/2
+
+Const TXTSIZE=256
+
+Const SPRTXTSIZE=128
+
+Const SHIPZ#=149
+Const WAVEZ#=150
+Const SHIPSZ#=2
+
+Const ASTLARGE=20
+Const ASTMEDIUM=10
+Const ASTSMALL=5
+Const ASTMAXSPEED#=0.5
+Const ASTMINSPEED#=0.4
+Const ASTSHIELD=200
+
+Const MAXSHIELD=100
+
+Const SHIPTYPE=1
+Const SWTYPE=2
+Const ASTTYPE=3
+
+Const POWNONE=0
+Const POWSPLIT=1
+Const POWTURBOTURN=2
+Const POWSHIELD=3
+Const POWFPS=4
+
+Const TURN_NORMAL#=3
+Const TURN_TURBO#=2
+Const MAXSPEED_NORMAL#=1
+Const MAXSPEED_TURBO#=2
+
+Const CAMERA_NORMAL=1
+Const CAMERA_FPS=2
+
+; ============================================
+; GLOBLS
+; ============================================
+;
+Global WINW=800
+Global WINH=600
+
+Global sw.Shockwave=Null
+
+
+; ============================================
+; MAIN
+; ============================================
+;
+Graphics3D WINW,WINH,32;,2
+
+SetBuffer BackBuffer()
+
+Global camera=CreateCamera()
+Global listener=CreateListener(camera,0.001)
+
+Dim snd_emitter(7)
+
+For f=0 To 7
+	snd_emitter(f)=CreatePivot(camera)
+Next
+
+PositionEntity snd_emitter(0),0,0,2
+PositionEntity snd_emitter(1),1,0,1
+PositionEntity snd_emitter(2),2,0,0
+PositionEntity snd_emitter(3),1,0,-1
+PositionEntity snd_emitter(4),0,0,-2
+PositionEntity snd_emitter(5),-1,0,-1
+PositionEntity snd_emitter(6),-2,0,0
+PositionEntity snd_emitter(7),-1,0,1
+
+CameraRange camera,0.1,10000
+CameraFogMode camera,0
+
+AmbientLight 255,255,255
+
+Global vectex=CreateVectex()
+Global asttex=CreateAsttex()
+Global powertex=CreatePowertex()
+Global shieldtex=CreateShieldtex()
+Global maptex=CreateMaptex()
+Global radar=CreateTexture(RADSIZE,RADSIZE,1+2+16+32+256)
+Global hud=CreateTexture(TXTSIZE,TXTSIZE,1+2+16+32+256)
+
+Global ship=CreateShip()
+Global particle=CreateParticle()
+Global large_asteroid=CreateAsteroid(ASTLARGE)
+Global medium_asteroid=CreateAsteroid(ASTMEDIUM)
+Global small_asteroid=CreateAsteroid(ASTSMALL)
+Global map=CreateMap()
+Global radar_spr=CreateSprite(camera)
+Global hud_spr=CreateSprite(camera)
+
+Global start_sfx=Load3DSound("sfx/start.wav")
+Global bonus_level_sfx=Load3DSound("sfx/bonus_level.wav")
+Global laugh_sfx=Load3DSound("sfx/laugh.wav")
+Global explode_sfx=Load3DSound("sfx/explode.wav")
+Global pop_sfx=Load3DSound("sfx/pop.wav")
+Global turbostart_sfx=Load3DSound("sfx/powerstart.wav")
+Global turbostop_sfx=Load3DSound("sfx/powerstop.wav")
+Global turnstart_sfx=Load3DSound("sfx/powerstart.wav")
+Global turnstop_sfx=Load3DSound("sfx/powerstop.wav")
+Global smartbomb_sfx=Load3DSound("sfx/smartbomb.wav")
+
+HideEntity particle
+HideEntity large_asteroid
+HideEntity medium_asteroid
+HideEntity small_asteroid
+
+EntityType ship,SHIPTYPE
+EntityRadius large_asteroid,ASTLARGE/2
+EntityRadius medium_asteroid,ASTMEDIUM/2
+EntityRadius small_asteroid,ASTSMALL/2
+EntityRadius ship,SHIPSZ
+
+;Collisions ASTTYPE,SWTYPE,2,1
+;Collisions ASTTYPE,SHIPTYPE,2,0
+Collisions ASTTYPE,ASTTYPE,1,1
+
+PositionEntity radar_spr,7,5,15
+EntityTexture radar_spr,radar
+PositionEntity hud_spr,0,0,2
+EntityTexture hud_spr,hud
+ScaleSprite hud_spr,1.15,0.85
+
+Global fps_camera=CreateCamera(ship)
+Global fps_radar_spr=CreateSprite(fps_camera)
+Global fps_hud_spr=CreateSprite(fps_camera)
+PositionEntity fps_radar_spr,7.4,5.3,9
+EntityTexture fps_radar_spr,radar
+PositionEntity fps_hud_spr,0,0,2
+EntityTexture fps_hud_spr,hud
+ScaleSprite fps_hud_spr,1.85,1.45
+TurnEntity fps_camera,-70,0,0
+MoveEntity fps_camera,0,5,-15
+CameraProjMode camera,0
+
+Global current_camera=camera
+
+Global globang=0
+Global start_level=1
+Global start_bonus=0
+Global quit=False
+Global MAX_SPEED#=MAXSPEED_NORMAL
+Global turn#=TURN_NORMAL
+Global speed#=0
+Global score=0
+Global shield=0
+Global dead=False
+Global highscore=0
+Global highlostchain=0
+Global new_highscore=False
+Global new_highlostchain=False
+Global hit_count=0
+Global hit_timer=0
+Global turbo_count=0
+Global turn_count=0
+Global fps_count=0
+Global is_bonus_level=False
+
+LoadHighScore()
+
+CreatePowerUp(POWSPLIT,99,1)
+CreatePowerUp(POWSHIELD,97,0)
+CreatePowerUp(POWTURBOTURN,95,10)
+CreatePowerUp(POWFPS,98,2)
+
+SetCamera(CAMERA_NORMAL)
+
+Global timer=CreateTimer(100)
+
+Restore InstructionData
+Read a$
+Global instruction$
+
+While a$<>"END"
+	instruction$=instruction$+a$
+	Read a$
+Wend
+
+Repeat
+
+	SetCameraFOV(60)
+
+	Menu()
+	
+	If quit
+		Exit
+	EndIf
+
+	speed=0
+	MAX_SPEED#=MAXSPEED_NORMAL
+	turn#=TURN_NORMAL
+	
+	ClearText()
+	
+	PositionEntity ship,0,0,SHIPZ
+	RotateMesh ship,0,0,0
+	
+	ClearParticles()
+	ClearSpriteText()
+	InitShockwave(180,WAVEZ)
+	InitAsteroids()
+	
+	score=0
+	shield=MAXSHIELD
+	dead=False
+	done=False
+	level=start_level
+	total_chain=0
+	hit_timer=0
+	hit_count=0
+	
+	new_level=True
+	end_level=False
+	
+	FlushKeys
+	Delete Each QSound
+	
+	While (Not dead) And (Not done) And (Not KeyHit(1))
+	
+		If new_level
+		
+			If (level Mod 5)=0
+				is_bonus_level=True
+			Else
+				is_bonus_level=False
+			EndIf
+			
+			ClearText()
+			
+			ResetPowerUps()
+			
+			AddScore(0)
+			SubShield(0)
+			
+			noast=5+2*level
+			
+			If noast>100
+				noast=100
+			EndIf
+	
+			For f=1 To noast
+				NewAsteroid(ASTLARGE,Rand(-FIELDSIZE,FIELDSIZE),Rand(-FIELDSIZE,FIELDSIZE))
+			Next
+			
+			If is_bonus_level
+				For f=30 To 50 Step 4
+					NewCameraSpriteText("BONUS LEVEL",$ffffff,0,0,EntityZ(camera)+f,-0.4,1,0.01)
+				Next
+				
+				EmitSound(bonus_level_sfx,camera)
+			Else
+				For f=30 To 50 Step 4
+					NewCameraSpriteText("LEVEL "+Str$(level),$ffffff,0,0,EntityZ(camera)+f,-0.4,1,0.01)
+				Next
+				
+				EmitSound(start_sfx,camera)
+			EndIf
+			
+			total_chain=0
+			hit_count=0
+			turn_count=0
+			turbo_count=0
+			new_level=False
+		EndIf
+	
+		If (First Asteroid)=Null And (Not end_level)
+			If hit_timer>0
+				hit_timer=0
+				
+				If hit_count>5
+					bonus=hit_count*50
+					NewCameraSpriteText("CHAIN BONUS",$ff0000,0,5,EntityZ(camera)+50,-0.2,1,0.005)
+					NewCameraSpriteText(Str$(bonus),$ffff00,0,3,EntityZ(camera)+50,-0.2,1,0.005)
+					AddScore(bonus)
+					total_chain=total_chain+hit_count
+				EndIf
+			EndIf
+
+			end_level=True
+			end_levelc=500
+			
+			HudTextCentre(50,"LEVEL COMPLETE!",$ffffff)
+
+			If start_bonus>0
+				HudTextCentre(100,"START BONUS",$ff0000)
+				HudTextCentre(110,Str$(start_bonus),$ffff00)
+				AddScore(start_bonus)
+				start_bonus=0
+			EndIf
+			
+			If total_chain>0
+				bonus=total_chain*17
+				HudTextCentre(160,"CHAIN BONUS",$ff0000)
+				HudTextCentre(170,Str$(bonus),$ffff00)
+				AddScore(bonus)
+			EndIf
+				
+			If shield=0
+				HudTextCentre(190,"SECRET ZERO SHIELD BONUS",$ff0000)
+				HudTextCentre(200,"99999",$ffff00)
+				AddScore(99999)
+				SubShield(-MAXSHIELD)
+			ElseIf shield=MAXSHIELD
+				HudTextCentre(190,"PERFECT SHIELD BONUS",$ff0000)
+				HudTextCentre(200,"20000",$ffff00)
+				AddScore(20000)
+			ElseIf total_chain>0
+				bonus=total_chain
+				
+				If (shield+bonus)>MAXSHIELD
+					bonus=MAXSHIELD-shield
+				EndIf
+				
+				HudTextCentre(190,"NEW SHIELDS WON",$ff0000)
+				HudTextCentre(200,Str$(bonus),$ffff00)
+				SubShield(-bonus)
+			EndIf
+
+			level=level+1
+		EndIf
+		
+		If end_level
+			end_levelc=end_levelc-1
+			
+			If end_levelc<200
+				If (level Mod 5)=0
+					HudTextCentre(128,"BONUS LEVEL!",$ffffff)
+				Else
+					HudTextCentre(128,"GET READY!",$ffffff)
+				EndIf
+			EndIf
+			
+			If end_levelc=0
+				end_level=False
+				new_level=True
+			EndIf
+		EndIf
+		
+		If turn_count>0
+			turn_count=turn_count-1
+			
+			If turn_count=0
+				CircleQSound(turnstop_sfx,1)
+				turn=TURN_NORMAL
+			EndIf
+		EndIf
+	
+		If turbo_count>0
+			turbo_count=turbo_count-1
+			
+			If turbo_count=0
+				CircleQSound(turbostop_sfx,1)
+				MAX_SPEED=MAXSPEED_NORMAL
+			EndIf
+		EndIf
+	
+		If fps_count>0
+			fps_count=fps_count-1
+			
+			If fps_count=0
+				CircleQSound(turbostop_sfx,1)
+				SetCamera(CAMERA_NORMAL)
+			EndIf
+		EndIf
+	
+		If KeyDown(203)
+			TurnEntity ship,0,0,turn
+		EndIf
+		
+		If KeyDown(205)
+			TurnEntity ship,0,0,-turn
+		EndIf
+		
+		If KeyHit(25)
+			FlushKeys
+			c=$ffff00
+			ci=-$111100
+			While (Not KeyHit(25)) And (Not KeyHit(1))
+				HudTextCentre(124,"P A U S E D",c)
+				c=c+ci
+				If c=0 Or c=$ffff00 Then ci=-ci
+				RenderWorld
+				Flip
+			Wend
+			HudTextCentre(124,"           ",$ffff00)
+		EndIf
+		
+		If speed<MAX_SPEED
+			speed=speed+0.02
+			If speed>MAX_SPEED Then speed=MAX_SPEED
+		ElseIf speed>MAX_SPEED
+			speed=speed-0.02
+			If speed<MAX_SPEED Then speed=MAX_SPEED
+		EndIf
+		
+		If hit_timer>0
+			hit_timer=hit_timer-1
+			
+			If hit_timer=0
+				If hit_count>5
+					bonus=hit_count*50
+					NewCameraSpriteText("CHAIN BONUS",$ff0000,0,5,EntityZ(camera)+50,-0.2,1,0.005)
+					NewCameraSpriteText(Str$(bonus),$ff0000,0,3,EntityZ(camera)+50,-0.2,1,0.005)
+					AddScore(bonus)
+					total_chain=total_chain+hit_count
+				EndIf
+				
+				hit_count=0
+			EndIf
+		EndIf
+		
+		MoveEntity ship,0,speed,0
+		
+		PositionEntity camera,EntityX(ship),EntityY(ship),0
+		;PointEntity camera,ship
+		
+		UpdateParticles()
+		UpdateSpriteText()
+	
+		UpdateWorld
+		
+		RenderWorld
+		
+		UpdateAsteroids()
+	
+		AddShockwave(ship)
+		
+		DrawRadar()
+		
+		ex=EntityX(ship)
+		ey=EntityY(ship)
+		
+		If ex<-MAPSIZE Or ex>MAPSIZE
+			RotateEntity ship,0,0,-EntityRoll(ship)
+			MoveEntity ship,0,speed,0
+		EndIf
+		
+		If ey<-MAPSIZE Or ey>MAPSIZE
+			RotateEntity ship,0,0,180-EntityRoll(ship)
+			MoveEntity ship,0,speed,0
+		EndIf
+
+		ProcessQSounds()
+		Flip
+		
+		WaitTimer(timer)
+		
+		globang=(globang+10) Mod 360
+		
+		If DEBUGMODE
+			If KeyHit(200)
+				MAX_SPEED=MAX_SPEED+0.1
+				NewCameraSpriteText(Str$(MAX_SPEED),$ff0000,0,5,EntityZ(camera)+50,-0.2,1,0.005)
+			EndIf
+			If KeyHit(208)
+				MAX_SPEED=MAX_SPEED-0.1
+				NewCameraSpriteText(Str$(MAX_SPEED),$ff0000,0,5,EntityZ(camera)+50,-0.2,1,0.005)
+			EndIf
+			If KeyHit(64)
+				For ast.Asteroid=Each Asteroid
+					FreeEntity ast\id
+					Delete ast
+				Next
+				NewCameraSpriteText("DELALL",$ff0000,0,5,EntityZ(camera)+50,-0.2,1,0.005)
+			EndIf
+			If KeyHit(65)
+				SubShield(shield)
+				NewCameraSpriteText("NOSHLD",$ff0000,0,5,EntityZ(camera)+50,-0.2,1,0.005)
+			EndIf
+			If KeyHit(66)
+				SubShield(-MAXSHIELD)
+				NewCameraSpriteText("FULLSHLD",$ff0000,0,5,EntityZ(camera)+50,-0.2,1,0.005)
+			EndIf
+		EndIf
+		
+	Wend
+	
+	SetCamera(CAMERA_NORMAL)
+	
+	new_highscore=False
+	new_highlostchain=False
+	
+	If dead
+	
+		CircleQSound(explode_sfx,25)
+	
+		fov#=60
+		
+		NewCameraSpriteText("GAME OVER!",$ffffff,0,0,EntityZ(camera)+0.5,0,0.1,-0.005)
+		
+		If hit_count>5
+			NewCameraSpriteText("LOST A",$800000,0,-2,EntityZ(camera)+0.5,0,0.1,-0.005)
+			NewCameraSpriteText("CHAIN OF",$800000,0,-4,EntityZ(camera)+0.5,0,0.1,-0.005)
+			NewCameraSpriteText(Str$(hit_count)+"!",$800000,0,-6,EntityZ(camera)+0.5,0,0.1,-0.005)
+		EndIf
+		
+		If score>highscore
+			new_highscore=True
+			highscore=score
+		EndIf
+		
+		If hit_count>5 And hit_count>highlostchain
+			new_highlostchain=True
+			highlostchain=hit_count
+		EndIf
+		
+		If new_highscore Or new_highlostchain
+			SaveHighScore()
+		EndIf
+		
+		f=0
+	
+		While (f<700) And (Not (KeyDown(57) Or KeyDown(1)))
+			ProcessQSounds()
+			SetCameraFOV(fov)
+			If fov<175
+				fov=fov+1
+			EndIf
+			UpdateAsteroids()
+			DrawRadar()
+			UpdateParticles()
+			UpdateSpriteText()
+			UpdateWorld
+			RenderWorld
+			Flip
+			f=f+1
+		Wend
+		
+		While fov>60
+			ProcessQSounds()
+			SetCameraFOV(fov)
+			fov=fov-5
+			UpdateAsteroids()
+			DrawRadar()
+			UpdateParticles()
+			UpdateSpriteText()
+			UpdateWorld
+			RenderWorld
+			Flip
+		Wend
+		
+		SetCameraFOV(60)
+		
+	EndIf
+	
+Forever
+
+End
+
+; ============================================
+; Utils
+; ============================================
+;
+.Utils
+
+Function SetCamera(cam)
+	Select cam
+		Case CAMERA_NORMAL
+			CameraProjMode camera,1
+			CameraProjMode fps_camera,0
+			ShowEntity hud_spr
+			ShowEntity radar_spr
+			HideEntity fps_hud_spr
+			HideEntity fps_radar_spr
+			current_camera=camera
+		Case CAMERA_FPS
+			CameraProjMode camera,0
+			CameraProjMode fps_camera,1
+			HideEntity hud_spr
+			HideEntity radar_spr
+			ShowEntity fps_hud_spr
+			ShowEntity fps_radar_spr
+			current_camera=fps_camera
+	End Select
+End Function
+
+Function SetCameraFOV(FOV#)
+   CameraZoom camera, 1.0 / Tan(FOV#/2.0)
+End Function
+
+Function Info()
+	Color 255,255,255
+	Text 0,0,"M:"+MeshWidth(ship)+","+MeshHeight(ship)+","+MeshDepth(ship)
+	Text 0,10,"S:"+MeshWidth(sw\id)+","+MeshHeight(sw\id)+","+MeshDepth(sw\id)
+End Function
+
+Function AddScore(s)
+	score=score+s
+	HudText(0,0,"SCORE")
+	HudTextCol(48,0,score,$ff0000)
+End Function
+
+Function SubShield(s)
+	orig=shield
+	shield=shield-s
+	If shield<0 And (Not dead) Then shield=0:dead=True:EmitSound(laugh_sfx,snd_emitter(Rand(0,7)))
+	If shield>300 Then shield=300
+	If orig=>50 And shield<50 Then EmitSound(laugh_sfx,snd_emitter(Rand(0,7)))
+	If orig=>20 And shield<20 Then EmitSound(laugh_sfx,snd_emitter(Rand(0,7)))
+	HudText(150,0,"SHEILD")
+	HudTextCol(206,0,shield+" ",$ff0000)
+End Function
+
+Function ClearTexture(t)
+	w=TextureWidth(t)-1
+	h=TextureHeight(t)-1
+	b=TextureBuffer(t)
+	LockBuffer b
+	For x=0 To w
+		For y=0 To h
+			WritePixelFast x,y,0,b
+		Next
+	Next
+	UnlockBuffer b
+End Function
+
+Function RectTexture(t,x,y,w,h,c)
+	tw=TextureWidth(t)-1
+	th=TextureHeight(t)-1
+	b=TextureBuffer(t)
+	LockBuffer b
+	For xc=x To x+w-1
+		For yc=y To y+h-1
+			If xc>=0 And xc<tw And yc>=0 And yc<th
+				WritePixelFast xc,yc,c,b
+			EndIf
+		Next
+	Next
+	UnlockBuffer b
+End Function
+
+; ============================================
+; Collisions
+; ============================================
+;
+.Collisions
+
+Function HitSW(e,size)
+	size=size/2
+	ex=EntityX(e)
+	ey=EntityY(e)
+	
+	eminx=ex-size
+	emaxx=ex+size
+	
+	eminy=ey-size
+	emaxy=ey+size
+	
+	Return MeshesIntersect(e,sw\id)
+End Function
+
+
+; ============================================
+; Sprite Text
+; ============================================
+;
+.SpriteTextRoutines
+
+Function ClearSpriteText()
+	For s.SpriteText=Each SpriteText
+		FreeEntity s\id
+		FreeTexture s\txt
+		Delete s
+	Next
+End Function
+
+Function UpdateSpriteText()
+	For s.SpriteText=Each SpriteText
+	
+		If s\life=0
+			s\a=s\a-s\ai
+
+			If s\a<0.05
+				FreeEntity s\id
+				FreeTexture s\txt
+				Delete s
+			Else
+				EntityAlpha s\id,s\a
+				MoveEntity s\id,0,0,s\zi
+			EndIf
+		Else
+			s\life=s\life-1
+			
+			If s\life=0
+				FreeEntity s\id
+				FreeTexture s\txt
+				Delete s
+			Else
+				MoveEntity s\id,s\xi,s\yi,s\zi
+			EndIf
+		EndIf
+		
+	Next
+End Function
+
+Function NewSpriteText(a$,col,x#,y#,z#,zi#,al#,ai#)
+	s.SpriteText=New SpriteText
+	s\txt=CreateTexture(SPRTXTSIZE,SPRTXTSIZE,1+2+16+32)
+	s\id=CreateSprite()
+	s\a=al
+	s\ai=ai
+	s\zi=zi
+	s\xi=0
+	s\yi=0
+	s\life=0
+
+	ScaleSprite s\id,20,20	
+	EntityTexture s\id,s\txt
+	PositionEntity s\id,x,y,z
+	EntityAlpha s\id,al
+	
+	ClearTexture(s\txt)
+	TextureText(s\txt,a$,col)
+End Function
+
+Function NewCameraSpriteText(a$,col,x#,y#,z#,zi#,al#,ai#)
+	s.SpriteText=New SpriteText
+	s\txt=CreateTexture(SPRTXTSIZE,SPRTXTSIZE,1+2+16+32)
+	s\id=CreateSprite(current_camera)
+	s\a=al
+	s\ai=ai
+	s\zi=zi
+	s\xi=0
+	s\yi=0
+	s\life=0
+
+	ScaleSprite s\id,10,10	
+	EntityTexture s\id,s\txt
+	PositionEntity s\id,x,y,z
+	EntityAlpha s\id,al
+	
+	ClearTexture(s\txt)
+	TextureText(s\txt,a$,col)
+End Function
+
+Function NewCameraSpriteTextScroll(a$,col,x#,y#,z#,xi#,yi#,zi#,life)
+	s.SpriteText=New SpriteText
+	s\txt=CreateTexture(SPRTXTSIZE,SPRTXTSIZE,1+2+16+32)
+	s\id=CreateSprite(camera)
+	s\a=al
+	s\ai=ai
+	s\zi=zi
+	s\xi=xi
+	s\yi=yi
+	s\life=life
+
+	ScaleSprite s\id,1,1
+	EntityTexture s\id,s\txt
+	PositionEntity s\id,x,y,z
+	EntityAlpha s\id,1
+	
+	ClearTexture(s\txt)
+	TextureText(s\txt,a$,col)
+End Function
+
+; ============================================
+; Text
+; ============================================
+;
+.TextRoutines
+
+Function ClearText()
+	b=TextureBuffer(hud)
+	LockBuffer b
+	For x=0 To TXTSIZE-1
+		For y=0 To TXTSIZE-1
+			WritePixelFast x,y,0,b
+		Next
+	Next
+	UnlockBuffer b
+End Function
+
+Function HudText(tx,ty,a$)
+	b=TextureBuffer(hud)
+	LockBuffer b
+	
+	For f=1 To Len(a$)
+		c=Asc(Mid$(a$,f,1))-32
+		For x=0 To 7
+			For y=0 To 7
+				WritePixelFast tx+x,ty+y,font_data(c,x,y),b
+			Next
+		Next
+		tx=tx+8
+	Next
+	UnlockBuffer b
+End Function
+
+
+Function HudTextCol(tx,ty,a$,col)
+	b=TextureBuffer(hud)
+	LockBuffer b
+	
+	For f=1 To Len(a$)
+		c=Asc(Mid$(a$,f,1))-32
+		For x=0 To 7
+			For y=0 To 7
+				WritePixelFast tx+x,ty+y,(font_data(c,x,y) And $ff000000) Or (font_data(c,x,y) And col),b
+			Next
+		Next
+		tx=tx+8
+	Next
+	UnlockBuffer b
+End Function
+
+
+Function HudTextCentre(ty,a$,col)
+	tx=TXTSIZE/2-Len(a$)*4
+	b=TextureBuffer(hud)
+	LockBuffer b
+	
+	For f=1 To Len(a$)
+		c=Asc(Mid$(a$,f,1))-32
+		For x=0 To 7
+			For y=0 To 7
+				WritePixelFast tx+x,ty+y,(font_data(c,x,y) And $ff000000) Or (font_data(c,x,y) And col),b
+			Next
+		Next
+		tx=tx+8
+	Next
+	UnlockBuffer b
+End Function
+
+
+Function TextureText(t,a$,col)
+	ty=TextureHeight(t)/2-4
+	tx=TextureWidth(t)/2-Len(a$)*4
+	b=TextureBuffer(t)
+	LockBuffer b
+	
+	For f=1 To Len(a$)
+		c=Asc(Mid$(a$,f,1))-32
+		For x=0 To 7
+			For y=0 To 7
+				WritePixelFast tx+x,ty+y,(font_data(c,x,y) And $ff000000) Or (font_data(c,x,y) And col),b
+			Next
+		Next
+		tx=tx+8
+	Next
+	UnlockBuffer b
+End Function
+
+
+; ============================================
+; Radar
+; ============================================
+;
+.Radar
+
+Function DrawRadar()
+	b=TextureBuffer(radar)
+	LockBuffer b
+	For x=0 To RADSIZE-1
+		For y=0 To RADSIZE-1
+			WritePixelFast x,y,$20ffffff,b
+		Next
+	Next
+
+	x=RADMID+EntityX(ship)/RADSCALE
+
+	If x<0
+		x=0
+	EndIf
+
+	If x>=RADSIZE
+		x=RADSIZE-1
+	EndIf
+	
+	For y=0 To RADSIZE-1
+		WritePixelFast x,y,$7fffffff,b
+	Next
+	
+	y=RADMID-EntityY(ship)/RADSCALE
+
+	If y<0
+		y=0
+	EndIf
+
+	If y>=RADSIZE
+		y=RADSIZE-1
+	EndIf
+	
+	For x=0 To RADSIZE-1
+		WritePixelFast x,y,$7fffffff,b
+	Next
+	
+	For a.Asteroid=Each Asteroid
+		If a\size=ASTLARGE
+			c=$ffffff00
+		ElseIf a\size=ASTMEDIUM
+			c=$ffc8c8c8
+		Else
+			c=$ffa0a0a0
+		EndIf
+		x=RADMID+EntityX(a\id)/RADSCALE
+		y=RADMID-EntityY(a\id)/RADSCALE
+		
+		If x>-1 And x<RADSIZE And y>-1 And y<RADSIZE
+			WritePixelFast x,y,c,b
+		EndIf
+	Next
+	UnlockBuffer b
+End Function
+
+
+; ============================================
+; Asteroids
+; ============================================
+;
+.Asteroids
+
+Function InitAsteroids()
+	For a.Asteroid=Each Asteroid
+		FreeEntity a\id
+		Delete a
+	Next
+End Function
+
+
+Function NewAsteroid(size,x#,y#)
+	a.Asteroid=New Asteroid
+	
+	If size=ASTLARGE
+		a\id=CopyEntity(large_asteroid)
+	ElseIf size=ASTMEDIUM
+		a\id=CopyEntity(medium_asteroid)
+	Else
+		a\id=CopyEntity(small_asteroid)
+	EndIf
+	
+	a\size=size
+	
+	EntityTexture a\id,shieldtex
+	PositionEntity a\id,x,y,WAVEZ
+	
+	a\colcnt=ASTSHIELD
+	
+	a\speed#=Rnd(ASTMINSPEED,ASTMAXSPEED)
+	ang=Rand(360)
+	
+	a\dx=Sin(ang)*a\speed
+	a\dy=Cos(ang)*a\speed
+	
+	a\power=PowerUp()
+	a\split=False
+	
+End Function
+
+
+Function UpdateAsteroids()
+
+	If False
+		sz=32
+		i=CreateImage(sz,sz)
+		CopyRect 0,0,sz,sz-1,0,1,TextureBuffer(shieldtex),ImageBuffer(i)
+		CopyRect 0,sz-1,sz,1,0,0,TextureBuffer(shieldtex),ImageBuffer(i)
+		CopyRect 0,0,sz,sz,0,0,ImageBuffer(i),TextureBuffer(shieldtex)
+		FreeImage i
+		RotateTexture shieldtex,globang
+	EndIf
+	
+	do_split=False
+	
+	For a.Asteroid=Each Asteroid
+	
+		upd=True
+		
+		If a\colcnt>0
+			a\colcnt=a\colcnt-1
+			
+			If a\colcnt=0
+				If a\power=POWNONE
+					EntityTexture a\id,asttex
+				Else
+					EntityTexture a\id,powertex
+				EndIf
+				EntityType a\id,ASTTYPE
+			EndIf
+			
+			hit_ship=False
+			hit_sw=False
+		Else
+			hit_ship=EntityDistance(a\id,ship)<(a\size/2+SHIPSZ)
+			hit_sw=HitSW(a\id,a\size)
+		EndIf
+		
+		If hit_ship
+			SubShield(1)
+			NewParticleMove(particle,EntityX(ship),EntityY(ship),EntityZ(ship)-1,10,2,Rnd(-2,2),Rnd(-2,2),0)
+		ElseIf hit_sw Or a\split
+		
+			If Not dead
+				AddScore(a\size)
+				
+				hit_timer=200
+				hit_count=hit_count+1
+				
+				If Not a\split
+					EmitSound(pop_sfx,a\id)
+					dz#=0.1
+					For f=10 To 100 Step 10
+						NewAlphaParticleMove(particle,EntityX(a\id),EntityY(a\id),EntityZ(a\id)-f,1.0,-0.01,f/10,0,0,dz)
+						dz=dz+0.1
+					Next
+				EndIf
+	
+				If a\size>ASTSMALL
+					x#=EntityX(a\id)
+					y#=EntityY(a\id)
+					
+					NewAsteroid(a\size/2,x,y)
+					NewAsteroid(a\size/2,x,y)
+				EndIf
+				
+				If a\power<>POWNONE
+					If a\split
+						ReturnPowerUp(a\power)
+					Else
+						Select a\power
+							Case POWSPLIT
+								NewCameraSpriteText("SMART BOMB!",$ff0000,0,0,EntityZ(camera)+30,-0.4,1,0.01)
+								do_split=True
+								CircleQSound(smartbomb_sfx,2)
+							
+							Case POWSHIELD
+								NewCameraSpriteText("SHEILD UP!",$ff0000,0,0,EntityZ(camera)+31,-0.4,1,0.01)
+								SubShield(-10)
+								
+							Case POWTURBOTURN
+								If Rand(100)>50
+									NewCameraSpriteText("TURBO NUTTER!",$ff0000,0,0,EntityZ(camera)+32,-0.4,1,0.01)
+									CircleQSOund(turbostart_sfx,1)
+									turbo_count=turbo_count+500
+									MAX_SPEED=MAXSPEED_TURBO
+								Else
+									NewCameraSpriteText("TURN LOSS!",$ff0000,0,0,EntityZ(camera)+33,-0.4,1,0.01)
+									CircleQSound(turnstart_sfx,1)
+									turn_count=turn_count+500
+									turn=TURN_TURBO
+								EndIf
+							Case POWFPS
+								SetCamera(CAMERA_FPS)
+								NewCameraSpriteText("FPS MODE!",$ff0000,0,0,EntityZ(camera)+33,-0.4,1,0.01)
+								CircleQSOund(laugh_sfx,4)
+								fps_count=fps_count+1000
+						End Select
+					EndIf
+				EndIf
+		
+				FreeEntity a\id
+				Delete a
+				upd=False
+			EndIf
+		EndIf
+		
+		If upd
+			If CountCollisions(a\id)>0
+				a\dx=CollisionNX(a\id,1)*a\speed
+				a\dy=CollisionNY(a\id,1)*a\speed
+			EndIf
+			
+			TurnEntity a\id,0,a\dx*2,0
+			TranslateEntity a\id,a\dx,a\dy,0
+			
+			ex=EntityX(a\id)
+			ey=EntityY(a\id)
+			
+			If ex<-MAPSIZE Or ex>MAPSIZE
+				s=Sgn(ex)
+				PositionEntity a\id,s*MAPSIZE,ey,WAVEZ
+				a\dx=-a\dx
+			EndIf
+
+			If ey<-MAPSIZE Or ey>MAPSIZE
+				s=Sgn(ey)
+				PositionEntity a\id,ex,s*MAPSIZE,WAVEZ
+				a\dy=-a\dy
+			EndIf
+		EndIf
+	Next
+	
+	If do_split
+		For a=Each Asteroid
+			a\split=True
+		Next
+	EndIf
+
+End Function
+
+
+; ============================================
+; Shockwave
+; ============================================
+;
+.Shochwave
+
+Function InitShockwave(length,z#)
+	If sw<>Null
+		FreeEntity sw\id
+	Else
+		sw=New Shockwave
+	EndIf
+	
+	Delete Each SWLine
+	CreateSWLine(0,0,0)
+	
+	sw\length=length
+	sw\id=CreateMesh()
+	PositionEntity sw\id,0,0,z
+	EntityType sw\id,SWTYPE
+	EntityRadius sw\id,1
+	CreateSurface(sw\id)
+	sw\z=z
+	
+	EntityFX sw\id,1+2+16+32
+End Function
+
+
+Function CreateSWLine.SWLine(x#,y#,roll#)
+	s.SWLine=New SWLine
+	sz#=0.5
+	
+	s\x1=x-sz*Cos(roll)
+	s\x2=x+sz*Cos(roll)
+	s\y1=y-sz*Sin(roll)
+	s\y2=y+sz*Sin(roll)
+	
+	s\r1=Rand(100,255)
+	s\g1=Rand(0,100)
+	s\b1=Rand(0,100)
+	s\r2=Rand(100,255)
+	s\g2=Rand(0,100)
+	s\b2=Rand(0,100)
+End Function
+
+
+Function AddShockwave(base)
+
+	x#=EntityX(base)
+	y#=EntityY(base)
+	roll#=EntityRoll(base)
+	
+	CreateSWLine(x,y,roll)
+	
+	If sw\length>0
+		sw\length=sw\length-1
+	Else
+		Delete First SWLine
+	EndIf
+		
+	s=GetSurface(sw\id,1)
+	ClearSurface s,True,True
+	
+	al#=0.1
+	
+	prev.SWLine=Null
+	
+	For sl.SWLine=Each SWLine
+		If prev<>Null
+			If True
+				v0=AddVertex(s,sl\x1,sl\y1,0)
+				v1=AddVertex(s,sl\x2,sl\y2,0)
+				v2=AddVertex(s,prev\x1,prev\y1,0)
+				v3=AddVertex(s,prev\x2,prev\y2,0)
+				
+				VertexColor s,v0,sl\r1,sl\g1,sl\b1,al
+				VertexColor s,v1,sl\r2,sl\g2,sl\b2,al
+				VertexColor s,v2,prev\r1,prev\g1,prev\b1,al
+				VertexColor s,v3,prev\r2,prev\g2,prev\b2,al
+	
+				AddTriangle(s,v0,v1,v2)
+				AddTriangle(s,v1,v3,v2)
+			EndIf
+			
+			If False
+				v0=AddVertex(s,sl\x1,sl\y1,-1)
+				v1=AddVertex(s,sl\x2,sl\y2,-1)
+				v2=AddVertex(s,prev\x1,prev\y1,-1)
+				v3=AddVertex(s,prev\x2,prev\y2,-1)
+				v4=AddVertex(s,sl\x1,sl\y1,1)
+				v5=AddVertex(s,sl\x2,sl\y2,1)
+				v6=AddVertex(s,prev\x1,prev\y1,1)
+				v7=AddVertex(s,prev\x2,prev\y2,1)
+				
+				VertexColor s,v0,sl\r1,sl\g1,sl\b1,al
+				VertexColor s,v1,sl\r2,sl\g2,sl\b2,al
+				VertexColor s,v2,prev\r1,prev\g1,prev\b1,al
+				VertexColor s,v3,prev\r2,prev\g2,prev\b2,al
+	
+				AddTriangle(s,v0,v1,v2)
+				AddTriangle(s,v1,v3,v2)
+				AddTriangle(s,v4,v6,v5)
+				AddTriangle(s,v4,v6,v7)
+			EndIf
+
+			If al<1.0
+				al=al+0.05
+			EndIf
+		EndIf
+		
+		prev=sl
+	Next
+End Function
+
+
+; ============================================
+; Particles
+; ============================================
+;
+.Particles
+
+Function ClearParticles()
+	For p.Particle=Each Particle
+		FreeEntity p\id
+		Delete p
+	Next
+End Function
+
+Function UpdateParticles()
+	For p.Particle=Each Particle
+		If p\life=0 Or p\a<=0
+			FreeEntity p\id
+			Delete p
+		Else
+			p\life=p\life-1
+			p\a=p\a+p\ai
+			EntityAlpha p\id,p\a
+			TurnEntity p\id,0,0,p\spin
+			MoveEntity p\id,p\dx,p\dy,p\dz
+		EndIf
+	Next
+End Function
+
+Function NewParticle(base,x#,y#,z#,life,spin#)
+	NewParticleMove(base,x,y,z,life,spin,0,0,0)
+End Function
+
+Function NewParticleMove(base,x#,y#,z#,life,spin#,dx#,dy#,dz#)
+	p.Particle=New Particle
+	p\id=CopyEntity(base)
+	ShowEntity p\id
+	PositionEntity p\id,x,y,z
+	p\life=life
+	p\a=1.0
+	p\dx=dx
+	p\dy=dy
+	p\dz=dz
+	p\spin=spin
+End Function
+
+Function NewAlphaParticle(base,x#,y#,z#,a#,ai#,spin#)
+	NewAlphaParticleMove(base,x,y,z,a,ai,spin,0,0,0)
+End Function
+
+Function NewAlphaParticleMove(base,x#,y#,z#,a#,ai#,spin#,dx#,dy#,dz#)
+	p.Particle=New Particle
+	p\id=CopyEntity(base)
+	ShowEntity p\id
+	EntityAlpha p\id,a
+	PositionEntity p\id,x,y,z
+	p\life=9999999
+	p\a=a
+	p\ai=ai
+	p\dx=dx
+	p\dy=dy
+	p\dz=dz
+	p\spin=spin
+End Function
+
+
+; ============================================
+; Mesh and Texture
+; ============================================
+;
+.MeshAndTexture
+
+Function CreateVectex()
+	s=256
+	t=CreateTexture(s,s,1+4+8+256)
+	i=CreateImage(s,s)
+	b=BackBuffer()
+	SetBuffer ImageBuffer(i)
+	Color 128,128,128
+	Rect 0,0,s,s,True
+	For f=0 To 128
+		Color 255-f,255-f,255-f
+		Rect f,f,s-f*2,s-f*2,False
+	Next
+	SetBuffer b
+	CopyRect 0,0,s,s,0,0,ImageBuffer(i),TextureBuffer(t)
+	FreeImage i
+	Return t
+End Function
+
+Function CreateParticle()
+	m=CreateMesh()
+	b=CreateBrush(255,0,0)
+	s=CreateSurface(m,b)
+	
+	sz#=2
+
+	v0=AddVertex(s,0,sz,0)
+	v1=AddVertex(s,-sz,-0,0)
+	v2=AddVertex(s,0,-sz,0)
+	v3=AddVertex(s,sz,0,0)
+	
+	AddTriangle(s,v0,v2,v1)
+	AddTriangle(s,v0,v3,v2)
+	
+	UpdateNormals m
+	
+	Return m
+End Function
+
+Function CreateShip()
+
+	m=CreateMesh()
+	b=CreateBrush(255,255,255)
+	BrushTexture b,vectex
+	s=CreateSurface(m,b)
+	
+	sz#=SHIPSZ
+
+	v0=AddVertex(s,0,sz,0,0,0)
+	v1=AddVertex(s,-sz,-sz,0,0,1)
+	v2=AddVertex(s,0,-sz/2,1,0,1)
+	v3=AddVertex(s,sz,-sz,0,1,0)
+	
+	AddTriangle(s,v0,v2,v1)
+	AddTriangle(s,v0,v3,v2)
+	
+	UpdateNormals m
+	
+	Return m
+
+End Function
+
+Function CreateAsttex()
+	s=256
+	t=CreateTexture(s,s,1+4+8+256)
+	i=CreateImage(s,s)
+	b=BackBuffer()
+	SetBuffer ImageBuffer(i)
+	Color 0,0,128
+	Rect 0,0,s,s,True
+	Color 64,64,255
+	For f=0 To 256 Step 32
+		Rect f,0,4,256,True
+		Rect 0,f,256,4,True
+	Next
+	SetBuffer b
+	CopyRect 0,0,s,s,0,0,ImageBuffer(i),TextureBuffer(t)
+	FreeImage i
+	Return t
+End Function
+
+Function TRANS_CreateAsttex()
+	s=256
+	t=CreateTexture(s,s,1+4+8+256)
+	ClearTexture(t)
+	For f=0 To 256 Step 32
+		RectTexture(t,f,0,4,256,$ffffffff)
+		RectTexture(t,0,f,256,4,$ffffffff)
+	Next
+	Return t
+End Function
+
+Function CreatePowertex()
+	s=256
+	t=CreateTexture(s,s,1+4+8+256)
+	i=CreateImage(s,s)
+	b=BackBuffer()
+	SetBuffer ImageBuffer(i)
+	Color 128,128,0
+	Rect 0,0,s,s,True
+	Color 255,255,0
+	For f=0 To 256 Step 32
+		Rect f,0,4,256,True
+		Rect 0,f,256,4,True
+	Next
+	SetBuffer b
+	CopyRect 0,0,s,s,0,0,ImageBuffer(i),TextureBuffer(t)
+	FreeImage i
+	Return t
+End Function
+
+Function TRANS_CreatePowertex()
+	s=256
+	t=CreateTexture(s,s,1+4+8+256)
+	ClearTexture(t)
+	For f=0 To 256 Step 32
+		RectTexture(t,f,0,4,256,$ffffff00)
+		RectTexture(t,0,f,256,4,$ffffff00)
+	Next
+	Return t
+End Function
+
+Function OLD_CreateShieldtex()
+	sz=32
+	t=CreateTexture(sz,sz,1+4+8+256)
+	i=CreateImage(sz,sz)
+	b=BackBuffer()
+	SetBuffer ImageBuffer(i)
+	For f=0 To sz-1
+		Color Rand(255),Rand(255),Rand(255)
+		Line 0,f,sz-1,f
+	Next
+	SetBuffer b
+	CopyRect 0,0,sz,sz,0,0,ImageBuffer(i),TextureBuffer(t)
+	FreeImage i
+	Return t
+End Function
+
+Function CreateShieldtex()
+	s=32
+	t=CreateTexture(s,s,1+4+8+256)
+	ClearTexture(t)
+	For x=0 To s Step 2
+		For y=0 To s Step 2
+			RectTexture(t,x+(y Mod 2),y,1,1,$ffffffff)
+			;RectTexture(t,x,y,1,1,$ffffffff)
+		Next
+	Next
+	Return t
+End Function
+
+Function CreateAsteroid(size#)
+
+	size=size/2
+
+	m=CreateSphere()
+	ScaleEntity m,size,size,size
+	Return m
+
+	m=CreateMesh()
+	s=CreateSurface(m)
+	
+	pt#=16.0
+	ai#=360.0/pt
+	
+	AddVertex(s,0,0,0,0.5,0.5)
+	
+	For f=0 To pt-1
+		a#=f*ai
+		x#=Sin(a)*size
+		y#=Cos(a)*size
+		AddVertex(s,x,y,z,Abs(Sin(a)),Abs(Cos(a)))
+	Next
+	
+	For f=1 To pt-1
+		AddTriangle(s,0,f,f+1)
+	Next
+	
+	AddTriangle(s,0,pt,1)
+	
+	UpdateNormals m
+	
+	Return m
+
+End Function
+
+Function CreateMaptex()
+	s=256
+	t=CreateTexture(s,s,1+4+8+256)
+	i=CreateImage(s,s)
+	b=BackBuffer()
+	SetBuffer ImageBuffer(i)
+	Color 0,0,64
+	Rect 0,0,s,s,True
+	For f=0 To 128
+		rd=Rand(128,255)
+		gn=Rand(128,255)
+		bl=Rand(128,255)
+		
+		x=Rand(1,s-1)
+		y=Rand(1,s-1)
+		Color rd/2,gn/2,bl/2
+		Plot x-1,y
+		Plot x+1,y
+		Plot x,y-1
+		Plot x,y+1
+		Color rd,gn,bl
+		Plot x,y
+	Next
+	Color 0,0,128
+	Rect 0,0,s,s,False
+	SetBuffer b
+	CopyRect 0,0,s,s,0,0,ImageBuffer(i),TextureBuffer(t)
+	FreeImage i
+	Return t
+End Function
+
+Function MapSurface(m,b,x1,y1,z1,x2,y2,z2,x3,y3,z3,x4,y4,z4)
+	s=CreateSurface(m,b)
+	
+	v0=AddVertex(s,x1,y1,z1,0,0)
+	v1=AddVertex(s,x2,y2,z2,1,0)
+	v2=AddVertex(s,x3,y3,z3,0,1)
+	v3=AddVertex(s,x4,y4,z4,1,1)
+	
+	AddTriangle(s,v0,v1,v2)
+	AddTriangle(s,v1,v3,v2)
+End Function
+
+Function CreateMap()
+
+	m=CreateMesh()
+	b=CreateBrush(255,255,255)
+	BrushTexture b,maptex
+	
+	sz=MAPSIZE+10
+	
+	MapSurface(m,b,	-sz,sz,sz,		sz,sz,sz,		-sz,-sz,sz,		sz,-sz,sz)
+	MapSurface(m,b,	-sz,sz,-sz,		sz,sz,-sz,		-sz,sz,sz,		sz,sz,sz)
+	MapSurface(m,b,	-sz,-sz,-sz,	-sz,sz,-sz,		-sz,-sz,sz,		-sz,sz,sz)
+	MapSurface(m,b,	sz,sz,-sz,		sz,-sz,-sz,		sz,sz,sz,		sz,-sz,sz)
+	MapSurface(m,b,	sz,-sz,-sz,		-sz,-sz,-sz,	sz,-sz,sz,		-sz,-sz,sz)
+		
+	UpdateNormals m
+	
+	Return m
+
+End Function
+
+
+; ============================================
+; Menu
+; ============================================
+;
+.TitleRoutines
+
+Function Menu()
+
+	FlushKeys
+	
+	InitAsteroids()
+
+	ClearText()
+	
+	PositionEntity ship,0,0,SHIPZ
+	RotateMesh ship,0,0,0
+	
+	ClearParticles()
+	ClearSpriteText()
+	InitShockwave(180,WAVEZ)
+	
+	done=False
+	turn=0
+	count=100
+	speed=0
+	r=0
+	g=0
+	b=0
+	i=1
+	tl$="abcdefgh"
+	ic=1
+	icl=Len(instruction$)
+	icp=1
+
+	HudTextCentre(20,"SHOCKWAVE",$ffffff)
+	HudTextCentre(30,"(C) 2004 IAN C",$ffffff)
+	
+	If DEBUGMODE
+		HudTextCentre(150,"**** DEBUG KEYS ENABLED ****",$ff0000)
+	EndIf
+	
+	HudTextCentre(50,"PRESS F1 FOR LEVEL",$ffff00)
+	HudTextCentre(60,"PRESS SPACE TO PLAY",$ffff00)
+	HudTextCentre(80,"PRESS ESC TO QUIT",$ffff00)
+	
+	HudTextCentre(170,"HIGH SCORE",$ffffff)
+	HudTextCentre(200,"LARGEST LOST CHAIN",$ffffff)
+	
+	AddScore(0)
+	start_bonus=(start_level-1)^2*1000
+	
+	ti=MilliSecs()
+	
+	While Not done
+	
+		HudText(245,0,Mid$(tl$,i,1))
+		
+		If (MilliSecs()-ti)>200
+			i=(i Mod Len(tl$))+1
+			ti=MilliSecs()
+		EndIf
+		
+		HudTextCentre(100,"   START LEVEL " + start_level+"   ",$00ffff)
+		HudTextCentre(110,"   BONUS " + start_bonus+"   ",$00ffff)
+		
+		If new_highscore
+			HudTextCentre(170,"NEW HIGH SCORE",(g Shl 16) Or (b Shl 8) Or r)
+		EndIf
+		
+		If new_highlostchain
+			HudTextCentre(200,"NEW LARGEST LOST CHAIN",(g Shl 16) Or (b Shl 8) Or r)
+		EndIf
+		
+		HudTextCentre(180,Str$(highscore),(r Shl 16) Or (g Shl 8) Or b)
+		HudTextCentre(210,Str$(highlostchain),(r Shl 16) Or (g Shl 8) Or b)
+		
+		r=(r+7) And 255
+		g=(g+5) And 255
+		b=(b+3) And 255
+		
+		ic=ic-1
+		
+		If ic=0
+			NewCameraSpriteTextScroll(Mid$(instruction$,icp,1),$ffffff,5,-2,EntityZ(camera)+5,-0.02,0,0,500)
+			ic=6
+			icp=icp+1
+			If icp>icl
+				icp=1
+			EndIf
+		EndIf
+	
+		If KeyHit(1)
+			done=True
+			quit=True
+		EndIf
+		
+		If KeyHit(57)
+			done=True
+		EndIf
+		
+		If KeyHit(59)
+			start_level=start_level+5
+			If start_level>30
+				start_level=1
+			EndIf
+			start_bonus=(start_level-1)^2*1000
+		EndIf
+		
+		count=count-1
+		
+		If count=0
+			turn=Rand(-1,1)
+			
+			If turn=0
+				count=Rand(1,200)
+			Else
+				count=Rand(10,200)
+			EndIf			
+		EndIf
+	
+		If turn=-1
+			TurnEntity ship,0,0,TURN_NORMAL
+		EndIf
+		
+		If turn=1
+			TurnEntity ship,0,0,-TURN_NORMAL
+		EndIf
+		
+		If speed<MAX_SPEED
+			speed=speed+0.002
+		EndIf
+	
+		MoveEntity ship,0,speed,0
+		
+		PositionEntity camera,EntityX(ship),EntityY(ship),0
+		;PositionEntity camera,0,0,0
+		;PointEntity camera,ship
+		
+		UpdateParticles()
+		UpdateSpriteText()
+	
+		UpdateWorld
+		
+		RenderWorld
+		
+		AddShockwave(ship)
+		
+		DrawRadar()
+		
+		ex=EntityX(ship)
+		ey=EntityY(ship)
+		
+		If ex<-MAPSIZE Or ex>MAPSIZE
+			RotateEntity ship,0,0,-EntityRoll(ship)
+			MoveEntity ship,0,speed,0
+		EndIf
+		
+		If ey<-MAPSIZE Or ey>MAPSIZE
+			RotateEntity ship,0,0,180-EntityRoll(ship)
+			MoveEntity ship,0,speed,0
+		EndIf
+		
+		Flip
+		
+		globang=(globang+10) Mod 360
+		
+	Wend
+
+End Function
+
+
+; ============================================
+; Highscore Routines
+; ============================================
+;
+.HiScoreRoutines
+
+Function LoadHighScore()
+	fp=ReadFile("hiscore.dat")
+
+	If fp=0
+		Return
+	EndIf
+
+	highscore=ReadInt(fp)
+	highlostchain=ReadInt(fp)
+	CloseFile fp
+End Function
+
+Function SaveHighScore()
+	fp=WriteFile("hiscore.dat")
+	
+	If fp=0
+		Return
+	EndIf
+	
+	WriteInt fp,highscore
+	WriteInt fp,highlostchain
+	CloseFile fp
+End Function
+
+
+; ============================================
+; Power Up Routines
+; ============================================
+;
+.PowerUpRoutines
+
+Function CreatePowerUp(id,chance,max)
+	p.PowerUp=New PowerUp
+	p\id=id
+	p\chance=chance
+	p\max=max
+End Function
+
+Function ResetPowerUps()
+	For p.PowerUp=Each PowerUp
+		p\count=0
+	Next
+End Function
+
+Function PowerUp()
+	If is_bonus_level
+		Return POWSPLIT
+	EndIf
+	
+	i=Rand(100)
+	
+	For p.PowerUp=Each PowerUp
+		If i>p\chance And p\count<p\max
+			p\count=p\count+1
+			Return p\id
+		EndIf
+	Next
+	
+	Return POWNONE
+End Function
+
+Function ReturnPowerUp(id)
+	For p.PowerUp=Each PowerUp
+		If p\id=id
+			p\count=p\count-1
+			Return
+		EndIf
+	Next
+End Function
+
+
+; ============================================
+; Queued Sound Routines
+; ============================================
+;
+.QSoundRoutines
+
+Function ProcessQSounds()
+	For s.QSound=Each QSound
+		If s\time=0
+			EmitSound(s\snd,s\obj)
+			Delete s
+		Else
+			s\time=s\time-1
+		EndIf
+	Next
+End Function
+
+
+Function QueueQSound(snd,time,source)
+	s.QSound=New QSound
+	s\snd=snd
+	s\time=time
+	s\obj=source
+End Function
+
+
+Function CircleQSound(snd,del)
+	For f=0 To 7
+		QueueQSound(snd,del*f,snd_emitter(f))
+	Next
+End Function
+
+
+
+; ============================================
+; Instruction Data
+; ============================================
+;
+.InstructionData
+Data "THE ALIENS HAVE SELECTED YOU TO REPRESENT THE HUMAN RACE "
+Data "IN SHOCKWAVE.  "
+Data "IF YOU FAIL 3 BILLION SOULS WILL BE LOST. MOST IMPORTANTLY, YOURS....   "
+Data "THERE IS A SPANNER IN THE WORKS THOUGH - YOUR SHIP IS BUST.  "
+Data "THERE IS NO CONTROL OVER ITS "
+Data "SPEED.  ONLY STEERING WORKS AND YOU CAN ONLY DESTROY THE SPHERES WITH YOUR SHOCKWAVE EXHAUST.  "
+Data "THE DESTROYED SPHERES MAY ALSO HAVE "
+Data "UNDESIRED EFFECTS ON THE SHIP...   OR EVEN GOOD ONES.  "
+Data "TO STEER USE THE LEFT AND RIGHT CURSOR KEYS.  PRESS P TO PAUSE.  PRESS ESCAPE TO QUIT.   "
+Data "    "
+Data "GOOD LUCK!                                       "
+Data "END"
\ No newline at end of file
-- 
cgit v1.2.3