Code archives/Algorithms/circle to arc.
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
OO circle to arc interaction with bounce. linear movement only, does not integrate time movement, not too difficult to integrate. | |||||
SuperStrict 'Create game Object Type Tgame Field stageW:Float Field stageH:Float Field maxV:Float Field gravity:Float Field LastTime:Float Field arc:TArc Field ball:Tball Method New() stageW = 480 stageH = 400 ball = Tball.Create(5,5,10,10,40) arc = Tarc.Create(170, 195.5, 60,-60,120) End Method Method update() Local length:Float = ball.length ball.ball2ArcCollision(arc,length) End Method 'Function To draw the points, lines And show text Method drawAll() 'draw ball path 'DrawLine ball.p2.x,ball.p2.y,ball.p1.x,ball.p1.y ball.display() arc.display() End Method End Type Type Tpoint Field x:Float Field y:Float End Type Type Tvector Field p0:Tpoint Field p1:Tpoint Field length:Float Field dx:Float Field dy:Float Field lx:Float Field ly:Float Field vx:Float Field vy:Float Field b:Float Field f:Float Field m:Float Field airf:Float Field lastTime:Float Field timeFrame:Float Method New() p0 = New Tpoint p1 = New Tpoint End Method 'Function To find all parameters For the vector Method update( frompoints:Int=False) 'x And y components If(frompoints) vx=p1.x-p0.x vy=p1.y-p0.y Else p1.x=p0.x+vx p1.y=p0.y+vy EndIf 'length of vector Length=Sqr(vx*vx+vy*vy) 'normalized unit-sized components If(Length>0) dx=vx/Length dy=vy/Length Else dx=0 dy=0 EndIf End Method 'find New vector bouncing from v2 Method bounce:Tvector(v2:Tvector) 'projection of v1 on v2 Local dp:Float = vx*v2.dx+vy*v2.dy Local vx1:Float = dp*v2.dx Local vy1:Float = dp*v2.dy 'projection of v1 on v2 normal dp = vx*v2.lx+vy*v2.ly Local vx2:Float = dp*v2.lx Local vy2:Float = dp*v2.ly 'reverse projection on v2 normal Local p2l:Float = Sqr(vx2*vx2+vy2*vy2) 'add the projections vx=vx1+v2.lx*p2l vy=vy1+v2.ly*p2l End Method Method display() DrawLine p0.x,p0.y,p1.x,p1.y End Method End Type Type Tball Extends Tvector Field vn:Tvector Field v2:Tvector Field v3:Tvector Field v:Tvector Field vbounce:Tvector Field p2:Tpoint Field r:Float Method New() v = New Tvector vn = New Tvector v2 = New Tvector v3 = New Tvector vbounce = New Tvector p2 = New Tpoint End Method Function Create:Tball(x1:Float,y1:Float,x2:Float,y2:Float,r:Float) Local b:Tball = New Tball b.p0.x = x1 b.p0.y = y1 b.p1.x = x2 b.p1.y = y2 b.r = r b.update(True) Return b End Function Method display() For Local a:Float = 0 Until 360 Local vx:Float = Cos(a)*r Local vy:Float = Sin(a)*r Plot p0.x+vx,p0.y+vy Next End Method 'find collision between balls Method ballvsBall:Tvector(pa:Tpoint, r:Float,Tlen:Float Var) 'dp for projection of vector between center of points of balls along movement vector Local dp:Float = (pa.x-p0.x) * dx + (pa.y-p0.y) * dy 'vector To center of arc in direction of movement vectors normal vn.p0.x = p0.x+dp*dx vn.p0.y = p0.y+dp*dy vn.p1.x=pa.x vn.p1.y=pa.y vn.update(True) 'sum of radius Local totalRadius:Float=Self.r+r 'check If vn is shorter Then combined radiuses Local diff:Float = totalRadius-vn.Length If (diff>0) 'collision 'amount To move back moving ball Local moveBack:Float=Sqr(totalRadius*totalRadius-vn.Length*vn.Length) v2.p0.x = p0.x v2.p0.y = p0.y v2.p1.x = vn.p0.x-moveBack*dx v2.p1.y = vn.p0.y-moveBack*dy v2.update(True) 'check If on the movement vector If(v2.Length<Tlen And (v2.vx*vx+v2.vy*vy)>0) Return v2 EndIf EndIf Return Null End Method 'collision Method ball2ArcCollision(arc:Tarc,Tlen:Float) 'start To calculate movement Local vx4:Float,vy4:Float,vx5:Float,vy5:Float,len5:Float Local collision:Tvector=ballvsBall(arc.p0, arc.radius,Tlen) If collision 'collision point found vx5 = collision.p1.x - arc.p0.x vy5 = collision.p1.y - arc.p0.y len5 = Sqr(vx5*vx5+vy5*vy5) 'check If the point is on the Right side of vector between arc points 'vector between starting point of arc And collision point If Len5 > 0 vx4 = (arc.p0.x+vx5/len5*arc.radius)-arc.arc.p0.x vy4 = (arc.p0.y+vy5/len5*arc.radius)-arc.arc.p0.y Else vx4 = arc.p0.x - arc.arc.p0.x vy4 = arc.p0.y - arc.arc.p0.y EndIf If(vx4*arc.arc.dy-vy4*arc.arc.dx) >= 0 p2.x=collision.p1.x p2.y=collision.p1.y v.vx = p2.x - arc.p0.x v.vy = p2.y - arc.p0.y v.update(False) vbounce.dx = v.dy vbounce.dy = -v.dx vbounce.lx = v.dx vbounce.ly = v.dy Else 'Not on the arc collision = Null EndIf EndIf 'need To check with other side of arc too If collision = Null If(vn.Length < arc.radius) 'amount To move back moving ball Local r:Float=arc.radius-r Local moveForward:Float=Sqr(r*r-vn.Length*vn.Length) v3.p0.x = p0.x v3.p0.y = p0.y v3.p1.x = vn.p0.x+moveForward*dx v3.p1.y = vn.p0.y+moveForward*dy v3.update(True) 'check If on the movement vector If(v3.Length<=Tlen And (v3.vx*vx+v3.vy*vy)>0) 'collision point found vx5 = v3.p1.x - arc.p0.x vy5 = v3.p1.y - arc.p0.y len5 = Sqr(vx5*vx5+vy5*vy5) 'check If the point is on the Right side of vector between arc points 'vector between starting point of arc And collision point If len5>0 vx4 = (arc.p0.x+vx5/len5*arc.radius) - arc.arc.p0.x vy4 = (arc.p0.y+vy5/len5*arc.radius) - arc.arc.p0.y Else vx4 = arc.p0.x - arc.arc.p0.x vy4 = arc.p0.y - arc.arc.p0.y EndIf If (vx4*arc.arc.dy-vy4*arc.arc.dx) >= 0 p2.x=v3.p1.x p2.y=v3.p1.y collision=v3 v.vx = p2.x - arc.p0.x v.vy = p2.y - arc.p0.y v.update(False) vbounce.dx = -v.dy vbounce.dy = v.dx vbounce.lx = -v.dx vbounce.ly = -v.dy EndIf EndIf EndIf 'now we need To check If endpoints of arc are being hit Local nextCollision:Tvector = ballvsBall(arc.arc.p0, 0,Tlen) If(nextCollision) If(collision=Null Or nextCollision.Length<collision.Length) collision = nextCollision p2.x=nextCollision.p1.x p2.y=nextCollision.p1.y v.vx = p2.x - arc.arc.p0.x v.vy = p2.y - arc.arc.p0.y v.update(False) vbounce.dx = v.dy vbounce.dy = -v.dx vbounce.lx = v.dx vbounce.ly = v.dy EndIf EndIf nextCollision=ballvsBall(arc.arc.p1, 0,Tlen) If(nextCollision) If(collision=Null Or nextCollision.Length<collision.Length) collision=nextCollision p2.x=nextCollision.p1.x p2.y=nextCollision.p1.y v.vx = p2.x - arc.arc.p1.x v.vy = p2.y - arc.arc.p1.y v.update(False) vbounce.dx = v.dy vbounce.dy = -v.dx vbounce.lx = v.dx vbounce.ly = v.dy EndIf EndIf EndIf If collision Local vx1:Float = p2.x-p0.x Local vy1:Float = p2.y-p0.y Tlen :- Sqr(vx1*vx1+vy1*vy1) bounce(vbounce) p0.x = p2.x p0.y = p2.y update(False) p1.x = p2.x+dx*Tlen p1.y = p2.y+dy*Tlen ball2ArcCollision(arc,Tlen) Else If (p1.x>game.stageW+r) p1.x = -r Else If (p1.x<-r) p1.x = game.stageW+r EndIf If (p1.y>game.stageH+r) p1.y = -r Else If (p1.y<-r) p1.y = game.stageH+r EndIf p0.x = p1.x p0.y = p1.y update(False) EndIf End Method End Type Type Tarc Extends Tvector Field ang1:Float Field ang2:Float Field degrees:Float Field radius:Float Field stp:Float Field arc:Tvector Const RATE:Float = Pi/180.0 Method New() arc = New Tvector End Method Function Create:Tarc(x:Float,y:Float,r:Float,a1:Float,a2:Float) Local a:Tarc = New Tarc a.p0.x = x a.p0.y = y a.radius = r If a1 > a2 Local ta:Float = a2 a2 = a1 a1 = ta EndIf a.degrees = a2-a1 If a.degrees > 360 a.degrees = 360 a2 = a1+360 EndIf a.ang1 = a1 a.ang2 = a2 a.stp = 1.0/(RATE*r) a.findArc() Return a End Function 'find End points of the arc from angles Method findArc() 'vector between End points of the arc arc.p0.x = p0.x+radius*Cos(ang1) arc.p0.y = p0.y+radius*Sin(ang1) arc.p1.x = p0.x+radius*Cos(ang2) arc.p1.y = p0.y+radius*Sin(ang2) arc.update(True) End Method Method Display() Local Angle:Float = ang1 While Angle < (ang1+degrees) Plot p0.x + Cos(Angle) * radius, p0.y + Sin((Angle)) * radius Angle :+ stp Wend DrawOval p0.x-1,p0.y-1,2,2 End Method End Type 'Create game Object Global game:Tgame = New Tgame Graphics game.stageW,game.StageH Repeat Cls game.update() game.drawAll() Flip() Until KeyDown(key_escape) |
Comments
None.
Code Archives Forum