Pool (бильярд)
Хороший проект по созданию бильярда. Все управление мышью. Правда я не сразу въехал в то, как управлять... Но получился довольно симпотный бильярд с компьютерным оппонентом.
Платформа: Windows, Linux
Автор: dodicat
'SCREENs Dim Shared As Integer xres,yres,potred,potyellow Dim As Integer fullscreen=1,alphascreen=64 Screenres 1024,768,32,,alphascreen ''or fullscreen 'or 'screenres 800,600,32,,alphascreen ''or fullscreen Screeninfo xres,yres Type V3 As Single x As Single y As Single z Declare Property length As Single Declare Property unit As V3 End Type #DEFINE vct Type<v3> #DEFINE dot * #DEFINE cross ^ #DEFINE map(a,b,x,c,d) ((d)-(c))*((x)-(a))/((b)-(a))+(c) #DEFINE round(x,N) Rtrim(Rtrim(Left(Str((x)+(.5*Sgn((x)))/(10^(N))),Instr(Str((x)+(.5*Sgn((x)))/(10^(N))),".")+(N)),"0"),".") #DEFINE incirc(c,mx,my) (c.x-mx)*(c.x-mx) +(c.y-my)*(c.y-my)<= c.r*c.r #DEFINE incircle(c,mx,my) (mx)>(c.x-c.r) And (mx)<(c.x+c.r) And (my)>(c.y-c.r) And (my)<(c.y+c.r) #DEFINE Rd( c ) (( c ) Shr 16 And 255 ) #DEFINE Gr( c ) (( c ) Shr 8 And 255 ) #DEFINE Bl( c ) (( c )And 255 ) #DEFINE redball Rgb(240,0,0) #DEFINE yellowball Rgb(240,240,0) #DEFINE whiteball Rgb(200,200,200) #DEFINE blackball Rgb(20,20,20) #DEFINE Intrange(f,l) Int(Rnd*((l+1)-(f))+(f)) #DEFINE ontable(p) p.x>.1*xres And p.x<.9*xres And p.y>.1*yres And p.y<.9*yres #MACRO arraydelete(a,position) Scope Dim As Integer index=position If index>=LBound(a) And index<=UBound(a) Then For x As Integer=index To Ubound(a)-1 a(x)=a(x+1) Next x Redim Preserve a(Lbound(a) To Ubound(a)-1) End If End Scope #EndMacro Type Line As v3 v1,v2 End Type Type _object As v3 position,velocity As Single mass,radius As Uinteger colour End Type Type Circle As Integer x As Integer y As Integer r As Uinteger col End Type Type msg As String s As Uinteger c End Type Type kick As V3 o As Integer pnum As Single block As Integer ballnumber End Type Operator + (v1 As v3,v2 As v3) As v3 Return vct(v1.x+v2.x,v1.y+v2.y,v1.z+v2.z) End Operator Operator -(v1 As v3,v2 As v3) As v3 Return vct(v1.x-v2.x,v1.y-v2.y,v1.z-v2.z) End Operator Operator * (f As Single,v1 As v3) As v3 Return vct(f*v1.x,f*v1.y,f*v1.z) End Operator Operator * (v1 As v3,v2 As v3) As Single Return v1.x*v2.x+v1.y*v2.y+v1.z*v2.z End Operator Operator ^ (v1 As v3,v2 As v3) As v3 Return vct(v1.y*v2.z-v2.y*v1.z,-(v1.x*v2.z-v2.x*v1.z),v1.x*v2.y-v2.x*v1.y) End Operator Operator <>(v1 As V3,v2 As V3) As Integer Return (v1.x<>v2.x) Or (v1.y<>v2.y) End Operator Property v3.length As Single Return Sqr(this.x*this.x+this.y*this.y+this.z*this.z) End Property Property v3.unit As v3 Dim n As Single=this.length If n=0 Then n=1e-20 Return vct(this.x/n,this.y/n,this.z/n) End Property '============================================================= Declare Function sound Alias"Beep"(Byval f As Integer,Byval d As Integer) As Integer Declare Function PotBeep Lib "user32" Alias "MessageBeep" (Byval As Integer) As Integer 'collisions Function segment_distance(l As Line,p As v3,Byref ip As v3=vct(0,0,0)) As Single Var s=l.v1,f=l.v2 Dim As Single linelength=(s-f).length Dim As Single dist= ((1/linelength)*((s-f) cross (p-s))).length Dim As Single lpf=(p-f).length,lps=(p-s).length If lps >= lpf Then Var temp=Sqr(lps*lps-dist*dist)/linelength If temp>=1 Then temp=1:dist=lpf ip=s+(temp)*(f-s) Return dist Else Var temp=Sqr(lpf*lpf-dist*dist)/linelength If temp>=1 Then temp=1:dist=lps ip=f+(temp)*(s-f) Return dist End If Return dist End Function Sub check_ball_to_ball_collisions(ball() As _object) For x As Integer=LBound(ball) To Ubound(ball)-1 For y As Integer=x+1 To Ubound(ball) Var seperation=(ball(x).position-ball(y).position).length Var impulse=(ball(x).position-ball(y).position).unit If seperation<=ball(x).radius+ball(y).radius Then ball(x).position=ball(y).position+(ball(x).radius+ball(y).radius)*impulse Var impact=ball(x).velocity-ball(y).velocity Var dv=impact dot impulse Var ma=ball(x).mass: Var mb=ball(y).mass ball(x).velocity=ball(x).velocity-dv*((2*mb/(ma+mb)))*impulse ball(y).velocity=ball(y).velocity+dv*((2*ma/(mb+ma)))*impulse End If Next y Next x End Sub Sub check_ball_to_line_collisions(LN() As Line, ball() As _object) For z As Integer=LBound(ball) To Ubound(ball) For z2 As Integer=LBound(Ln) To Ubound(Ln) Dim As v3 closepoint Var seperation=segment_distance(Ln(z2),ball(z).position,closepoint) If seperation<=ball(z).radius Then Var impact=-1*ball(z).velocity Var impulse=(closepoint-ball(z).position).unit ball(z).position=closepoint-(ball(z).radius)*impulse Var dv=(impact dot impulse) ball(z).velocity=ball(z).velocity+2*dv*impulse End If Next z2 Next z End Sub Sub ORB(cx As Double,_ cy As Double,_ radius As Double,_ col As Uinteger,_ offsetX As Double=0,_ offsetY As Double=0,_ e As Double=0,_ resolution As Double=32,_ im As Any Pointer=0) 'Dim As Double d Dim As Integer red,green,blue,r,g,b Dim As Double ox,oy,nx,ny ox=cx+offsetX*radius oy=cy+offsetY*radius red=rd(col) green=gr(col) blue=bl(col) For d As Single = radius To 0 Step -radius/resolution nx=(cx-ox)*(d-radius)/radius + cx ny=(cy-oy)*(d-radius)/radius + cy r=-red*(d/radius-1) g=-green*(d/radius-1) b=-blue*(d/radius-1) Circle im,(nx,ny),d,Rgb(r+20,g+20,b+20),,,e,F Next d End Sub 'SPEED REGULATOR Function framecounter() As Integer Var t1=Timer,t2=t1 Static As Double t3,frames,answer frames+=1 If (t2-t3)>=1 Then t3=t2:answer=frames:frames=0 Function= answer End Function Function Regulate(MyFps As Integer,Byref fps As Integer) As Integer fps=framecounter() Static As Double timervalue,lastsleeptime Dim As Double delta Var k=fps-myfps,i=1/myfps If Abs(k)>1 Then delta+=i*Sgn(k) Var sleeptime=lastsleeptime+(i-Timer+timervalue)*2000+delta If sleeptime<1 Then sleeptime=1 lastsleeptime=sleeptime timervalue=Timer Return sleeptime End Function Sub setup(balls() As _object) Dim As Integer rad=(xres/10+yres/10)/9 Dim As Integer c Var d=map(20,16,rad,42,32) For n As Integer=1 To 15 balls(n).radius=rad balls(n).mass=1 balls(n).velocity=vct(0,0,0) If n Mod 2 Then balls(n).colour=RGB(240,0,0) Else balls(n).colour=RGB(240,240,0) If n>=1 And n<=5 Then c=n balls(n).position=vct(.2*xres,.3*yres+d*c,0) c=c+1 End If If n>5 And n<=9 Then c=n-5 balls(n).position=vct(.236*xres,.325*yres+d*c,0) End If If n>9 And n<=12 Then c=n-9 balls(n).position=vct((.236+.036)*xres,.35*yres+d*c,0) End If If n>12 And n<=14 Then c=n-12 balls(n).position=vct((.236+.036+.036)*xres,.375*yres+d*c,0) End If If n=15 Then balls(n).position=vct((.236+.036+.036+.036)*xres,.35*yres+d*c,0) End If Next n balls(11).colour=RGB(20,20,20) balls(16).position=vct(.7*xres,(.05+.85)/2*yres,0) balls(16).radius=rad'20 balls(16).mass=1 balls(16).colour=RGB(200,200,200) balls(16).velocity=vct(0,0,0) Var dy=yres/2-balls(15).position.y For n As Integer=LBound(balls) To Ubound(balls) balls(n).position.y=balls(n).position.y+dy Next n End Sub Sub setcircles(c() As Circle) c(1)=Type<Circle>(.5*xres,.025*yres,5,Rgb(200,0,200))'speed c(2)=Type<Circle>(.5*xres,.9*yres,10,Rgb(200,200,200))'target c(3)=Type<Circle>(.8*xres,.025*yres,8,Rgb(0,200,200))'strike c(5)=Type<Circle>(.04*xres,.4*yres,5,Rgb(0,0,255))'screw c(6)=Type<Circle>(.2*xres,.05*yres,19)'help End Sub Sub setedges(edge() As Line) Var Hgap=vct(26,0,0),Vgap=vct(0,26,0) Var dg=1.4 Var T_L=vct(.1*xres,.1*yres,0),T_R=vct(.9*xres,.1*yres,0) Var tC=.5*(T_R+T_L) Var B_R=vct(.9*xres,.9*yres,0) Var B_L=vct(.1*xres,.9*yres,0) Var bC=.5*(B_R+B_L) edge(1)=Type<Line>(T_l+dg*hgap,tc-hgap)'top edge(2)=Type<Line>(tc+hgap,T_R-dg*hgap)'top edge(3)=Type<Line>(T_R+dg*vgap,B_R-dg*vgap) 'r edge edge(4)=Type<Line>(B_R-dg*hgap,bc+hgap) 'bot edge(5)=Type<Line>(bc-hgap,B_l+dg*hgap) 'bot edge(6)=Type<Line>(B_l-dg*vgap,T_l+dg*vgap) 'left End Sub Sub setpockets(pockets() As V3,Vpockets() As V3,Opockets() As V3,size As Single) size=size/2 Dim As Single dsize=yres/80 Dim As v3 tc=Type<v3>(.5*(.1*xres+.9*xres),.1*yres,0) Dim As v3 bc=Type<v3>(.5*(.1*xres+.9*xres),.9*yres,0) pockets(1)=Type<v3>(.1*xres,.1*yres,0)+vct(dsize,dsize,0) pockets(2)=tc+vct(0,-dsize,0) pockets(3)=Type<v3>(.9*xres,.1*yres,0)+vct(-dsize,dsize,0) pockets(4)=Type<v3>(.9*xres,.9*yres,0)+vct(-dsize,-dsize,0) pockets(5)=bc+vct(0,dsize,0) pockets(6)=Type<v3>(.1*xres,.9*yres,0)+vct(dsize,-dsize,0) Vpockets(1)=pockets(1)+vct(size,size,0):Opockets(1)=pockets(1)+vct(-2*size,-2*size,0) Vpockets(2)=pockets(2)+vct(0,size,0):Opockets(2)=pockets(2)+vct(0,-2*size,0) Vpockets(3)=pockets(3)+vct(-size,size,0):Opockets(3)=pockets(3)+vct(2*size,-2*size,0) Vpockets(4)=pockets(4)+vct(-size,-size,0):Opockets(4)=pockets(4)+vct(2*size,2*size,0) Vpockets(5)=pockets(5)+vct(0,-size,0):Opockets(5)=pockets(5)+vct(0,2*size,0) Vpockets(6)=pockets(6)+vct(size,-size,0):Opockets(6)=pockets(6)+vct(-2*size,2*size,0) End Sub Sub tempdrawpockets(p() As V3,col As Uinteger) For n As Integer=1 To 6 Circle (p(n).x,p(n).y),10,col Next n End Sub 'DRAWING SUBS Sub digits(t As String,x As Integer,y As Integer,clr As Uinteger,sz As Single,img As Any Pointer=0) x=x-2*sz #MACRO thickline(x1,y1,x2,y2,colour,thickness,image) Scope Dim As Any Pointer im=image Var h=Sgn(x2-x1)*(x2-x1)+Sgn(y2-y1)*(y2-y1) Var s=(y1-y2)/h Var c=(x2-x1)/h Line im,(x1-s*thickness/2,y1-c*thickness/2)-(x2+s*thickness/2,y2+c*thickness/2),colour,bf End Scope #EndMacro #MACRO display(_a,_b,_c,_d,_e,_f,_g) x=x+2*sz If _a=1 Then :thickline(x,y,(x+sz),y,clr,(sz/5),img):End If If _b=1 Then :thickline((x+sz),y,(x+sz),(y+sz),clr,(sz/5),img):End If If _c=1 Then :thickline((x+sz),(y+sz),(x+sz),(y+2*sz),clr,(sz/5),img):End If If _d=1 Then :thickline((x+sz),(y+2*sz),x,(y+2*sz),clr,(sz/5),img):End If If _e=1 Then :thickline(x,(y+2*sz),x,(y+sz),clr,(sz/5),img):End If If _f=1 Then :thickline(x,(y+sz),x,y,clr,(sz/5),img):End If If _g=1 Then :thickline(x,(y+sz),(x+sz),(y+sz),clr,(sz/5),img):End If #EndMacro For z As Integer=0 To Len(t)-1 Select Case As Const t[z] Case 48 :display(1,1,1,1,1,1,0) '"0" Case 49 :display(0,1,1,0,0,0,0) '"1" Case 50 :display(1,1,0,1,1,0,1) '"2" Case 51 :display(1,1,1,1,0,0,1) '"3" Case 52 :display(0,1,1,0,0,1,1) '"4" Case 53 :display(1,0,1,1,0,1,1) '"5" Case 54 :display(1,0,1,1,1,1,1) '"6" Case 55 :display(1,1,1,0,0,0,0) '"7" Case 56 :display(1,1,1,1,1,1,1) '"8" Case 57 : display(1,1,1,1,0,1,1) '"9" Case 58 '":" Circle((x+2*sz),(y+sz/2)),(sz/5),clr,,,,f Circle((x+2*sz),(y+1.5*sz)),(sz/5),clr,,,,f x=x+sz Case 45 :display(0,0,0,0,0,0,1) '"-" Case 46 '"." Circle((x+2*sz),(y+1.9*sz)),(sz/5),clr,,,,f x=x+sz Case 32 '" " x=x+sz End Select Next z End Sub Function lineto(a As V3,b As v3,L As Single) As v3 Var u=(b-a).unit Return a+L*u End Function Sub drawballs(ball() As _object,pocket() As v3,s As String="",ptb As Integer,cpu As Integer,V As V3,ptp As Integer) Var r=2*ball(1).radius For n As Integer=LBound(ball) To Ubound(ball) If cpu=1 And ptb<>0 And ptp<>0 Then If n=ptb Then Dim As v3 u=(pocket(ptp)-ball(ptb).position) u=u.unit Dim As Single l=ball(ptb).velocity.length ball(n).velocity=l*u End If End If ball(n).position=ball(n).position+ball(n).velocity If n<>Ubound(ball) Then If ball(n).velocity<>vct(0,0,0) Then If Len(s)<11 Then s=s+Str(ball(n).colour) End If End If End If If Len(s) Then ball(Ubound(ball)).mass=1 End If ORB(ball(n).position.x,ball(n).position.y,ball(n).radius,ball(n).colour) Var k=map(0,30,ball(n).velocity.length,.001,0) ball(n).velocity=(.99+k)*ball(n).velocity If (ball(n).velocity).length<.2 Then ball(n).velocity=vct(0,0,0) End If Next n End Sub Sub DrawImage(z() As Line,im As Any Pointer=0) Line im,(.1*xres,.1*yres)-(.9*xres,.9*yres),Rgb(0,80,0),bf'table For n As Integer=LBound(z) To Ubound(z) Line im,(z(n).v1.x,z(n).v1.y)-(z(n).v2.x,z(n).v2.y),Rgb(00,85,0) Next n For k As Integer=0 To 5 Line im,(.09*xres-k,.09*yres-k)-(.91*xres+k,.91*yres+k),Rgb(100,50,0),b'outside Next k Dim As Uinteger back=RGB(0,0,70) Paint im,(5,5),back,Rgb(100,50,0) Circle im,(.09*xres,.09*yres),45,back,,,,f Circle im,(.09*xres,.91*yres),45,back,,,,f Circle im,(.91*xres,.09*yres),45,back,,,,f Circle im,(.91*xres,.91*yres),45,back,,,,f Circle im,(.5*xres,.08*yres),30,back,,,,f Circle im,(.5*xres,.92*yres),30,back,,,,f Circle im,(.2*xres,.05*yres),20 Draw String im,(.24*xres,.05*yres),"<-Helper" Line im,(.395*xres,.025*yres-7)-(.605*xres,.025*yres+7),Rgb(200,200,200),b 'rack Line im,(.02*xres,.1*yres)-(.07*xres,.31*yres),Rgb(100,100,100),b Draw String im,(.31*xres,.025*yres),"Speed ->" Draw String im,(.63*xres,.025*yres),"<- Speed" Circle im,(.8*xres,.025*yres),8,Rgb(200,100,00),,,,f Draw String im,(.82*xres,.025*yres),"<-- STRIKE" Draw String im,(10,.75*yres),"Scores" Draw String im,(10,.5*yres),"Messages" 'screw ORB(.04*xres,.4*yres,.04*xres,whiteball,,,,,im) Draw String im,(.03*xres,.33*yres),"Top" Draw String im,(.025*xres,.47*yres),"Screw" Line im,(.04*xres,.35*yres)-(.04*xres,.45*yres) End Sub Sub drawcircles(c() As Circle,moveflag As Integer,startflag As Integer) If moveflag=0 Then c(2).col=RGB(255,0,200) Else c(2).col=RGB(200,200,200) Circle(c(1).x,c(1).y),c(1).r,c(1).col,,,,f Circle(c(2).x,c(2).y),c(2).r/3,c(2).col,,,,f If moveflag=0 Then Circle(c(4).x,c(4).y),c(4).r,c(4).col,,,,f'cue If startflag Then For n As Integer=0 To 200 Step 3 Var p=lineto(Type<V3>(c(4).x,c(4).y),Type<v3>(c(2).x,c(2).y),-n) Circle(p.x,p.y),4+n/100,Rgb(100,50+n/4,0),,,,f Next n End If End If Circle(c(5).x,c(5).y),c(5).r,c(5).col,,,,f Circle(c(6).x,c(6).y),c(6).r,c(6).col,,,,f End Sub 'SCREEN MOUSE Sub _line(x1 As Integer,y1 As Integer,x2 As Integer,y2 As Integer,l As Integer,col As Uinteger,Byref xp As Integer=0,Byref yp As Integer=0) Dim As Integer diffx=x2-x1,diffy=y2-y1,ln=Sqr(diffx*diffx+diffy*diffy) If ln=0 Then ln=1e-6 Dim As Single nx=diffx/ln,ny=diffy/ln xp=x1+l*nx:yp=y1+l*ny Line(x1,y1)-(xp,yp),col End Sub Sub Bmouse(mx As Integer,my As Integer,sz As Integer) Dim As Integer xp,yp _line(mx,my,mx+sz,my+.8*sz,sz,Rgb(50,50,50),xp,yp) _line(xp,yp,mx+sz/2,yp+.03*sz,.4*sz,Rgb(50,50,50),xp,yp) Var tx=xp,ty=yp _line(mx,my,mx,my+1.2*sz,sz,Rgb(50,50,50),xp,yp) _line(xp,yp,mx+sz/2,yp-sz/2,.4*sz,Rgb(50,50,50),xp,yp) _line(xp,yp,mx+sz/2,yp+sz/2,sz,Rgb(50,50,50),xp,yp) _line(xp,yp,xp+sz/2,yp-.4*sz,.2*sz,Rgb(50,50,50),xp,yp) _line(xp,yp,tx,ty,.95*sz,Rgb(50,50,50),xp,yp) Paint(mx+.1*sz,my+.2*sz),Rgb(200,00,00),Rgb(50,50,50) End Sub '================ CHECK SUBS =========================== Function fixspeed(v As V3,n As Single) As Single Dim As Single totdist=v.length,speed Var lngth=map(0,n*xres,totdist,0,20) speed=lngth If speed>20 Then speed=20 Return speed End Function Function pathtopocket2(all() As _object,Byval b As V3,Byval p As V3,Byref num As Integer=0) As Integer Dim As V3 tmp=vct(p-b) tmp=tmp.unit Dim As V3 dv=all(Lbound(all)).radius*tmp Dim As Line seg=Type<Line>(b+2.2*dv,p+2.2*dv) num=0 Dim As Single r=2*all(Lbound(all)).radius For n As Integer=LBound(all) To Ubound(all) If segment_distance(seg,all(n).position) < r Then Return 0 End If num=n Next n Return -1 End Function Function pathtoball(all() As _object,Byref num As _object,col As Uinteger,start As Integer) As Integer If all(start).colour=col Then num=all(start) Return start End If Return 0 End Function Function pathtoballFULL(all() As _object,Byref num As _object,col As Uinteger,start As Integer,finish As Integer) As Integer Dim As Single r=2*all(1).radius,sd Dim As V3 cueball=all(Ubound(all)).position For n1 As Integer=start To finish Dim As Integer retval If all(n1).colour=col Then Var d=(all(n1).position-cueball).length Var thisball=all(n1) For n2 As Integer=LBound(all) To Ubound(all)-1 retval=1 If n2<>n1 Then For k As Single=r/2 To d-r/2+1 Step 1 Dim As V3 v=lineto(cueball,thisball.position,k) If (v-all(n2).position).length<r Then retval=0:Exit For,For End If Next k End If Next n2 If retval=1 Then num=thisball retval=n1 Return retval End If'n<>n2 End If 'colour Next n1 Return 0 End Function Function pathtoballPART(all() As _object,Byref num As _object,col As Uinteger) As Integer Dim As Single r=2*all(1).radius,sd Dim As Integer start=1 Dim As V3 cueball=all(Ubound(all)).position go: For n1 As Integer=start To Ubound(all)-1 Dim As Integer retval If all(n1).colour=col Then Var d=(all(n1).position-cueball).length Var thisball=all(n1) For n2 As Integer=LBound(all) To Ubound(all)-1 If all(n2).colour=redball Or all(n2).colour=blackball Then retval=1 If n2<>n1 Then For k As Single=r/2 To d-r/2 Step 1 Dim As V3 v=lineto(cueball,thisball.position,k) If (v-all(n2).position).length<r Then retval=0:Exit For,For End If Next k End If End If Next n2 If retval=1 Then If start>= Ubound(all)-1 Then Return 0 num=thisball retval=n1 Return retval End If'n<>n2 End If 'colour Next n1 Return 0 End Function Function Dpath(all() As _object,b As V3,o2 As V3,o As V3) As Integer Dim As Single r=2*all(Ubound(all)).radius For n As Integer=LBound(all) To Ubound(all)-1 If all(n).position<>o Then If (all(n).position-o2).length<r Then Return 0 End If Next n Var d=(o2-b).length For n2 As Integer=LBound(all) To Ubound(all)-1 For k As Single=r+1 To d-1.5*r Dim As V3 v=lineto(b,o2,k) If (v-all(n2).position).length<r+1 Then Return 0 End If Next k Next n2 Return -1 End Function Function directpath(all() As _object, num As V3,num2 As V3) As Integer Dim As Single r=2*all(Ubound(all)).radius Var d=(num2-num).length For n2 As Integer=LBound(all) To Ubound(all)-1 For k As Single=r+1 To d-1*r-1 Dim As V3 v=lineto(num,num2,k) If (v-all(n2).position).length<r Then Return 0 End If Next k Next n2 Return -1 End Function Function straightpath(all() As _object, num As V3,num2 As V3) As Integer Dim As Single r=2*all(Ubound(all)).radius Var d=(num-num2).length For n2 As Integer=LBound(all) To Ubound(all)-1 For k As Single=r/2 To d' step 1 Dim As V3 v=lineto(num,num2,k) If (v-all(n2).position).length<r+1 Then Return 0 End If Next k Next n2 Return -1 End Function Function Bpath(all() As _object,Byref num As _object,v1 As V3,col As Uinteger) As Integer Dim As Single r=2*all(Ubound(all)).radius For n1 As Integer=LBound(all) To Ubound(all)-1 Dim As Integer retval If all(n1).colour=col Then Var d=(all(n1).position-v1).length Var thisball=all(n1) For n2 As Integer=LBound(all) To Ubound(all)-1 retval=1 If n2<>n1 Then For k As Single=r/2 To d-r/2 Step 1 Dim As V3 v=lineto(v1,thisball.position,k) If (v-all(n2).position).length<r Then retval=0:Exit For,For End If Next k End If Next n2 If retval=1 Then num=thisball retval=n1 Return retval End If'n<>n2 End If 'colour Next n1 Return 0 End Function 'check moving Function checkVELOCITY(ball() As _object) As Single Dim As Single ke For n As Integer=LBound(ball) To Ubound(ball) ke=ke+.5*ball(n).mass*ball(n).velocity*ball(n).velocity Next n Return ke End Function Sub respot(ball() As _object) Dim As V3 oldpos=vct(.7*xres,.5*yres,0),newpos=oldpos Dim As Integer flag st: flag=0 For n As Integer=LBound(ball) To Ubound(ball)-1 Var d=(newpos-ball(n).position).length If d<2*ball(Ubound(ball)).radius Then flag=1:Exit For Next n If flag=0 Then ball(Ubound(ball)).position=newpos:ball(Ubound(ball)).velocity=vct(0,0,0):Exit Sub Else newpos=oldpos+vct(intrange(0,.15*xres),intrange(-.25*yres,.25*yres),0) Goto st End If End Sub 'check potted Sub checkPOTS(ball() As _object,pocket() As V3,pocket2() As V3,Byref Pflag As Integer,trackblack As Integer) Dim As Integer k,f For n1 As Integer=LBound(ball) To Ubound(ball) For n2 As Integer=LBound(pocket) To Ubound(pocket) Dim As Circle c=Type<Circle>(pocket(n2).x,pocket(n2).y,ball(Lbound(ball)).radius) Dim As Circle c2=Type<Circle>(pocket2(n2).x,pocket2(n2).y,ball(Lbound(ball)).radius) If incircle(c,ball(n1).position.x,ball(n1).position.y) Or incircle(c2,ball(n1).position.x,ball(n1).position.y) Then potbeep(&h00000040L) k=n1 Exit For,For End If Next n2 Next n1 If k=0 Then For n As Integer=LBound(ball) To Ubound(ball)-1 If ball(n).position.x<.09*xres Or ball(n).position.x>.91*xres Or _ ball(n).position.y<.09*yres Or ball(n).position.y>.91*yres Then k=n:f=1:Exit For End If Next n End If If k=UBound(ball) Then pflag=1 ball(Ubound(ball)).velocity=vct(0,0,0) ball(Ubound(ball)).position=vct(.05*xres,.6*yres,0) End If If k=trackblack Then Pflag=13:Exit Sub If k <>0 And Pflag<>1 Then If ball(k).colour=yellowball Then Pflag=2 If ball(k).colour=redball Then Pflag=3 If f Then pflag=4 ball(k).radius=0:ball(k).mass=0 arraydelete(ball,k) End If End Sub Sub bsort(array() As Kick) For p1 As Integer = 1 To Ubound(array) - 1 For p2 As Integer = p1 + 1 To Ubound(array) If array(p1).block>array(p2).block Then Swap array(p1),array(p2) Next p2 Next p1 End Sub #MACRO show() Screenlock Cls Put(0,0),im,Pset drawballs(balls(),vpockets(),s,catchptb,cpu,Catchvector,w2.pnum) check_ball_to_ball_collisions(balls()) check_ball_to_line_collisions(edge(),balls()) drawcircles(circ(),moveflag,startflag) If lineflag=1 Then Line(balls(Ubound(balls)).position.x,balls(Ubound(balls)).position.y)-(circ(2).x,circ(2).y),Rgba(255,255,255,200),,&b01 Var BaL=vct(balls(Ubound(balls)).position.x,balls(Ubound(balls)).position.y) Var tgt=vct(circ(2).x,circ(2).y) temp=lineto(bal,tgt,-balls(1).radius)''''''''''''''''''' Var lngth=.6*xres-.4*xres Qs=lineto(temp,tgt,-lngth/3) Line(temp.x,temp.y)-(Qs.x,Qs.y),Rgb(200,0,200) End If If msgflag=0 Then Draw String(.51*xres,.9*yres),"<-- Pick up this target" digits(round(speed,1),.48*xres,.05*yres,Rgb(200,200,200),.5*balls(Ubound(balls)).radius) Draw String(10,30),"FPS = " & fps Draw String (5,50),test.s,test.c digits(Str(scoreRED),.065*yres,.8*yres,Rgb(200,0,0),yres/75) digits(Str(scoreYellow),.005*yres,.8*yres,Rgb(200,200,0),yres/75) Draw String(5,.52*yres),message.s,message.c If strikeflag=1 Then Circle(circ(3).x,circ(3).y),8,circ(3).col,,,,f:strikeflag=0 For n As Integer=LBound(balls) To Ubound(balls) If balls(n).colour=blackball Then trackblack=n Next n If cpu=0 And moveflag=0 And help=-1 Then For n1 As Integer=LBound(balls) To Ubound(balls)-1 For n2 As Integer=LBound(Vpockets) To Ubound(Vpockets) Dim As Integer path Dim As _object oo Dim As V3 o3 If balls(n1).colour=redball Then Var pp= pathtopocket2(balls(),balls(n1).position,Vpockets(n2)) Var pb=pathtoball(balls(),oo,redball,n1) If pp And pb Then Dim As V3 tocue=(balls(n1).position-balls(Ubound(balls)).position) Var ang=tocue dot (Vpockets(n2)-balls(n1).position) ang=ang/(tocue.length*(Vpockets(n2)-balls(n1).position).length) If Acos(ang)<1 Then Dim As V3 topocket=(Vpockets(n2)-oo.position) topocket=topocket.unit o3=oo.position-1.9*balls(Ubound(balls)).radius*topocket If ontable(o3) Then path=Dpath(balls(),balls(Ubound(balls)).position,o3,oo.position) End If End If If pp And path And pb Then Circle(o3.x,o3.y),5,Rgba(0,0,200,50),,,,f Line(balls(n1).position.x,balls(n1).position.y)-(vpockets(n2).x,Vpockets(n2).y),Rgba(200,200,200,100) End If End If End If Next n2 Next n1 End If '========================================== If test.s="PLAYER" Then Bmouse(mx,my,1.3*balls(Ubound(balls)).radius) 'tempdrawpockets(Vpockets(),rgb(200,200,200)) Screenunlock #EndMacro #MACRO mouse(P,condition,flag) Dim As Integer x=mx,y=my,dx,dy While mb = 1 Getmouse mx,my,,mb show() If (condition) Then If mx<>p.x Or my<>p.y Then dx = mx - p.x dy = my - p.y x = mx y = my If flag<>2 Then p.x=mx If flag=3 Then'screw p.x=.04*xres Dim As V3 tmp If segment_distance(TS,Type<V3>(mx,my),tmp)<5 Then p.y=tmp.y p.x=.04*xres balls(Ubound(balls)).mass=map(.35*yres,.45*yres,p.y,1.5,.5) End If End If If flag=2 Then'cue Dim As Line sl=Type<Line>(temp,Qs) Dim As V3 tmp If segment_distance(sl,Type<v3>(mx,my,0),tmp)<5 Then p.y=tmp.y p.x=tmp.x startflag=1 circ(4)=Type<Circle>(p.x,p.y,5,Rgb(0,0,255)) Var totlngth=(temp-Qs).length Var seglength=(temp-Type<v3>(p.x,p.y,0)).length speed=map(0,totlngth,seglength,0,20) lastspeed=speed circ(1).x=map(0,20,speed,.4*xres,.6*xres) End If End If If flag=0 Then'speed speed=map((.4*xres),(.6*xres),p.x,0,20) lastspeed=speed End If If flag=1 Then'target cpu=0 p.y=my If moveflag=0 Then lineflag=1 dirn=(vct(p.x-balls(Ubound(balls)).position.x,p.y-balls(Ubound(balls)).position.y)).unit End If End If End If End If Wend #EndMacro #MACRO player() circ(5).y=map(1.5,.5,balls(Ubound(balls)).mass,.35*yres,.45*yres) If test.s="COMPUTER" And cb=0 Then test.s="PLAYER":test.c=redball show() If cpu=0 Then speed=lastspeed:circ(1).x=map(0,20,speed,.4*xres,.6*xres) 'highlght target If moveflag=0 And mb=1 Then Circle(circ(2).x,circ(2).y),balls(1).radius,Rgb(100,100,100) 'speed If incircle(Circ(1),mx,my) And cpu=0 Then If mb=1 Then circ(4)=Type<Circle>(0,0,0,0) mouse(circ(1), mx>.4*xres And mx<.6 * xres And my<.035*yres,0) End If 'target If incircle(Circ(2),mx,my) Then If moveflag=0 Then If mb=1 Then circ(4)=Type<Circle>(0,0,0,0) vflag=1 mouse(circ(2), mx>1 And mx<xres-1 And my<yres-1 And my>1,1) End If End If 'strike If moveflag=0 And vflag=1 Then Var LB=Type<Circle>(balls(Ubound(balls)).position.x,balls(Ubound(balls)).position.y,.8*balls(1).radius) If incircle(Circ(3),mx,my) Or incircle(LB,mx,my) And cpu=0 Then If mb=1 Then circ(4)=Type<Circle>(0,0,0,0) strikeflag=1 startflag=1 If mb=1 Then potred=0 lineflag=0 msgflag=1 vflag=0 balls(Ubound(balls)).velocity=speed*dirn End If End If End If Dim As Line sl=Type<Line>(temp,Qs) If segment_distance(sl,Type<V3>(mx,my))<5 And mb=1 Then circ(4)=Type<Circle>(mx,my,5) End If If incircle(Circ(4),mx,my) Then If lineflag=1 Then cpu=0 mouse(circ(4),1=1,2) End If End If If incircle(circ(5),mx,my) And cpu=0 Then mouse(circ(5),1=1,3) End If If incircle(circ(6),mx,my) Then If mb=1 Then If help=1 Then help=-1:circ(6).col=RGB(0,0,200) End If If startflag=1 Then If moveflag=0 And lineflag=0 And strikeflag=0 Then play=0 If potred=1 Then play=1 End If End If #EndMacro #MACRO compute() help=1:circ(6).col=RGB(0,0,50) test.s="COMPUTER":test.c=yellowball balls(Ubound(balls)).mass=1 circ(5).y=map(1.5,.5,balls(Ubound(balls)).mass,.35*yres,.45*yres) show() Dim As Integer start=1,interflag ptp=0 block=0 sound(400,1) start=1 speed=10 Redim w(0) begin: Do ptb=0 If numyellow>0 Then ptb=pathtoball(balls(),o,yellowball,start):If ptb Then Exit Do'FULL Else ptb=pathtoball(balls(),o,blackball,start):If ptb Then Exit Do End If Exit Do Loop If ptb Then 'CHECK POT For n2 As Integer=LBound(Vpockets) To Ubound(Vpockets) Dim As V3 tocue=(o.position-balls(Ubound(balls)).position),o2 Var ang=tocue dot (Vpockets(n2)-o.position) ang=ang/(tocue.length*(Vpockets(n2)-o.position).length) If Acos(ang)<block Then ptp=0 ptp= pathtopocket2(balls(),o.position,Vpockets(n2)) Dim As Integer path If ptp Then Dim As V3 topocket=(Vpockets(n2)-o.position) topocket=topocket.unit o2=o.position-1.75*balls(Ubound(balls)).radius*topocket path=Dpath(balls(),balls(Ubound(balls)).position,o2,o.position) If path Then Sleep 50 Redim Preserve w(1 To Ubound(w)+1) With w(Ubound(w)) .o=o.position .pnum=n2 .block=block .ballnumber=ptb End With End If End If End If Next n2 End If'ptb While block<=1.5 block=block+.1 Goto begin Wend While start<=UBound(balls)-1 start=start+1:block=0:Goto begin Wend If Ubound(w)<>0 Then bsort(w()) w2=w(Lbound(w)) interflag=1 catchptb=w2.ballnumber Var topocket=(Vpockets(w2.pnum)-w2.o) Catchvector=topocket topocket=topocket.unit w2.o=w2.o-1.75*balls(Ubound(balls)).radius*topocket Var cuetoball=w2.o-balls(Ubound(balls)).position Dim As Single totdist=catchvector.length+cuetoball.length Var lngth=map(0,1.5*xres,totdist,0,20) Var f=map(0,1.5,w2.block,1,1.5) speed=f*lngth If speed>20 Then speed=20 dirn=cuetoball.unit End If 'DIRECT If interflag=0 Then If numyellow>0 Then ptb=pathtoballFULL(balls(),o,yellowball,1,Ubound(balls)-1) Else ptb=pathtoballFULL(balls(),o,blackball,1,Ubound(balls)-1) End If If ptb <>0 Then dirn=(o.position-balls(Ubound(balls)).position).unit Var totdist=(o.position-balls(Ubound(balls)).position).length speed=fixspeed((o.position-balls(Ubound(balls)).position),1) interflag=1 End If End If If interflag=0 Then 'indirect If numyellow>0 Then ptb=pathtoballPART(balls(),o,yellowball) Else ptb=pathtoballPART(balls(),o,blackball) End If If ptb<>0 Then dirn=(o.position-balls(Ubound(balls)).position).unit interflag=1 End If speed=12 End If If interflag=0 Then Dim As Uinteger clr If numyellow>0 Then clr=yellowball Else clr=blackball Dim As V3 cueball=balls(Ubound(balls)).position,p 'Glance hit For n As Integer=1 To Ubound(balls)-1 If balls(n).colour=clr Then Var v=balls(n).position-cueball Var norm=v.unit Swap norm.x,norm.y:norm.x=-norm.x p=balls(n).position+1.9*balls(Ubound(balls)).radius*norm ptb=directpath(balls(),p,cueball) If ptb Then dirn=p-cueball:dirn=dirn.unit:speed=fixspeed(v,1.5):interflag=1:Goto cont3 p=balls(n).position-1.9*balls(Ubound(balls)).radius*norm ptb=directpath(balls(),p,cueball) If ptb Then dirn=p-cueball:dirn=dirn.unit:speed=fixspeed(v,1.5):interflag=1:Goto cont3 End If'colour Next n End If cont3: 'snookered If interflag=0 Then Dim As Integer path Dim As V3 cueball=balls(Ubound(balls)).position Var r=2*balls(Ubound(balls)).radius Dim As Single totlen For l As Integer=1 To 6 Dim As V3 perp If l=1 Or l=2 Then perp=vct(0,1,0) If l=4 Or l= 5 Then perp=vct(0,1,0) If l=3 Or l= 6 Then perp=vct(1,0,0) Var V1=edge(l).v1,V2=edge(l).v2 Var dist=(V1-V2).length For k As Single=0 To dist Step 3 path=0 Dim As V3 v=lineto(V1,V2,k) path=straightpath(balls(),cueball,v) If path Then path=0 If numyellow>0 Then path=Bpath(balls(),o,v,yellowball) Else path=Bpath(balls(),o,v,blackball) End If totlen=(v-cueball).length End If If path Then Dim As V3 leg1=(v-cueball),leg2=(o.position-v) leg1=leg1.unit:leg2=leg2.unit Var dt=Abs(Abs(leg1 dot perp)-Abs(leg2 dot perp)) If dt <.005 Then dirn=(v-cueball).unit ptb=path totlen=totlen+(o.position-v).length Var lngth=map(0,1.5*xres,totlen,0,20) speed=lngth If speed>20 Then speed=20 interflag=1 Exit For,For End If End If Next k Next l End If 'ptb=0 'no hit or pot If interflag=0 Then Dim As Single dist=2*xres,k For n As Integer=1 To Ubound(balls)-1 Var d=(balls(Ubound(balls)).position-balls(n).position).length If dist>d Then dist=d:k=n Next n speed=fixspeed(balls(Ubound(balls)).position-balls(k).position,1.5) dirn=-1*(balls(Ubound(balls)).position-balls(k).position).unit End If circ(1).x=map(0,20,speed,.4*xres,.6*xres) balls(Ubound(balls)).velocity=speed*dirn strikeflag=1 startflag=0 play=1 #EndMacro Dim As Any Pointer im=ImageCreate(xres,yres,Rgb(0,50,0)) Redim As _object balls(1 To 16) Dim As Line edge(1 To 6) Dim As Line TS=Type<Line>(vct(.04*xres,.35*yres),vct(.04*xres,.45*yres)) Dim As Circle circ(1 To 4+2) Dim As V3 pockets(1 To 6) Dim As V3 Vpockets(1 To 6) Dim As V3 Opockets(1 To 6) setcircles(circ()) setup(balls()) setedges(edge()) DrawImage(edge(),im) setpockets(pockets(),Vpockets(),Opockets(),balls(1).radius) Dim As Integer mx,my,mb Dim As String i Dim As Integer fps,msgflag,Vflag,Moveflag,lineflag,potflag,circflag Dim As Integer strikeflag,startflag Dim As Single speed=10,block,lastspeed=10 Dim As V3 dirn=vct(0,0,0),temp,Qs,Catchvector Dim As Integer play=1,cpu Dim As Integer trackblack=100 Dim As _object o Dim As Integer ptb,catchptb,messageflag,cueflag,ptp,help=1 Dim As Integer numyellow=7,numred=7 Dim As String s Dim As msg message,test:test.s="PLAYER":test.c=redball Dim As Integer scoreRED,scoreYellow Dim As v3 cueball Redim As kick w(0) Dim As kick w2 Windowtitle "Version " &__FB_VERSION__ Setmouse ,,0 Do Getmouse mx,my,,mb i=InKey potflag=0 checkPOTS(balls(),pockets(),Opockets(),potflag,trackblack) #MACRO pots() Select Case potflag Case 1'cue If cpu=1 Then scorered+=1:potred=1:potyellow=0 If cpu=0 Then scoreyellow+=1:potyellow=1:potred=0 cueflag=1:help=1:circ(6).col=RGB(0,0,50) If cpu =1 Then play=1 Case 2 'yellow Static As Integer y:w2.pnum=0 Dim As Integer rad=balls(1).radius/2 ORB(.03*xres,yres/8+2*rad*y,rad,Rgb(200,200,0),,,,,im) y=y+1:help=1:circ(6).col=RGB(0,0,50) numyellow=numyellow-1 If cpu=0 And cueflag=0 Then scoreyellow+=1:potred=0:potyellow=1 End If If cpu=1 And cueflag=0 Then If potred<>1 Then potyellow=1 scoreYellow+=1 End If Case 3 'red Static As Integer r:w2.pnum=0 Dim As Integer rad=balls(1).radius/2 ORB(.06*xres,yres/8+2*rad*r,rad,Rgb(200,0,0),,,,,im) r=r+1:help=1:circ(6).col=RGB(0,0,50) numred=numred-1 If cpu=1 And cueflag=0 Then scorered+=1:potred=1:potyellow=0 If cpu=0 And cueflag=0 Then If potyellow<>1 Then potred=1 scoreRed+=1 End If Case 4 ptb=0 If cpu=1 Then scorered+=1 If cpu=0 Then scoreyellow+=1 Case 13'black Dim As Integer nr,ny Dim As String msg For n As Integer=LBound(balls) To Ubound(balls) If balls(n).colour=redball Then nr=nr+1 If balls(n).colour=yellowball Then ny=ny+1 Next n If nr=0 And cpu=0 Then scorered+=5:msg="Check scores" If ny=0 And cpu=1 Then scoreyellow+=5:msg="Check scores" If ny And cpu Then msg="Player wins" If nr And cpu=0 Then msg="Computer wins" show() Draw String (xres/2,yres/2),"Game over -- " &msg Exit Do Case Else End Select #EndMacro Var cb=checkVELOCITY(balls()) pots() If cb=0 Then If Instr(message.s,"Red") Or Instr(message.s,"Seek") And cpu=1 Then scorered+=1 If Instr(message.s,"Yellow") Or Instr(message.s,"Seek") And cpu=0 Then scoreyellow+=1 If Instr(message.s,"Black") And cpu=1 And numyellow>0 Then scorered+=1 If Instr(message.s,"Black") And cpu=0 And numred>0 Then scoreyellow+=1 s="":catchptb=0 message.s=LCase(message.s) End If If cb=0 Then Moveflag=0 Else Moveflag=1 If cb=0 And cueflag=1 Then cueflag=0:respot(balls()) If cpu=1 Then If message.s="red ball" Or message.s="black ball" Then strikeflag=1 startflag=0 play=1 potyellow=0:potred=1 w2.pnum=0 End If message.s="" End If If cpu=0 Then If message.s="yellow ball" Or message.s="black ball" Then play=0 message.s="" End If If play =1 Then If cpu=0 Then If cb<>0 Then If Len(s)=0 Then message.s="Seek":message.c=redball Else message.s="" If Len(s)<> 0 Then If Mid(s,6,1)<>"1" Then message.s="Yellow ball":message.c=yellowball If Mid(s,6,1)="0" Then message.s="Black ball":message.c=RGB(100,100,100) End If End If End If If cpu=1 Then If cb<>0 Then If Len(s)=0 Then message.s="Seek":message.c=yellowball Else message.s="" If Len(s)<>0 Then If Mid(s,6,1)<>"8" Then message.s="Red ball":message.c=redball If Mid(s,6,1)="0" Then message.s="Black ball":message.c=RGB(100,100,100) End If End If End If player() End If If play=0 Or potyellow=1 And cb=0 Then potyellow=0 cpu=1 Sleep 500 compute() End If Sleep Regulate(60,fps),1 Loop Until I=Chr(27) Screenunlock Sleep Imagedestroy im