12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496 |
- ' *******************************************************************
- ' Digesteroids - V1.0
- ' --------------------------------------------------------
- ' An evil biscuit corporation are using their army of
- ' sweet snack food to take over the world. Use your ship
- ' to take down the evil invading corporation before
- ' they infest the world with dunkables sweetmeal biscuits.
- ' REQUIRES 1024x768x32! @75Hz
- ' --------------------------------------------------------
- ' Author: Rob Hutchinson 2004
- ' Email: [email protected]
- ' Written entirely in Protean IDE:
- ' WWW: http://www.proteanide.co.uk/
- ' --------------------------------------------------------
- ' Yep, there's stuff in here, I didnt get time to implement
- ' Pickups, Weapons and Vortexes.
- ' *******************************************************************
-
- Strict
- ' Import various utilities.
- Import "simplephysics.bmx"
- Import "dynamicgame.bmx"
- Import "MathUtil.bmx"
- ' Screen settings.
- Const WIDTH = 1024 ' Width of the screen.
- Const HEIGHT = 768 ' Height of the screen.
- Const DEPTH = 32 ' Depth of the screen.
- Const REFRESHRATE = 75 ' How often to update the screen (Per second).
- ' Game Settings
- Const DYNAMICTIMING = True ' If true then the game will try to keep up with
- Const DESIREDFPS = 75 ' The Desired FPS of the game, can be independant of Refresh Rate.
- Function ScreenPan(OffsetX:Float, OffsetY:Float)
- Local Width,Height,Depth,Hz
- Width=GraphicsWidth()
- Height=GraphicsHeight()
- Depth=GraphicsDepth()
- Hz=GraphicsHertz()
- glMatrixMode GL_PROJECTION
- glLoadIdentity
- glOrtho 0,Width,Height,0,-1,1
- glTranslatef OffsetX, OffsetY,0
- glMatrixMode GL_MODELVIEW
- EndFunction
- Function QFlushKeys()
- ' Quick implementation of flushkeys as BMX doesnt have one at time of writing, sure it
- ' will be added though.
- For Local Key:Int = 0 To 255
- KeyHit(Key)
- KeyDown(Key)
- Next
- End Function
- '#Region Scene: MainMenu
- ' The main menu scene.
- Type MainMenuScene Extends T2DDynamicGameScene
- '#Region DrawTextCentered
- Function DrawTextCentered:Int(Text:String,Y:Int)
- Local Out:Int = (WIDTH / 2) - (TextWidth(Text) / 2)
- DrawText(Text, Out, Y)
- Return Out
- End Function
- '#End Region
- '#Region Declarations
- Const STARS_PER_SECOND = 6
- Field BackColor:Float
- Field Direction:Float = 0.01
- Field ExitGame:Int = False
- Field Music:TSound
- Field MusicChannel:TChannel
- Field Title:TImage
- Field LowerTitle:TImage
- Field Options:TImage
- Field Craft:TImage
- Field EnteredText:String = ""
- Field LastHighScore:Int
- Field ShowCredits:Int = False
- Field Viewing:Int = VIEW_MENU
- Field HoverOver:Int = VIEW_START
- Const VIEW_MENU = 0
- Const VIEW_START = 0
- Const VIEW_INSTRUCTIONS = 1
- Const VIEW_HIGHSCORES = 2
- Const VIEW_QUIT = 3
- Const VIEW_ENTERHIGH = 4
- Field Stars:TPhysicsProviderCollection = New TPhysicsProviderCollection
- Field World:TWorldPhysicsProvider = TWorldPhysicsProvider.Create(0.0, 0.0, 0.0, True)
- '#End Region
- '#Region Method: FinishScoreEntry
- Method FinishScoreEntry()
- Self.ViewMenu(VIEW_HIGHSCORES)
- Scores.Add(Self.LastHighScore, Self.EnteredText)
- ' Add this to the high scores..
- Self.LastHighScore = 0
- Self.EnteredText = ""
- End Method
- '#End Region
- '#Region Method: ViewMenu
- Method ViewMenu(Menu:Int)
- Self.Viewing = Menu
- Self.HoverOver = Menu
- QFlushKeys()
- End Method
- '#End Region
- '#Region Method: Update
- Method Update()
- Self.Stars.ApplyPhysics()
- ' Add new stars..
- For Local CountStars:Int = 0 To STARS_PER_SECOND
- Local Star:TMenuStar = TMenuStar.Create(World, Self, 10.0)
- Self.Stars.AddLast(Star)
- Next
- ' Do enter key checking..
- Select Self.Viewing
- Case VIEW_MENU
- If KeyHit(KEY_ENTER) Then
- Select Self.HoverOver
- Case VIEW_START
- Self.TerminateMainLoop = True
-
- Case VIEW_INSTRUCTIONS
- Self.ViewMenu(VIEW_INSTRUCTIONS)
-
- Case VIEW_HIGHSCORES
- Self.ViewMenu(VIEW_HIGHSCORES)
-
- Case VIEW_QUIT
- Self.TerminateMainLoop = True
- Self.ExitGame = True
-
- End Select
- EndIf
- If KeyHit(KEY_UP)
- Self.HoverOver :- 1
- If Self.HoverOver < VIEW_START Then Self.HoverOver = VIEW_START
- EndIf
- If KeyHit(KEY_DOWN)
- Self.HoverOver :+ 1
- If Self.HoverOver > VIEW_QUIT Then Self.HoverOver = VIEW_QUIT
- EndIf
- If KeyHit(KEY_ESCAPE) Then
- Self.TerminateMainLoop = True
- Self.ExitGame = True
- Else
- If KeyHit(KEY_C)
- Self.TerminateMainLoop = True
- Self.ShowCredits = True
- EndIf
- EndIf
- Case VIEW_INSTRUCTIONS, VIEW_HIGHSCORES
- If KeyHit(KEY_ENTER) Or KeyHit(KEY_ESCAPE)
- Self.Viewing = VIEW_MENU
- EndIf
- Case VIEW_ENTERHIGH
- ' Check for alpha keys.
- For Local Count:Int = KEY_A To KEY_Z
- If KeyHit(Count) Then Self.EnteredText = Self.EnteredText + Chr(Count)
- Next
- ' Check for number key hits
- For Local Count:Int = KEY_0 To KEY_9
- If KeyHit(Count) Then Self.EnteredText = Self.EnteredText + Chr(Count)
- Next
- ' Special case, check for space bar
- If KeyHit(KEY_SPACE)
- Self.EnteredText = Self.EnteredText + " "
- EndIf
- ' Remove a character when user hits backspace.
- If KeyHit(KEY_BACKSPACE)
- If Len(Self.EnteredText) > 0
- Self.EnteredText = Mid(Self.EnteredText,0,Len(Self.EnteredText))
- EndIf
- EndIf
- ' If 5 characters are entered, end high score entry.
- If Len(Self.EnteredText) = 5 Then Self.FinishScoreEntry()
-
- If KeyHit(KEY_ENTER)
- Self.FinishScoreEntry()
- EndIf
- End Select
- End Method
- '#End Region
- '#Region Method: Render
- Method Render()
- Cls
- ScreenPan(0,0)
- SetTransform
- SetAlpha 1.0
- SetBlend(SOLIDBLEND)
- Self.Stars.Draw()
- SetColor 255,255,255
- SetBlend(ALPHABLEND)
- DrawImage(Self.Title,0,40)
- DrawImage(Self.LowerTitle,0,660)
- Local StartPosX:Int = 150
- Local StartPosY:Int = 245
- Select Self.Viewing
- Case VIEW_MENU
- ' Showing main menu
- DrawImage(Self.Options,450,330)
- SetRotation -90
- Select Self.HoverOver
- Case VIEW_START
- DrawImage(Self.Craft,416,352)
-
- Case VIEW_INSTRUCTIONS
- DrawImage(Self.Craft,416,352 + 37)
-
- Case VIEW_HIGHSCORES
- DrawImage(Self.Craft,416,352 + 74)
-
- Case VIEW_QUIT
- DrawImage(Self.Craft,416,352 + 145)
-
- End Select
- Case VIEW_HIGHSCORES
- Scores.Render(385,310)
- Case VIEW_ENTERHIGH
- DrawTextCentered("CONGRATULATIONS!",StartPosY)
- DrawTextCentered("You have a new high score!",StartPosY+50)
- DrawTextCentered("Please enter your name (5 characters)",StartPosY+65)
- Local TextX:Int = DrawTextCentered(Self.EnteredText,StartPosY+250)
- DrawRect(TextX + TextWidth(Self.EnteredText), StartPosY+250, 12, 15)
- Case VIEW_INSTRUCTIONS
- DrawText("Welcome to Digesteroids!",StartPosX,StartPosY)
- DrawText("------------------------",StartPosX,StartPosY+20)
- DrawText("An evil biscuit corporation are using their army of sweet snack food to take over the world.",StartPosX,StartPosY+50)
- DrawText("Fortunately, the ingredients the evil corporation used are vulnerable to big sweaty laser",StartPosX,StartPosY+70)
- DrawText("blasts. Use your ship's cannon to take out the corporation before they infest the world with",StartPosX,StartPosY+90)
- DrawText("sweetmeal dunkables biscuits. But be careful, space is small (just big enough to fit inside",StartPosX,StartPosY+110)
- DrawText("your screen), it is also cyclical, so beware of incoming oval shaped objects.",StartPosX,StartPosY+130)
- DrawText("Keys:",StartPosX,StartPosY+180)
- DrawText(" - UP CURSOR ARROW = Thrust",StartPosX,StartPosY+200)
- DrawText(" - DOWN CURSOR ARROW = Teleport",StartPosX,StartPosY+220)
- DrawText(" - LEFT CURSOR ARROW = Rotate Ship Left",StartPosX,StartPosY+240)
- DrawText(" - RIGHT CURSOR ARROW = Rotate Ship Right",StartPosX,StartPosY+260)
- DrawText(" - ESCAPE = QUIT",StartPosX,StartPosY+280)
- DrawText("Yes, that's right, it's a glorified asteroids game!",StartPosX,StartPosY+320)
- SetColor 255,0,0
- DrawText("Note: Your score is based on the speed at which your ship is travelling when it fired.",StartPosX,StartPosY+340)
- End Select
- End Method
- '#End Region
- '#Region Method: Start
- Method Start()
- Self.MusicChannel = AllocChannel()
- If Self.Music = Null Then Self.Music = LoadSound("sounds\menu.ogg",True)
- PlaySound(Self.Music,Self.MusicChannel)
- SetChannelVolume MusicChannel,1.0
- ' Load GFX..
- If Self.Title = Null Then Self.Title = LoadImage("graphics\title.png")
- If Self.LowerTitle = Null Then Self.LowerTitle = LoadImage("graphics\lower.png")
- If Self.Options = Null Then Self.Options = LoadImage("graphics\options.png")
- If Self.Craft = Null Then Self.Craft = LoadImage("graphics\ship.png")
- ' Add a screen full of stars.
- For Local CountStars:Int = 0 To 1000
- Local Star:TMenuStar = TMenuStar.Create(World, Self, 10.0)
- Star.X = Rnd(WIDTH)
- Self.Stars.AddLast(Star)
- Next
- End Method
- '#End Region
- '#Region Method: Finish
- Method Finish()
- Self.Stars.Clear()
- Self.MusicChannel.Stop()
- Self.MusicChannel = Null
- End Method
- '#End Region
-
- End Type
- '#End Region
- '#Region Scene: MainGame
- ' Main Game scene
- Type MainGameScene Extends T2DDynamicGameScene
- '#Region Declarations
- Const STARS_PER_SECOND = 3
- Const FINISH_AT_LEVEL = 6
- Field Level:Int = 1
- Field Completed:Int = False
-
- Field DigestiveImage:TImage
- Field ShipImage:TImage
- Field StarsImage:TImage
- Field LargeImpactSound:TSound
- Field World:TWorldPhysicsProvider = TWorldPhysicsProvider.Create(0.0, 0.0, 0.0, True)
- Field Digestives:TPhysicsProviderCollection = New TPhysicsProviderCollection
- Field Bullets:TPhysicsProviderCollection = New TPhysicsProviderCollection
- Field Stars:TPhysicsProviderCollection = New TPhysicsProviderCollection
- Field Chunks:TFountain
- Const CHUNK_COUNT = 2
- Field ChunkImages:TImage[CHUNK_COUNT + 1]
- Field Player:TPlayer
- Field Shake:Float
- Field Pickups:TList = New TList
- '#End Region
- '#Region Method: Update
- Method Update()
- If KeyHit(KEY_ESCAPE) Then Self.TerminateMainLoop = True
- CheckEndOfLevel() ' Check if we need to move to the next level (IE, all digestives gone)
- ' Add new stars..
- For Local CountStars:Int = 0 To STARS_PER_SECOND
- Local Speed:Float = Self.Player.Speed()
- If Speed < 1.0 Then Speed = 1.0
- Local Star:TStar = TStar.Create(World, Self, Speed)
- Self.Stars.AddLast(Star)
- Next
- ' Update screenshake...
- Self.Shake :/ 1.02
- If Self.Shake < 0.0 Then Self.Shake = 0.0
- If Self.Shake > 6.0 Then Self.Shake = 6.0
- ' Update all the stars.
- Self.Stars.ApplyPhysics()
- ' Update the chunks
- Self.Chunks.UpdateWithFriction(TPhysicsProvider.AxisX | TPhysicsProvider.AxisY)
- ' Update all the digestives.
- Self.Digestives.ApplyPhysics()
- ' Update all the bullets.
- Self.Bullets.ApplyPhysics()
- ' Update the player.
- Self.Player.Update()
- Self.Player.ApplyFriction(TPhysicsProvider.AxisX | TPhysicsProvider.AxisY)
- Self.Player.ApplyPhysics()
- End Method
- '#End Region
- '#Region Method: Render
- Method Render()
- SetClsColor 0,0,0
- Cls
-
- If Self.Shake > 0.0 Then
- ScreenPan(Rnd(Shake),Rnd(Shake))
- EndIf
- ' Draw the spazzy psychodelic effect if it is enabled.
- Self.DrawPsychodelic()
-
- SetAlpha 1
- SetTransform
- ' Draw all the stars.
- Self.Stars.Draw()
- Self.Chunks.Draw()
- ' Draw the digestives.
- SetColor 255,255,255
- SetBlend(ALPHABLEND)
- Digestives.Draw()
- ' Draw the bullets
- SetBlend(LIGHTBLEND)
- Bullets.Draw()
-
- ' Draw the player.
- SetBlend(ALPHABLEND)
- Player.Draw()
- ' Draw the hud
- DrawHUD()
- End Method
- '#End Region
- '#Region Method: Start
- Method Start()
- AutoMidHandle True
- Self.Shake = 0
- Self.Chunks = TFountain.Create(Self.World,TRectangle.Create(0,0,WIDTH,HEIGHT))
- ' Load in the required Images...
- If Self.DigestiveImage = Null Then Self.DigestiveImage = LoadImage("graphics\digestive.png")
- If Self.ShipImage = Null Then Self.ShipImage = LoadImage("graphics\ship.png")
- If Self.StarsImage = Null Then Self.StarsImage = LoadImage("graphics\stars.png")
- For Local LoadCount:Int = 0 To CHUNK_COUNT
- Self.ChunkImages[LoadCount] = LoadImage("graphics\piece" + String(LoadCount + 1) + ".png")
- Next
- ' Set up the player
- Self.Player = TPlayer.Create(Self.World, Self.ShipImage,Self)
- Self.Player.LoadAssets()
- ' Load up the sounds.
- If Self.LargeImpactSound = Null Then Self.LargeImpactSound = LoadSound("Sounds\ImpactLarge.wav")
- ' Reset the game..
- Self.ResetGame()
- ' Create all the weapons..
- Self.Pickups.Clear()
- Local Bullet1Image:TImage = LoadImage("graphics\bullet1.png")
- Local Fire1Sound:TSound = LoadSound("sounds\fire.wav")
- ' Local Blaster:TWeapon = TWeapon.Create(Speed,Graphic,Size,Radius,Veer,FireRate,MainGame,Sound)
- Local Blaster:TWeapon = TWeapon.Create(10, Bullet1Image, 0.65, 4.0, 0,30, Self, Fire1Sound, Bullet1Image, "Blaster")
- Local FastBlaster:TWeapon = TWeapon.Create(9, Bullet1Image, 0.3, 4.0, 0.0, 15, Self, Fire1Sound, Bullet1Image, "Blaster Mk2")
- Local SprayBlaster:TWeapon = TWeapon.Create(8, Bullet1Image, 0.35, 4.0, 5.0, 1, Self, Fire1Sound, Bullet1Image, "Blaster Mk3")
- Local BlasterPickup:TPickup = TPickup.Create(TPickup.MODIFIER_WEAPON,0,0,True,Blaster,Bullet1Image,0.01,Bullet1Image)
- Local FastBlasterPickup:TPickup = TPickup.Create(TPickup.MODIFIER_WEAPON,0,0,True,FastBlaster,Bullet1Image,0.01,Bullet1Image)
- Local SprayBlasterPickup:TPickup = TPickup.Create(TPickup.MODIFIER_WEAPON,0,0,True,SprayBlaster,Bullet1Image,0.008,Bullet1Image)
- Local Score1000Pickup:TPickup = TPickup.Create(TPickup.MODIFIER_SCORE,1000,0,True,Null,Null,0.02,Bullet1Image)
- Local Score500Pickup:TPickup = TPickup.Create(TPickup.MODIFIER_SCORE,500,0,True,Null,Null,0.03,Bullet1Image)
- Local RotationPickup:TPickup = TPickup.Create(TPickup.MODIFIER_ROTATION,1.1,0,True,Null,Null,0.01,Bullet1Image)
- Local PsychodelicPickup:TPickup = TPickup.Create(TPickup.MODIFIER_PSYCHODELIC,0,1000,False,Null,Null,0.04,Bullet1Image)
- Local LivesPickup:TPickup = TPickup.Create(TPickup.MODIFIER_LIVES,1,0,True,Null,Null,0.001,Bullet1Image)
- Self.Player.Weapon = Blaster
- End Method
- '#End Region
- '#Region Method: Finish
- Method Finish()
- Self.Player.ThrusterChannel.Stop
- Self.Player.ThrusterChannel = Null
- End Method
- '#End Region
-
- '#Region Method: CheckEndOfLevel
- Method CheckEndOfLevel()
- If Digestives.IsEmpty() = True
- ' No more digestives..
- Level :+ 1
- If Level = FINISH_AT_LEVEL Then
- ' This was the last level.
- Self.Completed = True
- Self.TerminateMainLoop = True
- Else
- ' Move to the next level
- GotoLevel(Level)
- EndIf
- EndIf
- End Method
- '#End Region
- '#Region Method: DrawHUD
- Method DrawHUD()
- SetColor 255,255,255
- SetAlpha 1.0
- SetRotation 0
- DrawText "Level: " + Level,0,0
- Local Lives:String = "Lives: " + Player.Lives
- Local Score:String = "Score: " + Player.Score
- DrawText Score,(WIDTH / 2) - (TextWidth(Score) / 2) ,0
- DrawText Lives,(WIDTH - TextWidth(Lives)) ,0
-
- Local fr$="000"+Int(Self.Player.Speed()*1000) Mod 1000
- Local sp$=Int(Self.Player.Speed()*1000)/1000+"."+fr[fr.length-3..]
-
- DrawText "Speed: " + sp,0,15
- DrawText "Teleports: " + Self.Player.Teleports,0,30
- End Method
- '#End Region
- '#Region Method: ResetGame
- Method ResetGame()
- Digestives.Clear()
- Bullets.Clear()
- Stars.Clear()
- Chunks.Particles.Clear()
- Player.Lives = 5
- Player.Reset()
- GotoLevel(1)
- End Method
- '#End Region
- '#Region Method: GotoLevel
- Method GotoLevel(ToLevel:Int)
- Level = ToLevel
- For Local Count:Int = 1 To ToLevel
- Local Digestive:TDigestive = TDigestive.Create(World, DigestiveImage,Self)
- Digestive.X = Rnd(0,WIDTH)
- Digestive.Y = Rnd(0,HEIGHT)
- Digestive.Rotation = Rnd(360)
- Digestive.Weight = 5
- Digestive.SetVelocityFromAngle(Rnd(360.0),Rnd(0.5,1.5))
- Digestive.HitSound = Self.LargeImpactSound
- Digestives.AddLast(Digestive)
- Next
- End Method
- '#End Region
- '#Region Method: DrawPsychodelic
- Field PsychoAngle:Float = 0
- Field Psycho:Int = False
-
- Method DrawPsychodelic()
- If Psycho = True
- SetColor Rnd(0.0,255),Rnd(0.0,255),Rnd(0.0,255)
- PsychoAngle :+ 8
- SetBlend(SOLIDBLEND)
- TileImage(StarsImage,Sin(PsychoAngle) * 200,Cos(PsychoAngle) * 200)
- Else
- SetColor 255,255,255
- EndIf
- End Method
- '#End Region
- '#Region Method: FindSafeLocation
- Method FindSafeLocation:TPointD(Radius:Float)
- While True
- Local X:Int = Rnd(0,WIDTH)
- Local Y:Int = Rnd(0,HEIGHT)
- If Self.IsLocationSafe(X,Y,Radius)
- Local Out:TPointD = New TPointD
- Out.X = X
- Out.Y = Y
- Return Out
- EndIf
- Wend
- End Method
- '#End Region
- '#Region Method: IsLocationSafe
- Method IsLocationSafe:Int(X:Int,Y:Int,Radius:Float)
- Local TryCircle:TCircle = New TCircle
- TryCircle.X = X
- TryCircle.Y = Y
- TryCircle.Radius = Radius
- For Local Item:TDigestive = EachIn Self.Digestives
- If Item.Circle.CollidesWith(TryCircle)
- Return False
- EndIf
- Next
- Return True
- End Method
- '#End Region
- End Type
- '#End Region
- '#Region Scene: Ending
- ' The ending scene.
- Type EndingScene Extends T2DDynamicGameScene
-
- '#Region Declarations
- Const STARS_PER_SECOND = 0
- Const MAGNET_COUNT = 5
- Field ScrollPoint:Float
- Field Music:TSound
- Field MusicChannel:TChannel
- Field Title:TImage
- Field Time:Int = 1000000
- Field TEXTS_COUNT = 23
- Field Texts:String[TEXTS_COUNT]
- Field Stars:TPhysicsProviderCollection = New TPhysicsProviderCollection
- Field World:TWorldPhysicsProvider = TWorldPhysicsProvider.Create(0.2, 0.0, 0.0, True)
- '#End Region
- '#Region Method: Update
- Method Update()
- Self.Stars.ApplyPhysics()
- If KeyHit(KEY_ESCAPE) Then
- Self.TerminateMainLoop = True
- EndIf
- Self.Time :+ 1
- If Self.Time > 100 Then
- Self.Time = 0
- ' Add a new magnet
- Local ThisMagnet:TEndMagnet = New TEndMagnet
- ThisMagnet.X = Rnd(WIDTH)
- ThisMagnet.Y = Rnd(HEIGHT)
- ThisMagnet.Radius = Rnd(200,500)
- ThisMagnet.Polarity = TMagnet.PositivePolarity
- ThisMagnet.Strength = Rnd(0.1,0.5)
- Self.World.Magnets.AddLast(ThisMagnet)
- Self.World.ApplyMagnets = True
- EndIf
- Local X:Int = WIDTH/2
- Local Y:Int = HEIGHT/2
- For Local Magnet:TEndMagnet = EachIn Self.World.Magnets
- For Local Count:Int = 0 To STARS_PER_SECOND
- Local ThisStar:TEndingStar = TEndingStar.Create(Self.World, Self, Rnd(1.0,5.0), Magnet.X + (Sin(Rnd(360.0)) * 5.0), Magnet.Y + (Cos(Rnd(360.0)) * 5.0))
- ThisStar.SetVelocityFromAngle(Rnd(360),Rnd(1.0,5.0))
- Self.Stars.AddLast(ThisStar)
- Magnet.Stars :+ 1
- Next
- If Magnet.Stars > 500 Then
- Self.World.Magnets.Remove(Magnet)
- EndIf
- Next
- ' Update the scoller
- Self.ScrollPoint :- 0.5
- If Self.Scrollpoint < -((TEXTS_COUNT * 25) + 100)
- Self.ScrollPoint = HEIGHT + 20
- EndIf
-
- End Method
- '#End Region
- '#Region Method: Render
- Method Render()
- Cls
- Self.Stars.Draw()
- SetColor 255,255,255
- For Local Count:Int = 0 To TEXTS_COUNT - 1
- MainMenuScene.DrawTextCentered(Self.Texts[Count],Self.ScrollPoint + (25 * Count))
- Next
- End Method
- '#End Region
- '#Region Method: Start
- Method Start()
- Self.MusicChannel = AllocChannel()
- If Self.Music = Null Then Self.Music = LoadSound("sounds\ending.ogg",True)
- If Self.MusicChannel <> Null
- PlaySound(Self.Music,Self.MusicChannel)
- EndIf
- Self.Texts[0] = "Cast of Characters"
- Self.Texts[1] = "------------------"
- Self.Texts[2] = ""
- Self.Texts[3] = "Space Craft.......................Intrepid"
- Self.Texts[4] = "Digestive...............Sweet Meal Biscuit"
- Self.Texts[5] = "Star...............................Himself"
- Self.Texts[6] = ""
- Self.Texts[7] = "Written by Rob Hutchinson in roughly 5 days."
- Self.Texts[8] = "Email: [email protected]"
- Self.Texts[9] = "Web: http://www.proteanide.co.uk/"
- Self.Texts[10] = ""
- Self.Texts[11] = "Special Thanks To"
- Self.Texts[12] = "-----------------"
- Self.Texts[13] = "Richard Makepeace.............Inspiration"
- Self.Texts[14] = "James Readman.................Inspiration"
- Self.Texts[15] = ""
- Self.Texts[16] = "Greets"
- Self.Texts[17] = "------"
- Self.Texts[18] = "Pickup, Cabsy, Peters, ZanaX, Compona, Helen, + all other family and friends."
- Self.Texts[19] = ""
- Self.Texts[20] = ""
- Self.Texts[21] = ""
- Self.Texts[22] = "Thank you for playing."
- Self.ScrollPoint = HEIGHT + 20
- End Method
- '#End Region
- '#Region Method: Finish
- Method Finish()
- Self.Stars.Clear()
- If Self.MusicChannel <> Null Then
- Self.MusicChannel.Stop()
- Self.MusicChannel = Null
- EndIf
- End Method
- '#End Region
- End Type
- '#End Region
- Type TCircle
-
- Field X:Int
- Field Y:Int
- Field Radius:Float
-
- Method CollidesWith:Int(Circle:TCircle)
- Local Distance:Double = TPhysicsUtility.DistanceBetweenPoints(Self.X,Self.Y,Circle.X,Circle.Y)
- If Distance < (Self.Radius + Circle.Radius) Then Return True
- Return False
- End Method
- Method Draw()
- SetBlend(ALPHABLEND)
- SetAlpha(0.5)
- SetRotation 0
- DrawCircle(X,Y,Int(Radius))
- End Method
- Function DrawCircle(X,Y,Radius)
- DrawOval(X - Radius,Y - Radius,Radius * 2,Radius * 2)
- End Function
- End Type
- Type TDigestive Extends TPhysicsProvider
- Field Image:TImage
- Field Alpha:Float = 1.0
- Field Rotation:Float = 0
- Field Scale:Float = 1.0
- Field Circle:TCircle = New TCircle
- Field GameScene:MainGameScene
- Const InitialRadius:Float = 70.0
- Field HitSound:TSound
- Method SplitIntoChunks(X:Int,Y:Int,Multiplier:Float)
- GameScene.Digestives.Remove(Self)
- Local Channel:TChannel = AllocChannel()
- If Channel <> Null
- Channel.SetVolume(Self.Scale)
- PlaySound(Self.HitSound, Channel)
- EndIf
- Self.GameScene.Chunks.X = X
- Self.GameScene.Chunks.Y = Y
-
- Self.GameScene.Player.Score :+ Int(((Self.Scale * 100.0) + 4.0) * Multiplier)
- Self.GameScene.Shake :+ (Self.Scale * 3.5)
-
- If Self.Scale > 0.2
- For Local Count:Int = 0 To Int(Self.Scale * 5)
- Local Digestive:TDigestive = TDigestive.Create(Self.World, Self.Image, Self.GameScene)
- Digestive.X = Self.X
- Digestive.Y = Self.Y
- Digestive.Rotation = Rnd(360)
- Digestive.Weight = 5
- Digestive.SetVelocityFromAngle(Rnd(360.0),Rnd(0.5,1.5))
- Digestive.SetDrawScale(Self.Scale / 2)
- Digestive.HitSound = Self.HitSound
- GameScene.Digestives.AddLast(Digestive)
- Next
- For Local ChunkCount:Int = 0 To 4 * (Self.Scale * 10)
- Local Particle:TStaticParticle = Self.GameScene.Chunks.AddStaticParticle(Self.GameScene.ChunkImages[(Int(Rnd(0,MainGameScene.CHUNK_COUNT)))], Rnd(360.0), Rnd(0.5,10.0), 0, 0.01, [255,255,255])
- Particle.Friction = 0.97
- Particle.Size = Rnd(0.5,1.0)
- Particle.Rotation = Rnd(-5.0,5.0)
- Next
- Else
- For Local ChunkCount2:Int = 0 To Rnd(3,8)
- Local Particle:TStaticParticle = Self.GameScene.Chunks.AddStaticParticle(Self.GameScene.ChunkImages[(Int(Rnd(0,MainGameScene.CHUNK_COUNT)))], Rnd(360.0), Rnd(0.5,10.0), 0, 0.01, [255,255,255])
- Particle.Friction = 0.97
- Particle.Size = Rnd(0.2,0.5)
- Particle.Rotation = Rnd(-5.0,5.0)
- Next
- End If
- End Method
- Method Draw()
- SetAlpha Self.ALPHA
- SetRotation Self.Rotation
- SetScale Self.Scale,Self.Scale
- DrawImage(Self.Image, Self.X, Self.Y)
- SetScale 1,1
- End Method
- Method SetDrawScale(Scale:Float)
- Self.Scale = Scale
- Self.Circle.Radius = Self.InitialRadius * Self.Scale
- End Method
- Method PhysicsApplied()
- Rotation:+2
- Local HalfWidth:Int = ((Image.Width * Self.Scale) / 2)
- Local HalfHeight:Int = ((Image.Height * Self.Scale) / 2)
- If X < -HalfWidth Then X = WIDTH + HalfWidth
- If Y < -HalfHeight Then Y = HEIGHT + HalfHeight
- If X > WIDTH + HalfWidth Then X = -HalfWidth
- If Y > HEIGHT + HalfHeight Then Y = -HalfHeight
- Self.Circle.X = Self.X
- Self.Circle.Y = Self.Y
- End Method
- Function Create:TDigestive(World:TWorldPhysicsProvider,Image:TImage,GameScene:MainGameScene)
- Local Out:TDigestive = New TDigestive
- Out.GameScene = GameScene
- Out.Circle.Radius = InitialRadius
- Out.World = World
- Out.Image = Image
- Return Out
- End Function
- End Type
- Type TPlayer Extends TPhysicsProvider
- Field Lives:Int
- Field Score:Int
- Field Weapon:TWeapon
- Field Dead:Int = True
- Field Teleports:Int = 2
- Field Image:TImage
- Field Rotation:Float
- Field Acceleration:Float
- Field MaxAcceleration:Float = 4.0
- Field Motion:Float = 0.001
- Field AccelerationDropMultiplier:Float = 8
- Field Circle:TCircle = New TCircle
- Field GameScene:MainGameScene
- Field FireRateCount:Float = 0
- Field Thruster:TFountain
- Field Death:TFountain
- Field ThrusterImage:TImage
- Field DeathImage:TImage
- Field SparkleImage:TImage
- Field ThrusterSound:TSound
- Field CrashSound:TSound
- Field ThrusterChannel:TChannel
- Field TeleportSound:TSound
- Method Draw()
- SetTransform
- ' Render the thruster...
- SetBlend LIGHTBLEND
- SetScale 0.6, 0.6
- SetAlpha 1.0
- Self.Thruster.Draw()
- Self.Death.Draw()
- If Not Self.Dead Then
- ' Render the player.
- SetBlend ALPHABLEND
- SetAlpha 1.0
- SetScale 1.0,1.0
- SetColor 255,255,255
- SetRotation 360 - Self.Rotation
- DrawImage(Self.Image, Self.X, Self.Y)
- EndIf
- End Method
- Method PhysicsApplied()
- Local HalfWidth:Int = (Image.Width / 2)
- Local HalfHeight:Int = (Image.Height / 2)
- If X < -HalfWidth Then X = WIDTH + HalfWidth
- If Y < -HalfHeight Then Y = HEIGHT + HalfHeight
- If X > WIDTH + HalfWidth Then X = -HalfWidth
- If Y > HEIGHT + HalfHeight Then Y = -HalfHeight
- Self.Circle.X = Self.X
- Self.Circle.Y = Self.Y
- End Method
- Method Update()
- ' Update thruster and death particles.
- Local Particle:TStaticParticle = Self.Thruster.AddStaticParticle(Self.ThrusterImage, Self.Rotation + 180 + Rnd(-5.0,5.0), 1.0, 1, 0.04, [255,255,255])
-
- Local ActualRotation:Float = Self.Rotation + 180
- Self.Thruster.X = Self.X + (Sin(ActualRotation) * 10)
- Self.Thruster.Y = Self.Y + (Cos(ActualRotation) * 10)
- Local ThisSpeed:Float = Self.Speed()
-
- If ThisSpeed < 0 Then ThisSpeed = 0
- If ThisSpeed > 10.0 Then ThisSpeed = 10.0
-
- ' Add particles to the thruster..
- Particle.Size = (ThisSpeed / 10)
- Self.ThrusterChannel.SetVolume(ThisSpeed / 10)
- Self.ThrusterChannel.SetPan(Float(Self.X / Float(WIDTH / 2.0) - 1.0))
- Self.GameScene.Shake:+ 0.10 * (ThisSpeed / 10.0)
- Self.Thruster.Update()
- Self.Death.UpdateWithFriction(TPhysicsProvider.AxisX | TPhysicsProvider.AxisY)
-
- If Self.Dead
- ' Player is currently dead, wait for a nice chance to put them back down.
- If Self.Lives < 1 Then
- ' Wait for the death particles to become zeroed.
- If Self.Death.Particles.IsEmpty() Then
- Self.GameScene.TerminateMainLoop = True
- EndIf
- Else
- ' Check to see if the center spot is safe to plop the ship on.
- If Self.GameScene.IsLocationSafe(WIDTH/2, HEIGHT/2, 70)
- Self.Dead = False
- For Local Pops:Int = 0 To 200
- Local Particle:TStaticParticle = Self.Death.AddStaticParticle(Self.SparkleImage, Rnd(360.0), Rnd(0.5,2.0), 0, Rnd(0.01, 0.03), [255,255,255])
- Particle.X = Self.X
- Particle.Y = Self.Y
- Particle.Rotation = Rnd(-1.0,1.0)
- Particle.Friction = 0.97
- Particle.Size = Rnd(0.1,0.2)
- Next
- EndIf
- EndIf
- Else
- ' Update fire rate counter...
- Self.FireRateCount :- 1
-
- If KeyDown(KEY_UP)
- ' Thrust
- Self.Acceleration :+ Self.Motion
- ' Clamp the acceleration
- If Self.Acceleration > Self.MaxAcceleration Then Self.Acceleration = Self.MaxAcceleration
- ' Add acceleration.
- Self.IncreaseVelocityFromAngle(Self.Rotation,Self.Acceleration)
- Else
- Self.Acceleration :- (Self.Motion * Self.AccelerationDropMultiplier)
- If Self.Acceleration < 0.0 Then Self.Acceleration = 0
- EndIf
-
- If KeyDown(KEY_LEFT)
- ' RotateLeft
- Self.Rotation :+ 3
- EndIf
-
- If KeyDown(KEY_RIGHT)
- ' RotateLeft
- Self.Rotation :- 3
- EndIf
-
- If KeyDown(KEY_SPACE)
- ' FIRE!
- If Self.FireRateCount <= 0 Then
- Self.FireRateCount = Self.Weapon.FireRate
- Self.Weapon.Fire(Self)
- End If
- EndIf
-
- If KeyHit(KEY_DOWN)
- ' TELEPORT
- If Self.Teleports > 0 Then
- Self.Teleports :- 1
- Local Location:TPointD = Self.GameScene.FindSafeLocation(20)
- PlaySound(Self.TeleportSound)
- Self.Death.X = Self.X
- Self.Death.Y = Self.Y
- For Local Pops:Int = 0 To 50
- Local Particle:TStaticParticle = Self.Death.AddStaticParticle(Self.SparkleImage, Rnd(360.0), Rnd(0.5,10.0), 0, 0.02, [255,255,255])
- Particle.X = Self.X
- Particle.Y = Self.Y
- Particle.Rotation = Rnd(-1.0,1.0)
- Particle.Friction = 0.97
- Particle.Size = Rnd(0.1,0.2)
- Next
- Self.X = Int(Location.X)
- Self.Y = Int(Location.Y)
- Self.Death.X = Self.X
- Self.Death.Y = Self.Y
- For Local Pops:Int = 0 To 20
- Local Particle:TStaticParticle = Self.Death.AddStaticParticle(Self.SparkleImage, Rnd(360.0), Rnd(0.5,2.0), 0, 0.02, [255,255,255])
- Particle.X = Self.X
- Particle.Y = Self.Y
- Particle.Rotation = Rnd(-1.0,1.0)
- Particle.Friction = 0.97
- Particle.Size = Rnd(0.1,0.2)
- Next
- EndIf
- EndIf
-
- ' COLLISION DETECT AGAINST DIGESTIVES!
- ' ---------------------------------------------------------
- For Local Item:TDigestive = EachIn Self.GameScene.Digestives
- If Item.Circle.CollidesWith(Self.Circle)
- Self.Lives :- 1
- Self.Dead = True
- PlaySound(Self.CrashSound)
-
- Local PlayerSpeed:Double = Self.Speed()
- Self.GameScene.Shake :+ PlayerSpeed / 1.5
- If PlayerSpeed > 10.0
- Item.SplitIntoChunks(Self.X,Self.Y,Self.Speed())
- EndIf
- Self.Death.X = Self.X
- Self.Death.Y = Self.Y
- For Local Pops:Int = 0 To 100
- If PlayerSpeed > 10 Then PlayerSpeed = 10
- Local Angle:Double = Self.Angle() + Rnd(-(80 - (8.0 * PlayerSpeed)), 80 - (8.0 * PlayerSpeed))
- Local Particle:TStaticParticle = Self.Death.AddStaticParticle(Self.DeathImage, Angle, Rnd(0.1, Self.Speed()), 0, 0.03, [255,255,255])
- Particle.Friction = 0.98
- Particle.Size = Rnd(0.1,0.7)
- Particle.Color = [Rand(80,255),24,Rand(24,128)]
- Next
- For Local Pops:Int = 0 To 300
- Local Particle:TStaticParticle = Self.Death.AddStaticParticle(Self.DeathImage, Rnd(360.0), Rnd(0.1, 7.0), 0, Rnd(0.01,0.04), [255,255,255])
- Particle.Friction = 0.99
- Particle.Size = Rnd(0.1,0.4)
- Particle.Color = [Rand(80,255),24,Rand(24,200)]
- Next
- Self.Reset()
- EndIf
- Next
- EndIf
- End Method
- Method Reset()
- Self.X = WIDTH / 2
- Self.Y = HEIGHT / 2
- Self.Acceleration = 0
- Self.VelocityX = 0
- Self.VelocityY = 0
- Self.Teleports = 2
- Self.Dead = 2
- End Method
- Method LoadAssets()
- If Self.ThrusterImage = Null Then Self.ThrusterImage = LoadImage("graphics\bullet1.png")
- If Self.DeathImage = Null Then Self.DeathImage = LoadImage("graphics\pop.png")
- If Self.SparkleImage = Null Then Self.SparkleImage = LoadImage("graphics\sparkle.png")
- ' Load in the sounds...
- If Self.ThrusterSound = Null Then Self.ThrusterSound = LoadSound("sounds\thrust.wav",True)
- If Self.CrashSound = Null Then Self.CrashSound = LoadSound("sounds\crash.wav",False)
- If Self.TeleportSound = Null Then Self.TeleportSound = LoadSound("sounds\teleport.wav",False)
-
- Self.ThrusterChannel = AllocChannel()
- Self.ThrusterChannel.SetVolume(0)
- PlaySound(Self.ThrusterSound,Self.ThrusterChannel)
- End Method
- Function Create:TPlayer(World:TWorldPhysicsProvider, Image:TImage, GameScene:MainGameScene)
- Local Out:TPlayer = New TPlayer
- Out.Thruster = TFountain.Create(World, TRectangle.Create(0,0,WIDTH,HEIGHT))
- Out.Death = TFountain.Create(World, TRectangle.Create(0,0,WIDTH,HEIGHT))
- Out.GameScene = GameScene
- Out.Circle.Radius = 10
- Out.World = World
- Out.Image = Image
- Out.Friction = 0.985
- Out.Reset()
- Return Out
- End Function
- End Type
- Type TBullet Extends TPhysicsProvider
- Field Image:TImage
- Field Circle:TCircle = New TCircle
- Field GameScene:MainGameScene
- Field Size:Float = 1.0
- Field ScoreMultiplier:Float = 1
- Field TTL:Int
- Field Fading:Float = 1.0
- Const TIME_TO_LIVE = 100
- Method Draw()
- SetScale(Self.Size,Self.Size)
- SetAlpha(Self.Fading)
- DrawImage(Self.Image, Self.X, Self.Y)
- End Method
- Method PhysicsApplied()
- Local HalfWidth:Int = (Image.Width / 2)
- Local HalfHeight:Int = (Image.Height / 2)
- If X < -HalfWidth Then X = WIDTH + HalfWidth
- If Y < -HalfHeight Then Y = HEIGHT + HalfHeight
- If X > WIDTH + HalfWidth Then X = -HalfWidth
- If Y > HEIGHT + HalfHeight Then Y = -HalfHeight
- ' Shall we kill it off?
- Self.TTL :+ 1
- If Self.TTL > TIME_TO_LIVE Then
- Self.Fading :- 0.015
- If Self.Fading < 0.05
- Self.GameScene.Bullets.Remove(Self)
- EndIf
- EndIf
-
- ' If X < -HalfWidth Or Y < -HalfHeight Or X > WIDTH + HalfWidth Or Y > HEIGHT + HalfHeight Then
- ' ' Bullet went off't screen
- ' Self.GameScene.Bullets.Remove(Self)
- ' EndIf
- Self.Circle.X = Self.X
- Self.Circle.Y = Self.Y
- ' COLLISION DETECT AGAINST DIGESTIVES!
- ' ---------------------------------------------------------
- For Local Item:TDigestive = EachIn Self.GameScene.Digestives
- If Item.Circle.CollidesWith(Self.Circle)
- If Self.Fading > 0.5
- Self.GameScene.Bullets.Remove(Self)
- Item.SplitIntoChunks(Self.Circle.X,Self.Circle.Y,Self.ScoreMultiplier)
- Exit
- EndIf
- EndIf
- Next
- End Method
- Function Create:TBullet(World:TWorldPhysicsProvider, Image:TImage, Player:TPlayer, Speed:Float, GameScene:MainGameScene, Size:Float, Radius:Float, Veer:Float)
- Local Out:TBullet = New TBullet
- Out.GameScene = GameScene
- Out.SetVelocityFromAngle(Player.Rotation + Rnd(-Veer,Veer),Speed)
- Out.Size = Size
- Out.Circle.Radius = Radius * Size
- Out.X = Player.X
- Out.Y = Player.Y
- Out.World = World
- Out.Image = Image
- Return Out
- End Function
- End Type
- Type TStar Extends TPhysicsProvider
- Field Color[]
- Field GameScene:MainGameScene
-
- Method Draw()
- SetColor Self.Color[0],Self.Color[1],Self.Color[2]
- DrawRect(X,Y,1,1)
- End Method
- Method PhysicsApplied()
- Self.VelocityX :* 1.01
- Self.VelocityY :* 1.01
-
- Local HalfWidth:Int = 5
- Local HalfHeight:Int = 5
- If X < -HalfWidth Or Y < -HalfHeight Or X > WIDTH + HalfWidth Or Y > HEIGHT + HalfHeight Then
- ' Bullet went off't screen
- Self.GameScene.Stars.Remove(Self)
- EndIf
- End Method
- Function Create:TStar(World:TWorldPhysicsProvider,GameScene:MainGameScene, Speed:Float)
- Local Out:TStar = New TStar
- Local Pigment = Rand(24,255)
- Out.GameScene = GameScene
- Out.Color = [Pigment,Pigment,Pigment]
- Out.SetVelocityFromAngle(Rnd(360),Rnd(0.2,0.9) * Speed)
- Out.X = WIDTH / 2
- Out.Y = HEIGHT / 2
- Out.World = World
- Return Out
- End Function
- End Type
- Type TMenuStar Extends TPhysicsProvider
- Field Color[]
- Field MenuScene:MainMenuScene
-
- Method Draw()
- SetColor Self.Color[0],Self.Color[1],Self.Color[2]
- DrawRect(X,Y,1,1)
- End Method
- Method PhysicsApplied()
- ' Self.VelocityX :* 1.01
- ' Self.VelocityY :* 1.01
-
- Local HalfWidth:Int = 5
- Local HalfHeight:Int = 5
- If X < -HalfWidth Or Y < -HalfHeight Or X > WIDTH + HalfWidth Or Y > HEIGHT + HalfHeight Then
- ' Bullet went off't screen
- Self.MenuScene.Stars.Remove(Self)
- EndIf
- End Method
- Function Create:TMenuStar(World:TWorldPhysicsProvider,MenuScene:MainMenuScene, Speed:Float)
- Local Out:TMenuStar = New TMenuStar
- Local Pigment = Rand(24,255)
- Out.MenuScene = MenuScene
- Out.Color = [Pigment,Pigment,Pigment]
- Out.SetVelocityFromAngle(90,Rnd(0.2,0.9) * Speed)
- Out.X = 0
- Out.Y = Rnd(HEIGHT)
- Out.World = World
- Return Out
- End Function
- End Type
- Type TEndingStar Extends TPhysicsProvider
- Field Color[]
- Field EndScene:EndingScene
-
- Method Draw()
- SetColor Self.Color[0],Self.Color[1],Self.Color[2]
- DrawRect(X,Y,1,1)
- End Method
- Method PhysicsApplied()
- ' Self.VelocityX :* 1.01
- ' Self.VelocityY :* 1.01
-
- Local HalfWidth:Int = 5
- Local HalfHeight:Int = 5
- If X < -HalfWidth Or Y < -HalfHeight Or X > WIDTH + HalfWidth Or Y > HEIGHT + HalfHeight Then
- ' Bullet went off't screen
- Self.EndScene.Stars.Remove(Self)
- EndIf
- End Method
- Function Create:TEndingStar(World:TWorldPhysicsProvider, EndScene:EndingScene, Speed:Float, X:Int, Y:Int)
- Local Out:TEndingStar = New TEndingStar
- Local Pigment = Rand(24,255)
- Out.EndScene = EndScene
- Out.Color = [Pigment,Pigment,Pigment]
- Out.X = X
- Out.Y = Y
- Out.World = World
- Return Out
- End Function
- End Type
- Type TPickup Extends TLink
- Const MODIFIER_SCORE = 0
- Const MODIFIER_LIVES = 1
- Const MODIFIER_ROTATION = 2
- Const MODIFIER_PSYCHODELIC = 3
- Const MODIFIER_WEAPON = 4
- Field Modifies:Int = MODIFIER_SCORE
- Field ByValue:Float
- Field LastsFor:Int
- Field Time:Int
- Field IsPermanent:Int = False
- Field Weapon:TWeapon
- Field Icon:TImage
- Field Probability:Double
- Field OwnedIcon:TImage
- Method Clone:TPickup()
- Local Out:TPickup = New TPickup
- Out.Modifies = Self.Modifies
- Out.ByValue = Self.ByValue
- Out.LastsFor = Self.LastsFor
- Out.IsPermanent = Self.IsPermanent
- Out.Weapon = Self.Weapon
- Out.Icon = Self.Icon
- Out.Probability = Self.Probability
- Out.OwnedIcon = Out.OwnedIcon
- Return Out
- End Method
- Function Create:TPickup(Modifies:Int,ByValue:Float,LastsFor:Int,IsPermanent:Int,Weapon:TWeapon,Icon:TImage,Probability:Double,OwnedIcon:TImage)
- Local Out:TPickup = New TPickup
- Out.Modifies = Modifies
- Out.ByValue = ByValue
- Out.LastsFor = LastsFor
- Out.IsPermanent = IsPermanent
- Out.Weapon = Weapon
- Out.Icon = Icon
- Out.Probability = Probability
- Out.OwnedIcon = OwnedIcon
- Return Out
- End Function
- End Type
- Type TWeapon Extends TLink
- Field Speed:Float
- Field Graphic:TImage
- Field Size:Float
- Field Radius:Float
- Field Veer:Float
- Field FireRate:Int
- Field MainGame:MainGameScene
- Field Sound:TSound
- Field Name:String
- Field Icon:TImage
- Method Fire(Player:TPlayer)
- Local Shot:TBullet = TBullet.Create(MainGame.World, Self.Graphic, Player, Self.Speed + Player.Speed(), Self.MainGame, Self.Size, Self.Radius, Self.Veer)
- Shot.ScoreMultiplier = (Player.Speed() * 4.0)
- If Shot.ScoreMultiplier < 1.0 Then Shot.ScoreMultiplier = 1.0
- Self.MainGame.Bullets.AddLast(Shot)
- PlaySound(Self.Sound)
- End Method
- Function Create:TWeapon(Speed:Float,Graphic:TImage,Size:Float,Radius:Float,Veer:Float,FireRate:Int,MainGame:MainGameScene,Sound:TSound,Icon:TImage,Name:String)
- Local Out:TWeapon = New TWeapon
- Out.Speed = Speed
- Out.Graphic = Graphic
- Out.Size = Size
- Out.Radius = Radius
- Out.Veer = Veer
- Out.FireRate = FireRate
- Out.MainGame = MainGame
- Out.Sound = Sound
- Out.Icon = Icon
- Out.Name = Name
- Return Out
- End Function
- End Type
- Type TEndMagnet Extends TMagnet
-
- Field Stars:Int
-
- End Type
- Type THighScores
- Const SCORE_COUNT = 10
- Field Scores:Int[SCORE_COUNT]
- Field Names:String[SCORE_COUNT]
- Method Render(X:Int, Y:Int)
- For Local Count:Int = 0 To SCORE_COUNT - 1
- DrawText(Self.Names[Count], X,Y + (Count * 20))
- Next
- For Local Count2:Int = 0 To SCORE_COUNT - 1
- DrawText(Self.Scores[Count2], X + 200,Y + (Count2 * 20))
- Next
- End Method
- Method IsHighScore:Int(Score:Int)
- For Local Count:Int = 0 To SCORE_COUNT - 1
- If Score > Self.Scores[Count] Then
- Return True
- EndIf
- Next
- Return False
- End Method
-
- Method Add(Score:Int,Name:String)
- ' Find out where we should put the score..
- Local PlaceAt:Int = SCORE_COUNT - 1
- For Local Count:Int = SCORE_COUNT - 1 To 0 Step -1
- If Score > Self.Scores[Count] Then
- PlaceAt = Count
- EndIf
- Next
- ' Shuffle them all down..
- For Local Shuffle:Int = SCORE_COUNT - 2 To PlaceAt Step -1
- Self.Scores[Shuffle + 1] = Self.Scores[Shuffle]
- Self.Names[Shuffle + 1] = Self.Names[Shuffle]
- Next
- Self.Scores[PlaceAt] = Score
- Self.Names[PlaceAt] = Name
- End Method
- Method Save(File:String)
- Local Out:TStream = OpenStream(File,False,True)
- If Out <> Null
- For Local Count:Int = 0 To SCORE_COUNT - 1
- WriteInt(Out,Self.Scores[Count])
- WriteLine(Out,Self.Names[Count])
- Next
- CloseStream(Out)
- EndIf
- End Method
- Function Load:THighScores(File:String)
- Local In:TStream = OpenStream(File,True,False)
- Local Out:THighScores = New THighScores
- If In = Null
- ' Fill it full of high scores..
- Out.Names[0] = "Loki"
- Out.Names[1] = "Booty"
- Out.Names[2] = "Rix"
- Out.Names[3] = "Jamez"
- Out.Names[4] = "Pies"
- Out.Names[5] = "Bobny"
- Out.Names[6] = "Berty"
- Out.Names[7] = "Billy"
- Out.Names[8] = "Bonny"
- Out.Names[9] = "Boxer"
- Out.Scores[0] = 100000
- Out.Scores[1] = 80000
- Out.Scores[2] = 50000
- Out.Scores[3] = 40000
- Out.Scores[4] = 30000
- Out.Scores[5] = 20000
- Out.Scores[6] = 10000
- Out.Scores[7] = 5000
- Out.Scores[8] = 4000
- Out.Scores[9] = 1000
- Else
- For Local Count:Int = 0 To SCORE_COUNT - 1
- Out.Scores[Count] = ReadInt(In)
- Out.Names[Count] = ReadLine(In)
- Next
- CloseStream(In)
- EndIf
- Return Out
- End Function
- End Type
- ' Main game setup.
- ' ------------------------
- Local Game:T2DDynamicGame = T2DDynamicGame.Create(WIDTH, HEIGHT, DEPTH, REFRESHRATE)
- Global Scores:THighScores = THighScores.Load("hi.dat")
- Game.DynamicTiming = DYNAMICTIMING
- Game.DesiredFPS = DESIREDFPS
- Game.Initialize() ' Go into graphics mode.
- HideMouse
- ' Create the main game scene.
- Local MenuScene:MainMenuScene = New MainMenuScene
- Local GameScene:MainGameScene = New MainGameScene
- Local EndScene:EndingScene = New EndingScene
- Local QuitFlag:Int = False
- While Not QuitFlag
- ' Attach The Game Scene To The Dynamic Game.
- Game.Setscene(Menuscene)
-
- ' Start The Main Loop.
- Game.Mainloop()
- If Not MenuScene.Exitgame
- If MenuScene.ShowCredits
- MenuScene.ShowCredits = False
- Game.SetScene(EndScene)
- Game.Mainloop()
- Else
- Game.Setscene(GameScene)
- Game.Mainloop()
- QFlushKeys()
- If GameScene.Completed
- GameScene.Completed = False
- Game.SetScene(EndScene)
- Game.Mainloop()
- EndIf
- QFlushKeys()
- ' Check for high score.
- If Scores.IsHighScore(GameScene.Player.Score) Then
- ' We got a high score.
- MenuScene.ViewMenu(MenuScene.VIEW_ENTERHIGH)
- MenuScene.LastHighScore = GameScene.Player.Score
- MenuScene.EnteredText = ""
- EndIf
- EndIf
- Else
- QuitFlag = True
- EndIf
- Wend
- Scores.Save("hi.dat")
- ' Clean up after we shut down.
- Game.ShutDown()
- ' Fin
- Const DEBUG = True
- Function DebugLog(Text:String)
- If DEBUG Then Print Text
- End Function
|