summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cvsignore3
-rw-r--r--Default.ppinchbin1727 -> 423 bytes
-rw-r--r--GFX/SHIP.pngbin0 -> 282 bytes
-rw-r--r--GFX/SHOCK.pngbin0 -> 173 bytes
-rw-r--r--GFX/keys_button.pngbin0 -> 6969 bytes
-rw-r--r--GFX/sprites.bmsbin3237 -> 4018 bytes
-rw-r--r--designer.bmx204
-rw-r--r--game.bmx102
-rw-r--r--level.bmx57
-rw-r--r--main.bmx124
-rw-r--r--types.bmx228
11 files changed, 604 insertions, 114 deletions
diff --git a/.cvsignore b/.cvsignore
index 953a728..d33eae2 100644
--- a/.cvsignore
+++ b/.cvsignore
@@ -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
index ab2cd03..2e9ea26 100644
--- a/Default.ppinch
+++ b/Default.ppinch
Binary files differ
diff --git a/GFX/SHIP.png b/GFX/SHIP.png
new file mode 100644
index 0000000..ff9dd2b
--- /dev/null
+++ b/GFX/SHIP.png
Binary files differ
diff --git a/GFX/SHOCK.png b/GFX/SHOCK.png
new file mode 100644
index 0000000..3e8b94c
--- /dev/null
+++ b/GFX/SHOCK.png
Binary files differ
diff --git a/GFX/keys_button.png b/GFX/keys_button.png
new file mode 100644
index 0000000..f712071
--- /dev/null
+++ b/GFX/keys_button.png
Binary files differ
diff --git a/GFX/sprites.bms b/GFX/sprites.bms
index e142fef..1045023 100644
--- a/GFX/sprites.bms
+++ b/GFX/sprites.bms
Binary files differ
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
diff --git a/game.bmx b/game.bmx
index ff6ddfa..fb0ada3 100644
--- a/game.bmx
+++ b/game.bmx
@@ -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
diff --git a/level.bmx b/level.bmx
index 254ac5d..4b1c020 100644
--- a/level.bmx
+++ b/level.bmx
@@ -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
diff --git a/main.bmx b/main.bmx
index 07e1048..e44f596 100644
--- a/main.bmx
+++ b/main.bmx
@@ -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)
diff --git a/types.bmx b/types.bmx
index 31cc433..caf62ad 100644
--- a/types.bmx
+++ b/types.bmx
@@ -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