Posted: 30th Jun 2011 21:01
I've been working with the AppGameKit Beta now for a few weeks, and wanted to share with those of you that are waiting anxiously to get your hands on it what I've been up to.

I needed a game idea that wouldn't necessarily be something I would sell later, but would be enough to test as many aspects of the kit as possible.

The result is Asteroid Blast.



It needs a few more little tweaks, but it's basically finished.
Posted: 30th Jun 2011 23:04
Wow, that looks great KISTech! An excellent example of what AppGameKit can do.

It needs a few more little tweaks, but it's basically finished.

All I can suggest is giving the score a fancier font.

When a bullet hits an asteroid and we see sparks fly, is that your own algorithm for handling those sprites or is that AGK's particle system?

Thanks for sharing KISTech!
Posted: 30th Jun 2011 23:28
Nice to see some stuff created with the AppGameKit! Thanks for giving us a glimps of whut's possible to do with this kit, KIStech.

is that your own algorithm for handling those sprites or is that AGK's particle system?

I think it is a selfmade particle function, but I would like to hear that it is in fact a built in AppGameKit particle system, though.

Also, is it possible to scroll the background?

And, what is the resolution this game runs in? Can you tell us the framerate this ran too?

Thanks!
Posted: 1st Jul 2011 0:46
is that your own algorithm for handling those sprites or is that AGK's particle system?


The sparks are from AGK's particle system. It's very easy to use and quite flexible.

is it possible to scroll the background?


Yes, although the method you choose is up to you. There are probably 2-3 different ways you could do it. Since I'm just now starting on another project that will involve that, I don't have any specifics.
I will say the backgrounds you see in Asteroid Blast are 800 x 600, and you're only seeing 320 x 480 of the upper right corner.

what is the resolution this game runs in? Can you tell us the framerate this ran too?


This uses the Virtual Resolution method, and is set at 320 x 480.

The frame rate seems to be locked in at 60 fps. It jumps around a bit on menus and at the beginning of the level, but once you start playing it settles in at 60.
Posted: 1st Jul 2011 12:06
The sparks are from AGK's particle system. It's very easy to use and quite flexible.

That's good news, I think I'll make good use of AGK's particle system.

The frame rate seems to be locked in at 60 fps

That's fine with me, I always use a sync rate of 60 in DBPro and aim for 60 fps.

Have you tried running it on mobile OSs like iOS and android?
Posted: 1st Jul 2011 19:05
At the moment we only have access to the Windows compiler, so I haven't seen it run on anything else yet.
Posted: 2nd Jul 2011 5:30
nice example of a few basics there, kistech.

am i needlessly concerned that some of the bullets strike asteroids but do nothing to them? some of the large ones are destroyed with one hit but that's not always the case. is there programming in there that requires some of asteroids to take more than one hit before destruction?

and, while i've skimmed very little of the agk info thus far, i have yet to see any code examples... care to/can you share?
Posted: 2nd Jul 2011 20:37
There is an algorithm that sets up the asteroids at start up. During that process it sets their scale. If the scale is greater than a certain value then the asteroid has to be hit twice to explode. However the impact should be causing an explosion.

Since making this video I did fix the explosions for the asteroids that hit the shield. They were all happening in the upper left corner instead of at the location of the asteroid.

[edit]
I'm checking to see if it's ok to post the source, or if it's to soon.
Posted: 3rd Jul 2011 0:40
and, while i've skimmed very little of the agk info thus far, i have yet to see any code examples... care to/can you share?

You could also check out the vids about the AppGameKit in the latest newsletter. They show some code.

Cheers
Posted: 3rd Jul 2011 1:40
@ Virtual Nomad, you can also check the first page of the "AGK Survey" thread stickied at the top of this board. Scoll down until you find Lee's post and there is a code snippet demonstrating all of the basics such as declaring variables.
Posted: 3rd Jul 2011 19:41
Ok. Here is the AppGameKit source code for Asteroid Blast.

PLEASE NOTE:
* The commands you see may or may not be the same in the final product. It's a beta after all, and things sometimes change.


The Client:
+ Code Snippet
rem
rem Asteroid Blast
rem Written by : Kevin Summers
rem

SetPrintSize(18)

rem Set Globals
global sw as integer
global sh as integer
global Stick1 as integer
global Stick2 as integer
global dim t[20] as integer
global optSound as integer
global optSoundVol as integer
global optMusic as integer
global optMusicVol as integer
global optInitials$ as string

rem Set the working resolution
sw = 320
sh = 480
SetVirtualResolution(sw, sh)

rem Variables for the virtual joysticks
Stick1 = 1
Stick2 = 2

rem Player Options
optSound = 1
optSoundVol = 70
optMusic = 1
optMusicVol = 70
optInitials$ = "AAA"

if GetFileExists("Options.txt") = 1
	f = OpenToRead("Options.txt")
	if FileEOF(f) = 0
		optSound = ReadInteger(f)
		optSoundVol = ReadInteger(f)
		optMusic = ReadInteger(f)
		optMusicVol = ReadInteger(f)
	endif
	CloseFile(f)
else
	f = OpenToWrite("Options.txt", 0)
	WriteInteger(f, optSound)
	WriteInteger(f, optSoundVol)
	WriteInteger(f, optMusic)
	WriteInteger(f, optMusicVol)
	CloseFile(f)
endif

rem Load our generic all purpose image
LoadImage(1, "White.jpg", 0)
CreateSprite(1, 1)
SetSpriteSize(1, sw, sh)
SetSpriteColor(1, 0, 0, 0, 255)
SetSpritePosition(1, 0, 0)
SetSpriteDepth(1, 9)

rem Logo Splash Screen
LoadImage(2, "Logo.png", 0)
CreateSprite(2, 2)
SetSpriteSize(2, sw, sw)
SetSpritePosition(2, 0, 80)
t# = timer()
a = 255
do
	a = a - 2
	if a < 0 then a = 0
	SetSpriteColor(1, 0, 0, 0, a)
	if timer() - t# > 2.0 then t# = 0.0
	sync()
	if t# = 0.0 then exit
loop
t# = timer()
do
	if timer() - t# > 2.0 then t# = 0.0
	sync()
	if t# = 0.0 then exit
loop
t# = timer()
do
	a = a + 4
	if a > 255 then a = 255
	SetSpriteColor(1, 0, 0, 0, a)
	if timer() - t# > 1.5 then t# = 0.0
	sync()
	if t# = 0.0 then exit
loop
DeleteSprite(2)
DeleteImage(2)

rem Let them know we're loading assets
tLoading = CreateText("Loading..")
SetTextSize(tLoading, 18)
SetTextPosition(tLoading, sw/2-(GetTextTotalWidth(tLoading)/2), sh/2-10)
sync()
SetSpritePosition(1, -320, 0)

rem Main menu logo and buttons
ABLogo = LoadImage("ABLogo.png", 0)
ABSpr = CreateSprite(ABLogo)
SetSpritePosition(ABLogo, -300, -300)
PlayImg = LoadImage("Btn_Play.png", 0)
PlaySpr = CreateSprite(PlayImg)
SetSpriteShape(PlaySpr, 3)
SetSpritePosition(PlaySpr, -300, -300)
HiScoreImg = LoadImage("Btn_HighScore.png", 0)
HiScoreSpr = CreateSprite(HiScoreImg)
SetSpriteShape(HiScoreSpr, 3)
SetSpritePosition(HiScoreSpr, -300, -300)
HiScoreImg2 = LoadImage("HighScores.png", 0)
HiScoreSpr2 = CreateSprite(HiScoreImg2)
SetSpritePosition(HiScoreSpr2, -300, -300)
ExitImg = LoadImage("Btn_Exit.png", 0)
ExitSpr = CreateSprite(ExitImg)
SetSpriteShape(ExitSpr, 3)
SetSpritePosition(ExitSpr, -300, -300)
OptionsImg = LoadImage("Btn_Options.png", 0)
OptionsSpr = CreateSprite(OptionsImg)
SetSpriteShape(OptionsSpr, 3)
SetSpritePosition(OptionsSpr, -300, -300)
InstructImg = LoadImage("Btn_Instruct.png", 0)
InstructSpr = CreateSprite(InstructImg)
SetSpriteShape(InstructSpr, 3)
SetSpritePosition(InstructSpr, -300, -300)
BackImg = LoadImage("Btn_Back.png", 0)
BackSpr = CreateSprite(BackImg)
SetSpriteShape(BackSpr, 3)
SetSpritePosition(BackSpr, -300, -300)
CursorImg = LoadImage("Cursor.png", 0)
Cursor = CreateSprite(CursorImg)
SetSpriteSize(Cursor, 32, 32)
SetSpritePosition(Cursor, -100, -100)

