diff options
-rw-r--r-- | .cvsignore | 3 | ||||
-rw-r--r-- | Default.ppinch | bin | 1727 -> 423 bytes | |||
-rw-r--r-- | GFX/SHIP.png | bin | 0 -> 282 bytes | |||
-rw-r--r-- | GFX/SHOCK.png | bin | 0 -> 173 bytes | |||
-rw-r--r-- | GFX/keys_button.png | bin | 0 -> 6969 bytes | |||
-rw-r--r-- | GFX/sprites.bms | bin | 3237 -> 4018 bytes | |||
-rw-r--r-- | designer.bmx | 204 | ||||
-rw-r--r-- | game.bmx | 102 | ||||
-rw-r--r-- | level.bmx | 57 | ||||
-rw-r--r-- | main.bmx | 124 | ||||
-rw-r--r-- | types.bmx | 228 |
11 files changed, 604 insertions, 114 deletions
@@ -1,2 +1,3 @@ main.debug.exe
-.bmx
\ No newline at end of file +.bmx
+ppinch.config
\ No newline at end of file diff --git a/Default.ppinch b/Default.ppinch Binary files differindex ab2cd03..2e9ea26 100644 --- a/Default.ppinch +++ b/Default.ppinch diff --git a/GFX/SHIP.png b/GFX/SHIP.png Binary files differnew file mode 100644 index 0000000..ff9dd2b --- /dev/null +++ b/GFX/SHIP.png diff --git a/GFX/SHOCK.png b/GFX/SHOCK.png Binary files differnew file mode 100644 index 0000000..3e8b94c --- /dev/null +++ b/GFX/SHOCK.png diff --git a/GFX/keys_button.png b/GFX/keys_button.png Binary files differnew file mode 100644 index 0000000..f712071 --- /dev/null +++ b/GFX/keys_button.png diff --git a/GFX/sprites.bms b/GFX/sprites.bms Binary files differindex e142fef..1045023 100644 --- a/GFX/sprites.bms +++ b/GFX/sprites.bms diff --git a/designer.bmx b/designer.bmx index a45034d..ff7db2f 100644 --- a/designer.bmx +++ b/designer.bmx @@ -22,7 +22,8 @@ Private ' **** Types ' Type TDesObj Abstract - Const SELSIZE:Int=3 + Field selsize:Int + Field removable:Int Function Create:TDesObj(x:Int, y:Int) Abstract Function CreateFromLevel:TDesObj(o:Object) Abstract @@ -36,10 +37,10 @@ Type TDesObj Abstract Method Snap() Abstract Method DrawSelBox(x:Int, y:Int) - Local x1:Int=x-SELSIZE - Local y1:Int=y-SELSIZE - Local x2:Int=x+SELSIZE - Local y2:Int=y+SELSIZE + Local x1:Int=x-selsize + Local y1:Int=y-selsize + Local x2:Int=x+selsize + Local y2:Int=y+selsize SetColor(255,255,255) DrawLine(x1,y1,x2,y1) @@ -49,10 +50,10 @@ Type TDesObj Abstract End Method Method InSelBox(px:Int, py:Int, x:Int, y:Int) - Local x1:Int=x-SELSIZE - Local y1:Int=y-SELSIZE - Local x2:Int=x+SELSIZE - Local y2:Int=y+SELSIZE + Local x1:Int=x-selsize + Local y1:Int=y-selsize + Local x2:Int=x+selsize + Local y2:Int=y+selsize Return px>=x1 And px<=x2 And py>=y1 And py<=y2 End Method @@ -102,6 +103,8 @@ Type TDesGrav Extends TDesObj o.g.friendly=False o.g.mass=25 o.g.repel=False + o.selsize=3 + o.removable=True Return o End Function @@ -116,6 +119,8 @@ Type TDesGrav Extends TDesObj no.g.friendly=lp.friendly no.g.mass=lp.mass no.g.repel=lp.repel + no.selsize=3 + no.removable=True Return no End Function @@ -170,6 +175,82 @@ Type TDesGrav Extends TDesObj End Type +Type TDesShip Extends TDesObj + Field x:Int + Field y:Int + Field a:Int + + Function Create:TDesShip(x:Int, y:Int) + Local o:TDesShip=New TDesShip + + o.x=x + o.y=y + o.a=0 + o.selsize=8 + o.removable=False + + Return o + End Function + + Function CreateFromLevel:TDesObj(o:Object) + Local lp:TLevel=TLevel(o) + Local no:TDesShip=New TDesShip + + no.x=lp.startx + no.y=lp.starty + no.a=lp.startang + no.selsize=8 + no.removable=False + + Return no + End Function + + Method Draw() + SetColor(255,255,255) + SetRotation(a) + DrawImage(GameGFX.ship,x,y) + SetRotation(0) + End Method + + Method DrawSelect() + DrawSelBox(x,y) + End Method + + Method MouseOver:Int(x:Int, y:Int) + Return InSelBox(x,y,self.x,self.y) + End Method + + Method Drag(x:Int, y:Int) + DrawCoord(x,y) + self.x=x + self.y=y + End Method + + Method Edit() + Designer.sd_ang.SetFloat(a) + + If GUIDialog(Designer.sdialog,Designer.sd_ok,Designer.sd_cancel,GameGFX.pointer) + a = Designer.sd_ang.text.ToInt() + EndIf + End Method + + Method Save(lev:TLevel) + lev.startx=x + lev.starty=y + lev.startang=a + End Method + + Method SetInfo(w:TLabel) + w.text="Angle: " + a + End Method + + Method Snap() + x=CalcSnap(x) + y=CalcSnap(y) + End Method + +End Type + Type TDesPoint Extends TDesObj Field l:TPointLine Field over_p1:Int @@ -193,6 +274,9 @@ Type TDesPoint Extends TDesObj o.l.gap=1 o.l.v.x=0 o.l.v.y=0 + + o.selsize=3 + o.removable=True Return o End Function @@ -211,6 +295,8 @@ Type TDesPoint Extends TDesObj no.l.v.y=lp.v.y no.l.circle=lp.circle no.l.circvel=lp.circvel + no.selsize=3 + no.removable=True Return no End Function @@ -415,13 +501,19 @@ Type Designer Global pd_ok:TButton Global pd_cancel:TButton + Global sdialog:TGUIHandler + Global sd_ang:TText + Global sd_ok:TButton + Global sd_cancel:TButton + Global ldialog:TGUIHandler Global ld_invert:TCheckbox - Global ld_placefriend:TCheckbox - Global ld_maxmass:TText + Global ld_wrap:TCheckbox + Global ld_maxwave:TText Global ld_winpercent:TText Global ld_timer:TText - Global ld_placemass:TText + Global ld_shipmass:TText + Global ld_wavemass:TText Global ld_ok:TButton Global ld_cancel:TButton @@ -479,6 +571,13 @@ Type Designer md_ok = TButton.Create(mdialog,p.x+5,p.y+p.h-25,p.w/2-10,20,"OK",Null) md_cancel = TButton.Create(mdialog,p.x+p.w/2+5,p.y+p.h-25,p.w/2-10,20,"Cancel",Null) + sdialog = TGUIHandler.Create() + p = TPanel.Create(sdialog,-1,-1,400,100) + l = TLabel.Create(sdialog,p.x+5,p.y+50,"Angle:") + sd_ang = TText.Create(sdialog,p.x+l.w+10,p.y+50,"",30,TText.NUMERIC|TText.POSITIVE) + sd_ok = TButton.Create(sdialog,p.x+5,p.y+p.h-25,p.w/2-10,20,"OK",Null) + sd_cancel = TButton.Create(sdialog,p.x+p.w/2+5,p.y+p.h-25,p.w/2-10,20,"Cancel",Null) + pdialog = TGUIHandler.Create() p = TPanel.Create(pdialog,-1,-1,400,200) l = TLabel.Create(pdialog,p.x+5,p.y+10,"Gap per point:") @@ -495,16 +594,18 @@ Type Designer ldialog = TGUIHandler.Create() p = TPanel.Create(ldialog,-1,-1,400,200) - ld_invert = TCheckbox.Create(ldialog,p.x+5,p.y+10,"Inverse gravity for dropped masses?") - ld_placefriend = TCheckbox.Create(ldialog,p.x+5,p.y+30,"Dropped masses are collectors (friendly)?") - l = TLabel.Create(ldialog,p.x+5,p.y+50,"Max Dropped Masses:") - ld_maxmass = TText.Create(ldialog,l.x+l.w+10,l.y,"",2,TText.NUMERIC|TText.INTEGER|TText.POSITIVE) + ld_invert = TCheckbox.Create(ldialog,p.x+5,p.y+10,"Ship has inverse gravity?") + ld_wrap = TCheckbox.Create(ldialog,p.x+5,p.y+30,"Universe wraps?") + l = TLabel.Create(ldialog,p.x+5,p.y+50,"Gravity Waves:") + ld_maxwave = TText.Create(ldialog,l.x+l.w+10,l.y,"",2,TText.NUMERIC|TText.INTEGER|TText.POSITIVE) l = TLabel.Create(ldialog,p.x+5,p.y+70,"Win percentage:") ld_winpercent = TText.Create(ldialog,l.x+l.w+10,l.y,"",3,TText.NUMERIC|TText.INTEGER|TText.POSITIVE) l = TLabel.Create(ldialog,p.x+5,p.y+90,"Timer (roughly seconds):") ld_timer = TText.Create(ldialog,l.x+l.w+10,l.y,"",3,TText.NUMERIC|TText.INTEGER|TText.POSITIVE) - l = TLabel.Create(ldialog,p.x+5,p.y+110,"Placed mass:") - ld_placemass = TText.Create(ldialog,l.x+l.w+10,l.y,"",20,TText.NUMERIC|TText.POSITIVE) + l = TLabel.Create(ldialog,p.x+5,p.y+110,"Ship mass:") + ld_shipmass = TText.Create(ldialog,l.x+l.w+10,l.y,"",20,TText.NUMERIC|TText.POSITIVE) + l = TLabel.Create(ldialog,p.x+5,p.y+130,"Gravity Wave mass:") + ld_wavemass = TText.Create(ldialog,l.x+l.w+10,l.y,"",20,TText.NUMERIC|TText.POSITIVE) ld_ok = TButton.Create(ldialog,p.x+5,p.y+p.h-25,p.w/2-10,20,"OK",Null) ld_cancel = TButton.Create(ldialog,p.x+p.w/2+5,p.y+p.h-25,p.w/2-10,20,"Cancel",Null) @@ -523,6 +624,8 @@ Type Designer obj.Clear() + obj.AddLast(TDesShip.CreateFromLevel(level)) + For Local o:Object=EachIn level.grav obj.AddLast(TDesGrav.CreateFromLevel(o)) Next @@ -544,19 +647,21 @@ Type Designer Function EditLevelSettings() ld_invert.checked = level.invmass - ld_placefriend.checked = level.placefriend - ld_maxmass.text = level.maxmass + ld_wrap.checked = level.wrap + ld_maxwave.text = level.maxwave ld_winpercent.text = level.winpercent ld_timer.text = level.timer - ld_placemass.SetFloat(level.placemass) + ld_shipmass.SetFloat(level.shipmass) + ld_wavemass.SetFloat(level.wavemass) If GUIDialog(ldialog,ld_ok,ld_cancel,GameGFX.pointer) level.invmass = ld_invert.checked - level.placefriend= ld_placefriend.checked - level.maxmass = ld_maxmass.text.ToInt() + level.wrap = ld_wrap.checked + level.maxwave = Min(MAX_WAVE,ld_maxwave.text.ToInt()) level.winpercent = Max(0,Min(100,ld_winpercent.text.ToInt())) level.timer = ld_timer.text.ToInt() - level.placemass = ld_placemass.text.ToDouble() + level.shipmass = ld_shipmass.text.ToDouble() + level.wavemass = ld_wavemass.text.ToDouble() EndIf End Function End Type @@ -624,14 +729,23 @@ Function DoDesigner() If KeyHit(KEY_MOUSERIGHT) If sel<>Null - Select GUIMenu("Object Menu",["Edit","Snap to grid","Delete"],x,y,GameGFX.pointer) - Case 0 - sel.Edit() - Case 1 - sel.Snap() - Case 2 - Designer.obj.Remove(sel) - End Select + If sel.removable + Select GUIMenu("Object Menu",["Edit","Snap to grid","Delete"],x,y,GameGFX.pointer) + Case 0 + sel.Edit() + Case 1 + sel.Snap() + Case 2 + Designer.obj.Remove(sel) + End Select + Else + Select GUIMenu("Object Menu",["Edit","Snap to grid"],x,y,GameGFX.pointer) + Case 0 + sel.Edit() + Case 1 + sel.Snap() + End Select + EndIf Else Select GUIMenu("Create Menu",["Create Gravity Point","Create Particle Line","Edit Level Settings"],x,y,GameGFX.pointer) Case 0 @@ -697,8 +811,6 @@ Function TestCallback(w:TWidget) While res<>TGame.LEVEL_FINISHED And res<>TGame.LEVEL_CANCELLED Cls res=g.Play() - SetColor(255,255,255) - DrawImage(GameGFX.pointer,MouseX(),MouseY()) FlushMem Flip Wend @@ -716,34 +828,32 @@ Function CheckCallback(w:TWidget) Designer.level.CreatePlayfield(m,p) - If m.Count()+Designer.level.maxmass>MAX_GRAV + If (m.Count()+1)>MAX_GRAV ok=False - s:+"|Too many masses (combining placed and dropped)" + s:+"| * Too many masses (combining placed and ship)" EndIf - Local friends:Int=(Designer.level.placefriend And Designer.level.maxmass>0) + Local friends:Int=False - If Not friends - For Local gp:TMass=EachIn m - If gp.friend - friends=True - EndIf - Next - EndIf + For Local gp:TMass=EachIn m + If gp.friend + friends=True + EndIf + Next If Not friends ok=False - s:+"|No collector masses (no particles can be captured by player)" + s:+"| * No collector masses (no particles can be captured by player)" EndIf If p.Count()>MAX_POINT ok=False - s:+"|Too many points (" + p.Count() + " -- maximum is " + MAX_POINT + s:+"| * Too many points (" + p.Count() + " -- maximum is " + MAX_POINT + ")" EndIf If p.Count()=0 ok=False - s:+"|No particles to collect!" + s:+"| * No particles to collect" EndIf If Not ok @@ -19,6 +19,7 @@ Type TGame Const LEVEL_CANCELLED:Int= 4 Field level:TLevel + Field ship:TShip Field mass:TList Field point:TList Field timer:Int @@ -42,13 +43,14 @@ Type TGame o.level=level o.mass=CreateList() o.point=CreateList() - o.level.CreatePlayfield(o.mass,o.point) + o.ship=o.level.CreatePlayfield(o.mass,o.point) + o.mass.AddLast(o.ship) o.timer=o.level.timer o.num=o.point.Count() o.done=LEVEL_NOTOVER o.frame=0 o.placed=0 - o.txtoff=[GameGFX.font.TextWidth("PARTICLES"),GameGFX.font.TextWidth("CAPTURED"),GameGFX.font.TextWidth("TIMER"),GameGFX.font.TextWidth("LEFT")] + o.txtoff=[GameGFX.font.TextWidth("PARTICLES"),GameGFX.font.TextWidth("CAPTURED"),GameGFX.font.TextWidth("TIMER"),GameGFX.font.TextWidth("WAVES")] o.playing=False o.col=0 o.coli=5 @@ -126,26 +128,31 @@ Type TGame GameGFX.font.CentreColoured("Need "+level.winpercent+"% to clear",y,col/2,col,col) y:+yi - Local n:Int=Int(level.placemass) + Local n:Int=Int(level.shipmass) + Local w:Int=Int(level.wavemass) If level.invmass n=-n + w=-w EndIf - If level.maxmass>1 - GameGFX.font.CentreColoured("You can place "+level.maxmass+" masses of " + n + " Newtons",y,col/2,col,col) - Else - GameGFX.font.CentreColoured("You can place 1 mass of " + n + " Newtons",y,col/2,col,col) + GameGFX.font.CentreColoured("Your ship has a mass of " + n + " Newtons",y,col/2,col,col) + y:+yi + + If level.maxwave>1 + GameGFX.font.CentreColoured("You can fire "+level.maxwave+" Gravity Waves of " + w + " Newtons",y,col/2,col,col) + ElseIf level.maxwave=1 + GameGFX.font.CentreColoured("You can fire 1 Gravity Wave of " + w + " Newtons",y,col/2,col,col) EndIf y:+yi - If level.placefriend - GameGFX.font.CentreColoured("PLACED MASSES ARE COLLECTORS!",y,col,col/2,col/2) + If level.wrap + GameGFX.font.CentreColoured("THE UNIVERSE IS WARPED!",y,col,col/2,col/2) y:+yi EndIf y:+yi - GameGFX.font.Centre("Press Left Mouse Button",y) + GameGFX.font.Centre("Press Space",y) y:+yi SetScale(1,1) @@ -155,8 +162,44 @@ Type TGame captured=0 lost=0 - If playing + If playing + If done=LEVEL_NOTOVER + If KeyDown(GameConfig.kleft) + ship.RotateLeft() + EndIf + + If KeyDown(GameConfig.kright) + ship.RotateRight() + EndIf + + If KeyDown(GameConfig.kthrust) + ship.Thrust() + EndIf + + If KeyDown(GameConfig.kreverse) + ship.Reverse() + EndIf + + If KeyHit(GameConfig.kblast) And placed<level.maxwave + If level.invmass + ship.mass=-level.wavemass + Else + ship.mass=level.wavemass + EndIf + TParticleMachine.AddShockwave(ship) + placed:+1 + Else + If level.invmass + ship.mass=-level.shipmass + Else + ship.mass=level.shipmass + EndIf + EndIf + EndIf + For Local m:TMass=EachIn mass + ship.Attract(m) + For Local s:TPoint=EachIn point s.Attract(m) Next @@ -167,7 +210,7 @@ Type TGame If playing For Local m:TMass=EachIn mass - m.Move() + m.Move(True)'(level.wrap) m.Draw() Next Else @@ -178,7 +221,7 @@ Type TGame If playing For Local s:TPoint=EachIn point - s.Move() + s.Move(level.wrap) s.Draw() If s.dead @@ -243,14 +286,12 @@ Type TGame GameGFX.font.DrawColoured(percent+"%",txtoff[1]+210,0,50,255,50) EndIf - GameGFX.font.Draw("LEFT",400,0) + GameGFX.font.Draw("WAVES",400,0) - SetScale(2,2) SetColor(255,255,255) - For Local f:Int=0 Until level.maxmass-placed - DrawImage(GameGFX.mass,410+txtoff[3]+f*10,3) + For Local f:Int=0 Until level.maxwave-placed + DrawImage(GameGFX.shock,410+txtoff[3]+f*10,3) Next - SetScale(1,1) GameGFX.font.Draw("TIMER",600,0) @@ -263,28 +304,36 @@ Type TGame Select done Case LEVEL_NOTOVER If playing + Rem If placed<level.maxmass And mass.Count()<MAX_GRAV - If MouseHit(1) + If KeyHit(KEY_SPACE) Local m:TMass=New TMass m.friend=level.placefriend m.inverse=level.invmass m.x=MouseX() m.y=MouseY() - m.img=GameGFX.mass + If m.friend + m.img=GameGFX.collector + Else + m.img=GameGFX.star + EndIf m.mass=level.placemass mass.AddLast(m) placed:+1 EndIf EndIf + EndRem Else Intro() - If MouseHit(1) + If KeyHit(KEY_SPACE) playing=True + FlushKeys() EndIf EndIf If KeyHit(KEY_ESCAPE) done=LEVEL_CANCELLED + FlushKeys() EndIf Case LEVEL_WON If final_percent=100 @@ -294,6 +343,7 @@ Type TGame If col=255 Or col=0 TParticleMachine.AddFirework(Rand(0,GraphicsWidth()),Rand(0,GraphicsHeight())) + 'TParticleMachine.AddShockwave(Rand(0,GraphicsWidth()),Rand(0,GraphicsHeight())) coli=-coli EndIf EndIf @@ -302,23 +352,25 @@ Type TGame SetAlpha(0.7) GameGFX.font.CentreColoured("LEVEL COMPLETED!",GraphicsHeight()/2+20,255,255,0) GameGFX.font.CentreColoured("You got the pass mark with "+pass_time+" left on the clock",GraphicsHeight()/2+40,255,255,0) - GameGFX.font.Centre("Press the Left Mouse Button",GraphicsHeight()/2+80) + GameGFX.font.Centre("Press Space",GraphicsHeight()/2+80) SetScale(1,1) SetAlpha(1) - If MouseHit(1) + If KeyHit(KEY_SPACE) done=LEVEL_FINISHED + FlushKeys() EndIf Case LEVEL_LOST SetScale(2,2) SetAlpha(0.7) GameGFX.font.CentreColoured("LEVEL FAILED!",GraphicsHeight()/2+20,255,64,64) - GameGFX.font.Centre("Press the Left Mouse Button",GraphicsHeight()/2+60) + GameGFX.font.Centre("Press Space",GraphicsHeight()/2+60) SetScale(1,1) SetAlpha(1) - If MouseHit(1) + If KeyHit(KEY_SPACE) done=LEVEL_FINISHED + FlushKeys() EndIf EndSelect @@ -10,10 +10,11 @@ Import noddybox.bitmapfont Import noddybox.algorithm Import "types.bmx" -Const MAGIC:String="PPINCH_0001" +Const MAGIC:String="PPINCH_0002" Const MAX_GRAV:Int=10 Const MAX_POINT:Int=1000 +Const MAX_WAVE:Int=10 Type TLevelException Field message:String @@ -151,34 +152,52 @@ End Type Type TLevel Field name:String - Field maxmass:Int + Field maxwave:Int Field grav:TList Field point:TList Field winpercent:Int Field timer:Int Field invmass:Int - Field placemass:Double - Field placefriend:Int + Field shipmass:Double + Field wavemass:Double + Field wrap:Int + Field startx:Double + Field starty:Double + Field startang:Int Method New() grav=CreateList() point=CreateList() name="Unititled" - maxmass=5 + maxwave=5 winpercent=50 - timer=60 + timer=120 invmass=False - placemass=25 - placefriend=True + shipmass=5 + wavemass=5 + wrap=False + startx=399 + starty=400 + startang=0 End Method - Method CreatePlayfield(masslist:TList, pointlist:TList) + Method CreatePlayfield:TShip(masslist:TList, pointlist:TList) For Local gp:TGravPoint=EachIn grav masslist.AddLast(gp.CreateMass()) Next For Local lp:TPointLine=EachIn point lp.CreatePoints(pointlist) Next + + Local s:TShip=New TShip + + s.x=startx + s.y=starty + s.a=startang + s.mass=shipmass + s.img=GameGFX.ship + + Return s End Method Function FromStream:TLevel(s:TStream) @@ -186,12 +205,16 @@ Type TLevel Local c:Int o.name=s.ReadLine() - o.maxmass=s.ReadInt() + o.maxwave=s.ReadInt() o.winpercent=s.ReadInt() o.timer=s.ReadInt() o.invmass=s.ReadInt() - o.placemass=s.ReadDouble() - o.placefriend=s.ReadInt() + o.shipmass=s.ReadDouble() + o.wavemass=s.ReadDouble() + o.wrap=s.ReadInt() + o.startx=s.ReadDouble() + o.starty=s.ReadDouble() + o.startang=s.ReadInt() c=s.ReadInt() For Local f:Int=1 To c @@ -208,12 +231,16 @@ Type TLevel Method ToStream(s:TStream) s.WriteLine(name) - s.WriteInt(maxmass) + s.WriteInt(maxwave) s.WriteInt(winpercent) s.WriteInt(timer) s.WriteInt(invmass) - s.WriteDouble(placemass) - s.WriteInt(placefriend) + s.WriteDouble(shipmass) + s.WriteDouble(wavemass) + s.WriteInt(wrap) + s.WriteDouble(startx) + s.WriteDouble(starty) + s.WriteInt(startang) s.WriteInt(grav.Count()) For Local o:TGravPoint=EachIn grav @@ -9,6 +9,7 @@ Strict Import noddybox.vector Import noddybox.bitmapfont Import noddybox.simplegui +Import noddybox.keysyms Import "types.bmx" Import "level.bmx" @@ -21,11 +22,12 @@ Import "menu.bmx" Incbin "GFX/font.bmf" Incbin "GFX/small.bmf" Incbin "GFX/STAR.png" -Incbin "GFX/MASS.png" +Incbin "GFX/SHIP.png" Incbin "GFX/POINT.png" Incbin "GFX/PARTICLE.png" Incbin "GFX/POINTER.png" Incbin "GFX/COLLECTOR.png" +Incbin "GFX/SHOCK.png" Incbin "GFX/play_button.png" Incbin "GFX/edit_button.png" Incbin "GFX/load_button.png" @@ -34,12 +36,21 @@ Incbin "GFX/quit_button.png" Incbin "GFX/left_button.png" Incbin "GFX/right_button.png" Incbin "GFX/scores_button.png" +Incbin "GFX/keys_button.png" ' Initialise ' SeedRnd(MilliSecs()) -SetGraphicsDriver GLMax2DDriver() + +?Win32 +If Switch("--directx") + SetGraphicsDriver D3D7Max2DDriver() +Else + SetGraphicsDriver GLMax2DDriver() +EndIf +? + Graphics 800,600,32,60 HideMouse @@ -51,11 +62,12 @@ SetAlpha(1.0) GameGFX.font=TBitmapFont.Load("incbin::GFX/font.bmf",0) GameGFX.smallfont=TBitmapFont.Load("incbin::GFX/small.bmf",0) GameGFX.star=LoadAnimImage("incbin::GFX/STAR.png",8,8,0,2) -GameGFX.mass=LoadAnimImage("incbin::GFX/MASS.png",8,8,0,2) +GameGFX.ship=LoadImage("incbin::GFX/SHIP.png",FILTEREDIMAGE) GameGFX.collector=LoadAnimImage("incbin::GFX/COLLECTOR.png",8,8,0,2) GameGFX.point=LoadImage("incbin::GFX/POINT.png",FILTEREDIMAGE) GameGFX.particle=LoadImage("incbin::GFX/PARTICLE.png",0) GameGFX.pointer=LoadImage("incbin::GFX/POINTER.png",0) +GameGFX.shock=LoadImage("incbin::GFX/SHOCK.png",0) GameGFX.play_button=LoadImage("incbin::GFX/play_button.png",0) GameGFX.edit_button=LoadImage("incbin::GFX/edit_button.png",0) GameGFX.load_button=LoadImage("incbin::GFX/load_button.png",0) @@ -64,26 +76,38 @@ GameGFX.quit_button=LoadImage("incbin::GFX/quit_button.png",0) GameGFX.left_button=LoadImage("incbin::GFX/left_button.png",0) GameGFX.right_button=LoadImage("incbin::GFX/right_button.png",0) GameGFX.scores_button=LoadImage("incbin::GFX/scores_button.png",0) +GameGFX.keys_button=LoadImage("incbin::GFX/keys_button.png",0) SetImageHandle(GameGFX.star,3,3) -SetImageHandle(GameGFX.mass,3,3) +SetImageHandle(GameGFX.ship,7,7) SetImageHandle(GameGFX.collector,3,3) SetImageHandle(GameGFX.point,3,3) SetImageHandle(GameGFX.particle,3,3) SetImageHandle(GameGFX.pointer,0,0) +SetImageHandle(GameGFX.shock,3,3) TPoint.img=GameGFX.point TParticle.img=GameGFX.particle TGUIFont.font=GameGFX.font +Lookup.Init() TParticleMachine.Init() +GameConfig.Load() Global quit:Int=False Global levelfile:String="Default.ppinch" Global levelset:TLevelSet=Null Global selected_level:Int=0 +' Check designer mode +' +If Switch("--design") + LevelDesigner() + EndGraphics + End +EndIf + ' Initialisation ' Try @@ -117,7 +141,7 @@ Function Error(s:String, fatal:Int=False) Local t:Int=0 FlushKeys() - SetScale(3,3) + SetScale(2,2) While Not KeyHit(KEY_ESCAPE) Cls @@ -150,6 +174,20 @@ Function Error(s:String, fatal:Int=False) End Function ' =================================== +' 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 ' =================================== ' @@ -162,6 +200,7 @@ Function Menu() Const MENU_LEFT:Int=6 Const MENU_RIGHT:Int=7 Const MENU_SCORES:Int=8 + Const MENU_KEYS:Int=9 Local done:Int=False Local menu:TMenu=TMenu.Create() @@ -170,12 +209,16 @@ Function Menu() Local x1:Int=(GraphicsWidth()/2-ImageWidth(GameGFX.play_button))/2 Local x2:Int=x1+GraphicsWidth()/2 + Local defkey:Int=0 + menu.Add(x1,100,GameGFX.play_button,MENU_PLAY) menu.Add(x2,100,GameGFX.scores_button,MENU_SCORES) menu.Add(x1,200,GameGFX.load_button,MENU_LOAD) menu.Add(x2,200,GameGFX.edit_button,MENU_EDIT) menu.Add(x1,300,GameGFX.toy_button,MENU_TOY) - menu.Add(x2,300,GameGFX.quit_button,MENU_QUIT) + menu.Add(x2,300,GameGFX.keys_button,MENU_KEYS) + menu.Add(-1,400,GameGFX.quit_button,MENU_QUIT) + menu.Add(64,530,GameGFX.left_button,MENU_LEFT) menu.Add(GraphicsWidth()-96,530,GameGFX.right_button,MENU_RIGHT) @@ -187,7 +230,62 @@ Function Menu() Cls - sel=menu.Render() + If defkey>0 + + SetScale(2,2) + + If defkey=6 + GameGFX.font.Centre("PRESS A KEY TO GO BACK TO THE MENU",50) + Else + GameGFX.font.Centre("DEFINE KEYS",50) + EndIf + + GameGFX.font.DrawColoured("Left",250,100,255,255*(defkey=1),0) + GameGFX.font.DrawColoured("Right",250,120,255,255*(defkey=2),0) + GameGFX.font.DrawColoured("Thrust",250,140,255,255*(defkey=3),0) + GameGFX.font.DrawColoured("Reverse",250,160,255,255*(defkey=4),0) + GameGFX.font.DrawColoured("Gravity Wave",250,180,255,255*(defkey=5),0) + GameGFX.font.DrawColoured(KeySym(GameConfig.kleft),500,100,255,255*(defkey=1),0) + GameGFX.font.DrawColoured(KeySym(GameConfig.kright),500,120,255,255*(defkey=2),0) + GameGFX.font.DrawColoured(KeySym(GameConfig.kthrust),500,140,255,255*(defkey=3),0) + GameGFX.font.DrawColoured(KeySym(GameConfig.kreverse),500,160,255,255*(defkey=4),0) + GameGFX.font.DrawColoured(KeySym(GameConfig.kblast),500,180,255,255*(defkey=5),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.kreverse=k + Case 5 + GameConfig.kblast=k + End Select + + defkey:+1 + + If defkey=7 + GameConfig.Save() + defkey=0 + EndIf + EndIf + + SetScale(1,1) + EndIf + + sel=menu.Render(defkey>0) Select sel Case MENU_PLAY @@ -203,6 +301,9 @@ Function Menu() Case MENU_TOY done=True FlushKeys() + Case MENU_KEYS + FlushKeys() + defkey=1 Case MENU_QUIT done=True quit=True @@ -215,11 +316,14 @@ Function Menu() Case MENU_RIGHT selected_level=(selected_level+1) Mod levelset.level.Count() End Select - + SetScale(2,2) GameGFX.font.CentreColoured("PARTICLE PINCH",0,255,255,0) - GameGFX.font.CentreColoured("Start Level",530,0,255,255) - GameGFX.font.Centre(levelset.Get(selected_level).name,545) + + If defkey=0 + GameGFX.font.CentreColoured("Start Level",528,0,255,255) + GameGFX.font.Centre(levelset.Get(selected_level).name,547) + EndIf SetScale(1,1) GameGFX.font.CentreColoured("Copyright (c) 2005 Ian Cowburn",20,255,0,0) @@ -10,16 +10,34 @@ Import noddybox.bitmapfont Const MASSSIZE:Int=8 Const MASSRAD:Int=4 +Const SHIPSIZE:Int=12 +Const SHIPRAD:Int=6 + +Type Lookup + Global si:Double[] + Global co:Double[] + + Function Init() + si=New Double[360] + co=New Double[360] + + For Local a:Int=0 To 359 + si[a]=Sin(a) + co[a]=Cos(a) + Next + End Function +End Type Type GameGFX Global font:TBitmapFont Global smallfont:TBitmapFont Global star:TImage - Global mass:TImage + Global ship:TImage Global collector:TImage Global point:TImage Global particle:Timage Global pointer:TImage + Global shock:TImage Global play_button:TImage Global edit_button:TImage @@ -29,17 +47,71 @@ Type GameGFX Global left_button:TImage Global right_button:TImage Global scores_button:TImage + Global keys_button:TImage End Type -Type TMass +Type GameConfig + Global kleft:Int + Global kright:Int + Global kthrust:Int + Global kreverse:Int + Global kblast:Int + + Function Load() + Local s:TStream=ReadStream("ppinch.config") + + If s=Null + kleft=KEY_O + kright=KEY_P + kthrust=KEY_Q + kreverse=KEY_A + kblast=KEY_SPACE + Return + EndIf + + s=LittleEndianStream(s) + + kleft=s.ReadInt() + kright=s.ReadInt() + kthrust=s.ReadInt() + kreverse=s.ReadInt() + kblast=s.ReadInt() + + s.Close() + End Function + + Function Save() + Local s:TStream=WriteStream("ppinch.config") + + If s=Null + Return + EndIf + + s=LittleEndianStream(s) + + s.WriteInt(kleft) + s.WriteInt(kright) + s.WriteInt(kthrust) + s.WriteInt(kreverse) + s.WriteInt(kblast) + + s.Close() + End Function +EndType + +Type TGfxObject Field x:Double Field y:Double +EndType + +Type TMass Extends TGfxObject Field v:TVector Field mass:Double Field friend:Int Field inverse:Int Field img:TImage Field swallow:Int + Field rad:Int Method New() v=TVector.Create() @@ -49,6 +121,7 @@ Type TMass friend=True inverse=False swallow=0 + rad=MASSRAD End Method Method Attract(o:TMass) @@ -70,15 +143,43 @@ Type TMass v.Add(d) - If d.Length()>MASSSIZE - d.SetLength(MASSSIZE) + If v.Length()>MASSSIZE + v.SetLength(MASSSIZE) EndIf EndIf End Method - Method Move() + Method Move(wrap:Int) x:+v.x y:+v.y + + If wrap + If x<0 + x:+GraphicsWidth() + EndIf + If x>GraphicsWidth() + x:-GraphicsWidth() + EndIf + If y<0 + y:+GraphicsHeight() + EndIf + If y>GraphicsHeight() + y:-GraphicsHeight() + EndIf + Else + If x<0 + x=0 + EndIf + If x>GraphicsWidth() + x=GraphicsWidth() + EndIf + If y<0 + y=0 + EndIf + If y>GraphicsHeight() + y=GraphicsHeight() + EndIf + EndIf End Method Method Draw() @@ -89,11 +190,61 @@ Type TMass End Type -Type TPoint +Type TShip Extends TMass + Field a:Int + + Method New() + v=TVector.Create() + x=-1 + y=-1 + mass=25 + friend=False + inverse=False + swallow=0 + rad=SHIPRAD + a=0 + End Method + + Method RotateLeft() + a:-2 + If a<0 + a:+359 + EndIf + End Method + + Method RotateRight() + a=(a+2) Mod 360 + End Method + + Method Thrust() + v.x:+Lookup.si[a]*0.1 + v.y:+Lookup.co[a]*-0.1 + If v.Length()>MASSSIZE + v.SetLength(MASSSIZE) + EndIf + End Method + + Method Reverse() + v.x:+Lookup.si[a]*-0.05 + v.y:+Lookup.co[a]*0.05 + If v.Length()>MASSSIZE + v.SetLength(MASSSIZE) + EndIf + End Method + + Method Draw() + SetColor(255,255,255) + SetRotation(a) + DrawImage(img,x,y) + SetRotation(0) + swallow=0 + End Method +End Type + + +Type TPoint Extends TGfxObject Global img:TImage - Field x:Double - Field y:Double Field lx:Double Field ly:Double Field v:TVector @@ -124,7 +275,7 @@ Type TPoint Local d:TVector=TVector.Create(o.x-x,o.y-y) Local l:Double=d.Length() - If l<MASSRAD + If l<o.rad If o.friend dead=True Else @@ -143,24 +294,39 @@ Type TPoint v.Add(d) - If d.Length()>MASSRAD - d.SetLength(MASSRAD) + If v.Length()>MASSRAD + v.SetLength(MASSRAD) EndIf EndIf Return dead End Method - Method Move() + Method Move(wrap:Int=False) If (Not dead) And (Not lost) lx=x ly=y x:+v.x y:+v.y - If x<0 Or y<0 Or x>GraphicsWidth() Or y>GraphicsHeight() - lost=True - TParticleMachine.AddLost(Self) + If wrap + If x<0 + x:+GraphicsWidth() + EndIf + If x>GraphicsWidth() + x:-GraphicsWidth() + EndIf + If y<0 + y:+GraphicsHeight() + EndIf + If y>GraphicsHeight() + y:-GraphicsHeight() + EndIf + Else + If x<0 Or y<0 Or x>GraphicsWidth() Or y>GraphicsHeight() + lost=True + TParticleMachine.AddLost(Self) + EndIf EndIf EndIf End Method @@ -176,6 +342,7 @@ End Type Type TParticle Global img:TImage + Field parent:TGfxObject Field x:Double Field y:Double Field a:Double @@ -228,6 +395,21 @@ Type TParticle Return o End Function + Function Angular:TParticle(x:Int, y:Int, a:Int, sp:Double, r:Int, g:Int, b:Int, al:Double, ali:Double, parent:TGfxObject) + Local o:TParticle=New TParticle + o.parent=parent + o.x=x + o.y=y + o.dx=sp*Lookup.si[a] + o.dy=sp*Lookup.co[a] + o.r=r + o.g=g + o.b=b + o.a=al + o.ai=ali + Return o + End Function + Method Update() x:+dx y:+dy @@ -236,7 +418,12 @@ Type TParticle If a>0 SetAlpha(a) SetColor(r,g,b) - DrawImage(img,x,y) + + If parent + DrawImage(img,parent.x+x,parent.y+y) + Else + DrawImage(img,x,y) + EndIf EndIf End Method End Type @@ -271,6 +458,15 @@ Type TParticleMachine Next End Function + Function AddShockwave(o:TGfxObject) + For Local a:Int=0 To 359 + list.AddLast(TParticle.Angular(0,0,a,1.0,255,255,0,1,-0.01,o)) + list.AddLast(TParticle.Angular(0,0,a,Rnd(0.8,1.2),255,0,0,1,-0.01,o)) + list.AddLast(TParticle.Angular(0,0,a,Rnd(0.8,1.2),255,0,0,1,-0.01,o)) + list.AddLast(TParticle.Angular(0,0,a,Rnd(0.8,1.2),255,0,0,1,-0.01,o)) + Next + End Function + Function Process() Local l:TLink=list.FirstLink() Local t:TLink |