From efbbdf1ebbc3f6964369c08d4cbe0978c5a424dd Mon Sep 17 00:00:00 2001 From: Ian C Date: Tue, 1 Nov 2005 00:07:13 +0000 Subject: Initial import --- .cvsignore | 4 + 2D/debris.2d | Bin 0 -> 60 bytes 2D/large.2d | Bin 0 -> 468 bytes 2D/lsaucer.2d | Bin 0 -> 276 bytes 2D/medium.2d | Bin 0 -> 468 bytes 2D/ship.2d | Bin 0 -> 148 bytes 2D/small.2d | Bin 0 -> 468 bytes 2D/ssaucer.2d | Bin 0 -> 244 bytes GFX/font.bmf | Bin 0 -> 45472 bytes SFX/explode1.wav | Bin 0 -> 87974 bytes SFX/explode2.wav | Bin 0 -> 86738 bytes SFX/explode3.wav | Bin 0 -> 86844 bytes SFX/fire.wav | Bin 0 -> 24740 bytes SFX/life.wav | Bin 0 -> 120156 bytes SFX/lsaucer.wav | Bin 0 -> 15440 bytes SFX/sfire.wav | Bin 0 -> 27110 bytes SFX/ssaucer.wav | Bin 0 -> 10786 bytes SFX/thrust.wav | Bin 0 -> 8184 bytes SFX/thumphi.wav | Bin 0 -> 10640 bytes SFX/thumplo.wav | Bin 0 -> 9016 bytes game.bmx | 347 ++++++++++++++++++++++++++++++++ hiscore.bmx | 164 +++++++++++++++ sounds.bmx | 118 +++++++++++ types.bmx | 593 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ vectoroids.bmx | 204 +++++++++++++++++++ 25 files changed, 1430 insertions(+) create mode 100644 .cvsignore create mode 100644 2D/debris.2d create mode 100644 2D/large.2d create mode 100644 2D/lsaucer.2d create mode 100644 2D/medium.2d create mode 100644 2D/ship.2d create mode 100644 2D/small.2d create mode 100644 2D/ssaucer.2d create mode 100644 GFX/font.bmf create mode 100644 SFX/explode1.wav create mode 100644 SFX/explode2.wav create mode 100644 SFX/explode3.wav create mode 100644 SFX/fire.wav create mode 100644 SFX/life.wav create mode 100644 SFX/lsaucer.wav create mode 100644 SFX/sfire.wav create mode 100644 SFX/ssaucer.wav create mode 100644 SFX/thrust.wav create mode 100644 SFX/thumphi.wav create mode 100644 SFX/thumplo.wav create mode 100644 game.bmx create mode 100644 hiscore.bmx create mode 100644 sounds.bmx create mode 100644 types.bmx create mode 100644 vectoroids.bmx diff --git a/.cvsignore b/.cvsignore new file mode 100644 index 0000000..f980c70 --- /dev/null +++ b/.cvsignore @@ -0,0 +1,4 @@ +*.exe +.bmx +vectoroids.config +vectoroids.hiscore diff --git a/2D/debris.2d b/2D/debris.2d new file mode 100644 index 0000000..42929f8 Binary files /dev/null and b/2D/debris.2d differ diff --git a/2D/large.2d b/2D/large.2d new file mode 100644 index 0000000..9592949 Binary files /dev/null and b/2D/large.2d differ diff --git a/2D/lsaucer.2d b/2D/lsaucer.2d new file mode 100644 index 0000000..e3b8c09 Binary files /dev/null and b/2D/lsaucer.2d differ diff --git a/2D/medium.2d b/2D/medium.2d new file mode 100644 index 0000000..3a151a0 Binary files /dev/null and b/2D/medium.2d differ diff --git a/2D/ship.2d b/2D/ship.2d new file mode 100644 index 0000000..1ac3a5e Binary files /dev/null and b/2D/ship.2d differ diff --git a/2D/small.2d b/2D/small.2d new file mode 100644 index 0000000..37b4f67 Binary files /dev/null and b/2D/small.2d differ diff --git a/2D/ssaucer.2d b/2D/ssaucer.2d new file mode 100644 index 0000000..e6fe0af Binary files /dev/null and b/2D/ssaucer.2d differ diff --git a/GFX/font.bmf b/GFX/font.bmf new file mode 100644 index 0000000..267e412 Binary files /dev/null and b/GFX/font.bmf differ diff --git a/SFX/explode1.wav b/SFX/explode1.wav new file mode 100644 index 0000000..1f9716c Binary files /dev/null and b/SFX/explode1.wav differ diff --git a/SFX/explode2.wav b/SFX/explode2.wav new file mode 100644 index 0000000..e54f129 Binary files /dev/null and b/SFX/explode2.wav differ diff --git a/SFX/explode3.wav b/SFX/explode3.wav new file mode 100644 index 0000000..98188a5 Binary files /dev/null and b/SFX/explode3.wav differ diff --git a/SFX/fire.wav b/SFX/fire.wav new file mode 100644 index 0000000..49d3000 Binary files /dev/null and b/SFX/fire.wav differ diff --git a/SFX/life.wav b/SFX/life.wav new file mode 100644 index 0000000..56eae06 Binary files /dev/null and b/SFX/life.wav differ diff --git a/SFX/lsaucer.wav b/SFX/lsaucer.wav new file mode 100644 index 0000000..ae56662 Binary files /dev/null and b/SFX/lsaucer.wav differ diff --git a/SFX/sfire.wav b/SFX/sfire.wav new file mode 100644 index 0000000..1702f11 Binary files /dev/null and b/SFX/sfire.wav differ diff --git a/SFX/ssaucer.wav b/SFX/ssaucer.wav new file mode 100644 index 0000000..4f5fd56 Binary files /dev/null and b/SFX/ssaucer.wav differ diff --git a/SFX/thrust.wav b/SFX/thrust.wav new file mode 100644 index 0000000..f92e40c Binary files /dev/null and b/SFX/thrust.wav differ diff --git a/SFX/thumphi.wav b/SFX/thumphi.wav new file mode 100644 index 0000000..041bf4a Binary files /dev/null and b/SFX/thumphi.wav differ diff --git a/SFX/thumplo.wav b/SFX/thumplo.wav new file mode 100644 index 0000000..524bc9e Binary files /dev/null and b/SFX/thumplo.wav differ diff --git a/game.bmx b/game.bmx new file mode 100644 index 0000000..13afedf --- /dev/null +++ b/game.bmx @@ -0,0 +1,347 @@ +' Vectoroids +' +' Copyright 2005 Ian Cowburn +' +' $Id$ +' +Strict +Import noddybox.vector +Import noddybox.bitmapfont +Import noddybox.vectorgfx +Import "types.bmx" +Import "sounds.bmx" + +Type TGame + + Field score:Int + Field astlist:TList + Field bullets:TList + Field lives:Int + Field ship:TVectorGfxObject + Field lifeship:TVectorGfxObject + Field shotdelay:Int + Field deaddelay:Int + Field x:Double + Field y:Double + Field dx:Double + Field dy:Double + Field waiting:Int + Field freq:Int + Field hit:Int + Field hyperdelay:Int + Field waitdelay:Int + Field leveldelay:Int + Field minspeed:Double + Field maxspeed:Double + Field numast:Int + Field extralife:Int + Field saucerdelay:Int + Field saucertime:Int + Field saucershot:Int + Field saucer:TSaucer + + Method New() + score=0 + astlist=CreateList() + bullets=CreateList() + lives=2 + ship=GameGFX.ship.Clone() + lifeship=GameGFX.ship.Clone() + deaddelay=250 + waiting=True + waitdelay=500 + x=GraphicsWidth()/2 + y=GraphicsHeight()/2 + dx=0 + dy=0 + ship.ang=0 + ship.x=x + ship.y=y + leveldelay=0 + extralife=10000 + + lifeship.y=5 + lifeship.scale=0.5 + + minspeed=0.1 + maxspeed=1.0 + numast=5 + + saucertime=120*50 + saucerdelay=0 + saucershot=25 + + NewLevel() + End Method + + Method NewLevel() + TAsteroid.minspeed=minspeed + TAsteroid.maxspeed=maxspeed + For Local f:Int=0 Until numast + astlist.AddLast(TAsteroid.Create()) + Next + freq=30 + hit=0 + bullets.Clear() + shotdelay=0 + hyperdelay=0 + End Method + + Method CheckShipLaunch() + Local x1:Int=GraphicsWidth()/2-100 + Local y1:Int=GraphicsHeight()/2-100 + Local x2:Int=GraphicsWidth()/2+100 + Local y2:Int=GraphicsHeight()/2+100 + + If waitdelay=0 Or KeyHit(GameConfig.khyper) + FlushKeys() + waiting=False + EndIf + + waitdelay:-1 + + For Local a:TAsteroid=EachIn astlist + If saucer Or (a.x>x1 And a.xy1 And a.y=0 + CheckShipLaunch() + EndIf + + If astlist.Count()=0 + If leveldelay=0 + leveldelay=200 + Else + leveldelay:-1 + If leveldelay=0 + numast=Min(20,numast+2) + minspeed=Min(0.5,minspeed+0.05) + maxspeed=Min(2.0,maxspeed+0.05) + saucertime=Max(10,saucertime-20) + saucershot=Max(25,saucershot-10) + NewLevel() + EndIf + EndIf + EndIf + + If lives>-1 And saucer=Null + saucerdelay:+1 + + If saucerdelay>saucertime + saucerdelay=0 + If score<10000 + saucer=TSaucer.Create(True,saucershot) + ElseIf score<20000 + saucer=TSaucer.Create(Rand(0,1),saucershot) + Else + saucer=TSaucer.Create(False,saucershot) + EndIf + EndIf + EndIf + + + If lives>-1 And Not waiting + If KeyDown(GameConfig.kleft) + ship.ang:-20 + If ship.ang<0 + ship.ang:+3600 + EndIf + EndIf + + If KeyDown(GameConfig.kright) + ship.ang=(ship.ang+20) Mod 3600 + EndIf + + If KeyDown(GameConfig.kthrust) + Sounds.PlayerThrust(True) + dx=Min(2,Max(-2,dx+Lookup.si[ship.ang]*0.1)) + dy=Min(2,Max(-2,dy+Lookup.co[ship.ang]*0.1)) + Else + Sounds.PlayerThrust(False) + EndIf + + If KeyDown(GameConfig.khyper) And hyperdelay=0 + x=Rand(10,GraphicsWidth()-10) + y=Rand(10,GraphicsHeight()-10) + dx=0 + dy=0 + hyperdelay=100 + EndIf + + If KeyDown(GameConfig.kfire) And shotdelay=0 + Sounds.PlayerFire() + bullets.AddLast(TShot.Create(ship)) + shotdelay=25 + EndIf + + If shotdelay>0 + shotdelay:-1 + EndIf + + If hyperdelay>0 + hyperdelay:-1 + EndIf + + If KeyHit(KEY_ESCAPE) + lives=-1 + TParticleMachine.AsteroidExplosion(ship.x,ship.y) + Sounds.ShipExplosion() + EndIf + + x:+dx + y:+dy + + If x<0 + x:+GraphicsWidth() + EndIf + + If x>=GraphicsWidth() + x:-GraphicsWidth() + EndIf + + If y<0 + y:+GraphicsHeight() + EndIf + + If y>=GraphicsHeight() + y:-GraphicsHeight() + EndIf + + ship.x=x + ship.y=y + EndIf + + SetAlpha(0.7) + + For Local a:TAsteroid=EachIn astlist + a.Update() + Next + + For Local f:Int=1 To lives + lifeship.x=f*9 + lifeship.Draw() + Next + + SetAlpha(1) + + GameGFX.font.Centre(score,0) + SetColor(255,255,255) + If lives<0 + For Local s:TShot=EachIn bullets + s.Update(bullets,astlist,saucer) + Next + Else + For Local s:TShot=EachIn bullets + Local sc:Int=s.Update(bullets,astlist,saucer) + score:+sc + + If sc + If score>extralife + If extralife=10000 + extralife=50000 + Else + extralife:+50000 + EndIf + lives:+1 + Sounds.ExtraLife() + EndIf + + hit:+1 + If hit>3 + hit=0 + If freq>15 + freq:-1 + EndIf + EndIf + EndIf + Next + EndIf + + Local hit:Int=False + + If saucer + SetAlpha(0.7) + If lives>-1 And Not waiting + hit=saucer.Update(ship) + Else + saucer.Update(Null) + EndIf + + SetAlpha(1) + + If saucer.Finished() + saucer=Null + Sounds.NoSaucer() + EndIf + EndIf + + If lives<0 + deaddelay:-1 + GameGFX.font.Centre("game over",292) + Else + If Not waiting + SetAlpha(0.7) + + If hit Or Collides(ship.DrawToPointList()) + TParticleMachine.ShipExplosion(ship.x,ship.y) + Sounds.ShipExplosion() + + lives:-1 + x=GraphicsWidth()/2 + y=GraphicsHeight()/2 + dx=0 + dy=0 + ship.ang=0 + ship.x=x + ship.y=y + waiting=True + waitdelay=500 + FlushKeys() + EndIf + + SetAlpha(1) + EndIf + EndIf + + TParticleMachine.Process() + Sounds.Update(freq) + + FlushMem + Flip + + Return deaddelay>0 + End Method + + Method Collides:Int(list:TList) + For Local a:TAsteroid=EachIn astlist + For Local p:TVectorGfxPoint=EachIn list + If a.obj.IsInside(p.x,p.y) + Return True + EndIf + Next + Next + + Return False + End Method + +End Type diff --git a/hiscore.bmx b/hiscore.bmx new file mode 100644 index 0000000..96c6935 --- /dev/null +++ b/hiscore.bmx @@ -0,0 +1,164 @@ +' Vectoroids +' +' Copyright 2005 Ian Cowburn +' +' $Id$ +' +Strict +Import "types.bmx" + +Type THiscore + + Const NUM:Int=5 + Field score:THiscoreEnt[] + Field col:Int[] + Field coli:Int[] + + Function Load:THiscore() + Local o:THiscore=New THiscore + + o.score=New THiscoreEnt[NUM] + o.col=New Int[NUM] + o.coli=New Int[NUM] + + For Local f:Int=0 Until NUM + o.col[f]=254-f*20 + o.coli[f]=1 + Next + + Local s:TStream=ReadStream("vectoroids.hiscore") + + If s=Null + For Local f:Int=0 Until NUM + o.score[f]=THiscoreEnt.Create("SV",10000-f*2000) + Next + Else + s=LittleEndianStream(s) + + For Local f:Int=0 Until NUM + Local sc:Int=s.ReadInt() + Local n:String=s.ReadString(3) + o.score[f]=THiscoreEnt.Create(n,sc) + Next + + s.Close() + EndIf + + Return o + End Function + + Method Save() + Return + + Local s:TStream=WriteStream("vectoroids.hiscore") + + If s=Null + Return + EndIf + + s=LittleEndianStream(s) + + For Local sc:THiscoreEnt=EachIn score + s.WriteInt(sc.score) + s.WriteString(sc.name) + Next + + s.Close() + End Method + + Method Display(y:Int) + GameGFX.font.Centre("ALL TIME HIGH SCORES",y) + y:+20 + + For Local f:Int=0 Until NUM + GameGFX.font.DrawColoured(score[f].name,300,y,col[f],col[f],col[f]) + Local l:Int=GameGFX.font.TextWidth(score[f].score) + GameGFX.font.DrawColoured(score[f].score,500-l,y,col[f],col[f],col[f]) + y:+10 + col[f]:+coli[f] + + If col[f]=255 Or col[f]=150 + coli[f]=-coli[f] + EndIf + Next + End Method + + Method CheckScore(sc:Int) + If scGameConfig.kleft Or del=0) + del=40 + last=GameConfig.kleft + cur:-1 + If cur<0 + cur:+Len(a) + EndIf + EndIf + + If KeyHit(GameConfig.kright) And (last<>GameConfig.kright Or del=0) + del=40 + last=GameConfig.kright + cur:+1 + If cur=Len(a) + cur=0 + EndIf + EndIf + + If KeyDown(GameConfig.khyper) And (last<>GameConfig.kright Or del=0) + del=40 + last=GameConfig.kright + cur:+1 + If cur=Len(a) + cur=0 + EndIf + EndIf + + GameGFX.font.Centre("enter your name for",0) + GameGFX.font.Centre("the hall of fame",20) + + Flip + FlushMem + Wend + + score.Sort() + Save() + End Method +End Type + +Type THiscoreEnt + Field score:Int + Field name:String + + Function Create:THiscoreEnt(name:String, score:Int) + Local o:THiscoreEnt=New THiscoreEnt + o.score=score + o.name=name + Return o + End Function + + Method Compare(o:Object) + Local os:THiscoreEnt=THiscoreEnt(o) + + If os + Return score-os.score + Else + Return 0 + EndIf + End Method +End Type diff --git a/sounds.bmx b/sounds.bmx new file mode 100644 index 0000000..c0bdf5d --- /dev/null +++ b/sounds.bmx @@ -0,0 +1,118 @@ +' Vectoroids +' +' Copyright 2005 Ian Cowburn +' +' $Id$ +' +Strict + +Incbin "SFX/explode1.wav" +Incbin "SFX/explode2.wav" +Incbin "SFX/explode3.wav" +Incbin "SFX/fire.wav" +Incbin "SFX/life.wav" +Incbin "SFX/lsaucer.wav" +Incbin "SFX/sfire.wav" +Incbin "SFX/ssaucer.wav" +Incbin "SFX/thrust.wav" +Incbin "SFX/thumphi.wav" +Incbin "SFX/thumplo.wav" + + +Type Sounds + Global explode:TSound[] + Global fire:TSound + Global life:TSound + Global lsaucer:TSound + Global sfire:TSound + Global ssaucer:TSound + Global thrust:TSound + Global thumphi:TSound + Global thumplo:TSound + + Global thrust_channel:TChannel + Global ssaucer_channel:TChannel + Global lsaucer_channel:TChannel + + Global frame:Int + Global hi:Int + + Function Init() + explode=New TSound[3] + explode[2]=LoadSound("incbin::SFX/explode1.wav") + explode[1]=LoadSound("incbin::SFX/explode2.wav") + explode[0]=LoadSound("incbin::SFX/explode3.wav") + fire=LoadSound("incbin::SFX/fire.wav") + life=LoadSound("incbin::SFX/life.wav") + lsaucer=LoadSound("incbin::SFX/lsaucer.wav",True) + sfire=LoadSound("incbin::SFX/sfire.wav") + ssaucer=LoadSound("incbin::SFX/ssaucer.wav",True) + thrust=LoadSound("incbin::SFX/thrust.wav",True) + thumplo=LoadSound("incbin::SFX/thumplo.wav") + thumphi=LoadSound("incbin::SFX/thumphi.wav") + + frame=0 + hi=True + + thrust_channel=thrust.Cue() + ssaucer_channel=ssaucer.Cue() + lsaucer_channel=lsaucer.Cue() + End Function + + Function Update(freq:Int) + If frame>freq + frame=0 + + If hi + thumphi.Play() + Else + thumplo.Play() + EndIf + + hi=Not hi + EndIf + frame:+1 + End Function + + Function AsteroidExplosion(size:Int) + explode[size].Play() + End Function + + Function ShipExplosion() + explode[0].Play() + End Function + + Function PlayerFire() + fire.Play() + End Function + + Function SaucerFire() + sfire.Play() + End Function + + Function ExtraLife() + life.Play() + End Function + + Function PlayerThrust(on:Int) + thrust_channel.SetPaused(Not on) + End Function + + Function SmallSaucer() + ssaucer_channel.SetPaused(False) + End Function + + Function LargeSaucer() + lsaucer_channel.SetPaused(False) + End Function + + Function NoSaucer() + lsaucer_channel.SetPaused(True) + ssaucer_channel.SetPaused(True) + End Function + + Function Clear() + PlayerThrust(False) + NoSaucer() + End Function +End Type diff --git a/types.bmx b/types.bmx new file mode 100644 index 0000000..588a152 --- /dev/null +++ b/types.bmx @@ -0,0 +1,593 @@ +' Vectoroids +' +' Copyright 2005 Ian Cowburn +' +' $Id$ +' +Strict +Import noddybox.vectorgfx +Import noddybox.vector +Import noddybox.bitmapfont + +Import "sounds.bmx" + +Incbin "GFX/font.bmf" +Incbin "2D/ship.2d" +Incbin "2D/large.2d" +Incbin "2D/medium.2d" +Incbin "2D/small.2d" +Incbin "2D/ssaucer.2d" +Incbin "2D/lsaucer.2d" +Incbin "2D/debris.2d" + +Type Lookup + Global si:Double[] + Global co:Double[] + + Function Init() + si=New Double[3600] + co=New Double[3600] + + For Local a:Int=0 To 3599 + si[a]=Sin(180-Double(a)/10) + co[a]=Cos(180-Double(a)/10) + Next + End Function +End Type + +Type GameGFX + Global font:TBitmapFont + Global ship:TVectorGfxObject + Global large:TVectorGfxObject + Global medium:TVectorGfxObject + Global small:TVectorGfxObject + Global debris:TVectorGfxObject + Global lsaucer:TVectorGfxObject + Global ssaucer:TVectorGfxObject + + Function Init() + font=TBitmapFont.Load("incbin::GFX/font.bmf",0) + ship=TVectorGfxObject.Load("incbin::2D/ship.2d") + large=TVectorGfxObject.Load("incbin::2D/large.2d") + medium=TVectorGfxObject.Load("incbin::2D/medium.2d") + small=TVectorGfxObject.Load("incbin::2D/small.2d") + debris=TVectorGfxObject.Load("incbin::2D/debris.2d") + lsaucer=TVectorGfxObject.Load("incbin::2D/lsaucer.2d") + ssaucer=TVectorGfxObject.Load("incbin::2D/ssaucer.2d") + + large.scale=1.5 + medium.scale=1.5 + small.scale=1.5 + + lsaucer.scale=1.5 + ssaucer.scale=2 + End Function +End Type + +Type GameConfig + Global kleft:Int + Global kright:Int + Global kfire:Int + Global kthrust:Int + Global khyper:Int + Global kpause:Int + + Function Load() + Local s:TStream=ReadStream("vectoroids.config") + + If s=Null + kleft=KEY_O + kright=KEY_P + kfire=KEY_Q + kthrust=KEY_S + khyper=KEY_SPACE + kpause=KEY_P + Return + EndIf + + s=LittleEndianStream(s) + + kleft=s.ReadInt() + kright=s.ReadInt() + kfire=s.ReadInt() + kthrust=s.ReadInt() + khyper=s.ReadInt() + kpause=s.ReadInt() + + s.Close() + End Function + + Function Save() + Local s:TStream=WriteStream("vectoroids.config") + + If s=Null + Return + EndIf + + s=LittleEndianStream(s) + + s.WriteInt(kleft) + s.WriteInt(kright) + s.WriteInt(kfire) + s.WriteInt(kthrust) + s.WriteInt(khyper) + s.WriteInt(kpause) + + s.Close() + End Function +EndType + +Type TAsteroid + Global minspeed:Double + Global maxspeed:Double + + Field x:Double + Field y:Double + Field dx:Double + Field dy:Double + Field obj:TVectorGfxObject + Field size:Int + + Function RndSpeed:Double() + Local r:Double=Rnd(minspeed,maxspeed) + If Rand(100)<50 + Return r + Else + Return -r + EndIf + End Function + + Function Create:TAsteroid() + Local no:TAsteroid=New TAsteroid + no.obj=GameGFX.large.Clone() + no.obj.ang=Rand(3600) + If Rand(10)<5 + no.x=Rnd(0,GraphicsWidth()/3.0) + Else + no.x=Rnd(GraphicsWidth()/3.0*2.0,GraphicsWidth()) + EndIf + no.y=Rnd(0,GraphicsHeight()) + no.dx=RndSpeed()/2 + no.dy=RndSpeed() + no.size=2 + Return no + End Function + + Method CreateShard:TAsteroid() + Local no:TAsteroid=New TAsteroid + no.x=x + no.y=y + no.size=size-1 + + If no.size=1 + no.obj=GameGFX.medium.Clone() + Else + no.obj=GameGFX.small.Clone() + EndIf + + no.dx=RndSpeed() + no.dy=RndSpeed() + + no.x:+no.dx*8 + no.y:+no.dy*8 + no.obj.ang=Rand(3600) + + Return no + End Method + + Method Update() + x:+dx + y:+dy + + If x<-obj.width + x:+GraphicsWidth()+obj.width*2 + ElseIf x>GraphicsWidth()+obj.width + x:-GraphicsWidth()+obj.width*2 + EndIf + + If y<-obj.height + y:+GraphicsHeight()+obj.height*2 + ElseIf y>GraphicsHeight()+obj.height + y:-GraphicsHeight()+obj.height*2 + EndIf + + obj.x=x + obj.y=y + obj.Draw() + End Method + + Method Blowup:Int(astlist:TList) + Local sc:Int=100-size*20 + + If size>0 + astlist.AddLast(CreateShard()) + astlist.AddLast(CreateShard()) + EndIf + + astlist.Remove(Self) + + Return sc + End Method +EndType + +Type TShot + Field x:Double + Field y:Double + Field dx:Double + Field dy:Double + Field life:Int + + Function Create:TShot(ship:TVectorGfxObject) + Local o:TShot=New TShot + o.dx=Lookup.si[ship.ang]*2 + o.dy=Lookup.co[ship.ang]*2 + o.x=ship.x+o.dx*4 + o.y=ship.y+o.dy*4 + o.life=200 + Return o + End Function + + Method Update:Int(shotlist:TList, astlist:TList, saucer:TSaucer) + life:-1 + + If life=0 + shotlist.Remove(Self) + Return 0 + EndIf + + x:+dx + y:+dy + + If x<0 + x:+GraphicsWidth() + EndIf + + If x>=GraphicsWidth() + x:-GraphicsWidth() + EndIf + + If y<0 + y:+GraphicsHeight() + EndIf + + If y>=GraphicsHeight() + x:-GraphicsHeight() + EndIf + + If saucer And saucer.obj.IsInside(x,y) + TParticleMachine.ShipExplosion(saucer.x,saucer.y) + Sounds.ShipExplosion() + Sounds.NoSaucer() + shotlist.Remove(Self) + saucer.dead=True + + If saucer.big + Return 500 + Else + Return 1000 + EndIf + EndIf + + For Local o:TAsteroid=EachIn astlist + If o.obj.IsInside(x,y) + TParticleMachine.AsteroidExplosion(o.x,o.y) + Sounds.AsteroidExplosion(o.size) + shotlist.Remove(Self) + Return o.Blowup(astlist) + EndIf + Next + + SetColor(255,255,255) + Plot(x,y) + + Return 0 + End Method +End Type + +Type TEnemyShot + Field x:Double + Field y:Double + Field dx:Double + Field dy:Double + Field life:Int + + Function Create:TEnemyShot(ship:TVectorGfxObject, v:TVector) + Local o:TEnemyShot=New TEnemyShot + o.dx=v.x + o.dy=v.y + o.x=ship.x + o.y=ship.y + o.life=250 + Return o + End Function + + Method Update:Int(shotlist:TList, ship:TVectorGfxObject) + life:-1 + + If life=0 + shotlist.Remove(Self) + Return False + EndIf + + x:+dx + y:+dy + + If x<0 + x:+GraphicsWidth() + EndIf + + If x>=GraphicsWidth() + x:-GraphicsWidth() + EndIf + + If y<0 + y:+GraphicsHeight() + EndIf + + If y>=GraphicsHeight() + x:-GraphicsHeight() + EndIf + + If ship And ship.IsInside(x,y) + Sounds.ShipExplosion() + shotlist.Remove(Self) + Return True + EndIf + + SetColor(255,255,255) + Plot(x,y) + + Return False + End Method +End Type + +Type TSaucer + Field x:Double + Field y:Double + Field dx:Double + Field dy:Double + Field dirx:Int + Field dirchange:Int + Field shotdel:Int + Field shotwait:Int + Field shotlist:TList + Field big:Int + Field obj:TVectorGfxObject + Field dead:Int + + Function Create:TSaucer(big:Int, shotdel:Int) + Local o:TSaucer=New TSaucer + + o.dead=False + o.dirx=Rand(100)<50 + + If o.dirx + If Rand(100)<50 + o.x=0 + o.dx=Rnd(1,2) + Else + o.x=GraphicsWidth()-1 + o.dx=Rnd(-2,-1) + EndIf + o.y=Rand(10,GraphicsHeight()-10) + Else + If Rand(100)<50 + o.y=0 + o.dy=Rnd(1,2) + Else + o.y=GraphicsHeight()-1 + o.dy=Rnd(-2,-1) + EndIf + o.x=Rand(10,GraphicsWidth()-10) + EndIf + + o.Turn() + + o.shotlist=New TList + o.big=big + o.shotdel=shotdel + o.shotwait=Rand(shotdel) + + If big + Sounds.LargeSaucer() + o.obj=GameGFX.lsaucer.Clone() + Else + Sounds.SmallSaucer() + o.obj=GameGFX.ssaucer.Clone() + EndIf + + Return o + End Function + + Method Turn() + dirchange=Rand(10,100) + If dirx + dy=Rnd(-2,2) + Else + dx=Rnd(-2,2) + EndIf + End Method + + Method Fire(ship:TVectorGfxObject) + shotwait=0 + Local v:TVector + + If big + v=TVector.Create(ship.x-x+Rnd(-40,40),ship.y-y+Rnd(-40,40)) + Else + v=TVector.Create(ship.x-x+Rnd(-10,10),ship.y-y+Rnd(-10,10)) + EndIf + + v.SetLength(2) + + Sounds.SaucerFire() + + shotlist.AddLast(TEnemyShot.Create(obj,v)) + End Method + + Method OffScreen:Int() + If dirx + Return x<0 Or x>GraphicsWidth() + Else + Return y<0 Or y>GraphicsHeight() + EndIf + End Method + + Method Finished:Int() + Return shotlist.Count()=0 And (dead Or OffScreen()) + End Method + + ' Returns True if ship hit by saucer's bullets + ' + Method Update:Int(ship:TVectorGfxObject) + If Not dead + x:+dx + y:+dy + + If dirx + If y<0 + y:+GraphicsHeight() + ElseIf y>GraphicsHeight() + y:-GraphicsHeight() + EndIf + Else + If x<0 + x:+GraphicsWidth() + ElseIf x>GraphicsWidth() + x:-GraphicsWidth() + EndIf + EndIf + + dirchange:-1 + + If dirchange=0 + Turn() + EndIf + + obj.x=x + obj.y=y + obj.Draw() + + If ship And Not OffScreen() + shotwait:+1 + If shotwait>shotdel + Fire(ship) + EndIf + EndIf + EndIf + + Local ret:Int=False + + For Local s:TEnemyShot=EachIn shotlist + ret=s.Update(shotlist,ship) Or ret + Next + + Return ret + End Method + +End Type + + +Type TParticle + Field obj:TVectorGfxObject + Field x:Double + Field y:Double + Field a:Double + Field dx:Double + Field dy:Double + Field ai:Double + + Function CreatePoint:TParticle(x:Int, y:Int, v:TVector, ai:Double=-0.05) + Local o:TParticle=New TParticle + o.obj=Null + o.x=x + o.y=y + o.dx=v.x+Rnd(-0.1,0.1) + o.dy=v.y+Rnd(-0.1,0.1) + o.a=1 + o.ai=ai + Return o + End Function + + Function CreateDebris:TParticle(x:Int, y:Int, v:TVector, ai:Double=-0.01) + Local o:TParticle=New TParticle + o.obj=GameGFX.debris.Clone() + o.obj.ang=Rand(0,3599) + o.x=x + o.y=y + o.dx=v.x+Rnd(-0.1,0.1) + o.dy=v.y+Rnd(-0.1,0.1) + o.a=1 + o.ai=-0.02 + Return o + End Function + + Method Update() + x:+dx + y:+dy + a:+ai + + If a>0 + SetAlpha(a) + + If obj + obj.x=x + obj.y=y + obj.ang=(obj.ang+30) Mod 3600 + obj.Draw() + Else + Plot(x,y) + EndIf + EndIf + End Method +End Type + + +Type TParticleMachine + Global list:TList + + Function Init() + list=CreateList() + End Function + + Function Clear() + list.Clear() + End Function + + Function AsteroidExplosion(x:Int,y:Int) + For Local f:Int=0 To 20 + list.AddLast(TParticle.CreatePoint(x+Rand(-3,3),y+Rand(-3,3),TVector.Create(Rnd(-2,2),Rnd(-2,2)))) + Next + End Function + + Function ShipExplosion(x:Int,y:Int) + For Local f:Int=0 To 30 + list.AddLast(TParticle.CreatePoint(x+Rand(-1,1),y+Rand(-1,1),TVector.Create(Rnd(-2,2),Rnd(-2,2)),-0.02)) + Next + For Local f:Int=0 To 3 + list.AddLast(TParticle.CreateDebris(x+Rand(-1,1),y+Rand(-1,1),TVector.Create(Rnd(-2,2),Rnd(-2,2)),-0.01)) + Next + End Function + + Function Process() + Local l:TLink=list.FirstLink() + Local t:TLink + + SetColor(255,255,255) + + While l<>Null + Local p:TParticle=TParticle(l.Value()) + p.Update() + + If p.a<0.01 + t=l.NextLink() + l.Remove() + l=t + Else + l=l.NextLink() + EndIf + Wend + + SetAlpha(1) + End Function +End Type diff --git a/vectoroids.bmx b/vectoroids.bmx new file mode 100644 index 0000000..8f51c55 --- /dev/null +++ b/vectoroids.bmx @@ -0,0 +1,204 @@ +' Vectoroids +' +' Copyright 2005 Ian Cowburn +' +' $Id$ +' +Strict + +Import noddybox.vector +Import noddybox.bitmapfont +Import noddybox.keysyms + +Import "types.bmx" +Import "game.bmx" +Import "sounds.bmx" +Import "hiscore.bmx" + + +' Initialise +' +SeedRnd(MilliSecs()) + +?Win32 +If Switch("--directx") + SetGraphicsDriver D3D7Max2DDriver() +Else + SetGraphicsDriver GLMax2DDriver() +EndIf +? + +Graphics 800,600,32,60 +HideMouse + +SetBlend(ALPHABLEND) +SetAlpha(1.0) + +' Globals +' +Lookup.Init() +GameGFX.Init() +TParticleMachine.Init() +GameConfig.Load() +Sounds.Init() + +Global quit:Int=False +Global hiscore:THiscore=THiscore.Load() + +' Main code +' +Menu() + +While Not quit + Local game:TGame=New TGame + While game.Play() + Wend + Sounds.Clear() + Menu() +Wend + +EndGraphics +End + + +' =================================== +' Argument Routines +' =================================== +' +Function Switch:Int(s:String) + For Local a:String=EachIn AppArgs + If a=s + Return True + EndIf + Next + + Return False +End Function + +' =================================== +' Menu Routines +' =================================== +' +Function Menu() + FlushKeys() + + Local done:Int=False + + Local defkey:Int=0 + Local obj:TVectorGfxObject + + Select Rand(1,2) + Case 1 + obj=GameGFX.large.Clone() + Case 2 + obj=GameGFX.ship.Clone() + End Select + + obj.scale=5 + obj.x=GraphicsWidth()/2 + obj.y=GraphicsHeight()/2 + + While Not done + If KeyHit(KEY_ESCAPE) + done=True + quit=True + EndIf + + Cls + + obj.ang=(obj.ang+1) Mod 3600 + + If defkey=0 + SetAlpha(0.5) + Else + SetAlpha(0.2) + EndIf + SetColor(255,255,255) + obj.Draw() + SetAlpha(1) + + If defkey>0 + + If defkey=7 + GameGFX.font.Centre("PRESS A KEY TO GO BACK TO THE MENU",120) + Else + GameGFX.font.Centre("DEFINE KEYS",120) + EndIf + + GameGFX.font.DrawColoured("left",250,150,255,255*(defkey=1),0) + GameGFX.font.DrawColoured("right",250,170,255,255*(defkey=2),0) + GameGFX.font.DrawColoured("thrust",250,190,255,255*(defkey=3),0) + GameGFX.font.DrawColoured("fire",250,210,255,255*(defkey=4),0) + GameGFX.font.DrawColoured("hyperspace",250,230,255,255*(defkey=5),0) + GameGFX.font.DrawColoured("pause",250,250,255,255*(defkey=6),0) + GameGFX.font.DrawColoured(KeySym(GameConfig.kleft).ToLower(),500,150,255,255*(defkey=1),0) + GameGFX.font.DrawColoured(KeySym(GameConfig.kright).ToLower(),500,170,255,255*(defkey=2),0) + GameGFX.font.DrawColoured(KeySym(GameConfig.kthrust).ToLower(),500,190,255,255*(defkey=3),0) + GameGFX.font.DrawColoured(KeySym(GameConfig.kfire).ToLower(),500,210,255,255*(defkey=4),0) + GameGFX.font.DrawColoured(KeySym(GameConfig.khyper).ToLower(),500,230,255,255*(defkey=5),0) + GameGFX.font.DrawColoured(KeySym(GameConfig.kpause).ToLower(),500,250,255,255*(defkey=6),0) + + Local k:Int=0 + + For Local f:Int=1 To 255 + If KeyHit(f) + k=f + Continue + EndIf + Next + + If k<>0 + Select defkey + Case 1 + GameConfig.kleft=k + Case 2 + GameConfig.kright=k + Case 3 + GameConfig.kthrust=k + Case 4 + GameConfig.kfire=k + Case 5 + GameConfig.khyper=k + Case 6 + GameConfig.kpause=k + End Select + + defkey:+1 + + If defkey=8 + GameConfig.Save() + defkey=0 + EndIf + EndIf + Else + GameGFX.font.CentreColoured("vectoroids",0,255,255,0) + GameGFX.font.CentreColoured("COPYRIGHT | 2005 IAN C",20,255,0,0) + + GameGFX.font.Centre("press space to play",150) + GameGFX.font.Centre("press r to redefine keys",190) + GameGFX.font.Centre("EXTRA LIFE AT 10000 PTS THEN EVERY 50000 PTS",520) + GameGFX.font.Centre("ESCAPE TO QUIT",560) + GameGFX.font.CentreColoured("BASED ON ASTEROIDS | 1979 ~~ ATARI INC.",580,255,0,0) + + hiscore.Display(400) + + If KeyHit(KEY_ESCAPE) + done=True + quit=True + EndIf + + If KeyHit(KEY_R) + FlushKeys() + defkey=1 + EndIf + + If KeyHit(KEY_SPACE) + FlushKeys() + done=True + EndIf + EndIf + + Flip + FlushMem + Wend +End Function -- cgit v1.2.3