#Import "PoolMod/PoolMod" Function Main() New AppInstance New Game App.Run() End Class Game Extends Window Field state:Int=0 Field fontImg:Image[] Field frame1:FrameAnimation Field frame2:FrameAnimation Field pvcBtn:Button2 Field pvpBtn:Button2 Field soloBtn:Button2 Field scores:Button2 Field pool8:Pool Field poolSolo:Pool Field alpha:Float=.0 Field started:Int=0 Field down:Int=0 Field pool:Pool Method New(title:String="Simple mojo app",width:Int=640,height:Int=480,flags:WindowFlags=Null) Super.New( title,width,height,flags ) state=1 atlasImg=Image.Load("asset::poolAtlasb.png") If atlasImg = Null RuntimeError("Unable to load poolatlasb.png") media=New Media(atlasImg) LargeText=New VaryFont(atlasImg) fontImg=LoadFrames(atlasImg,0,512,10,16,96) If Not fontImg RuntimeError("Unable to load fontImg.png") SetFont(fontImg,32) Text=New BitmapText(fontImg,77) frame1=New FrameAnimation(media,50,50,DEVICE_WIDTH-100,DEVICE_HEIGHT-100,2,40) frame2=New FrameAnimation(media,50,20,DEVICE_WIDTH-100,DEVICE_HEIGHT-40,0,40) Local buttonImg:Image[]=media.buttonImg pvcBtn=New Button2(buttonImg,(DEVICE_WIDTH-buttonImg[0].Width)/2,120,"VS Computer",Null) pvpBtn=New Button2(buttonImg,(DEVICE_WIDTH-buttonImg[0].Width)/2,200,"VS Player",Null) soloBtn=New Button2(buttonImg,(DEVICE_WIDTH-buttonImg[0].Width)/2,280,"VS Time",Null) scores=New Button2(buttonImg,(DEVICE_WIDTH-buttonImg[0].Width)/2,360,"Scores",Null) inputName=New TextFieldGui(150,150,"Player 1",Null,200) pool8= New EightBall() poolSolo= New PoolSoloTime() scoreTableVsTime= New ScoreTable("scoreTable.dat") alpha=0.0 started=1 frame1.Init() End Method OnUpdate:Int() If Mouse.ButtonDown(MouseButton.Left) Self.down=1 If state=1 If(Mouse.ButtonDown(MouseButton.Left)=0 And down=1) frame2.Init() alpha=0 down=0 state=2 End ElseIf state=2 pvcBtn.Update() pvpBtn.Update() soloBtn.Update() scores.Update() If True = pvcBtn.GetState() pool=pool8 pool.SetupPVC() state=6 pool.Reset() Elseif True = pvpBtn.GetState() pool = pool8 pool.SetupPVP() state = 6 pool.Reset() Elseif True = soloBtn.GetState() pool = poolSolo pool.SetupTimed() state=6 pool.InitGame() Elseif True = scores.GetState() state=7 scoreTableVsTime.InitFrame() End ElseIf(state=6) If pool.Update()=0 Self.state=7 Local record:Record=Self.pool.GetRecord() scoreTableVsTime.SetRecord(record) scoreTableVsTime.SaveTable() scoreTableVsTime.InitFrame() End ElseIf state=7 If scoreTableVsTime.Update()=False Self.frame2.Init() Self.alpha=0 Self.down=0 Self.state=2 End Elseif(state=4) End Return 1 End Method OnRender(canvas:Canvas) Override OnUpdate() App.RequestRender() canvas.Color = New Color(1,1,1) canvas.DrawImage(media.titleImg,0.0,0.0) If(state=1) Self.frame1.Render(canvas) If(started=1) canvas.Color = New Color(1,1,1) canvas.DrawImage(media.titleImg,0.0,0.0) Self.started=0 Else If Self.frame1.Update()=0 canvas.DrawImage(media.logoImg,180.0,60.0) Local str:String="HEXOBOT" Local x:Int=(DEVICE_WIDTH-LargeText.TextWidth(str))/2 Local y:Int=340 If(Self.alpha<1.0) canvas.Alpha = alpha Self.alpha+=.02 End str="Touch To Continue" canvas.Color = New Color(1,1,1) x= (DEVICE_WIDTH-Text.Width(str))/2 y=DEVICE_HEIGHT-80 Text.Draw(canvas,str,x,y) End End canvas.Alpha = 1.0 ElseIf(state=2) Self.frame2.Render(canvas) If(Self.frame2.Update()=0) canvas.DrawImage(media.logoImg,180.0,60.0,0) If(Self.alpha<1.0) canvas.Alpha = alpha alpha+=0.02 End pvcBtn.Render(canvas) pvpBtn.Render(canvas) soloBtn.Render(canvas) scores.Render(canvas) End canvas.Alpha = 1.0 Elseif(state=6) Self.pool.Render(canvas) Elseif(state=7) scoreTableVsTime.Render(canvas) End End End Global atlasImg:Image Global inputName:TextFieldGui Class Pool Field engine:ElasticEngine Field ballList:List Field arcList:List Field pottedList:List Field turnList:List Field tableImg:Image Field arrowsImg:Image Field ballImg:Image Field railAnimation:RailAnimation Field Exiting:Int=0 Field player:Record Field state:Int=0 Field cue:Ball Field activePlayer:User Field otherPlayer:User Field incrementer:Int=0 Field scoreLevel:Int=1 Field maxLevel:Int=15 Field decrementer:Int=0 Field user:User Field minLevel:Int Method Setup16() For Local a:ArcWall = Eachin arcList Select a.num Case 1 a.SetTarget(a.P.x+16.0,a.P.y+16.0) Case 2 a.SetTarget(a.P.x,a.P.y+15.0) Case 3 a.SetTarget(a.P.x-16.0,a.P.y+16.0) Case 4 a.SetTarget(a.P.x-16.0,a.P.y-16.0) Case 5 a.SetTarget(a.P.x,a.P.y-15.0) Case 6 a.SetTarget(a.P.x+16.0,a.P.y-16.0) End Select Next Self.engine.Add3DBall(180.8,180.0,10.0,0.0,0.0,media.ballImg,new Color(1,1,.1),new Color(.6,.2,.6),1,0) Self.engine.Add3DBall(162.6,170.0,10.0,0.0,0.0,media.ballImg,new Color(.3,.3,1),new Color(1,1,0),2,0) Self.engine.Add3DBall(162.6,190.0,10.0,0.0,0.0,media.ballImg,new Color(1,.25,.25),new Color(1,1,0),3,0) Self.engine.Add3DBall(144.4,160.0,10.0,0.0,0.0,media.ballImg,new Color(.35,.2,1),new Color(1,1,0),4,0) Self.engine.Add3DBall(144.4,200.0,10.0,0.0,0.0,media.ballImg,new Color(1,.35,.12),new Color(0,1,1),5,0) Self.engine.Add3DBall(126.2,150.0,10.0,0.0,0.0,media.ballImg,new Color(.12,.8,.12),New Color(0,0,1),6,0) Self.engine.Add3DBall(126.2,170.0,10.0,0.0,0.0,media.ballImg,new Color(.8,.1,.1),new Color(.9,.9,.9),7,0) Self.engine.Add3DBall(144.4,180.0,10.0,0.0,0.0,media.ballImg,new Color(.35,.35,.35),new Color(.93,.93,.93),8,0) Self.engine.Add3DBall(126.2,190.0,10.0,0.0,0.0,media.ballImg,new Color(1,1,.1),new Color(.6,.2,.6),9,0) Self.engine.Add3DBall(126.2,210.0,10.0,0.0,0.0,media.ballImg,new Color(.3,.3,1),new Color(1,1,0),10,0) Self.engine.Add3DBall(108.0,140.0,10.0,0.0,0.0,media.ballImg,new Color(1,.25,.25),new Color(1,1,0),11,0) Self.engine.Add3DBall(108.0,160.0,10.0,0.0,0.0,media.ballImg,new Color(.35,.2,1),new Color(1,1,0),12,0) Self.engine.Add3DBall(108.0,180.0,10.0,0.0,0.0,media.ballImg,new Color(1,.35,.12),new Color(0,1,1),13,0) Self.engine.Add3DBall(108.0,200.0,10.0,0.0,0.0,media.ballImg,new Color(.12,.8,.12),New Color(0,0,1),14,0) Self.engine.Add3DBall(108.0,220.0,10.0,0.0,0.0,media.ballImg,new Color(.8,.1,.1),new Color(.9,.9,.9),15,0) Self.cue=Self.engine.Add3DBall(490.0,180.0,10.0,-15.0,0.05,media.ballImg,new Color(1,1,1),new Color(.6,.2,.6),16,0) End Method SetupPVC() Abstract Method Reset() Abstract Method SetupPVP() Abstract Method SetupTimed() Abstract Method InitGame() Abstract Method Update:Int() Abstract Method GetRecord:Record() Return Self.player End Method Render(canvas:Canvas) Abstract Method BallInHole() For Local a:ArcWall = Eachin arcList For Local b:Ball = Eachin ballList If(a.BallInside(b)) engine.RemoveBall(b) pottedList.AddLast(b) turnList.AddLast(b) railAnimation.AddJob(b) media.PlayPocketCol() If(b.num<16) incrementer+=5000 player.score+=scoreLevel*100 scoreLevel+=1 If scoreLevel>maxLevel scoreLevel=maxLevel player.IncrementPocketed() Else decrementer += 30000 media.PlayScratch() End End End End End Method ListContains:Bool(list:List,num:Int) For Local b2:Ball = Eachin list If(b2.num=num) Return True End End Return False End Method ListContains:Bool(list:List,b:Ball) For Local b2:Ball = Eachin list If(b2=b) Return True Next Return False End Method RestoreCue() Virtual state=9 cue.Init(0,0) cue.SetPosition(490,180) turnList.RemoveEach(cue) pottedList.RemoveEach(cue) railAnimation.RemoveCueBall() engine.AddBall(cue) End Method ListContainsSolids:Bool(list:List) For Local b:Ball = Eachin list If(b.num<8) Return True End Return False End Method ListContainsStripes:Bool(list:List) For Local b:Ball = Eachin list If(b.num>8 And b.num<16) Return True End Return False End End Class EightBall Extends Pool Field inacuracy:Float Field timeFrame:Float Field lastTime:Float Field down:Int=0 Field finalText1:String="" Field finalText2:String="" Method Init() Self.Exiting=1 End Method New() inacuracy=0.4 engine=New ElasticEngine() engine.SetGravity(0.0,0.0) engine.SetFriction(0.98) ballList=Self.engine.ballList arcList=New List pottedList= New List turnList=New List tableStorage= New TableStorage() tableStorage.GetTable(0,Self.engine,Self.arcList) tableImg=media.tableImg arrowsImg=media.arrowsImg ballImg=media.ballImg railAnimation=New RailAnimation() railAnimation.ShowStops(0) Init() player=New Record() state=1 Setup16() lastTime = Millisecs() End Method SetupTimed() Override RuntimeError("invald attemp to create 8ball pool timed") End Method SetupPVC() Override Self.activePlayer= New Player("Player 1",cue,engine,media.ghostImg,media.ballImg,media.stickImg,media.rotatorImg,media.buttonImg,media.stripImg,media.frameTopImg,media.frameBotImg,media.topImg,media.botImg,media.lrImg,media.meterImg,media.stretchImg,media.sliderImg) Self.otherPlayer= New Cpu("Cpu",cue,engine,arcList,media.stickImg,media.ballImg,inacuracy) End Method SetupPVP() Override Self.activePlayer=New Player("Player 1",cue,engine,media.ghostImg,media.ballImg,media.stickImg,media.rotatorImg,media.buttonImg,media.stripImg,media.frameTopImg,media.frameBotImg,media.topImg,media.botImg,media.lrImg,media.meterImg,media.stretchImg,media.sliderImg) Self.otherPlayer=New Player("Player 2",cue,engine,media.ghostImg,media.ballImg,media.stickImg,media.rotatorImg,media.buttonImg,media.stripImg,media.frameTopImg,media.frameBotImg,media.topImg,media.botImg,media.lrImg,media.meterImg,media.stretchImg,media.sliderImg) End Method InitGame() Override End Method Reset() Override For Local b:Ball= Eachin Self.pottedList Self.engine.AddBall(b) Self.pottedList.RemoveEach(b) End Self.turnList.Clear() Self.railAnimation.Reset() For Local b2:Ball = Eachin Self.ballList b2.Init(0.0,0.0) If(b2.num=1) b2.SetPosition(180.8,180.0) ElseIf(b2.num=2) b2.SetPosition(162.6,170.0) ElseIf(b2.num=3) b2.SetPosition(162.6,190.0) ElseIf(b2.num=4) b2.SetPosition(144.4,160.0) ElseIf(b2.num=5) b2.SetPosition(144.4,200.0) ElseIf(b2.num=6) b2.SetPosition(126.2,150.0) ElseIf(b2.num=7) b2.SetPosition(126.2,170.0) ElseIf(b2.num=8) b2.SetPosition(144.4,180.0) ElseIf(b2.num=9) b2.SetPosition(126.2,190.0) ElseIf(b2.num=10) b2.SetPosition(126.2,210.0) ElseIf(b2.num=11) b2.SetPosition(108.0,140.0) ElseIf(b2.num=12) b2.SetPosition(108.0,160.0) ElseIf(b2.num=13) b2.SetPosition(108.0,180.0) ElseIf(b2.num=14) b2.SetPosition(108.0,200.0) ElseIf(b2.num=15) b2.SetPosition(108.0,220.0) ElseIf(b2.num=16) b2.SetPosition(490.0,180.0) End b2.ResetAnimation() Next Self.state=2 Self.Exiting=1 Self.down=False End Method AssignBalls() For Local b:Ball = Eachin Self.turnList If(Self.activePlayer.OwnsSolids()) If(b.num<=8) Self.activePlayer.AddBall(b) Else If(b.num>8) Self.otherPlayer.AddBall(b) End End Else If(Self.activePlayer.OwnsStripes()) If(b.num>=8) Self.activePlayer.AddBall(b) Else Self.otherPlayer.AddBall(b) End Else If(b.num<8) Self.activePlayer.SetToSolids() Self.otherPlayer.SetToStripes() Self.activePlayer.AddBall(b) Else If(b.num>8) Self.activePlayer.SetToStripes() Self.otherPlayer.SetToSolids() Self.activePlayer.AddBall(b) Else Self.activePlayer.AddBall(b) End End End End End End Method ResolveTurn() If Self.turnList.Empty Self.Exiting=0 Self.state=10 Return End Self.state=3 If(Self.Exiting=1) For Local b:Ball = Eachin turnList If(b.num<8) activePlayer.SetToSolids() otherPlayer.SetToStripes() Exit End If(b.num>8 And b.num<16) activePlayer.SetToStripes() otherPlayer.SetToSolids() Exit End End If ListContains(turnList,cue) state=9 If ListContains(turnList,8) state=7 Else RestoreCue() End Else If(ListContains(Self.turnList,8)) state=6 End End For Local b2:Ball = Eachin turnList If(activePlayer.OwnsSolids()) If b2.num<=8 activePlayer.AddBall(b2) Elseif b2.num>8 And b2.num<16 otherPlayer.AddBall(b2) Else RestoreCue() End Else If activePlayer.OwnsStripes() If b2.num>=8 And b2.num<16 activePlayer.AddBall(b2) Elseif b2.num<8 otherPlayer.AddBall(b2) Else RestoreCue() End ElseIf b2.num=8 activePlayer.AddBall(b2) End End End Self.Exiting=0 Else Local b3:Ball=engine.GetFirstCollision() If activePlayer.CompletedSet()=True If ListContains(turnList,8) state=6 If ListContains(turnList,cue) state=7 If activePlayer.OwnsSolids() If b3.num>8 And b3.num<16 state=7 Else If b3.num<8 Self.state=7 End Else If ListContains(turnList,cue) state=7 Else state=10 End End Else If b3<>Null If b3.num<8 And activePlayer.OwnsStripes() state=10 If b3.num>8 And b3.num<16 And activePlayer.OwnsSolids() state=10 End If activePlayer.OwnsSolids() If ListContainsSolids(turnList)=False state=10 Else If activePlayer.OwnsStripes() If ListContainsStripes(turnList)=False state=10 End End If ListContains(turnList,cue) RestoreCue() If ListContains(turnList,8) state=7 Self.AssignBalls() End End Self.turnList.Clear() Return End Method SwitchPlayers() Self.user=activePlayer Self.activePlayer=otherPlayer Self.otherPlayer=user End Method Update:Int() Override Local SelfTime:Float = Millisecs() timeFrame=(SelfTime-lastTime)/30.0 lastTime=SelfTime Local done:Int=0 If state=1 state=2 activePlayer.SetButtonText("position") activePlayer.Init() ElseIf state=2 If Not activePlayer.Positioning() state=3 activePlayer.SetButtonText("Shoot") activePlayer.Init() End ElseIf state=3 If Not activePlayer.Aiming() state=4 End ElseIf state=4 If Not activePlayer.ShootingAnimating() lastTime=(Millisecs()) state=5 End ElseIf state=5 engine.Update(timeFrame) BallInHole() If Not engine.BallsMoving() ResolveTurn() engine.ClearFirstCollision() activePlayer.Init() End ElseIf state=10 SwitchPlayers() activePlayer.Init() state=3 ElseIf state=9 SwitchPlayers() activePlayer.SetButtonText("position") activePlayer.Init() state=2 ElseIf state=6 finalText1=activePlayer.name+" WINS GAME" finalText2=otherPlayer.name+" LOST GAME" state=8 ElseIf state=7 finalText1=otherPlayer.name+" WINS GAME" finalText2=activePlayer.name+" LOST GAME" state=8 ElseIf state=8 If Mouse.ButtonDown(MouseButton.Left) down=1 If Not Mouse.ButtonDown(MouseButton.Left) And down=1 done=1 Endif railAnimation.Update(timeFrame*2.0) Return Not done End Method Method Render(canvas:Canvas) Override canvas.DrawImage(media.railImg,5.0,360.0,0) Self.railAnimation.Render(canvas) canvas.Color = New Color(1,1,1) canvas.DrawImage(Self.tableImg,0.0,0.0,0) Self.engine.Render(canvas) canvas.Color = New Color(1,1,1) If(state=2) canvas.Alpha = .2 canvas.DrawRect(466.0,37.0,140.0,288.0) canvas.Alpha = .3 canvas.DrawImage(arrowsImg,cue.P.x,cue.P.y,0) canvas.Alpha = 1.0 activePlayer.RenderButton(canvas) Elseif state=4 Or state=3 activePlayer.Render(canvas,1) ElseIf state=8 Text.Draw(canvas,finalText1,200,100) Text.Draw(canvas,finalText2,200,150) End Local x:Float=25.0 canvas.Color = New Color(1,1,1) End End Class TableStorage Field currentTable:Int=0 Method New() Self.currentTable=-1 End Field table:Table Method GetTable:Table(index:Int,engine:ElasticEngine,arcList:List) If currentTable=index Return Self.table Else If(index<1 And index>-1) If index = 0 engine.RemoveWalls() Local wall:Wall[]=New Wall[](New Arc(28.0,28.0,17.0,135.0,315.0,0.0,0.0,media.arcImg,New Color(1,0,0)), New Line(41.0,17.0,58.0,34.0,media.lineImg,new Color(1,0,0)), New Line(59.0,34.0,296.0,34.0,media.lineImg,new Color(1,0,0)), New Line(296.0,33.0,303.0,25.0,media.lineImg,new Color(1,0,0)), New Line(303.0,24.0,303.0,19.0,media.lineImg,new Color(1,0,0)), New Arc(320.0,18.0,17.0,180.0,360.0,0.0,0.0,media.arcImg,new Color(1,0,0)), New Line(338.0,19.0,338.0,24.0,media.lineImg,new Color(1,0,0)), New Line(337.0,25.0,345.0,33.0,media.lineImg,new Color(1,0,0)), New Line(345.0,34.0,582.0,34.0,media.lineImg,new Color(1,0,0)), New Line(583.0,33.0,599.0,17.0,media.lineImg,new Color(1,0,0)), New Arc(612.0,28.0,17.0,225.0,405.0,0.0,0.0,media.arcImg,new Color(1,0,0)), New Line(624.0,41.0,609.0,57.0,media.lineImg,new Color(1,0,0)), New Line(608.0,57.0,608.0,304.0,media.lineImg,new Color(1,0,0)), New Line(609.0,305.0,624.0,320.0,media.lineImg,new Color(1,0,0)), New Arc(613.0,333.0,17.0,-45.0,135.0,0.0,0.0,media.arcImg,new Color(1,0,0)), New Line(599.0,344.0,584.0,328.0,media.lineImg,new Color(1,0,0)), New Line(584.0,327.0,345.0,327.0,media.lineImg,new Color(1,0,0)), New Line(344.0,328.0,338.0,335.0,media.lineImg,new Color(1,0,0)), New Line(338.0,336.0,338.0,341.0,media.lineImg,new Color(1,0,0)), New Arc(320.0,342.0,17.0,0.0,180.0,0.0,0.0,media.arcImg,new Color(1,0,0)), New Line(303.0,341.0,303.0,336.0,media.lineImg,new Color(1,0,0)), New Line(303.0,335.0,296.0,328.0,media.lineImg,new Color(1,0,0)), New Line(295.0,327.0,59.0,327.0,media.lineImg,new Color(1,0,0)), New Line(58.0,328.0,41.0,344.0,media.lineImg,new Color(1,0,0)), New Arc(27.0,333.0,17.0,45.0,225.0,0.0,0.0,media.arcImg,new Color(1,0,0)), New Line(16.0,320.0,31.0,305.0,media.lineImg,new Color(1,0,0)), New Line(33.0,304.0,33.0,58.0,media.lineImg,new Color(1,0,0)), New Line(32.0,57.0,17.0,43.0,media.lineImg,new Color(1,0,0))) table=New Table(wall,engine,arcList) Return table End End End Return Null End End Global tableStorage:TableStorage Class Table Method New(wall:Wall[],engine:ElasticEngine,arcList:List) Local n:Int=1, t:Int=0 While(t < wall.Length) Local w:Wall=wall[t] t=t+1 If w.name ="Line" Local l:Line=Cast(w) If l.image engine.AddLineWallImage(l.x1,l.y1,l.x2,l.y2,w.image,New Color(0,0,0)) Else engine.AddLineWallOutline(l.x1,l.y1,l.x2,l.y2,Null,l.color) Endif ElseIf w.name ="Arc" Local a:Arc=Cast(w) If a.image Local w:ArcWall=engine.AddArcWallImage(a.x1,a.y1,a.radius,a.startAngle,a.endAngle,a.image,New Color(1,1,1)) arcList.AddLast(w) w.num=n n+=1 Else Local w:ArcWall=engine.AddArcWallOutline(a.x1,a.y1,a.radius,a.startAngle,a.endAngle,a.color) If arcList = Null Then RuntimeError("arclist not initialized") arcList.AddLast(w) w.num=n n+=1 Endif ElseIf(w.name ="Circle") Endif End End End Class PoolSoloTime Extends Pool Field blinkOn:Int=0 Field timed:Int Field minutes:Int Field seconds:Int Field lastTime:Float Field timeFrame:Float Field blinkTime:Int Field blink:Int Field oldTime:Int Field endTime:Int=0 Field time:Int=0 Field down:Int=0 Method New() Self.engine=New ElasticEngine() Self.engine.SetGravity(0.0,0.0) ' Self.engine.SetFriction(0.970) Self.ballList=Self.engine.ballList Self.arcList=New List Self.pottedList= New List Self.turnList= New List tableStorage= New TableStorage() tableStorage.GetTable(0,Self.engine,Self.arcList) Self.tableImg=media.tableImg Self.arrowsImg=media.arrowsImg Self.ballImg=media.ballImg Self.railAnimation=New RailAnimation() Self.railAnimation.ShowStops(0) Self.Exiting=1 Self.Setup16() Self.player=New Record() Self.player.SetName("Player") Self.blinkOn=0 End Method SetupPVC() Override RuntimeError("invalid Setup in Solo Play") End Method SetupPVP() Override RuntimeError("invalid Setup in Solo Play") End Method InitTime() Self.endTime=Millisecs()+180000 Self.time=180000 End Method SetupTimed() Override Self.activePlayer= New Player("",cue,engine,media.ghostImg, media.ballImg,media.stickImg,media. rotatorImg,media.buttonImg,media.stripImg, media.frameTopImg,media. frameBotImg,media. topImg,media. botImg, media.lrImg, media.meterImg,media.stretchImg,media.sliderImg) Self.InitTime() End Method Reset() Override For Local b:Ball = Eachin Self.pottedList Self.engine.AddBall(b) Self.pottedList.RemoveEach(b) End Self.turnList.Clear() Self.railAnimation.Reset() For Local b2:Ball = Eachin Self.ballList b2.Init(0.0,0.0) If b2.num=1 b2.SetPosition(180.8,180.0) Elseif(b2.num=2) b2.SetPosition(162.6,170.0) Elseif(b2.num=3) b2.SetPosition(162.6,190.0) Elseif(b2.num=4) b2.SetPosition(144.4,160.0) Elseif(b2.num=5) b2.SetPosition(144.4,200.0) Elseif(b2.num=6) b2.SetPosition(126.2,150.0) Elseif(b2.num=7) b2.SetPosition(126.2,170.0) Elseif(b2.num=8) b2.SetPosition(144.4,180.0) Elseif(b2.num=9) b2.SetPosition(126.2,190.0) Elseif(b2.num=10) b2.SetPosition(126.2,210.0) Elseif(b2.num=11) b2.SetPosition(108.0,140.0) Elseif(b2.num=12) b2.SetPosition(108.0,160.0) Elseif(b2.num=13) b2.SetPosition(108.0,180.0) Elseif(b2.num=14) b2.SetPosition(108.0,200.0) Elseif(b2.num=15) b2.SetPosition(108.0,220.0) End b2.ResetAnimation() End Exiting=1 End Method InitGame() Override player.Reset() activePlayer.ResetBalls() Reset() Exiting=1 state=12 cue.SetPosition(490.0,180.0) InitTime() End Method RestoreCue() Override state=9 cue.Init(0.0,0.0) cue.SetPosition(320.0,180.0) turnList.RemoveEach(cue) pottedList.RemoveEach(cue) railAnimation.RemoveCueBall() engine.AddBall(cue) End Method ResolveTurn() Self.state=3 If Not turnList.Empty For Local b:Ball = Eachin Self.turnList If(b.num<16) activePlayer.AddBall(b) Else RestoreCue() player.UpdateBallSinRow(Self.scoreLevel) scoreLevel=Self.minLevel End End Self.turnList.Clear() Else Self.scoreLevel=Self.minLevel End If(Self.activePlayer.CompletedAll()=True) player.IncrementCompletedSets() activePlayer.ResetBalls() Reset() End Self.Exiting=0 End Method Update:Int() Override If(decrementer>0) decrementer-=500 endTime-=500 End If incrementer>0 incrementer-=200 endTime+=500 timed+=500 If(timed>=2000) media.PlayBeep() timed=0 End End time= (endTime-Millisecs())/1000 minutes= time/60 seconds=time Mod 60 Local SelfTime:Float= Millisecs() timeFrame=(SelfTime-lastTime)/30.0 lastTime=SelfTime If time<=0 player.UpdateBallSinRow(Self.scoreLevel) state=6 blinkOn=0 Else If time<=10 blinkOn=1 If Millisecs()>= blinkTime+300 blink = Not (blink<>0) blinkTime = Millisecs() End If time0 down=1 If Mouse.ButtonDown(MouseButton.Left)=0 And down=1 down=0 done=1 End Elseif state=8 Endif Self.railAnimation.Update(timeFrame*3.0) Return Not done End Method Render(canvas:Canvas) Override canvas.DrawImage(media.railImg,5.0,360.0,0) railAnimation.Render(canvas) canvas.Color = New Color(1,1,1) canvas.DrawImage(tableImg,0.0,0.0,0) engine.Render(canvas) If(state=12) canvas.Color = New Color(1,1,1) inputName.Render(canvas) Elseif(state=2) canvas.Alpha = .2 canvas.DrawRect(466.0,37.0,140.0,288.0) canvas.Alpha = .3 canvas.DrawImage(arrowsImg,cue.P.x,cue.P.y,0) canvas.Alpha = 1.0 activePlayer.RenderButton(canvas) ElseIf(state=4 Or state=3) If decrementer>0 canvas.Color = New Color(1,.4,0) Else canvas.Color = New Color(1,1,1) End Local sec:String=String(seconds) If(sec.Length = 1) sec="0"+sec If blinkOn If blink Text.Draw(canvas,"Time Left "+String(minutes)+":"+sec,400,370) Else Text.Draw(canvas,"Time Left "+String(minutes)+":"+sec,400,370) End canvas.Color = New Color(1,1,1) Text.Draw(canvas,"Score "+String(player.score),400,400) Text.Draw(canvas,"Multiplier 100 x"+String(scoreLevel),400,430) activePlayer.Render(canvas,0) ElseIf(state=5) If decrementer > 0 canvas.Color = New Color(1,.4,0) Else canvas.Color = New Color(1,1,1) End Local sec2:String=String(seconds) If sec2.Length=1 sec2="0"+sec2 If blinkOn<>0 If blink Text.Draw(canvas,"Time Left "+String(minutes)+":"+sec2,400,370) Else Text.Draw(canvas,"Time Left "+String(minutes)+":"+sec2,400,370) End canvas.Color = New Color(1,1,1) Text.Draw(canvas,"Score "+String(player.score),400,400) Text.Draw(canvas,"Multiplier 100 x"+String(scoreLevel),400,430) ElseIf(state=6) Local tx:Int=120 Local ty:Int=100 canvas.Alpha = .7 canvas.Color = New Color(.2,0,1) canvas.DrawRect(tx-20,ty-20,400.0,240.0) canvas.Alpha = 1.0 canvas.Color = New Color(1,1,1) canvas.DrawText("Name "+player.name,tx,ty+0,0.0,0.0) canvas.DrawText("Score "+String(player.score),tx,ty+30,0.0,0.0) canvas.DrawText("completed Sets "+String(player.mostCompletedSets),tx,ty+60,0.0,0.0) canvas.DrawText("Most Balls In A Row "+String(player.mostBallSinRow),tx,ty+90,0.0,0.0) canvas.DrawText("Most Pocketed "+String(player.mostPocketed),tx,ty+120,0.0,0.0) canvas.DrawText(" Press to exit ",tx+100,ty+170,0.0,0.0) ElseIf(state=8) End End End Global scoreTableVsTime:ScoreTable Class User Field ballList:List Field cue:Ball Field position:PVector2D Field ballImg:Image Field ghostImg:Image[] Field cueStick:CueStick Field name:String="" Global firstShot:Int Field completedSet:Int=0 Field engine:ElasticEngine Field ghostBall:GhostBall Field control:Control Field button:Button2 Field ballOwnerType:Int=0 Field angle:Float Field oldAngle:Float Method New() ballList=New List End Method SetButtonText(str:String) Virtual Return End Method Init() Abstract Method Positioning:Bool() Abstract Method Aiming:Bool() Abstract Method ShootingAnimating:Bool() Abstract Method SetToSolids() ballOwnerType=2 End Method SetToStripes() ballOwnerType=1 End Method OwnsSolids:Bool() Return ballOwnerType=2 End Method AddBall(b:Ball) Self.ballList.AddLast(b) End Method OwnsStripes:Bool() Return Self.ballOwnerType=1 End Method CompletedSet:Bool() Return Self.ballList.Count()=7 End Method RenderButton(canvas:Canvas) Abstract Method Render(canvas:Canvas,state:Int) Virtual canvas.Color = New Color(0.0,0.0,0.0) Text.Draw(canvas, name,544,371) canvas.Color = New Color(1,1,1) Text.Draw(canvas,Self.name,545,370) Local lowy:Float=370.0 Local hiy:Float=371.0 Local lowx:Float=400.0 Local hix:Float=401.0 Local t_1:Int=ballOwnerType If ballOwnerType = 2 canvas.Color = New Color(0,0,0) Text.Draw(canvas,"SOLIDS",lowx,hiy) canvas.Color = New Color(1,1,1) Text.Draw(canvas,"SOLIDS",hix,lowy) ElseIf ballOwnerType = 1 canvas.Color = New Color(0,0,0) Text.Draw(canvas,"STRIPES",lowx,hiy) canvas.Color = New Color(1,1,1) Text.Draw(canvas,"STRIPES",hix,lowy) Else canvas.Color = New Color(0.0,0.0,0.0) Text.Draw(canvas,"Game Is Open",lowx,hiy) canvas.Color = New Color(1,1,1) Text.Draw(canvas,"Game Is Open",hix,lowy) End End Method ResetBalls() Self.ballList.Clear() End Method CompletedAll:Bool() Return Self.ballList.Count()=15 End End Class Class Player Extends User Field oldTouch:Int=0 Field oldMouseDown:Int=0 Field oldMouseX:Int=0 Field oldMouseY:Int=0 Field rotatorImg:Image Method New(name:String,cue:Ball,engine:ElasticEngine,t_ghostImg:Image[],ballImg:Image,stickImg:Image[],rotatorImg:Image,buttonImg:Image[],stripImg:Image,frameTopImg:Image[],frameBotImg:Image[],topImg:Image,botImg:Image,lrImg:Image[],meterImg:Image,stretchImg:Image,sliderImg:Image) Self.cue=cue Self.position=cue.P Self.ballImg=ballImg Self.ghostImg=t_ghostImg Self.cueStick=New CueStick(cue.P,cue.radius+1.0,stickImg,180.0) Self.name=name User.firstShot=1 Self.completedSet=0 Self.engine=engine Self.ghostBall=New GhostBall(cue.P,cue.radius,t_ghostImg,180.0,stripImg) Self.control=New Control(cue,5,420,.5,meterImg,stretchImg,sliderImg,40) Self.oldTouch=0 Self.button=New Button2(buttonImg,360,400,"shoot",Null) Self.rotatorImg = rotatorImg End Method Init() Override ghostBall.dx=Cos(cueStick.angle) ghostBall.dy=Sin(cueStick.angle) cueStick.SetAngle(cueStick.angle) engine.CollisionDistance2Ghost(ghostBall) End Method Positioning:Bool() Override button.Update() If button.GetState() Local overlapping:Int=0 For Local b:Ball = Eachin engine.ballList If b=cue Continue Local vx:Float=Self.cue.P.x-b.P.x Local vy:Float=Self.cue.P.y-b.P.y If(vx*vx+vy*vy<=4.0*b.radius*b.radius) overlapping=1 End End If overlapping=0 Return False End If Mouse.ButtonDown(MouseButton.Left) If oldMouseDown engine.CollisionDistance2Ghost(Self.ghostBall) cue.P.x+=Mouse.X-(oldMouseX) cue.P.y+=Mouse.Y-(oldMouseY) If cue.P.x<476.0 cue.P.x=476.0 If cue.P.x>596.0 cue.P.x=596.0 If cue.P.y<47.0 cue.P.y=47.0 If cue.P.y>315.0 cue.P.y=315.0 End End oldMouseDown=Mouse.ButtonDown(MouseButton.Left) oldMouseX=Mouse.X oldMouseY=Mouse.Y Return True End Method SetButtonText(str:String) Override button.SetText(str) End Method Aiming:Bool() Override If control.Update() angle=control.angle cueStick.SetAngle(angle) If control.Length<0.0 cueStick.SetDistance(0.0) Else If control.Length>40.0 cueStick.SetDistance(40.0) Else cueStick.SetDistance(control.Length) End End ghostBall.dx=Cos(angle) ghostBall.dy=Sin((angle)) engine.CollisionDistance2Ghost(ghostBall) oldAngle=angle Else If(control.Length>0.0) cueStick.SetAnimation2() control.Length=0.0 Return False End End Return True End Method ShootingAnimating:Bool() override If cueStick.Update()=0 cue.Init(cueStick.dx*40.0*control.volume,cueStick.dy*40.0*control.volume) media.PlayShootCol() Return False End Return True End Method RenderButton(canvas:Canvas) Override button.Render(canvas) End Method Render(canvas:Canvas,status:Int) Override control.Render(canvas) canvas.DrawImage(rotatorImg,position.x,position.y,-angle-1.6,1.0,1.0) ' If status Render(canvas,1) ghostBall.Render(canvas) cueStick.Render(canvas) End End Class CueStick Field position:PVector2D Field len:Float=.0 Field image:Image[] Field rotatorImg:Image Field offset:Float=.0 Field angle:Float=.0 Field dx:Float=.0 Field dy:Float=.0 Field offsetx:Float=.0 Field offsety:Float=.0 Field distance:Float=.0 Field animStep:Float=.0 Field animx:Float=.0 Field animy:Float=.0 Field animAngle:Float=.0 Field animDelay:Int=0 Field power:Float=.0 Method SetAngle(ang:Float) If ang<>angle angle=ang dx=Cos(angle) dy=Sin(angle) offsetx=-dx*len offsety=-dy*len End End Method New(pos:PVector2D,offset:Float,image:Image[],angle:Float) Self.position=pos Self.len=offset Self.image=image Self.offset=offset Self.SetAngle(angle) Self.rotatorImg = rotatorImg End Method SetDistance(d:Float) distance=d animStep=30.0 animx=-dx*distance animy=-dy*distance End Method SetAnimation2() animAngle=0 animDelay=Millisecs()+1 End Method Update:Int() If animDelay= 90.0 animx=0.0 animy=0.0 distance=0.0 animAngle=0.0 Return 0 Else Local Length:Float=Cos(animAngle*ATR)* distance animx=-dx*Length animy=-dy*Length If animAngle < 90.0 animAngle += animStep End animDelay=Millisecs()+1 End Return 1 End Method Render(canvas:Canvas) canvas.Color = New Color(1,1,1) Local x:Float=position.x+offsetx+animx Local y:Float=position.y+offsety+animy canvas.DrawImage(image[0],x,y,-angle,1.0,1.0) End Method SetAngleCpu(ang:Float) If ang<>Self.angle angle=ang dx=Cos(angle) dy=Sin(angle) offsetx=-dx*len offsety=-dy*len End End Method Init(d:Float) animStep=d/4.0 animx=0.0 animy=0.0 End Method UpdateCpu:Int() If(Self.animDelay=90.0) animx=0.0 animy=0.0 animAngle=0.0 Return 0 Else Local Length:Float=-Sin(animAngle*ATR)*30.0 animx=Length*dx animy=Length*dy If animAngle>90.0 Local pwr:Float = power/4.0 If pwr<1.0 pwr=1.0 animAngle += animStep*pwr Else animAngle += animStep End End animDelay=Millisecs()+1 End Return 1 End End Class Control Field x:Int Field y:Int Field width:Float Field height:Float Field meterImg:Image Field stretchImg:Image Field sliderImg:Image Field volume:Float Field sliderx:Int Field framed:Int Field active:Int Field oldMouseDown:Int Field maxValue:Float Field stp:Float Field cue:Ball Field topLRImg:Image[] Field botLRImg:Image[] Field midTopImg:Image Field midBotImg:Image Field midLRImg:Image[] Field tw:Float Field th:Float Field x2:Float Field vx:Float Field y2:Float Field vy:Float Field dx:Float Field dy:Float Field Length:Float Field activeVolume:Float Field angle:Float Method New(cue:Ball,x:Int,y:Int,volume:Float,meterImg:Image,stretchImg:Image,sliderImg:Image,maxValue:Int) Self.x=x Self.y=y Self.width= meterImg.Width Self.height= meterImg.Height Self.meterImg=meterImg Self.stretchImg=stretchImg Self.sliderImg=sliderImg Self.stretchImg=stretchImg If volume>1.0 volume=1.0 If volume<0.0 volume=0.0 Self.volume=volume Self.sliderx= volume*Self.width Self.framed = 0 Self.active = 0 Self.oldMouseDown = 0 Self.maxValue=(maxValue) Self.stp=Self.width/maxValue Self.cue=cue End Method SetFrame(tlrImg:Image[],blrImg:Image[],mtImg:Image,mbImg:Image,mlrImg:Image[]) Self.topLRImg=tlrImg Self.botLRImg=blrImg Self.midTopImg=mtImg Self.midBotImg=mbImg Self.midLRImg=mlrImg Self.tw= tlrImg[0].Width Self.th= tlrImg[0].Height Self.framed=1 End Method Update:Int() Local state:Int=1 If Mouse.ButtonDown(MouseButton.Left) If Self.oldMouseDown Self.vx=Mouse.X-Self.x2 Self.vy=Mouse.Y-Self.y2 Self.Length=Self.vx*-Self.dx+Self.vy*-Self.dy If(Self.Length>Self.maxValue) Self.volume=Self.maxValue*Self.stp/Self.width Else If(Self.Length<0.0) Self.volume=0.0 Else Self.volume=Self.Length*Self.stp/Self.width End End Else Self.x2=Mouse.X Self.y2=Mouse.Y End Else If Self.oldMouseDown Self.vx=Mouse.X-Self.x2 Self.vy=Mouse.Y-Self.y2 Self.Length=Self.vx*-Self.dx+Self.vy*-Self.dy If(Self.Length>Self.maxValue And Self.Length>=0.0) Self.volume=Self.maxValue*Self.stp/Self.width Else If(Self.Length<0.0) Self.volume=0.0 Else Self.volume=Self.Length*Self.stp/Self.width End End Self.oldMouseDown=Mouse.ButtonDown(MouseButton.Left) Return 0 Else Self.volume=Self.activeVolume Self.vx=Mouse.X-Self.cue.P.x Self.vy=Mouse.Y-Self.cue.P.y Self.angle=(ATan2(Self.vy,Self.vx)) Self.dx=Cos((Self.angle)) Self.dy=Sin((Self.angle)) End End Self.oldMouseDown=Mouse.ButtonDown(MouseButton.Left) Self.sliderx=((Self.volume*Self.width)) Return 1 End Method Render(canvas:Canvas) If framed Local px:Float=x-tw Local py:Float=y-th canvas.DrawImage(topLRImg[0],px,py) canvas.DrawImage(midTopImg,px+tw,py,0.0,width,1.0) canvas.DrawImage(topLRImg[1],px+width+tw,py) canvas.DrawImage(midLRImg[0],px,py+th,0.0,1.0,height) canvas.DrawImage(midLRImg[1],px+tw+width,py+th,0.0,1.0,height) canvas.DrawImage(botLRImg[0],px,py+th+height) canvas.DrawImage(midBotImg,px+tw,py+th+height,0.0,width,1.0) canvas.DrawImage(botLRImg[1],px+tw+width,py+th+height) End canvas.DrawImage(meterImg,x,y,0) Local w:Float=(1.0-volume)*width canvas.DrawImage(stretchImg,x+sliderx,y,0.0,w,1.0) canvas.DrawImage(sliderImg,x+sliderx,y,0) Text.Draw(canvas,"POWER",x+50,y+10) End End Class Cpu Extends User Field pocketList:List Field activeBallList:List Field aimWait:Int=0 Field delay:Int=0 Field inacuracy:Float=.0 Field power:Float=.0 Method New(name:String,cue:Ball,engine:ElasticEngine,arcList:List,stickImg:Image[],ballImg:Image,inacuracy:Float) Self.cue=cue Self.position=cue.P Self.cueStick= New CueStick(cue.P,cue.radius+1.0,stickImg,180.0) Self.ballImg=ballImg Self.pocketList=arcList Self.activeBallList=engine.ballList Self.aimWait=100 Self.delay=Millisecs()+Self.aimWait Self.inacuracy=inacuracy Self.name=name Self.engine=engine End Method Init() Override End Method Positioning:Bool() Override Repeat cue.P.x=Rnd(476,596) cue.P.y=Rnd( 47,315) Local overlapped:Int=0 For Local b:Ball = Eachin engine.ballList If b=cue Continue End Local vx:Float=b.P.x-Self.cue.P.x Local vy:Float=b.P.y-Self.cue.P.y If (vx*vx+vy*vy<=4.0*b.radius*b.radius) overlapped=1 Exit End End If overlapped=0 Exit Forever cue.Init(0.0,0.0) Return False End Method Get8Ball:Ball() For Local b:Ball = Eachin activeBallList If(b.num=8) Return b End End Return Null End Method PathToPocket:Bool(b1:Ball,dx:Float,dy:Float) For Local b2:Ball = Eachin Self.activeBallList If(b2=b1 Or b2=Self.cue) Continue End Local vx:Float=b2.P.x-b1.P.x Local vy:Float=b2.P.y-b1.P.y Local dp:Float=vx*dy-vy*dx If(Abs(dp)0.0) Return False End End End Return True End Method PathToBall:Bool(b1:Ball,dx:Float,dy:Float,skipBall:Ball) Local vx:Float=skipBall.P.x-b1.P.x Local vy:Float=skipBall.P.y-b1.P.y Local len:Float=vx*dx+vy*dy For Local b3:Ball = Eachin activeBallList If(b3=b1 Or b3=skipBall) Continue Local vx2:Float=b3.P.x-b1.P.x Local vy2:Float=b3.P.y-b1.P.y Local dp:Float=vx2*dy-vy2*dx If(Abs(dp)0.0 And dp20.0) dx1=vx1/d1 dy1=vy1/d1 End If(d1=0.0 Or Self.PathToPocket(ball,dx1,dy1)) Local px:Float=ball.P.x-dx1*(arc.radius+ball.radius) Local py:Float=ball.P.y-dy1*(arc.radius+ball.radius) vx1=px-cue.P.x vy1=py-cue.P.y d1=Sqrt(vx1*vx1+vy1*vy1) Local ang:Float=(ATan2(vy1,vx1)) If(PathToBall(cue,Cos((ang)),Sin((ang)),ball)) If(d11 counter=Rnd(1.0,(counter+1)) Local n:Int=1 For Local b2:Ball = Eachin activeBallList If b2.num < 8 If(n=counter) Return b2 n+=1 Endif End End Return Null End Method GetRndStripedBall:Ball() Local counter:Int=0 Local low:Int=0 For Local b:Ball = Eachin activeBallList If(b.num>=8 And b.num<16) counter+=1 Else low+=1 End End counter=(((low)+Rnd(1.0,(counter+1)))) Local n:Int=1 For Local b2:Ball = Eachin activeBallList If n=counter Return b2 n+=1 End Return Null End Method GetRndBall:Ball() Local counter:Int=Self.activeBallList.Count() counter=((Rnd(0.0,(counter-1)))) Local n:Int=0 For Local b:Ball = Eachin activeBallList If n=counter Return b n+=1 End Return Null End Method Aiming:Bool() Override Local vx:Float Local vy:Float If ballList.Count() = 7 Local b:Ball=Get8Ball() Local pocket:ArcWall=FindBestPocket(b) If pocket vx=b.P.x-pocket.target.x vy=b.P.y-pocket.target.y Local len:Float=Sqrt(vx*vx+vy*vy) Local px:Float=b.P.x+vx/len*(b.radius+cue.radius) Local py:Float=b.P.y+vy/len*(b.radius+cue.radius) vx=px-cue.P.x vy=py-cue.P.y Else vx=b.P.x-cue.P.x vy=b.P.y-cue.P.y End Else Local ball:Ball Local pocket2:ArcWall Local distance:Float=INVALID_DISTANCE For Local b2:Ball = Eachin activeBallList If(ballOwnerType=2 And b2.num>7) Continue If(ballOwnerType=1 And b2.num<9) Continue If(b2.num=8 Or b2=cue) Continue Local pkt:ArcWall=FindBestPocket(b2) If pkt vx=pkt.target.x-b2.P.x vy=pkt.target.y-b2.P.y Local ln:Float=Sqrt(vx*vx+vy*vy) If(ln