From 497670ace3bfaf6b28931ac12c4a0a8ee553bf55 Mon Sep 17 00:00:00 2001 From: Ian C Date: Tue, 27 Sep 2005 00:48:54 +0000 Subject: Designer pretty much complete. Some bug fixes to the game engine. --- Default.ppinch | Bin 60 -> 419 bytes designer.bmx | 291 +++++++++++++++++++++++++++++++++++++++++++++------------ game.bmx | 112 ++++++++++++++-------- level.bmx | 80 ++++++++++++---- main.bmx | 4 +- types.bmx | 21 +++-- 6 files changed, 384 insertions(+), 124 deletions(-) diff --git a/Default.ppinch b/Default.ppinch index 529588e..8ecbc3b 100644 Binary files a/Default.ppinch and b/Default.ppinch differ diff --git a/designer.bmx b/designer.bmx index a29a19e..9f7af86 100644 --- a/designer.bmx +++ b/designer.bmx @@ -31,7 +31,7 @@ Type TDesObj Abstract Method MouseOver:Int(x:Int, y:Int) Abstract Method Drag(x:Int, y:Int) Abstract Method Edit() Abstract - Method Save(l:TLevel) Abstract + Method Save(lev:TLevel) Abstract Method DrawSelBox(x:Int, y:Int) Local x1:Int=x-SELSIZE @@ -54,6 +54,10 @@ Type TDesObj Abstract Return px>=x1 And px<=x2 And py>=y1 And py<=y2 End Method + + Method DrawCoord(x:Int, y:Int) + GameGFX.guifont.Draw(x+","+y,0,0) + End Method End Type Type TDesGrav Extends TDesObj @@ -87,13 +91,12 @@ Type TDesGrav Extends TDesObj End Function Method Draw() + SetColor(255,255,255) If g.friendly - SetColor(0,255,0) + DrawImage(GameGFX.collector,g.x,g.y) Else - SetColor(255,0,0) + DrawImage(GameGFX.star,g.x,g.y) EndIf - - DrawOval(g.x-MASSRAD,g.y-MASSRAD,MASSSIZE,MASSSIZE) End Method Method DrawSelect() @@ -105,6 +108,7 @@ Type TDesGrav Extends TDesObj End Method Method Drag(x:Int, y:Int) + DrawCoord(x,y) g.x=x g.y=y End Method @@ -121,8 +125,8 @@ Type TDesGrav Extends TDesObj EndIf End Method - Method Save(l:TLevel) - l.grav.AddLast(g) + Method Save(lev:TLevel) + lev.grav.AddLast(g) End Method End Type @@ -166,26 +170,41 @@ Type TDesPoint Extends TDesObj no.l.gap=lp.gap no.l.v.x=lp.v.x no.l.v.y=lp.v.y + no.l.circle=lp.circle + no.l.circvel=lp.circvel Return no End Function Method Draw() - Local lp:TList=DoLine(l.x1,l.y1,l.x2,l.y2) - Local i:Int=0 + SetColor(255,128,128) + + If l.circle + DrawLine(l.x1,l.y1,l.x2,l.y1) + + Local p:TAlgoPoint[]=DoCircle(l.x1,l.y1,Abs(l.x2-l.x1)) + + For Local f:Int=0 To 359 + Local nf:Int=(f+1) Mod 360 + DrawLine(p[f].x,p[f].y,p[nf].x,p[nf].y) + Next + Else + Local lp:TList=DoLine(l.x1,l.y1,l.x2,l.y2) + + For Local p:TAlgoPoint=EachIn lp + Plot(p.x,p.y) + Next + EndIf - SetColor(0,255,0) - DrawLine(l.x1,l.y1,l.x1+l.v.x*10,l.y1+l.v.y*10) - DrawLine(l.x2,l.y2,l.x2+l.v.x*10,l.y2+l.v.y*10) + Local lp:TList=CreateList() - For Local p:TAlgoPoint=EachIn lp - If (i Mod l.gap)=0 - SetColor(255,255,255) - Else - SetColor(200,0,0) - EndIf - Plot(p.x,p.y) - i:+1 + l.CreatePoints(lp) + + For Local p:TPoint=EachIn lp + SetColor(0,255,0) + DrawLine(p.x,p.y,p.x+p.v.x*10,p.y+p.v.y*10) + SetColor(128,128,255) + DrawImage(GameGFX.point,p.x,p.y) Next End Method @@ -198,41 +217,75 @@ Type TDesPoint Extends TDesObj End Method Method MouseOver:Int(x:Int, y:Int) - If InSelBox(x,y,l.x1,l.y1) - over_p1=True - Return True - EndIf - If InSelBox(x,y,l.x2,l.y2) - over_p1=False - Return True + If l.circle + If InSelBox(x,y,l.x1,l.y1) + over_p1=True + Return True + EndIf + If InSelBox(x,y,l.x2,l.y1) + over_p1=False + Return True + EndIf + Else + If InSelBox(x,y,l.x1,l.y1) + over_p1=True + Return True + EndIf + If InSelBox(x,y,l.x2,l.y2) + over_p1=False + Return True + EndIf EndIf Return False End Method Method Drag(x:Int, y:Int) - If over_p1 - l.x1=x - l.y1=y + Local cx:Int=x + Local cy:Int=y + + If l.circle + If over_p1 + Local diff:Int=l.x2-l.x1 + l.x1=x + l.y1=y + l.x2=l.x1+diff + l.y2=l.y1 + Else + l.x2=x + l.y2=l.y1 + cy=l.y2 + EndIf Else - l.x2=x - l.y2=y + If over_p1 + l.x1=x + l.y1=y + Else + l.x2=x + l.y2=y + EndIf EndIf + + DrawCoord(cx,cy) End Method Method Edit() Designer.pd_gap.text = l.gap Designer.pd_vx.text = l.v.x Designer.pd_vy.text = l.v.y + Designer.pd_circle.checked = l.circle + Designer.pd_circvel.text = l.circvel If GUIDialog(Designer.pdialog,Designer.pd_ok,Designer.pd_cancel,GameGFX.pointer) - l.gap = Designer.pd_gap.text.ToInt() + l.gap = Max(1,Designer.pd_gap.text.ToInt()) l.v.x = Designer.pd_vx.text.ToFloat() l.v.y = Designer.pd_vy.text.ToFloat() + l.circle = Designer.pd_circle.checked + l.circvel = Designer.pd_circvel.text.ToFloat() EndIf End Method - Method Save(l:TLevel) - l.point.AddLast(l) + Method Save(lev:TLevel) + lev.point.AddLast(l) End Method End Type @@ -250,7 +303,6 @@ Type Designer Global levelset:TLevelSet Global level:TLevel - Global levelsetfname:String Global done:Int Global levelindex:Int @@ -259,6 +311,7 @@ Type Designer Global fname_txt:TText Global fname_load:TButton Global fname_save:TButton + Global fname_new:TButton Global setname_txt:TText @@ -266,7 +319,6 @@ Type Designer Global levadd_but:TButton Global levins_but:TButton Global levdel_but:TButton - Global levinv_check:TCheckbox Global levnum:TNumberInt Global hide_check:TCheckbox @@ -286,9 +338,21 @@ Type Designer Global pd_gap:TText Global pd_vx:TText Global pd_vy:TText + Global pd_circle:TCheckbox + Global pd_circvel:TText Global pd_ok:TButton Global pd_cancel:TButton + Global ldialog:TGUIHandler + Global ld_invert:TCheckbox + Global ld_placefriend:TCheckbox + Global ld_maxmass:TText + Global ld_winpercent:TText + Global ld_timer:TText + Global ld_placemass:TText + Global ld_ok:TButton + Global ld_cancel:TButton + Function Initialise() If Not init Local l:TLabel @@ -300,15 +364,15 @@ Type Designer levelset = New TLevelSet level = New TLevel - levelsetfname = "Default.ppinch" levelindex = 0 gui = TGUIHandler.Create() TLabel.Create(gui,0,0,"File") - fname_txt = TText.Create(gui,TEXTX,0,"",32) + fname_txt = TText.Create(gui,TEXTX,0,"Default.ppinch",32) fname_load = TButton.Create(gui,fname_txt.x+fname_txt.w+10,0,50,12,"Load",LoadCallback) fname_save = TButton.Create(gui,fname_load.x+fname_load.w+10,0,50,fname_load.h,"Save",SaveCallback) + fname_new = TButton.Create(gui,fname_save.x+fname_save.w+10,0,50,fname_load.h,"New",NewCallback) TLabel.Create(gui,0,10,"Levelset name") setname_txt = TText.Create(gui,TEXTX,10,"",32) @@ -319,10 +383,10 @@ Type Designer levins_but = TButton.Create(gui,levadd_but.x+levadd_but.w+10,levname_txt.y,50,12,"Insert",InsertLevelCallback) levdel_but = TButton.Create(gui,levins_but.x+levins_but.w+10,levname_txt.y,50,12,"Delete",DeleteLevelCallback) - levinv_check = TCheckbox.Create(gui,0,35,"Invert placed masses",InvertPlacedCallback) - l = TLabel.Create(gui,levinv_check.w+50,35,"Level:") + l = TLabel.Create(gui,0,35,"Level:") levnum = TNumberInt.Create(gui,l.x+l.w+10,35,LevelNumberCallback) levnum.value = 0 + levnum.change = 1 levnum.minval = 0 levnum.maxval = 0 @@ -342,24 +406,84 @@ Type Designer md_cancel = TButton.Create(mdialog,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,100) + p = TPanel.Create(pdialog,-1,-1,400,200) l = TLabel.Create(pdialog,p.x+5,p.y+10,"Gap per point:") - pd_gap = TText.Create(pdialog,p.x+90,p.y+10,"",30,TText.NUMERIC|TText.INTEGER|TText.POSITIVE) + pd_gap = TText.Create(pdialog,l.x+l.w+10,l.y,"",30,TText.NUMERIC|TText.INTEGER|TText.POSITIVE) l = TLabel.Create(pdialog,p.x+5,p.y+30,"Initial dx:") + pd_vx = TText.Create(pdialog,l.x+l.w+10,l.y,"",30,TText.NUMERIC) l = TLabel.Create(pdialog,p.x+5,p.y+50,"Initial dy:") - pd_vx = TText.Create(pdialog,p.x+90,p.y+30,"",30,TText.NUMERIC) - pd_vy = TText.Create(pdialog,p.x+90,p.y+50,"",30,TText.NUMERIC) + pd_vy = TText.Create(pdialog,l.x+l.w+10,l.y,"",30,TText.NUMERIC) + pd_circle = TCheckbox.Create(pdialog,p.x+5,p.y+70,"Circle?") + l = TLabel.Create(pdialog,p.x+5,p.y+90,"Circular velocity:") + pd_circvel = TText.Create(pdialog,l.x+l.w+10,l.y,"",30,TText.NUMERIC) pd_ok = TButton.Create(pdialog,p.x+5,p.y+p.h-25,p.w/2-10,20,"OK",Null) pd_cancel = TButton.Create(pdialog,p.x+p.w/2+5,p.y+p.h-25,p.w/2-10,20,"Cancel",Null) + 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) + 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) + 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) + levelset.level.AddLast(level) init=True EndIf done = False - fname_txt.text = levelsetfname + LoadLevel() + End Function + + Function LoadLevel() setname_txt.text = levelset.name + level = TLevel(ListAt(levelset.level,levelindex).Value()) levname_txt.text = level.name + + obj.Clear() + + For Local o:Object=EachIn level.grav + obj.AddLast(TDesGrav.CreateFromLevel(o)) + Next + + For Local o:Object=EachIn level.point + obj.AddLast(TDesPoint.CreateFromLevel(o)) + Next + End Function + + Function SaveLevel() + levelset.name = setname_txt.text + level.name = levname_txt.text + level.grav.Clear() + level.point.Clear() + For Local o:TDesObj=EachIn obj + o.Save(level) + Next + End Function + + Function EditLevelSettings() + ld_invert.checked = level.invmass + ld_placefriend.checked = level.placefriend + ld_maxmass.text = level.maxmass + ld_winpercent.text = level.winpercent + ld_timer.text = level.timer + ld_placemass.text = level.placemass + + 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.winpercent = Max(0,Min(100,ld_winpercent.text.ToInt())) + level.timer = ld_timer.text.ToInt() + level.placemass = ld_placemass.text.ToFloat() + EndIf End Function End Type @@ -413,11 +537,13 @@ Function DoDesigner() Designer.obj.Remove(sel) End Select Else - Select GUIMenu("Create Menu",["Create Gravity Point","Create Particle Line"],x,y,GameGFX.pointer) + Select GUIMenu("Create Menu",["Create Gravity Point","Create Particle Line","Edit Level Settings"],x,y,GameGFX.pointer) Case 0 Designer.obj.AddLast(TDesGrav.Create(x,y)) Case 1 Designer.obj.AddLast(TDesPoint.Create(x,y)) + Case 2 + Designer.EditLevelSettings() End Select EndIf sel=Null @@ -444,10 +570,15 @@ End Function ' **** Utils ' -Function LoadLevel() -End Function - -Function SaveLevel() +Function ListAt:TLink(l:TList, i:Int) + Local tl:TLink=l.FirstLink() + + While i>0 And tl<>Null + i:-1 + tl=tl.NextLink() + Wend + + Return tl End Function ' **** Callbacks @@ -463,6 +594,19 @@ Function QuitCallback(w:TWidget) End Function Function TestCallback(w:TWidget) + Designer.SaveLevel() + Local g:TGame=TGame.Create(Designer.level) + + While Not KeyHit(KEY_ESCAPE) + Cls + g.Play() + SetColor(255,255,255) + DrawImage(GameGFX.pointer,MouseX(),MouseY()) + FlushMem + Flip + Wend + + FlushKeys() End Function Function CheckCallback(w:TWidget) @@ -470,35 +614,56 @@ End Function Function LoadCallback(w:TWidget) Try - Local load:TLevelSet=TLevelSet.Load(Designer.fname_txt.text) - Designer.levelset=load + If GUIYesNo("Overwrite current level set?",GameGFX.pointer) + Local load:TLevelSet=TLevelSet.Load(Designer.fname_txt.text) + Designer.levelset=load + Designer.levelindex=0 + Designer.levnum.maxval=Designer.levelset.level.Count()-1 + Designer.LoadLevel() + EndIf Catch e:TLevelException GUINotify("Failed to load '" + Designer.fname_txt.text + "'||"+e.message,GameGFX.pointer) EndTry End Function Function SaveCallback(w:TWidget) + Designer.SaveLevel() If Not Designer.levelset.Save(Designer.fname_txt.text) GUINotify("Failed to save '" + Designer.fname_txt.text + "'",GameGFX.pointer) + Else + GUINotify("'" + Designer.fname_txt.text + "' saved OK",GameGFX.pointer) EndIf End Function -Function InvertPlacedCallback(w:TWidget) - Local c:TCheckbox=TCheckbox(w) - Designer.level.invmass=c.checked +Function NewCallback(w:TWidget) + If GUIYesNo("Lose current level set?",GameGFX.pointer) + Designer.levelindex=0 + Designer.levnum.maxval=0 + Designer.levelset=New TLevelSet + Designer.levelset.level.AddLast(New TLevel) + Designer.fname_txt.text="Untitled.ppinch" + Designer.LoadLevel() + EndIf End Function Function LevelNumberCallback(w:TWidget) Local c:TNumberInt=TNumberInt(w) - SaveLevel() + Designer.SaveLevel() Designer.levelindex=c.value - LoadLevel() + Designer.LoadLevel() End Function Function AddLevelCallback(w:TWidget) + Designer.levelset.level.AddLast(New TLevel) + Designer.levnum.maxval=Designer.levelset.level.Count()-1 End Function Function InsertLevelCallback(w:TWidget) + Designer.SaveLevel() + Local l:TLink=ListAt(Designer.levelset.level,Designer.levelindex) + Designer.levelset.level.InsertBeforeLink(New TLevel,l) + Designer.levnum.maxval=Designer.levelset.level.Count()-1 + Designer.LoadLevel() End Function Function DeleteLevelCallback(w:TWidget) @@ -507,6 +672,14 @@ Function DeleteLevelCallback(w:TWidget) Return EndIf - If GUIYesNo("Delete this level:|"+Designer.levname_txt.text,GameGFX.pointer) + If GUIYesNo("Delete this level?||"+Designer.levname_txt.text,GameGFX.pointer) + ListAt(Designer.levelset.level,Designer.levelindex).Remove() + + If Designer.levelindex>=Designer.levelset.level.Count() + Designer.levelindex:-1 + Designer.levnum.value=Designer.levelindex + EndIf + Designer.levnum.maxval=Designer.levelset.level.Count()-1 + Designer.LoadLevel() EndIf End Function \ No newline at end of file diff --git a/game.bmx b/game.bmx index cc5a8b9..8c66ef8 100644 --- a/game.bmx +++ b/game.bmx @@ -10,12 +10,12 @@ Import noddybox.bitmapfont Import "types.bmx" Import "level.bmx" -Const LEVEL_NOTOVER:Int= 0 -Const LEVEL_WON:Int= 1 -Const LEVEL_LOST:Int= 2 - Type TGame + Const LEVEL_NOTOVER:Int= 0 + Const LEVEL_WON:Int= 1 + Const LEVEL_LOST:Int= 2 + Field level:TLevel Field mass:TList Field point:TList @@ -31,6 +31,8 @@ Type TGame Field col:Int Field coli:Int + Field final_percent:Int + Function Create:TGame(level:TLevel) Local o:TGame=New TGame @@ -43,19 +45,21 @@ Type TGame o.done=LEVEL_NOTOVER o.frame=0 o.placed=0 - o.txtoff=[GameGFX.font.TextWidth("PARTICLES"),GameGFX.font.TextWidth("CAPTURED"),GameGFX.font.TextWidth("LOST"),GameGFX.font.TextWidth("TIMER")] + o.txtoff=[GameGFX.font.TextWidth("PARTICLES"),GameGFX.font.TextWidth("CAPTURED"),GameGFX.font.TextWidth("TIMER")] o.playing=False o.col=0 - o.coli=1 + o.coli=5 + o.final_percent=0 Return o End Function Method Intro() Local y:Int=GraphicsHeight()/4 Local yi:Int=25 + col:+coli - If col=255 Or col=128 + If col=255 Or col=0 coli=-coli EndIf @@ -64,55 +68,84 @@ Type TGame GameGFX.font.CentreColoured(level.name,y,col,col,255-col) y:+yi - GameGFX.font.CentreColoured("Need "+level.winpercent+"% to clear",GraphicsHeight()/2,col/2,col,col) + GameGFX.font.CentreColoured("Need "+level.winpercent+"% to clear",y,col/2,col,col) y:+yi - GameGFX.font.CentreColoured("You can place "+level.maxmass+" masses",GraphicsHeight()/2,col/2,col,col) + GameGFX.font.CentreColoured("You can place "+level.maxmass+" masses",y,col/2,col,col) y:+yi - If level.invmass + If level.invmass GameGFX.font.CentreColoured("PLACED MASSES ARE INVERTED!",y,col,col/2,col/2) y:+yi EndIf + If level.placefriend + GameGFX.font.CentreColoured("PLACED MASSES ARE COLLECTORS!",y,col,col/2,col/2) + y:+yi + EndIf + + y:+yi + GameGFX.font.Centre("Press Left Mouse Button",y) + y:+yi + SetScale(1,1) End Method Method Play:Int() captured=0 lost=0 - - For Local m:TMass=EachIn mass - For Local s:TPoint=EachIn point - s.Attract(m) + + If playing + For Local m:TMass=EachIn mass + For Local s:TPoint=EachIn point + s.Attract(m) + Next Next - Next + EndIf TParticleMachine.Process() - For Local m:TMass=EachIn mass - m.MoveAndDraw() - Next + If playing + For Local m:TMass=EachIn mass + m.Move() + m.Draw() + Next + Else + For Local m:TMass=EachIn mass + m.Draw() + Next + EndIf + + If playing + For Local s:TPoint=EachIn point + s.Move() + s.Draw() + + If s.dead + captured:+1 + ElseIf s.lost + lost:+1 + EndIf + Next + Else + For Local s:TPoint=EachIn point + s.Draw() + Next + EndIf - For Local s:TPoint=EachIn point - s.MoveAndDraw() + If playing And done=LEVEL_NOTOVER + frame:+1 - If s.dead - captured:+1 - ElseIf s.lost - lost:+1 + If frame=60 And timer>0 + frame=0 + timer:-1 EndIf - Next - - frame:+1 - - If frame=60 And timer>0 - timer:-1 EndIf Local percent:Int=Int(Float(captured)/Float(num)*100.0) - If (timer=0 Or num=0) And done=LEVEL_NOTOVER + If (timer=0 Or num=captured+lost) And done=LEVEL_NOTOVER + final_percent=percent If percent>=level.winpercent done=LEVEL_WON Else @@ -122,17 +155,20 @@ Type TGame GameGFX.font.Draw("PARTICLES",0,0) GameGFX.font.DrawColoured(num-captured-lost,txtoff[0]+10,0,255,255,0) + GameGFX.font.Draw("CAPTURED",200,0) - GameGFX.font.DrawColoured(percent+"%",txtoff[1]+210,0,255,0,255) - GameGFX.font.Draw("LOST",400,0) - GameGFX.font.DrawColoured((100-percent)+"%",txtoff[2]+410,0,255,0,0) + If done=LEVEL_NOTOVER + GameGFX.font.DrawColoured(percent+"%",txtoff[1]+210,0,255,0,255) + Else + GameGFX.font.DrawColoured(final_percent+"%",txtoff[1]+210,0,255,0,255) + EndIf GameGFX.font.Draw("TIMER",600,0) If timer>10 - GameGFX.font.Draw(timer,txtoff[3]+610,0) + GameGFX.font.Draw(timer,txtoff[2]+610,0) Else - GameGFX.font.DrawColoured(timer,txtoff[3]+610,0,255,0,0) + GameGFX.font.DrawColoured(timer,txtoff[2]+610,0,255,0,0) EndIf Select done @@ -141,12 +177,14 @@ Type TGame If placedMASSSIZE - d.SetLength(MASSSIZE) + If d.Length()>MASSRAD + d.SetLength(MASSRAD) EndIf EndIf Return dead End Method - Method MoveAndDraw() + Method Move() If (Not dead) And (Not lost) lx=x ly=y x:+v.x y:+v.y - SetColor(r,g,b) - DrawImage(img,x,y,0) - If x<0 Or y<0 Or x>GraphicsWidth() Or y>GraphicsHeight() lost=True TParticleMachine.AddLost(Self) EndIf EndIf End Method + + Method Draw() + If (Not dead) And (Not lost) + SetColor(r,g,b) + DrawImage(img,x,y,0) + EndIf + End Method End Type -- cgit v1.2.3