rem Set the physics boundaries (0 = off 1 = on)
SetPhysicsWallTop(0)
SetPhysicsWallBottom(0)
SetPhysicsWallLeft(0)
SetPhysicsWallRight(0)

rem Load Music
BGMusic = LoadMusic("Mus_BGMusic.mp3")

rem Load Sound Effects
SndExplode = LoadSound("Snd_Explode.wav")
SndLaser = LoadSound("Snd_Laser.wav")
SndBomb = LoadSound("Snd_Bleep.wav")
SndShield = LoadSound("Snd_ShieldPhase.wav")
SndBombLaunch = LoadSound("Snd_Warning.wav")
SndTriShot = LoadSound("Snd_Hydrolic.wav")

rem Load Background
type nebula_data
	img as integer
	spr as integer
endtype
dim Nebulas[5] as nebula_data
for x = 1 to 4
	Nebulas[x].img = LoadImage("Nebula"+str(x)+".png", 0)
	Nebulas[x].spr = CreateSprite(Nebulas[x].img)
	SetSpritePosition(Nebulas[x].spr, -800, -600)
	SetSpriteDepth(Nebulas[x].spr, 5000)
next x
Nebula = Random(1, 4)

rem Load Ship
global Ship as integer
global ShipF as integer
global ShipL as integer
global ShipR as integer
ShipImg = LoadImage("Ship.png", 0)
ShipF = CreateSprite(ShipImg)
SetSpriteScale(ShipF, 0.5, 0.5)
SetSpriteOffset(ShipF, 32, 32)
SetSpritePositionByOffset(ShipF, -100, -100)
SetSpriteShape(ShipF, 3)
ShipLImg = LoadImage("ShipL.png", 0)
ShipL = CreateSprite(ShipLImg)
SetSpriteScale(ShipL, 0.5, 0.5)
SetSpriteOffset(ShipL, 32, 32)
SetSpritePositionByOffset(ShipL, -100, -100)
SetSpriteShape(ShipL, 3)
ShipRImg = LoadImage("ShipR.png", 0)
ShipR = CreateSprite(ShipRImg)
SetSpriteScale(ShipR, 0.5, 0.5)
SetSpriteOffset(ShipR, 32, 32)
SetSpritePositionByOffset(ShipR, -100, -100)
SetSpriteShape(ShipR, 3)

rem Setup Particles for Explosions
Shrapnel = LoadImage("shrapnel3.png", 0)
Explode = CreateParticles(0, 0)
ExplodeX = 160
ExplodeY = 200
ExpFreq = 100
ExpLife = 1.0
ExpMax = 20
fire = 0

rem Load Powerups
PUShieldImg = LoadImage("PU_Shield.png", 0)
PUShield = CreateSprite(PUShieldImg)
SetSpriteScale(PUShield, 0.25, 0.25)
SetSpriteOffset(PUShield, 16, 16)
SetSpritePositionByOffset(PUShield, -100, -100)
SetSpriteShape(PUShield, 1)
ShieldImg = LoadImage("Shield.png", 0)
Shield = CreateSprite(ShieldImg)
SetSpriteOffset(Shield, 64, 64)
SetSpritePositionByOffset(Shield, -100, -100)
SetSpriteShape(Shield, 1)
PUShieldActive = 0
ShieldActive = 0
ShieldTime = 0
ShieldHits = 0
PUTriShotImg = LoadImage("PU_Trishot.png", 0)
PUTriShot = CreateSprite(PUTriShotImg)
SetSpriteScale(PUTriShot, 0.25, 0.25)
SetSpriteOffset(PUTriShot, 16, 16)
SetSpritePositionByOffset(PUTriShot, -100, -100)
SetSpriteShape(PUTriShot, 1)
PUTriShotActive = 0
TriShotActive = 0
TriShotTime = 0
iTriShot = CreateSprite(Shrapnel)
SetSpriteOffset(iTriShot, 16, 16)
SetSpriteColor(iTriShot, 64, 255, 64, 255)
SetSpritePosition(iTriShot, -100, -100)
PUBombImg = LoadImage("PU_Bomb.png", 0)
PUBomb = CreateSprite(PUBombImg)
SetSpriteScale(PUBomb, 0.25, 0.25)
SetSpriteOffset(PUBomb, 16, 16)
SetSpritePositionByOffset(PUBomb, -100, -100)
SetSpriteShape(PUBomb, 1)
BombImg = LoadImage("Bomb.png", 0)
Bomb = CreateSprite(BombImg)
SetSpriteOffset(Bomb, 32, 32)
SetSpritePositionByOffset(Bomb, -100, -100)
SetSpriteShape(Bomb, 3)
PUBombActive = 0
BombActive = 0
BombTime = 0
iBomb = CreateSprite(BombImg)
SetSpriteScale(iBomb, 0.5, 0.5)
SetSpriteOffset(iBomb, 16, 16)
SetSpritePositionByOffset(iBomb, -100, -100)

rem Blast radius sprite for the bomb used for collision detection
rem against the asteroids when the bomb goes off.
BlastRadiusImg = LoadImage("BlastRadius.png", 0)
BlastRadius = CreateSprite(BlastRadiusImg)
SetSpriteScale(BlastRadius, 3.0, 3.0)
SetSpriteOffset(BlastRadius, 192, 192)
SetSpriteShape(BlastRadius, 1)
SetSpritePositionByOffset(BlastRadius, -300, -300)
SetSpriteVisible(BlastRadius, 0)

rem Load Asteroids
AsteroidCount = 60
type asteroid_data
	spr as integer
	act as integer
	hits as integer
endtype
dim AsteroidImg[8] as integer
dim Asteroids[AsteroidCount] as asteroid_data
for x = 1 to 8
	AsteroidImg[x] = LoadImage("Rock"+str(x)+".png", 0)
next x

