' From the book '2d game collision detection' ' line vs oriented rectangle collision Import mojo ' This is the collision class. ' Class collision ' Collision function ' Here the line vs oriented rectangle collision Function line_oriented_rectangle_collide:Bool( l:line, r:orientedrectangle) Local lr:rectangle lr = New rectangle( New vector2d(0,0), multiply_vector(r.halfextend,2)) Local l1:line = New line( New vector2d(0,0), New vector2d(0,0)) l1.base = subtract_vector(l.base,r.center) l1.base = rotate_vector(l1.base,-r.rotation) l1.base = add_vector(l1.base,r.halfextend) l1.direction = rotate_vector(l.direction,-r.rotation) Return line_rectangle_collide(l1,lr) End Function ' The rectangle vs Line Collision ' needed for line vs oriented rectangle collion Function line_rectangle_collide:Bool(l:line,r:rectangle) Local n:vector2d = rotate_vector_90(l.direction) Local dp1:Float,dp2:Float Local dp3:Float,dp4:Float Local c1:vector2d = r.origin Local c2:vector2d = add_vector(c1,r.size) Local c3:vector2d = New vector2d(c2.x,c1.y) Local c4:vector2d = New vector2d(c1.x,c2.y) c1 = subtract_vector(c1,l.base) c2 = subtract_vector(c2,l.base) c3 = subtract_vector(c3,l.base) c4 = subtract_vector(c4,l.base) dp1 = dot_product(n,c1) dp2 = dot_product(n,c2) dp3 = dot_product(n,c3) dp4 = dot_product(n,c4) Return (dp1 * dp2 <= 0) Or (dp2 * dp3 <= 0) Or (dp3 * dp4 <= 0) End Function ' ' helper functions ' Function dot_product:Float(a:vector2d,b:vector2d) Return a.x * b.x + a.y * b.y End Function Function rotate_vector_90:vector2d(v:vector2d) Local r:vector2d = New vector2d() r.x = -v.y r.y = v.x Return r End Function Function multiply_vector:vector2d(v:vector2d,scalar:Float) Local r:vector2d = New vector2d() r.x = v.x * scalar r.y = v.y * scalar Return r End Function ' Here is the function that rotates a vector. It returns the ' new rotated vector. ' Function rotate_vector:vector2d(v:vector2d,degrees:Float) Local r:vector2d = New vector2d() r.x = v.x * Cos(degrees) - v.y * Sin(degrees) r.y = v.x * Sin(degrees) + v.y * Cos(degrees) Return r End Function Function add_vector:vector2d(a:vector2d,b:vector2d) Local r:vector2d = New vector2d(0,0) r.x = a.x + b.x r.y = a.y + b.y Return r End Function Function subtract_vector:vector2d(a:vector2d,b:vector2d) Local r:vector2d = New vector2d() r.x = a.x - b.x r.y = a.y - b.y Return r End Function End Class Class vector2d ' x and y hold the position of the vector Field x:Int,y:Int Method New(x:Int,y:Int) Self.x = x Self.y = y End Method End Class Class rectangle ' origin is a vector that holds the x and y coordinates ' of the rectangle Field origin:vector2d ' size is a vector that holds the x(width) and ' y(height) of the rectangle Field size:vector2d Method New(origin:vector2d,size:vector2d) Self.origin = origin Self.size = size End Method Method draw() ' x1,y1,w,h are used to hold the rectangle ' location and size. Local x1:Int=origin.x Local y1:Int=origin.y Local w:Int=size.x Local h:Int=size.y DrawRect x1,y1,w,h End Method End Class Class line ' base is a vector which holds the origin ' of the line Field base:vector2d Field direction:vector2d Method New(base:vector2d,direction:vector2d) Self.base = base Self.direction = direction End Method Method draw() DrawLine base.x,base.y,direction.x,direction.y End Method End Class Class orientedrectangle Field center:vector2d Field halfextend:vector2d Field rotation:Float Method New(center:vector2d,halfextend:vector2d,rotation:Float) Self.center = center Self.halfextend = halfextend Self.rotation = rotation End Method Method draw() Local v1:vector2d,v2:vector2d,v3:vector2d,v4:vector2d 'topside v1 = New vector2d(-halfextend.x,-halfextend.y) v2 = New vector2d(halfextend.x,-halfextend.y) v1 = rotate_vector(v1,rotation) v2 = rotate_vector(v2,rotation) v1.x += center.x v1.y += center.y v2.x += center.x v2.y += center.y ' rightside v3 = New vector2d(halfextend.x,halfextend.y) v3 = rotate_vector(v3,rotation) v3.x += center.x v3.y += center.y ' bottom side v4 = New vector2d(-halfextend.x,halfextend.y) v4 = rotate_vector(v4,rotation) v4.x += center.x v4.y += center.y DrawLine v1.x,v1.y,v2.x,v2.y DrawLine v2.x,v2.y,v3.x,v3.y DrawLine v3.x,v3.y,v4.x,v4.y DrawLine v4.x,v4.y,v1.x,v1.y End Method Function rotate_vector:vector2d(v:vector2d,degrees:Float) Local r:vector2d = New vector2d() r.x = v.x * Cos(degrees) - v.y * Sin(degrees) r.y = v.x * Sin(degrees) + v.y * Cos(degrees) Return r End Function End Class ' col is the caller of the class collision. ' we use it to use the collision methods. Global col:collision = New collision Class MyGame Extends App Field angle:Float=0 Method OnCreate() SetUpdateRate(60) End Method Method OnUpdate() angle+=1 If angle > 360 Then angle=0 End Method Method OnRender() Cls 0,0,0 SetColor 255,255,255 'set up the line Local line1:line = New line( New vector2d(0,0), New vector2d(MouseX,MouseY)) 'set up the oriented rectangle (base, halfextend(size),angle) Local orect1:orientedrectangle orect1 = New orientedrectangle( New vector2d(320,200), New vector2d(100,50), angle) ' Here we test for collision If col.line_oriented_rectangle_collide(line1,orect1) DrawText "Line vs Oriented Rectangle Collision",0,0 Else DrawText "Line vs Oriented Rectangle NO Collision",0,0 End If ' Here we draw the line and oriented ' rectangle. line1.draw orect1.draw DrawText "Move the Mouse to test for Collision",DeviceWidth/2,0 End Method End Class Function Main() New MyGame() End Function
Artificial intelligence/templates/examples/rts/rpg/strategy ect. in MonkeyX/CerberusX language. You can download the free version of MonkeyX from itch.io or Cerberus-x.com The Flash applets will stop working in around 2020.
Sunday, March 5, 2017
Monkey-X - Collision - Line vs Oriented Rectangle - code example
Monkey-X - Collision - Line vs Line Segment - code example
' From the book '2d game collision detection' ' line vs line segment collision #rem If a line collides with a segment you only need to know if the segments end points lie on the same side of the line. If they do then a collision is impossible. #end Import mojo ' This is the collision class. ' Class collision ' Collision function Function line_segment_collide:Bool(l:line,s:segment) Return Not on_one_side(l,s) End Function ' ' helper functions ' Function on_one_side:Bool(axis:line,s:segment) Local d1:vector2d = subtract_vector(s.point1,axis.base) Local d2:vector2d = subtract_vector(s.point2,axis.base) Local n:vector2d = rotate_vector_90(axis.direction) Return dot_product(n,d1) * dot_product(n,d2) > 0 End Function Function subtract_vector:vector2d(a:vector2d,b:vector2d) Local r:vector2d = New vector2d() r.x = a.x - b.x r.y = a.y - b.y Return r End Function Function dot_product:Float(a:vector2d,b:vector2d) Return a.x * b.x + a.y * b.y End Function Function rotate_vector_90:vector2d(v:vector2d) Local r:vector2d = New vector2d() r.x = -v.y r.y = v.x Return r End Function End Class Class vector2d ' x and y hold the position of the vector Field x:Int,y:Int Method New(x:Int,y:Int) Self.x = x Self.y = y End Method End Class Class line ' base is a vector which holds the origin ' of the line Field base:vector2d Field direction:vector2d Method New(base:vector2d,direction:vector2d) Self.base = base Self.direction = direction End Method Method draw() DrawLine base.x,base.y,direction.x,direction.y End Method End Class Class segment ' point1 and point2 are two vectors. ' A vector has a x and y coordinate. Field point1:vector2d Field point2:vector2d Method New(point1:vector2d,point2:vector2d) Self.point1 = point1 Self.point2 = point2 End Method Method draw() DrawLine point1.x,point1.y,point2.x,point2.y End Method End Class ' col is the caller of the class collision. ' we use it to use the collision methods. Global col:collision = New collision Class MyGame Extends App Method OnCreate() SetUpdateRate(60) End Method Method OnUpdate() End Method Method OnRender() Cls 0,0,0 SetColor 255,255,255 Local line1:line = New line( New vector2d(0,0), New vector2d(MouseX,MouseY)) Local segline1:segment = New segment( New vector2d(100,200), New vector2d(400,100)) ' Here we test for collision If col.line_segment_collide(line1,segline1) DrawText "Line vs Line Segment Collision",0,0 Else DrawText "Line vs Line Segment NO Collision",0,0 End If line1.draw segline1.draw DrawText "Move the Mouse to test for Collision",DeviceWidth/2,0 End Method End Class Function Main() New MyGame() End Function
Monkey -X - Collision - Point vs Oriented Rectangle - code example
' From the book '2d game collision detection' ' point vs oriented rectangle collision Import mojo ' This is the collision class. ' Class collision ' Collision function ' The point vs oriented rectangle collision Function oriented_rectangle_point_collide:Bool( r:orientedrectangle, p:vector2d) Local lr:rectangle lr = New rectangle( New vector2d(0,0), multiply_vector(r.halfextend,2)) Local lp:vector2d = subtract_vector(p,r.center) lp = rotate_vector(lp,-r.rotation) lp = add_vector(lp,r.halfextend) Return point_rectangle_collide(lp,lr) End Function ' The point vs rectangle Collision ' needed for point in oriented rectangle collision Function point_rectangle_collide:Bool(p:vector2d,r:rectangle) Local left:Float = r.origin.x Local right:Float = left + r.size.x Local bottom:Float = r.origin.y Local top:Float = bottom + r.size.y Return left <= p.x And bottom <= p.y And p.x <= right And p.y <= top End Function ' ' helper functions ' Function multiply_vector:vector2d(v:vector2d,scalar:Float) Local r:vector2d = New vector2d() r.x = v.x * scalar r.y = v.y * scalar Return r End Function Function subtract_vector:vector2d(a:vector2d,b:vector2d) Local r:vector2d = New vector2d() r.x = a.x - b.x r.y = a.y - b.y Return r End Function ' Here is the function that rotates a vector. It returns the ' new rotated vector. ' Function rotate_vector:vector2d(v:vector2d,degrees:Float) Local r:vector2d = New vector2d() r.x = v.x * Cos(degrees) - v.y * Sin(degrees) r.y = v.x * Sin(degrees) + v.y * Cos(degrees) Return r End Function Function add_vector:vector2d(a:vector2d,b:vector2d) Local r:vector2d = New vector2d(0,0) r.x = a.x + b.x r.y = a.y + b.y Return r End Function End Class Class vector2d ' x and y hold the position of the vector Field x:Int,y:Int Method New(x:Int,y:Int) Self.x = x Self.y = y End Method End Class Class rectangle ' origin is a vector that holds the x and y coordinates ' of the rectangle Field origin:vector2d ' size is a vector that holds the x(width) and ' y(height) of the rectangle Field size:vector2d Method New(origin:vector2d,size:vector2d) Self.origin = origin Self.size = size End Method Method draw() ' x1,y1,w,h are used to hold the rectangle ' location and size. Local x1:Int=origin.x Local y1:Int=origin.y Local w:Int=size.x Local h:Int=size.y DrawRect x1,y1,w,h End Method End Class Class orientedrectangle Field center:vector2d Field halfextend:vector2d Field rotation:Float Method New(center:vector2d,halfextend:vector2d,rotation:Float) Self.center = center Self.halfextend = halfextend Self.rotation = rotation End Method Method draw() Local v1:vector2d,v2:vector2d,v3:vector2d,v4:vector2d 'topside v1 = New vector2d(-halfextend.x,-halfextend.y) v2 = New vector2d(halfextend.x,-halfextend.y) v1 = rotate_vector(v1,rotation) v2 = rotate_vector(v2,rotation) v1.x += center.x v1.y += center.y v2.x += center.x v2.y += center.y ' rightside v3 = New vector2d(halfextend.x,halfextend.y) v3 = rotate_vector(v3,rotation) v3.x += center.x v3.y += center.y ' bottom side v4 = New vector2d(-halfextend.x,halfextend.y) v4 = rotate_vector(v4,rotation) v4.x += center.x v4.y += center.y DrawLine v1.x,v1.y,v2.x,v2.y DrawLine v2.x,v2.y,v3.x,v3.y DrawLine v3.x,v3.y,v4.x,v4.y DrawLine v4.x,v4.y,v1.x,v1.y End Method Function rotate_vector:vector2d(v:vector2d,degrees:Float) Local r:vector2d = New vector2d() r.x = v.x * Cos(degrees) - v.y * Sin(degrees) r.y = v.x * Sin(degrees) + v.y * Cos(degrees) Return r End Function End Class ' col is the caller of the class collision. ' we use it to use the collision methods. Global col:collision = New collision Class MyGame Extends App ' This variable we use to rotate ' the oriented rectangle. Field angle:Float=0 Method OnCreate() SetUpdateRate(60) End Method Method OnUpdate() angle+=1 If angle>359 Then angle = 0 End Method Method OnRender() Cls 0,0,0 SetColor 255,255,255 Local center:vector2d = New vector2d(320,200) Local halfdivide:vector2d = New vector2d(100,50) Local orect1:orientedrectangle = New orientedrectangle( center, halfdivide, angle) ' Here we create a vector with the mouse it's coordinates. ' We use this point to test collsion with the orect. Local point:vector2d = New vector2d(MouseX,MouseY) ' Here we test for collision If col.oriented_rectangle_point_collide( orect1, point) DrawText "Point vs Oriented Rect Collision",0,0 Else DrawText "Point vs Oriented Rect NO Collision",0,0 End If orect1.draw DrawText "Move the Mouse to test for Collision",DeviceWidth/2,0 End Method End Class Function Main() New MyGame() End Function
Saturday, March 4, 2017
Monkey-X - Collision - Rectangle vs Line Segment - code example
' From the book '2d game collision detection' ' rectangle vs Line segment collision Import mojo ' This is the collision class. ' Class collision ' Collision function ' Rectangle vs Line Segment Function Function rectangle_segment_collide:Bool(r:rectangle,s:segment) ' First we test the line vs rectangle collision Local sline:line = New line() sline.base = s.point1 sline.direction = subtract_vector( s.point2, s.point1) If (Not line_rectangle_collide(sline,r)) Then Return False End If ' Here we test the ranges of the line ' with the rectangle Local rrange:range = New range() Local srange:range = New range() rrange.minimum = r.origin.x rrange.maximum = r.origin.x + r.size.x srange.minimum = s.point1.x srange.maximum = s.point2.x srange = sort_range(srange) If(Not overlapping_ranges(rrange,srange)) Then Return False End If rrange.minimum = r.origin.y rrange.maximum = r.origin.y + r.size.y srange.minimum = s.point1.y srange.maximum = s.point2.y srange = sort_range(srange) Return overlapping_ranges(rrange,srange) End Function ' The rectangle vs Line Collision ' needed for rectangle vs line segment Function line_rectangle_collide:Bool(l:line,r:rectangle) Local n:vector2d = rotate_vector_90(l.direction) Local dp1:Float,dp2:Float Local dp3:Float,dp4:Float Local c1:vector2d = r.origin Local c2:vector2d = add_vector(c1,r.size) Local c3:vector2d = New vector2d(c2.x,c1.y) Local c4:vector2d = New vector2d(c1.x,c2.y) c1 = subtract_vector(c1,l.base) c2 = subtract_vector(c2,l.base) c3 = subtract_vector(c3,l.base) c4 = subtract_vector(c4,l.base) dp1 = dot_product(n,c1) dp2 = dot_product(n,c2) dp3 = dot_product(n,c3) dp4 = dot_product(n,c4) Return (dp1 * dp2 <= 0) Or (dp2 * dp3 <= 0) Or (dp3 * dp4 <= 0) End Function ' ' helper functions ' Function sort_range:range(r:range) Local sorted:range = r If (r.minimum > r.maximum) sorted.minimum = r.maximum sorted.maximum = r.minimum End If Return sorted End Function Function overlapping_ranges:Bool(a:range,b:range) Return overlapping( a.minimum, a.maximum, b.minimum, b.maximum) End Function Function overlapping:Bool(mina:Float,maxa:Float,minb:Float,maxb:Float) Return minb <= maxa And mina <= maxb End Function Function rotate_vector_90:vector2d(v:vector2d) Local r:vector2d = New vector2d() r.x = -v.y r.y = v.x Return r End Function Function add_vector:vector2d(a:vector2d,b:vector2d) Local r:vector2d = New vector2d(0,0) r.x = a.x + b.x r.y = a.y + b.y Return r End Function Function subtract_vector:vector2d(a:vector2d,b:vector2d) Local r:vector2d = New vector2d() r.x = a.x - b.x r.y = a.y - b.y Return r End Function Function dot_product:Float(a:vector2d,b:vector2d) Return a.x * b.x + a.y * b.y End Function End Class Class vector2d ' x and y hold the position of the vector Field x:Int,y:Int Method New(x:Int,y:Int) Self.x = x Self.y = y End Method End Class Class line Field base:vector2d Field direction:vector2d Method New(base:vector2d,direction:vector2d) Self.base = base Self.direction = direction End Method Method draw() DrawLine base.x,base.y,direction.x,direction.y End Method End Class Class rectangle ' origin is a vector that holds the x and y coordinates ' of the rectangle Field origin:vector2d ' size is a vector that holds the x(width) and ' y(height) of the rectangle Field size:vector2d Method New(origin:vector2d,size:vector2d) Self.origin = origin Self.size = size End Method Method draw() ' x1,y1,w,h are used to hold the rectangle ' location and size. Local x1:Int=origin.x Local y1:Int=origin.y Local w:Int=size.x Local h:Int=size.y DrawRect x1,y1,w,h End Method End Class Class range Field minimum:Float Field maximum:Float Method New(minimum:Float,maximum:Float) Self.minimum = minimum Self.maximum = maximum End Method End Class Class segment ' point1 and point2 are two vectors. ' A vector has a x and y coordinate. Field point1:vector2d Field point2:vector2d Method New(point1:vector2d,point2:vector2d) Self.point1 = point1 Self.point2 = point2 End Method Method draw() DrawLine point1.x,point1.y,point2.x,point2.y End Method End Class ' col is the caller of the class collision. ' we use it to use the collision methods. Global col:collision = New collision Class MyGame Extends App Field angle:Float Method OnCreate() SetUpdateRate(30) End Method Method OnUpdate() angle+=1 If angle > 360 Then angle = 0 End Method Method OnRender() Cls 0,0,0 SetColor 255,255,255 ' this is a line segment setup Local point1:vector2d = New vector2d(MouseX,MouseY) Local point2:vector2d = New vector2d(MouseX+100,MouseY+100) ' ls is short for line segment Local ls:segment = New segment(point1,point2) ' ' This is the rectangle Local origin:vector2d = New vector2d(320,200) Local size:vector2d = New vector2d(100,50) Local rect1:rectangle = New rectangle(origin,size) ' Here we test for collision If col.rectangle_segment_collide(rect1,ls) DrawText "Rectangle vs Line Segment Collision",0,0 Else DrawText "Rectangle vs Line Segment NO Collision",0,0 End If ' Here we draw the line and rectangle ls.draw rect1.draw DrawText "Move the Mouse to test for Collision",DeviceWidth/2,0 End Method End Class Function Main() New MyGame() End Function
Monkey-X - Collision - Rectangle vs Line - code example
' From the book '2d game collision detection' ' rectangle vs Line collision Import mojo ' This is the collision class. ' Class collision ' Collision function ' The rectangle vs Line Collision Function line_rectangle_collide:Bool(l:line,r:rectangle) Local n:vector2d = rotate_vector_90(l.direction) Local dp1:Float,dp2:Float Local dp3:Float,dp4:Float Local c1:vector2d = r.origin Local c2:vector2d = add_vector(c1,r.size) Local c3:vector2d = New vector2d(c2.x,c1.y) Local c4:vector2d = New vector2d(c1.x,c2.y) c1 = subtract_vector(c1,l.base) c2 = subtract_vector(c2,l.base) c3 = subtract_vector(c3,l.base) c4 = subtract_vector(c4,l.base) dp1 = dot_product(n,c1) dp2 = dot_product(n,c2) dp3 = dot_product(n,c3) dp4 = dot_product(n,c4) Return (dp1 * dp2 <= 0) Or (dp2 * dp3 <= 0) Or (dp3 * dp4 <= 0) End Function ' ' helper functions ' Function rotate_vector_90:vector2d(v:vector2d) Local r:vector2d = New vector2d() r.x = -v.y r.y = v.x Return r End Function Function add_vector:vector2d(a:vector2d,b:vector2d) Local r:vector2d = New vector2d(0,0) r.x = a.x + b.x r.y = a.y + b.y Return r End Function Function subtract_vector:vector2d(a:vector2d,b:vector2d) Local r:vector2d = New vector2d() r.x = a.x - b.x r.y = a.y - b.y Return r End Function Function dot_product:Float(a:vector2d,b:vector2d) Return a.x * b.x + a.y * b.y End Function End Class Class vector2d ' x and y hold the position of the vector Field x:Int,y:Int Method New(x:Int,y:Int) Self.x = x Self.y = y End Method End Class Class line Field base:vector2d Field direction:vector2d Method New(base:vector2d,direction:vector2d) Self.base = base Self.direction = direction End Method Method draw() DrawLine base.x,base.y,direction.x,direction.y End Method End Class Class rectangle ' origin is a vector that holds the x and y coordinates ' of the rectangle Field origin:vector2d ' size is a vector that holds the x(width) and ' y(height) of the rectangle Field size:vector2d Method New(origin:vector2d,size:vector2d) Self.origin = origin Self.size = size End Method Method draw() ' x1,y1,w,h are used to hold the rectangle ' location and size. Local x1:Int=origin.x Local y1:Int=origin.y Local w:Int=size.x Local h:Int=size.y DrawRect x1,y1,w,h End Method End Class ' col is the caller of the class collision. ' we use it to use the collision methods. Global col:collision = New collision Class MyGame Extends App Field angle:Float Method OnCreate() SetUpdateRate(30) End Method Method OnUpdate() angle+=1 If angle > 360 Then angle = 0 End Method Method OnRender() Cls 0,0,0 SetColor 255,255,255 ' this is a line setup Local base:vector2d = New vector2d(0,0) Local direction:vector2d = New vector2d(MouseX,MouseY) Local line1:line = New line(base,direction) ' ' This is the rectangle Local origin:vector2d = New vector2d(320,200) Local size:vector2d = New vector2d(100,100) Local rect1:rectangle = New rectangle(origin,size) ' Here we test for collision If col.line_rectangle_collide(line1,rect1) DrawText "Line vs Rectangle Collision",0,0 Else DrawText "Line vs Rectangle NO Collision",0,0 End If ' Here we draw the line and rectangle line1.draw rect1.draw DrawText "Move the Mouse to test for Collision",DeviceWidth/2,0 DrawText "Info : Lines are infinite in length.",DeviceWidth/2,20 End Method End Class Function Main() New MyGame() End Function
Monkey-X - Collision - Point vs Rectangle - code example
' From the book '2d game collision detection' ' point vs rectangle collision Import mojo ' This is the collision class. ' Class collision ' Collision function ' The point vs rectangle Collision Function point_rectangle_collide:Bool(p:vector2d,r:rectangle) Local left:Float = r.origin.x Local right:Float = left + r.size.x Local bottom:Float = r.origin.y Local top:Float = bottom + r.size.y Return left <= p.x And bottom <= p.y And p.x <= right And p.y <= top End Function End Class Class vector2d ' x and y hold the position of the vector Field x:Int,y:Int Method New(x:Int,y:Int) Self.x = x Self.y = y End Method End Class Class rectangle ' origin is a vector that holds the x and y coordinates ' of the rectangle Field origin:vector2d ' size is a vector that holds the x(width) and ' y(height) of the rectangle Field size:vector2d Method New(origin:vector2d,size:vector2d) Self.origin = origin Self.size = size End Method Method draw() ' x1,y1,w,h are used to hold the rectangle ' location and size. Local x1:Int=origin.x Local y1:Int=origin.y Local w:Int=size.x Local h:Int=size.y DrawRect x1,y1,w,h End Method End Class ' col is the caller of the class collision. ' we use it to use the collision methods. Global col:collision = New collision Class MyGame Extends App Field angle:Float Method OnCreate() SetUpdateRate(30) End Method Method OnUpdate() angle+=1 If angle > 360 Then angle = 0 End Method Method OnRender() Cls 0,0,0 SetColor 255,255,255 ' this is a point(vector) with the mouse coordinates Local point:vector2d = New vector2d(MouseX,MouseY) ' ' This is the rectangle Local origin:vector2d = New vector2d(320,200) Local size:vector2d = New vector2d(100,100) Local rect1:rectangle = New rectangle(origin,size) ' Here we test for collision If col.point_rectangle_collide(point,rect1) DrawText "Point vs Rectangle Collision",0,0 Else DrawText "Point vs Rectangle NO Collision",0,0 End If rect1.draw DrawText "Move the Mouse to test for Collision",DeviceWidth/2,0 End Method End Class Function Main() New MyGame() End Function
Monkey-X - Collision - Circle vs Oriented Rectangle - code example
' From the book '2d game collision detection' ' circle vs oriented rectangle collision Import mojo ' This is the collision class. ' Class collision ' Collision function ' the circle vs oriented rectangle collision Function circle_oriented_rectangle_collide:Bool(c:circle, r:orientedrectangle) Local origin:vector2d = New vector2d(0,0) Local size:vector2d = New vector2d(0,0) Local lr:rectangle = New rectangle(origin,size) lr.size = multiply_vector(r.halfextend,2) Local center:vector2d = New vector2d(0,0) Local lc:circle = New circle(center,c.radius) Local distance:vector2d = subtract_vector(c.center,r.center) distance = rotate_vector(distance,-r.rotation) lc.center = add_vector(distance,r.halfextend) Return circle_rectangle_collide(lc,lr) End Function ' needed for circle vs oriented rectangle collision Function circle_rectangle_collide:Bool(c:circle,r:rectangle) Local clamped:vector2d = clamp_on_rectangle(c.center,r) Return circle_point_collide(c,clamped) End Function ' Needed for circle_segment_collide Function circle_point_collide:Bool(c:circle,p:vector2d) Local distance:vector2d = subtract_vector(c.center,p) Return vector_length(distance) <= c.radius End Function ' Helper Functions ........ ' ' Function multiply_vector:vector2d(v:vector2d,scalar:Float) Local r:vector2d = New vector2d() r.x = v.x * scalar r.y = v.y * scalar Return r End Function Function clamp_on_rectangle:vector2d(p:vector2d,r:rectangle) Local clamp:vector2d = New vector2d() clamp.x = Clamp(p.x,r.origin.x,r.origin.x+r.size.x) clamp.y = Clamp(p.y,r.origin.y,r.origin.y+r.size.y) Return clamp End Function Function vector_length:Float(v:vector2d) Return Sqrt(v.x * v.x + v.y * v.y) End Function Function subtract_vector:vector2d(a:vector2d,b:vector2d) Local r:vector2d = New vector2d() r.x = a.x - b.x r.y = a.y - b.y Return r End Function Function add_vector:vector2d(a:vector2d,b:vector2d) Local r:vector2d = New vector2d(0,0) r.x = a.x + b.x r.y = a.y + b.y Return r End Function ' Here is the function that rotates a vector. It returns the ' new rotated vector. ' Function rotate_vector:vector2d(v:vector2d,degrees:Float) Local r:vector2d = New vector2d() r.x = v.x * Cos(degrees) - v.y * Sin(degrees) r.y = v.x * Sin(degrees) + v.y * Cos(degrees) Return r End Function End Class Class vector2d ' x and y hold the position of the vector Field x:Int,y:Int Method New(x:Int,y:Int) Self.x = x Self.y = y End Method End Class Class rectangle ' origin is a vector that holds the x and y coordinates ' of the rectangle Field origin:vector2d ' size is a vector that holds the x(width) and ' y(height) of the rectangle Field size:vector2d Method New(origin:vector2d,size:vector2d) Self.origin = origin Self.size = size End Method Method draw() ' x1,y1,w,h are used to hold the rectangle ' location and size. Local x1:Int=origin.x Local y1:Int=origin.y Local w:Int=size.x Local h:Int=size.y DrawRect x1,y1,w,h End Method End Class Class circle Field center:vector2d Field radius:Float Method New(center:vector2d,radius:Float) Self.center = center Self.radius = radius End Method Method draw() DrawCircle center.x,center.y,radius End Method End Class Class orientedrectangle Field center:vector2d Field halfextend:vector2d Field rotation:Float Method New(center:vector2d,halfextend:vector2d,rotation:Float) Self.center = center Self.halfextend = halfextend Self.rotation = rotation End Method Method draw() Local v1:vector2d,v2:vector2d,v3:vector2d,v4:vector2d 'topside v1 = New vector2d(-halfextend.x,-halfextend.y) v2 = New vector2d(halfextend.x,-halfextend.y) v1 = rotate_vector(v1,rotation) v2 = rotate_vector(v2,rotation) v1.x += center.x v1.y += center.y v2.x += center.x v2.y += center.y ' rightside v3 = New vector2d(halfextend.x,halfextend.y) v3 = rotate_vector(v3,rotation) v3.x += center.x v3.y += center.y ' bottom side v4 = New vector2d(-halfextend.x,halfextend.y) v4 = rotate_vector(v4,rotation) v4.x += center.x v4.y += center.y DrawLine v1.x,v1.y,v2.x,v2.y DrawLine v2.x,v2.y,v3.x,v3.y DrawLine v3.x,v3.y,v4.x,v4.y DrawLine v4.x,v4.y,v1.x,v1.y End Method Function rotate_vector:vector2d(v:vector2d,degrees:Float) Local r:vector2d = New vector2d() r.x = v.x * Cos(degrees) - v.y * Sin(degrees) r.y = v.x * Sin(degrees) + v.y * Cos(degrees) Return r End Function End Class ' col is the caller of the class collision. ' we use it to use the collision methods. Global col:collision = New collision Class MyGame Extends App Field angle:Float Method OnCreate() SetUpdateRate(30) End Method Method OnUpdate() angle+=1 If angle > 360 Then angle = 0 End Method Method OnRender() Cls 0,0,0 SetColor 255,255,255 ' Here we set up the circle where we test ' the collision with Local cc:vector2d = New vector2d(320,200) Local r:Float = 50 Local circle1:circle = New circle(cc,r) ' Here we set up the oriented rectangle Local orc:vector2d = New vector2d(MouseX,MouseY) Local ors:vector2d = New vector2d(100,50) 'size of the oriented rectangle Local orect:orientedrectangle = New orientedrectangle(orc,ors,angle) ' Collision test If col.circle_oriented_rectangle_collide(circle1,orect) DrawText "Circle vs Oriented rect Collide",0,0 Else DrawText "Circle vs Oriented rect NO Collision",0,0 End If orect.draw circle1.draw DrawText "Move the Mouse to test for Collision",DeviceWidth/2,0 End Method End Class Function Main() New MyGame() End Function
Subscribe to:
Posts (Atom)