rem Set the size of the asteroids, then place them off the top of
rem the screen to allow gravity to pull them down onto the screen.
i = 0
for x = 1 to AsteroidCount
	i = i + 1
	if i = 9 then i = 1
	Asteroids[x].spr = CreateSprite(AsteroidImg[i])
	a# = Random(2, 5) / 10.0
	SetSpriteScale(Asteroids[x].spr, a#, a#)
	SetSpriteAngle(Asteroids[x].spr, Random(0, 359))
	w = GetImageWidth(AsteroidImg[i]) * a#
	SetSpriteOffset(Asteroids[x].spr, w/2, w/2)
	SetSpritePositionByOffset(Asteroids[x].spr, Random(w/2, sw-(w/2)), -(Random(60, 300)))
	SetSpriteShape(Asteroids[x].spr, 3)
next x

rem Laser / Photon setup
type laser_data
	spr as integer
	act as integer
endtype
LaserCount = 50
dim Laser[LaserCount] as laser_data
w = GetImageWidth(Shrapnel) / 2
for x = 1 to LaserCount
	Laser[x].spr = CreateSprite(Shrapnel)
	SetSpriteColor(Laser[x].spr, 64, 64, 255, 255)
	SetSpriteOffSet(Laser[x].spr, w, w)
	SetSpritePositionByOffset(Laser[x].spr, -50, -50)
	SetSpriteShape(Laser[x].spr, 1)
next x

asteroidTime# = timer()

global Lives as integer = 3
global Score as integer = 0
global Level as integer = 1

rem Setup all of the text objects
global tDebug as integer
tDebug = CreateText(" ")
SetTextSize(tDebug, 18)
SetTextPosition(tDebug, 10, 230)
global tScore as integer
tScore = CreateText("Score : "+str(Score))
SetTextSize(tScore, 16)
SetTextPosition(tScore, 0, -30)
global tLives as integer
tLives = CreateText("Lives : "+str(Lives))
SetTextSize(tLives, 16)
SetTextPosition(tLives, 0, -30)
global tLevel as integer
tLevel = CreateText("Level : "+str(Level))
SetTextSize(tLevel, 22)
SetTextPosition(tLevel, 0, -30)
SetTextColor(tLevel, 255, 255, 0, 255)
global tGameOver as integer
tGameOver = CreateText("GAME OVER")
SetTextSize(tGameOver, 28)
SetTextPosition(tGameOver, 0, -50)
SetTextColor(tGameOver, 255, 64, 92, 255)
global tGetHiScore as integer
tGetHiScore = CreateText("Downloading High Scores..")
SetTextSize(tGetHiScore, 18)
SetTextPosition(tGetHiScore, 0, -50)
SetTextColor(tGetHiScore, 200, 200, 200, 255)
global tNetworkError1 as integer
global tNetworkError2 as integer
tNetworkError1 = CreateText("Server unavailable.")
tNetworkError2 = Createtext("Try again later.")
SetTextSize(tNetworkError1, 18)
SetTextSize(tNetworkError2, 18)
SetTextPosition(tNetworkError1, 0, -50)
SetTextPosition(tNetworkError2, 0, -50)
SetTextColor(tNetworkError1, 200, 200, 200, 255)
SetTextColor(tNetworkError2, 200, 200, 200, 255)
global tCountdown as integer
tCountdown = CreateText("3")
SetTextSize(tCountdown, 28)
SetTextPosition(tCountdown, 0, -50)
SetTextColor(tCountdown, 255, 255, 0, 255)
global tRoundTime as integer
tRoundTime = CreateText("60")
SetTextSize(tRoundTime, 16)
SetTextPosition(tRoundTime, 0, -50)
SetTextColor(tRoundTime, 255, 255, 255, 255)

rem Setup High Score text objects
type hiscore_data
	txt as integer
	sc as integer
endtype
dim HiScores[10] as hiscore_data
global HiScoreHeader as integer
HiScoreHeader = CreateText("Name          Score")
SetTextSize(HiScoreHeader, 22)
SetTextPosition(HiScoreHeader, 0, -50)
SetTextColor(HiScoreHeader, 255, 255, 128, 255)
f = 0
if GetFileExists("Scores.txt") = 1
	f = OpenToRead("Scores.txt")
endif
for x = 1 to 10
	if f = 0
		HiScores[x].txt = CreateText("AAA .......... 1000")
		HiScores[x].sc = 1000
	else
		n$ = ReadString(f) + " "
		HiScores[x].sc = ReadInteger(f)
		tTemp = CreateText(str(HiScores[x].sc))
		fx = GetTextLength(tTemp)
		DeleteText(tTemp)
		for y = 1 to 13 - fx
			n$ = n$ + "."
		next y
		n$ = n$ + " " + str(HiScores[x].sc)
		HiScores[x].txt = CreateText(n$)
	endif
	SetTextSize(HiScores[x].txt, 22)
	SetTextPosition(HiScores[x].txt, 0, -50)
	SetTextColor(HiScores[x].txt, 255, 255, 128, 255)
next x
if f > 0 then CloseFile(f)
SetTextPosition(tLoading, 0, -50)
fade = 0

rem Download the current high scores from the server
gosub GetHighScores



rem Main Loop
Main:
	do
		gosub StartScreen
		if Branch = 1
			Branch = 0
			gosub HiScoreScreen
		endif
		if Branch = 2
			Branch = 0
			gosub OptionsScreen
		endif
		if Branch = 3
			Branch = 0
			gosub Instructions
		endif
		if Branch = 4
			Branch = 0
			gosub GamePlay
		endif
		if Branch = 5 then exit
	loop

	end


rem Start Screen (MAIN MENU)
StartScreen:
	if GetMusicPlaying() = 1
		StopMusic()
	endif
	if optMusic = 1
		PlayMusic(BGMusic, optMusicVol, 1, 0)
	endif
	Branch = 0
	SetSpritePosition(Nebulas[Nebula].spr, 0, 0)
	SetSpritePosition(ABLogo, 32, 0)
	SetSpriteDepth(ABLogo, 2)
	SetSpritePosition(HiScoreSpr, 92, 130)
	SetSpriteDepth(HiScoreSpr, 2)
	SetSpritePosition(OptionsSpr, 92, 190)
	SetSpriteDepth(OptionsSpr, 2)
	SetSpritePosition(InstructSpr, 92, 250)
	SetSpriteDepth(InstructSpr, 2)
	SetSpritePosition(PlaySpr, 92, 310)
	SetSpriteDepth(PlaySpr, 2)
	SetSpritePosition(ExitSpr, 92, 370)
	SetSpriteDepth(ExitSpr, 2)
	SetSpriteDepth(Cursor, 1)
	SetPhysicsGravity(0.0, 0.0)
	SetTextPosition(tScore, 0, -30)
	SetTextPosition(tLives, 0, -30)

	rem Make sure there's no asteroids drifting through the menu
	for x = 1 to AsteroidCount
		Asteroids[x].act = 0
		SetSpritePhysicsAngularVelocity(Asteroids[x].spr, 0.0)
		SetSpritePhysicsVelocity(Asteroids[x].spr, 0.0, 0.0)
		SetSpritePhysicsOff(Asteroids[x].spr)
		SetSpritePositionByOffset(Asteroids[x].spr, Random(64, sw-64), -64)
	next x

	do
		tx = 0
		ty = 0
		if GetTouchCount(0) > 0
			ti = GetFirstTouchEvent(0)
			tx = GetTouchCurrentX(ti)
			ty = GetTouchCurrentY(ti)
		endif
		if tx > 0 and ty > 0
			SetSpritePosition(Cursor, tx-8, ty-8)
		else
			SetSpritePosition(Cursor, GetMouseX()-8, GetMouseY()-8)
		endif

		if GetSpriteCollision(HiScoreSpr, Cursor) = 1
			if GetmouseLeftPressed() = 1 or (tx > 0 and ty > 0)
				Branch = 1
				exit
			endif
		endif

		if GetSpriteCollision(OptionsSpr, Cursor) = 1
			if GetMouseLeftPressed() = 1 or (tx > 0 and ty > 0)
				Branch = 2
				exit
			endif
		endif

		if GetSpriteCollision(InstructSpr, Cursor) = 1
			if GetMouseLeftPressed() = 1 or (tx > 0 and ty > 0)
				Branch = 3
				exit
			endif
		endif

		if GetSpriteCollision(PlaySpr, Cursor) = 1
			if GetMouseLeftPressed() = 1 or (tx > 0 and ty > 0)
				SetPhysicsGravity(0.0, 10.0)
				Restart = 1
				Branch = 4
				exit
			endif
		endif

		if GetSpriteCollision(ExitSpr, Cursor) = 1
			if GetMouseLeftPressed() = 1 or (tx > 0 and ty > 0)
				Branch = 5
				exit
			endif
		endif

		sync()
	loop

	rem Move everything off screen
	SetSpritePosition(ABLogo, -300, -300)
	SetSpritePosition(PlaySpr, -300, -300)
	SetSpritePosition(HiScoreSpr, -300, -300)
	SetSpritePosition(OptionsSpr, -300, -300)
	SetSpritePosition(InstructSpr, -300, -300)
	SetSpritePosition(ExitSpr, -300, -300)
	SetSpritePosition(Cursor, -100, -100)
	SetTextPosition(tSetInitials1, -100, -100)
	SetTextPosition(tSetInitials2, -100, -100)
	SetTextPosition(tSetInitials3, -100, -100)

return


rem Main Game Loop
GamePlay:

	Level = 1
	Score = 0
	Lives = 3
	Active = 0
	RoundTime = 0
	dead = 1

	do

		if dead = 1 then gosub Intermission

		t# = timer()

		RT = 60 - (t# - RoundTime)

		if RT =< 0
			SetTextPosition(tRoundTime, 0, -50)
			RT = 0
			Active = 0
			if Score => 0
				Level = Level + 1
			endif
			SetSpritePhysicsOff(Ship)
			SetSpritePosition(Ship, -100, -100)
			gosub Intermission
		endif

		if RT < 10
			SetTextString(tRoundTime, "0"+str(RT))
		else
			SetTextString(tRoundTime, str(RT))
		endif

		SetTextString(tScore, "Score : "+str(Score))

		rem Move Powerups
		if PUShieldActive = 1
			SetSpritePositionByOffset(PUShield, GetSpriteXByOffset(PUShield), GetSpriteYByOffset(PUShield)+1)
			if GetSpriteCollision(Ship, PUShield) = 1
				SetSpritePositionByOffset(PUShield, -100, -100)
				if optSound = 1
					PlaySound(SndShield, optSoundVol, 0, 0)
				endif
				PUShieldActive = 0
				ShieldActive = 1
				ShieldTime = t#
				ShieldHits = 0
			endif
			if GetSpriteYByOffset(PUShield) > 500
				ShieldDrop = t# + Random(0, 20)
				SetSpritePositionByOffset(PUShield, -100, -100)
				PUShieldActive = 0
			endif
		endif
		if PUTriShotActive = 1
			SetSpritePositionByOffset(PUTriShot, GetSpriteXByOffset(PUTriShot), GetSpriteYByOffset(PUTriShot)+1)
			if GetSpriteCollision(Ship, PUTriShot) = 1
				SetSpritePositionByOffset(PUTriShot, -100, -100)
				if optSound = 1
					PlaySound(SndTriShot, optSoundVol, 0, 0)
				endif
				PUTriShotActive = 0
				SetSpritePosition(iTriShot, sw/2-32, sh-32)
				TriShotActive = 1
				TriShotTime = t#
			endif
			if GetSpriteYByOffset(PUTriShot) > 500
				SetSpritePositionByOffset(PUTriShot, -100, -100)
				PUTriShotActive = 0
			endif
		endif
		if PUBombActive = 1
			SetSpritePositionByOffset(PUBomb, GetSpriteXByOffset(PUBomb), GetSpriteYByOffset(PUBomb)+1)
			if GetSpriteCollision(Ship, PUBomb) = 1
				SetSpritePositionByOffset(PUBomb, -100, -100)
				if optSound = 1
					PlaySound(SndBomb, optSoundVol, 0, 0)
				endif
				PUBombActive = 0
				BombActive = 1
				SetSpritePosition(iBomb, sw/2, sh-32)
				BombTime = 0
			endif
			if GetSpriteYByOffset(PUBomb) > 500
				SetSpritePositionByOffset(PUBomb, -100, -100)
				PUBombActive = 0
			endif
		endif

		rem Shield Active
		if ShieldActive = 1
			SetSpritePositionByOffset(Shield, GetSpriteXByOffset(Ship), GetSpriteYByOffset(Ship))
			if t# - ShieldTime > 20
				ShieldActive = 0
				SetSpritePositionByOffset(Shield, -100, -100)
			endif
		endif

		rem TriShot Active
		if TriShotActive = 1
			if t# - TriShotTime > 10
				TriShotActive = 0
				TRiShotTime = 0
				SetSpritePosition(iTriShot, -100, -100)
			endif
		endif

		rem Fired Bomb is Active
		if BombActive = 1
			if BombTime > 0
				SetSpritePositionByOffset(Bomb, GetSpriteXByOffset(Bomb), GetSpriteYByOffset(Bomb)-1)
				if GetSpriteYByOffset(Bomb) < 200 then SetSpritePositionByOffset(Bomb, GetSpriteXByOffset(Bomb), 200)
				if t# - Bombtime > 5
					SetSpritePositionByOffset(BlastRadius, GetSpriteXByOffset(Bomb), GetSpriteYByOffset(Bomb))
					ExplodeX = GetSpriteXByOffset(Bomb)
					ExplodeY = GetSpriteYByOffset(Bomb)
					ExpFreq = 300
					ExpLife = 2.0
					ExpMax = 300
					if optSound = 1
						PlaySound(SndExplode, optSoundVol, 0, 0)
					endif
					Fire = 1
					gosub Explosions
					for x = 1 to AsteroidCount
						if GetSpriteCollision(Asteroids[x].spr, BlastRadius) = 1
							Score = Score + 10
							Asteroids[x].act = 0
							SetSpritePhysicsOff(Asteroids[x].spr)
							SetSpritePositionByOffset(Asteroids[x].spr, sw/2, -100)
						endif
					next x
					SetSpritePositionByOffset(BlastRadius, -300, -300)
					SetSpritePositionByOffset(Bomb, -100, -100)
					BombTime = 0
					BombActive = 0
					SetSpritePosition(iBomb, -100, -100)
				endif
			endif
		endif

		rem Check if the Photon has gone past the allowed game area
		rem and remove it to make it available for reuse
		for fx = 1 to LaserCount
			if GetSpriteY(Laser[fx].spr) < 16
				SetSpritePhysicsOff(Laser[fx].spr)
				SetSpritePosition(Laser[fx].spr, 0, -100)
				Laser[fx].act = 0
			endif
		next fx

		for fx = 1 to AsteroidCount
			if Asteroids[fx].act = 1
				rem Check if the asteroid made it past the player
				if GetSpriteY(Asteroids[fx].spr) > 500
					if Active = 1 then Score = Score - 50
					Asteroids[fx].act = 0
					SetSpritePhysicsOff(Asteroids[fx].spr)
					SetSpritePositionByOffset(Asteroids[fx].spr, sw/2, -100)
				endif
				rem Check if the asteroid drifted off the left or right edge of the screen
				X = GetSpriteX(Asteroids[fx].spr)
				if X < -30 or X > 340
					Asteroids[fx].act = 0
					SetSpritePhysicsOff(Asteroids[fx].spr)
					SetSpritePositionByOffset(Asteroids[fx].spr, sw/2, -100)
				endif
				rem Check if an asteroid hit the shield
				if GetSpriteCollision(Asteroids[fx].spr, Shield) = 1
					ExplodeX = GetSpriteXByOffset(Asteroids[fx].spr)
					ExplodeY = GetSpriteYByOffset(Asteroids[fx].spr)
					ExpLife = 3.0
					ExpFreq = 100
					ExpMax = 100
					if optSound = 1
						PlaySound(SndExplode, optSoundVol, 0, 0)
					endif
					Score = Score + 10
					ShieldHits = ShieldHits + 1
					SetSpritePhysicsOff(Asteroids[fx].spr)
					SetSpritePositionByOffset(Asteroids[fx].spr, sw/2, -100)
					if ShieldHits => 3
						ShieldTime = 0
						ShieldActive = 0
						SetSpritePositionByOffset(Shield, -100, -100)
					endif
					Fire = 1
					gosub Explosions
				endif
				rem Check if an asteroid hit the ship
				if GetPhysicsCollision(Asteroids[fx].spr, Ship) = 1
					ExplodeX = GetPhysicsCollisionWorldX()
					ExplodeY = GetPhysicsCollisionWorldY()
					ExpFreq = 100
					ExpLife = 1.0
					ExpMax = 30
					if optSound = 1
						PlaySound(SndExplode, optSoundVol, 0, 0)
					endif
					dead = 1
					Active = 0
					Score = Score - 100
					Lives = Lives - 1
					SetTextString(tLives, "Lives : "+str(Lives))
					fire = 1
					gosub Explosions
					SetSpritePhysicsOff(Ship)
					SetSpritePositionByOffset(Ship, -200, -200)
					exit
				endif
			endif
		next fx

		rem Release asteroids at the proper interval
		if t# - asteroidTime# > asteroidFreq# and Active = 1
			for x = 1 to AsteroidCount
				if Asteroids[x].act = 0
					SetSpritePositionByOffset(Asteroids[x].spr, Random(20, sw-20), -50)
					SetSpritePhysicsOn(Asteroids[x].spr, 2)
					SetSpritePhysicsVelocity(Asteroids[x].spr, 0.0, 0.0)
					SetSpritePhysicsAngularVelocity(Asteroids[x].spr, 0.0)
					if GetSpriteWidth(Asteroids[x].spr) < 48
						Asteroids[x].hits = 1
					else
						Asteroids[x].hits = 0
					endif
					Asteroids[x].act = 1
					exit
				endif
			next x
			asteroidTime# = t#
		endif

		rem Check for Photons hitting Asteroids
		for fx = 1 to LaserCount
			if Laser[fx].act = 1
				if GetSpriteY(Laser[fx].spr) > 16
					for ax = 1 to AsteroidCount
						if Asteroids[ax].act = 1
							if GetPhysicsCollision(Laser[fx].spr, Asteroids[ax].spr) = 1
								Asteroids[ax].hits = Asteroids[ax].hits + 1
								if Asteroids[ax].hits < 2
									ExpFreq = 50
									ExpLife = 0.75
									ExpMax = 20
								else
									ExpFreq = 80
									ExpLife = 1.0
									ExpMax = 20
								endif
								ExplodeX = GetPhysicsCollisionWorldX()
								ExplodeY = GetPhysicsCollisionWorldY()
								if optSound = 1
									PlaySound(SndExplode, optSoundVol, 0, 0)
								endif
								fire = 1
								gosub Explosions
								rem Decide if a Powerup will be dropped by a large asteroid being destroyed
								if GetSpriteWidth(Asteroids[ax].spr) => 48 and Asteroids[ax].hits = 2
									a = Random(0, 50)
									if (a = 0 or a = 5 or a = 10 or a = 15 or a = 20 or a = 25 or a = 30 or a = 35 or a = 40 or a = 45 or a = 50) and Level > 1
										if Level = 2 then PU = 1
										if Level = 3 then PU = 2
										if Level > 3 then PU = 3
										PU = Random(1, PU)
										spx = GetSpriteXbyOffset(Asteroids[ax].spr)
										spy = GetSpriteYbyOffset(Asteroids[ax].spr)
										if PU = 1 and PUShieldActive = 0 and PUTriShotActive = 0 and PUBombActive = 0 and ShieldActive = 0
											SetSpritePositionByOffset(PUShield, spx, spy)
											PUShieldActive = 1
										endif
										if PU = 2 and PUTriShotActive = 0 and PUShieldActive = 0 and PUBombActive = 0 and TriShotActive = 0
											SetSpritePositionByOffset(PUTriShot, spx, spy)
											PUTriShotActive = 1
										endif
										if PU = 3 and PUBombActive = 0 and PUTriShotActive = 0 and PUShieldActive = 0 and BombActive = 0
											SetSpritePositionByOffset(PUBomb, spx, spy)
											PUBombActive = 1
										endif
									endif
								endif
								rem Give points for destroying an Asteroid
								if Asteroids[ax].hits = 2
									SetSpritePhysicsOff(Asteroids[ax].spr)
									Asteroids[ax].act = 0
									SetSpritePositionByOffset(Asteroids[ax].spr, Random(20, 300), -(Random(60, 300)))
									Score = Score + 10
								endif
								SetSpritePhysicsOff(Laser[fx].spr)
								Laser[fx].act = 0
								SetSpritePositionByOffset(Laser[fx].spr, -50, -50)
							endif
						endif
					next ax
				else
					rem Reset the Photon for reuse
					SetSpritePhysicsDelete(Laser[fx].spr)
					SetSpritePhysicsOn(Laser[fx].spr, 3)
					SetSpritePhysicsVelocity(Laser[fx].spr, 0.0, -25.0)
				endif
			endif
		next fx

		rem Ship Movement
		sx = GetSpriteXByOffset(Ship)
		sy = GetSpriteYByOffset(Ship)
		SetSpriteAngle(Ship, 0.0)
		SetSpritePhysicsAngularVelocity(Ship, 0.0)

		JX = GetVirtualJoystickX(Stick1)
		JY = GetVirtualJoystickY(Stick2)

		rem Move Left
		if (GetKeystate(37) = 1 or JX < 0) and Active = 1
			if sx > 30
				if Ship <> ShipL
					SetSpritePhysicsOff(Ship)
					SetSpritePositionByOffSet(Ship, -200, -200)
					Ship = ShipL
					SetSpritePhysicsOn(Ship, 2)
					SetSpritePositionByOffSet(Ship, sx, sy)
				endif
				ShipVX = -10
				SetSpritePhysicsVelocity(Ship, ShipVX, 0.0)
			else
				if Ship <> ShipF
					SetSpritePhysicsOff(Ship)
					SetSpritePositionByOffset(Ship, -200, -200)
					Ship = ShipF
					SetSpritePhysicsOn(Ship, 2)
					SetSpritePositionByOffset(Ship, sx, sy)
				endif
				ShipVX = 0
				SetSpritePhysicsVelocity(Ship, ShipVX, 0.0)
			endif
		endif

		rem Move Right
		if (GetKeystate(39) = 1 or JX > 0) and Active = 1
			if sx < 290
				if Ship <> ShipR
					SetSpritePhysicsOff(Ship)
					SetSpritePositionByOffSet(Ship, -200, -200)
					Ship = ShipR
					SetSpritePhysicsOn(Ship, 2)
					SetSpritePositionByOffset(Ship, sx, sy)
				endif
				ShipVX = 10
				SetSpritePhysicsVelocity(Ship, ShipVX, 0.0)
			else
				if Ship <> ShipF
					SetSpritePhysicsOff(Ship)
					SetSpritePositionByOffset(Ship, -200, -200)
					Ship = ShipF
					SetSpritePhysicsOn(Ship, 2)
					SetSpritePositionByOffset(Ship, sx, sy)
				endif
				ShipVX = 0
				SetSpritePhysicsVelocity(Ship, ShipVX, 0.0)
			endif
		endif

		rem Reset after turning
		if GetKeystate(37) = 0 and GetKeystate(39) = 0 and JX = 0
			if Ship <> ShipF
				SetSpritePhysicsOff(Ship)
				SetSpritePositionByOffset(Ship, -200, -200)
				Ship = ShipF
				SetSpritePhysicsOn(Ship, 2)
				SetSpritePositionByOffset(Ship, sx, sy)
			endif
			ShipVX = 0
			SetSpritePhysicsVelocity(Ship, ShipVX, 0.0)
		endif

		rem Fire Photons
		if t# - firetime# > 0.325 then firetime# = 0.0

		if (GetKeyState(32) = 1 or JY > 0) and firetime# = 0.0 and Active = 1
			nl = 1
			if TriShotActive = 1 then nl = 3
			al = 0
			for fx = 1 to LaserCount
				if Laser[fx].act = 0
					al = al + 1
					if al = 1 then SetSpritePositionByOffset(Laser[fx].spr, sx, sy-72)
					if al = 2 then SetSpritePositionByOffset(Laser[fx].spr, sx+32, sy-72)
					if al = 3 then SetSpritePositionByOffset(Laser[fx].spr, sx-32, sy-72)
					SetSpritePhysicsDelete(Laser[fx].spr)
					SetSpritePhysicsOn(Laser[fx].spr, 2)
					if nl = 1
						SetSpritePhysicsVelocity(Laser[fx].spr, ShipVX/2, -25.0)
					else
						if al = 1 then SetSpritePhysicsVelocity(Laser[fx].spr, 0.0, -25.0)
						if al = 2 then SetSpritePhysicsVelocity(Laser[fx].spr, 5.0, -25.0)
						if al = 3 then SetSpritePhysicsVelocity(Laser[fx].spr, -5.0, -25.0)
					endif
					Laser[fx].act = 1
					if nl = 3
						SetSpriteColor(Laser[fx].spr, 64, 255, 64, 255)
					else
						SetSpriteColor(Laser[fx].spr, 64, 64, 255, 255)
					endif
					if al = nl
						al = 0
						if optSound = 1
							PlaySound(SndLaser, optSoundVol, 0, 0)
						endif
						exit
					endif
				endif
			next fx
			firetime# = t#
		endif

		rem Release the bomb if you've captured the Powerup
		if (GetKeystate(38) = 1 or JY < 0) and BombActive = 1 and BombTime = 0
			SetSpritePositionByOffset(Bomb, GetSpriteXByOffset(Ship), GetSpriteYByOffset(Ship)-16)
			BombTime = t#
		endif

		rem Escape to exit if you have a keyboard
		if GetKeystate(27) = 1
			while GetKeyState(27) = 1
			endwhile
			exit
		endif

		rem Exit the Game Loop if you are out of lives and you die
		if Lives = 0 and Dead = 1
			Active = 0
			exit
		endif

		Sync ( )

	loop

	rem Remove the virtual joysticks before leaving the Game Loop
	DeleteVirtualJoystick(Stick1)
	DeleteVirtualJoystick(Stick2)

	rem Clean up the Photons
	for x = 1 to LaserCount
		Laser[x].act = 0
		SetSpritePhysicsOff(Laser[x].spr)
		SetSpritePosition(Laser[x].spr, sw/2, sh+50)
	next x

	rem Clean up the Asteroids
	for x = 1 to AsteroidCount
		Asteroids[x].act = 0
		SetSpritePhysicsOff(Asteroids[x].spr)
		SetSpritePosition(Asteroids[x].spr, sw/2, -100)
	next x

	rem Move Text Objects off screen
	SetTextPosition(tLevel, 0, -50)
	SetTextPosition(tRoundTime, 0, -50)
	SetTextPosition(tCountdown, 0, -50)

	rem Move the ship off screen
	SetSpritePhysicsOff(Ship)
	SetSpritePositionByOffset(Ship, -100, -100)

	rem Check if the player got a High Score
	for x = 1 to 10
		if Score > HiScores[x].sc then exit
	next x
	if x < 11
		gosub EnterInitials
		gosub SendHiScore
	endif

	rem Move the Powerup icons off screen
	SetSpritePosition(iBomb, -100, -100)
	SetSpritePosition(iTriShot, -100, -100)

	rem Game Over screen
	if Lives = 0 and Dead = 1
		SetSpritePositionByOffset(PUShield, sw/2, -100)
		SetSpritePositionByOffset(PUTriShot, sw/2, -100)
		SetSpritePositionByOffset(PUBomb, sw/2, -100)
		PUShieldActive = 0
		PUTriShotActive = 0
		PUBombActive = 0
		SetSpritePosition(ABLogo, 32, 0)
		SetTextPosition(tGameOver, sw/2-(GetTextTotalWidth(tGameOver)/2.0), 230)
		t# = timer()
		do
			if timer() - t# > 4.0 then exit
			sync()
		loop
		SetSpritePosition(ABLogo, -300, -300)
		SetTextPosition(tGameOver, 0, -50)
	endif

	if x < 11 then goto HiScoreScreen

	Branch = 0

return


rem Intermission Screen
Intermission:
	SetTextPosition(tRoundTime, 0, -50)
	SetSpritePosition(iBomb, -100, -100)
	SetSpritePosition(iTriShot, -100, -100)
	SetTextString(tScore, "Score : "+str(Score))
	SetTextString(tLevel, "Level : "+str(Level))
	SetTextPosition(tLevel, sw/2-(GetTextTotalWidth(tLevel)/2.0), sh/2-30)
	for x = 1 to AsteroidCount
		Asteroids[x].act = 0
		SetSpritePositionByOffset(Asteroids[x].spr, Random(20, sw-20), -50)
		SetSpritePhysicsOff(Asteroids[x].spr)
	next x
	for x = 1 to LaserCount
		Laser[x].act = 0
		SetSpritePositionByOffset(Laser[x].spr, -100, sh+50)
	next x

	SetSpritePosition(PUShield, sw/2, -100)
	SetSpritePosition(Shield, -300, -300)
	PUShieldActive = 0
	SetSpritePosition(PUTriShot, sw/2, -100)
	PUTriShotActive = 0
	SetSpritePosition(PUBomb, sw/2, -100)
	SetSpritePosition(Bomb, -150, -150)
	PUBombActive = 0
	SetSpritePosition(Nebulas[Nebula].spr, -800, -600)
	Nebula = Random(1, 4)
	SetSpritePosition(Nebulas[Nebula].spr, 0, 0)
	dead = 0
	CountdownTime = timer()
	SetTextPosition(tCountdown, sw/2-10, sh/2-10)

	do
		t# = timer()
		CT = 5 - (t# - CountdownTime)
		if CT = 0
			SetTextPosition(tLevel, 0, -50)
			SetTextString(tCountDown, "GO!")
			SetTextPosition(tCountdown, sw/2-32, sh/2-10)
		else
			SetTextString(tCountdown, str(CT))
		endif
		if t# - CountdownTime > 5
			RoundTime = t#
			CountdownTime = 0
			asteroidTime# = t#
			SetTextPosition(tRoundTime, sw/2-10, 0)
			SetTextPosition(tCountdown, 0, -50)
			Active = 1
			ShieldActive = 0
			ShieldHits = 0
			ShieldTime = 0
			PUShieldDrop = t# + Random(10, 30)
			TriShotActive = 0
			TriShotTime = 0
			PUTriShotDrop = t# + Random(10, 30)
			BombActive = 0
			BombTime = 0
			PUBombDrop = t# + Random(10, 30)
			asteroidFreq# = 0.75 - (Level * 0.01)
			Ship = ShipF
			SetSpritePositionByOffset(Ship, sw/2, sh-70)
			SetSpritePhysicsOn(Ship, 2)
			SetTextPosition(tScore, 0, 0)
			SetTextPosition(tLives, sw-GetTextTotalWidth(tLives), 0)
			AddVirtualJoystick(Stick1, 30, sh-30, 30)
			AddVirtualJoystick(Stick2, sw-30, sh-30, 30)
			exit
		endif

		sync()

	loop

return


rem Explosions
Explosions:
	if fire = 1
		SetParticlesPosition(Explode, ExplodeX, ExplodeY)
		ResetParticleCount(Explode)
		SetParticlesFrequency(Explode, ExpFreq)
		SetParticlesLife(Explode, ExpLife)
		SetParticlesSize(Explode, 32)
		SetParticlesStartZone(Explode, -10, 0, 10, 0)
		SetParticlesImage(Explode, Shrapnel)
		SetParticlesDirection(Explode, 10, 10)
		SetParticlesAngle(Explode, 360)
		SetParticlesVelocityRange(Explode, 5.0, 20.0)
		SetParticlesMax(Explode, ExpMax)
		AddParticlesColorKeyFrame(Explode, 0.0, 0, 0, 0, 0)
		AddParticlesColorKeyFrame(Explode, (ExpLife * 0.25), 255, 255, 0, 255)
		AddParticlesColorKeyFrame(Explode, (ExpLife * 0.75), 255, 64, 64, 0)
		fire = 0
	endif
return


rem Enter Initials
EnterInitials:
	t1 = CreateText("YOU HAVE A HIGH SCORE!!")
	SetTextSize(t1, 18)
	SetTextPosition(t1, sw/2-(GetTextTotalWidth(t1)/2), 30)
	t2 = CreateText("Enter Your Initials")
	SetTextSize(t2, 18)
	SetTextPosition(t2, sw/2-(GetTextTotalWidth(t2)/2), 50)

	StartTextInput()
	Text$ = ""
	do
		if GetTextInputCompleted() = 1
			if GetTextInputCancelled() = 0
				Text$ = GetTextInput()
				if len(Text$) < 4
					SetTextString(tInitials, left(Text$,len(Text$)))
					optInitials$ = Text$
				endif
			endif
			exit
		endif
		sync()
	loop

	DeleteText(t1)
	DeleteText(t2)
return


rem High Score Screen
HiScoreScreen:
	gosub GetHighScores
	SetSpritePosition(HiScoreSpr2, 32, 30)
	SetTextPosition(HiScoreHeader, sw/2-(GetTextTotalWidth(HiScoreHeader)/2), 100)
	for x = 1 to 10
		SetTextPosition(HiScores[x].txt, sw/2-(GetTextTotalWidth(HiScores[x].txt)/2), 100+(x * 24))
	next x
	SetSpritePosition(BackSpr, 92, 410)

	do
		tx = 0
		ty = 0
		if GetTouchCount(0) > 0
			ti = GetFirstTouchEvent(0)
			tx = GetTouchCurrentX(ti)
			ty = GetTouchCurrentY(ti)
		endif
		if tx > 0 and ty > 0
			SetSpritePosition(Cursor, tx-8, ty-8)
		else
			SetSpritePosition(Cursor, GetMouseX()-8, GetMouseY()-8)
		endif

		if GetSpriteCollision(BackSpr, Cursor) = 1
			if GetMouseLeftPressed() = 1 or (tx > 0 and ty > 0)
				SetSpritePosition(HiScoreSpr2, -300, -300)
				SetSpritePosition(BackSpr, -300, -300)
				SetTextPosition(HiScoreHeader, 0, -50)
				for x = 1 to 10
					SetTextPosition(HiScores[x].txt, 0, -50)
				next x
				exit
			endif
		endif

		sync()
	loop

return


rem Options Screen
OptionsScreen:
	OptionsImg = LoadImage("Options.png", 0)
	Options = CreateSprite(OptionsImg)
	SetSpriteScale(Options, 1.5, 1.5)
	MusicImg = LoadImage("Music.png", 0)
	Music = CreateSprite(MusicImg)
	SoundImg = LoadImage("Sound.png", 0)
	Sound = CreateSprite(SoundImg)

	SetSpritePosition(Options, 64, 8)
	SetSpritePosition(Music, 92, 110)
	SetSpritePosition(Sound, 92, 210)

	HoverImg = LoadImage("Btn_Hover.png", 0)
	Hover = CreateSprite(HoverImg)
	SetSpriteDepth(Hover, 5)
	MusicSelect = CreateSprite(HoverImg)
	SetSpriteScale(MusicSelect, 2, 1)
	SetSpriteDepth(MusicSelect, 5)
	SetSpriteColor(MusicSelect, 64, 64, 64, 128)
	SoundSelect = CreateSprite(HoverImg)
	SetSpriteScale(SoundSelect, 2, 1)
	SetSpriteDepth(SoundSelect, 5)
	SetSpriteColor(SoundSelect, 64, 64, 64, 128)

	OnImg = LoadImage("Btn_ON.png", 0)
	On1 = CreateSprite(OnImg)
	SetSpriteDepth(On1, 4)
	SetSpriteShape(On1, 3)
	On2 = CreateSprite(OnImg)
	SetSpriteDepth(On2, 4)
	SetSpriteShape(On2, 3)
	OffImg = LoadImage("Btn_OFF.png", 0)
	Off1 = CreateSprite(OffImg)
	SetSpriteDepth(Off1, 4)
	SetSpriteShape(Off1, 3)
	Off2 = CreateSprite(OffImg)
	SetSpriteDepth(Off2, 4)
	SetSpriteShape(Off2, 3)

	SetSpritePosition(On1, sw/2-100, 164)
	SetSpritePosition(Off1, sw/2+48, 164)
	SetSpritePosition(On2, sw/2-100, 264)
	SetSpritePosition(Off2, sw/2+48, 264)

	SetSpritePosition(BackSpr, 92, 410)

	Entry = 1

	do
		if optMusic = 1
			SetSpritePosition(MusicSelect, GetSpriteX(On1), GetSpriteY(On1))
		else
			SetSpritePosition(MusicSelect, GetSpriteX(Off1), GetSpriteY(Off1))
		endif
		if optSound = 1
			SetSpritePosition(SoundSelect, GetSpriteX(On2), GetSpriteY(On2))
		else
			SetSpritePosition(SoundSelect, GetSpriteX(Off2), GetSpriteY(Off2))
		endif
		tx = 0
		ty = 0
		if GetTouchCount(0) > 0
			ti = GetFirstTouchEvent(0)
			tx = GetTouchCurrentX(ti)
			ty = GetTouchCurrentY(ti)
		endif
		if tx > 0 and ty > 0
			SetSpritePosition(Cursor, tx-8, ty-8)
		else
			SetSpritePosition(Cursor, GetMouseX()-8, GetMouseY()-8)
		endif
		SetSpritePosition(Hover, -40, -40)
		SetSpriteScale(Hover, 1, 1)

		if GetSpriteCollision(On1, Cursor) = 1
			SetSpriteScale(Hover, 2, 1)
			SetSpritePosition(Hover, GetSpriteX(On1), GetSpriteY(On1))
			if GetMouseLeftPressed() = 1 or (tx > 0 and ty > 0)
				optMusic = 1
			endif
		endif

		if GetSpriteCollision(On2, Cursor) = 1
			SetSpriteScale(Hover, 2, 1)
			SetSpritePosition(Hover, GetSpriteX(On2), GetSpriteY(On2))
			if GetMouseLeftPressed() = 1 or (tx > 0 and ty > 0)
				optSound = 1
			endif
		endif

		if GetSpriteCollision(Off1, Cursor) = 1
			SetSpriteScale(Hover, 2, 1)
			SetSpritePosition(Hover, GetSpriteX(Off1), GetSpriteY(Off1))
			if GetMouseLeftPressed() = 1 or (tx > 0 and ty > 0)
				optMusic = 0
			endif
		endif

		if GetSpriteCollision(Off2, Cursor) = 1
			SetSpriteScale(Hover, 2, 1)
			SetSpritePosition(Hover, GetSpriteX(Off2), GetSpriteY(Off2))
			if GetMouseLeftPressed() = 1 or (tx > 0 and ty > 0)
				optSound = 0
			endif
		endif

		if GetSpriteCollision(BackSpr, Cursor) = 1
			if GetMouseLeftPressed() = 1 or (tx > 0 and ty > 0)
				DeleteSprite(On1)
				DeleteSprite(On2)
				DeleteImage(OnImg)
				DeleteSprite(Off1)
				DeleteSprite(Off2)
				DeleteImage(OffImg)
				DeleteSprite(MusicSelect)
				DeleteSprite(SoundSelect)
				DeleteSprite(Hover)
				DeleteImage(HoverImg)
				DeleteSprite(Options)
				DeleteImage(OptionsImg)
				DeleteSprite(Music)
				DeleteImage(MusicImg)
				DeleteSprite(Sound)
				DeleteImage(SoundImg)
				SetSpritePosition(BackSpr, -300, -300)
				f = OpenToWrite("Options.txt", 0)
				WriteInteger(f, optSound)
				WriteInteger(f, optSoundVol)
				WriteInteger(f, optMusic)
				WriteInteger(f, optMusicVol)
				CloseFile(f)
				exit
			endif
		endif

		sync()
	loop
return


rem Get High Scores from the Server
GetHighScores:
	if fade = 1
		SetSpritePosition(1, 0, 0)
		SetSpriteColor(1, 0, 0, 0, 0)
		a = 0
		t# = timer()
		do
			a = a + 3
			if a => 255 then a = 255
			SetSpriteColor(1, 0, 0, 0, a)
			if timer() - t# > 1.5 then exit
			sync()
		loop
	endif
	SetTextPosition(tGetHiScore, sw/2-(GetTextTotalWidth(tGetHiScore)/2), sh/2-10)

	c$ = "Client"+str(Random())
	iNetID = JoinNetwork("50.43.112.52", 4100, c$)
	t# = timer()
	do
		if iNetID > 0
			c = GetNetworkNumClients(iNetID)
			if c > 1 then exit
		endif
		if timer() - t# > 4.0 then exit
		sync()
	loop

	if isNetworkActive(iNetID) = 0
		SetTextPosition(tGetHiScore, 0, -50)
		SetTextPosition(tNetworkError1, sw/2-(GetTextTotalWidth(tNetworkError1)/2), sh/2-20)
		SetTextPosition(tNetworkError2, sw/2-(GetTextTotalWidth(tNetworkError2)/2), sh/2)
		t# = timer()
		do
			if timer() - t# > 4.0 then exit
			sync()
		loop
	else
		sid = GetNetworkServerID(iNetID)
		t# = timer()
		do
			msg = GetNetworkMessage(iNetID)
			if msg > 0
				id = GetNetworkMessageFromClient(msg)
				if id = sid
					f = OpenToWrite("Scores.txt")
					for x = 1 to 10
						n$ = GetNetworkMessageString(msg)
						WriteString(f, n$)
						HiScores[x].sc = GetNetworkMessageInteger(msg)
						WriteInteger(f, HiScores[x].sc)
						tTemp = CreateText(str(HiScores[x].sc))
						fx = GetTextLength(tTemp)
						DeleteText(tTemp)
						fx = fx - (3 - len(n$))
						n$ = n$ + " "
						for y = 1 to 13 - fx
							n$ = n$ + "."
						next y
						n$ = n$ + " " + str(HiScores[x].sc)
						SetTextString(HiScores[x].txt, n$)
					next x
					CloseFile(f)
					DeleteNetworkMessage(msg)
					exit
				endif
			endif

			if timer() - t# > 5.0 then exit

			sync()
		loop
	endif

	if isNetworkActive(iNetID) = 1 then CloseNetwork(iNetID)
	SetTextPosition(tGetHiScore, 0, -50)
	SetTextPosition(tNetworkError1, 0, -50)
	SetTextPosition(tNetworkError2, 0, -50)
	if fade = 1
		t# = timer()
		a = 255
		do
			a = a - 3
			if a < 0 then a = 0
			SetSpriteColor(1, 0, 0, 0, a)
			if timer() - t# > 1.5 then exit
			sync()
		loop
	endif
	SetSpritePosition(1, -sw, 0)
return


SendHiScore:
	iNetID = JoinNetwork("50.43.112.52", 4100, "Client"+str(Random()))
	t# = timer()
	do
		if isNetworkActive(iNetID) = 1
			if Score > 0
				sid = GetNetworkServerID(iNetID)
				msg = CreateNetworkMessage()
				AddNetworkMessageString(msg, optInitials$)
				AddNetworkMessageInteger(msg, Score)
				SendNetworkMessage(iNetID, sid, msg)
				DeleteNetworkMessage(msg)
				Score = 0
			endif
			if timer() - t# > 2.0
				exit
			endif
		endif
		if timer() - t# > 4.0 then exit
		sync()
	loop

	if isNetworkActive(iNetID) = 1
		CloseNetwork(iNetID)
	endif
return


rem Instructions Screen
Instructions:
	SetSpritePosition(BackSpr, 92, 410)
	t[1] = CreateText("Instructions")
	t[2] = CreateText("Left/Right Arrows or Left Joystick")
	t[3] = CreateText("moves the ship")

	t[4] = CreateText("SPACE or Right Joystick DOWN Fires")

	t[5] = CreateText("Up Arrow or Right Joystick UP")
	t[6] = Createtext("launches bomb when available")

	t[7] = Createtext("Larger Asteroids must be")
	t[8] = Createtext("shot twice and may drop")
	t[9] = Createtext("Powerups")

	t[10] = Createtext("Shields last for 20 seconds")
	t[11] = Createtext("but can only take 3 hits")

	t[12] = CreateText("You must have a positive")
	t[13] = CreateText("score at the end of a level")
	t[14] = CreateText("to advance to the next level.")

	SetTextSize(t[1], 18)
	for x = 2 to 14
		SetTextSize(t[x], 14)
	next x

	SetTextPosition(t[1], sw/2-(GetTextTotalWidth(t[1])/2), 20)
	SetTextPosition(t[2], 10, 60)
	SetTextPosition(t[3], 10, 80)

	SetTextPosition(t[4], 10, 110)

	SetTextPosition(t[5], 10, 140)
	SetTextPosition(t[6], 10, 160)

	SetTextPosition(t[7], 10, 190)
	SetTextPosition(t[8], 10, 210)
	SetTextPosition(t[9], 10, 230)

	SetTextPosition(t[10], 10, 260)
	SetTextPosition(t[11], 10, 280)

	SetTextPosition(t[12], 10, 310)
	SetTextPosition(t[13], 10, 330)
	SetTextPosition(t[14], 10, 350)

	do
		tx = 0
		ty = 0
		if GetTouchCount(0) > 0
			ti = GetFirstTouchEvent(0)
			tx = GetTouchCurrentX(ti)
			ty = GetTouchCurrentY(ti)
		endif
		if tx > 0 and ty > 0
			SetSpritePosition(Cursor, tx-8, ty-8)
		else
			SetSpritePosition(Cursor, GetMouseX()-8, GetMouseY()-8)
		endif

		if GetSpriteCollision(BackSpr, Cursor) = 1
			if GetMouseLeftPressed() = 1 or (tx > 0 and ty > 0)
				SetSpritePosition(BackSpr, -300, -300)
				exit
			endif
		endif

		sync()

	loop

	for x = 1 to 14
		DeleteText(t[x])
	next x
return



The Server:
+ Code Snippet
rem
rem Asteroid Blast Server
rem Written by : Kevin Summers
rem

iNetID = HostNetwork("AsteroidBlast", "Server", 4100)

type hiscore_data
	n$ as string
	sc as integer
endtype
dim HiScores[11] as hiscore_data

if GetFileExists("Scores.txt") = 1
	f = OpenToRead("Scores.txt")
	for x = 1 to 10
		if FileEOF(f) then exit
		n$ = ReadString(f)
		HiScores[x].n$ = n$
		HiScores[x].sc = ReadInteger(f)
	next x
	CloseFile(f)
else
	f = OpenToWrite("Scores.txt", 0)
	for x = 1 to 10
		n$ = "AAA"
		WriteString(f, n$)
		HiScores[x].n$ = n$
		HiScores[x].sc = 0
		WriteInteger(f, HiScores[x].sc)
	next x
	CloseFile(f)
endif


rem Main Loop
do
	t# = timer()
	for x = 1 to 10
		if x = 1
			id = GetNetworkFirstClient(iNetID)
		else
			id = GetNetworkNextClient(iNetID)
		endif
		if id = 0 then exit
		if GetNetworkClientDisconnected(iNetID, id) = 1
			DeleteNetworkClient(iNetID, id)
		endif
	next x

	msg = GetNetworkMessage(iNetID)
	if msg > 0
		id = GetNetworkMessageFromClient(msg)
		if id > 1
			n$ = GetNetworkMessageString(msg)
			sc = GetNetworkMessageInteger(msg)
			DeleteNetworkMessage(msg)
			for fx = 1 to 10
				if sc > HiScores[fx].sc then exit
			next fx
			if fx < 11
				for x = 10 to fx+1 step -1
					HiScores[x].n$ = HiScores[x-1].n$
					HiScores[x].sc = HiScores[x-1].sc
				next x
				HiScores[fx].n$ = n$
				HiScores[fx].sc = sc
			endif
		endif
		DeleteNetworkMessage(mid)
	endif

	if t# - PacketTime > 1.0
		if GetNetworkNumClients(iNetID) > 1
			msgid = CreateNetworkMessage()
			for x = 1 to 10
				AddNetworkMessageString(msgid, HiScores[x].n$)
				AddNetworkMessageInteger(msgid, HiScores[x].sc)
			next x
			SendNetworkMessage(iNetID, 0, msgid)
		endif
		PacketTime = t#
	endif

	if t# - FileSaveTime > 300.0
		f = OpenToWrite("Scores.txt", 0)
		for x = 1 to 10
			WriteString(f, HiScores[x].n$)
			WriteInteger(f, HiScores[x].sc)
		next x
		CloseFile(f)
		FileSaveTime = t#
	endif

	Print("Active  : "+str(IsNetworkActive(iNetID)))
	Print("Clients : "+str(GetNetworkNumClients(iNetID)))
	Print(" ")
	for x = 1 to 10
		Print(HiScores[x].n$+"    "+str(HiScores[x].sc))
	next x

	if GetKeyState(27) = 1
		CloseNetwork(iNetID)
		exit
	endif

	Sync()
loop

end
Posted: 3rd Jul 2011 21:06
KISTech:
Thanks for the source.
Where is the server that you are saving high scores to?
I haven't played around with networking so any info would be greatly appreciated.
Will you use this same method when you submit it to an app store?
Posted: 3rd Jul 2011 21:41
I have a dedicated server here just for hosting game server programs. Worlds Apart Online, Fields of War, and the Asteroid Blast server are all currently running on it.

The networking in Asteroid Blast is very basic.

The client connects to the server at the start, and the server responds with the full list of the 10 high scores. Which gives the client a current list to compare the player's score to.

In the event the player gets a score that qualifies the client connects and sends the player's initials and score to the server.

Much more complicated scenarios are possible. This is just a quick, connect, send some data, and disconnect.

With the latency of cell phone networks though, I don't think a true multiplayer game would work over the internet, but it would work fine over a local Wifi connection.
Posted: 10th Aug 2011 22:55
Nice work KISTech!! Very kind to share the code too
Posted: 10th Aug 2011 23:19
Thanks! The code is slightly out of date, as some of the commands have changed syntax slightly since I posted that, and I've updated the input methods to be more cross-platform.

This will likely be released to all available app stores for free with ads in the main menu, but not on the game play screen. We'll have to see how that all plays out when the AppGameKit is released.
Posted: 10th Aug 2011 23:47
Thanks for sharing the code, it's always handy to see code in action.
Posted: 11th Aug 2011 14:38
I've just looked at the code for this game and unfortunately its clear I will never be able to make an iphone game after all.

Thanks for sharing. At least I didn't burn $75 on AppGameKit to find this out.

I though the scripting language was supposed to be much easier than C++ but it looks ridiculously hard to me.
Posted: 11th Aug 2011 16:48
Nomad - It's actually not that hard. The amount of code he has in this project is probably the turn off but it doesn't take that long to write that much. I can probably agree that it could use some clean up by using include files and such but with the amount of time involved with testing, I can attest that sometimes you have to get the job done one way or another.
$75 is a pretty fantastic price for something like this but you have to start off slow when coding games. This is not KISTech's first game. My games have been a little slower coming but I have one working right now that took me a few months to write due to job/school etc... and that was with another tool. I'm planning on moving my game over to this, so that may be another Month of coding but I think the results will be much better.
If you really want to code games, I would seriously recommend starting with a small game such as Pong and working your way up from there.
That's what I had to do.
Posted: 11th Aug 2011 17:06
Really? You think that's hard? It's no harder than DBP, and way easier than the C++ version you can use??
Posted: 11th Aug 2011 19:03
Its not that hard, it can just appear a bit overwhelming.