Post by johnno56 on Oct 3, 2019 4:24:27 GMT -6
I am NOT a mathmatician, nor profess to be one, so I will try my best to explain collision detect (2D) as clearly as I know how.
When two objects "overlap", or try to occupy the same space, a collision occurs and the game or program will have the necessary instructions to react to a collision... eg: Bullet object 'overlaps' an enemy object... Boom! Score updated. Next enemy...
Some Basic dialects have a collision detection system 'built in', however, RCBasic does not. But, all is 'not' lost, "we have the technology"... lol
There are several 'types' of collision systems. To name but a few: Axial Aligned Bounding Box and Circular Bounding.
Axial Aligned Bounding Box (AABB): This system is one of the 'cheapest', in regards to memory usage, collision system out there.
As the title aludes to... Boxes are the favoured shape. Mapping the co-ordinates of each box 'edge' or 'side' is far quicker than mapping every pixel on every side of every box.
--------------------------------------------------------------------------------
This is the function that will be used to 'detect' if box 1 is overlapping box 2.
"Overlap" is just function name. You can call it what you will.
function Overlap(x1, y1, w1, h1, x2, y2, w2, h2)
if x1 + w1 < x2 then
return false
end if
if y1 + h1 < y2 then
return false
end if
if x2 + w2 < x1 then
return false
end if
if y2 + h2 < y1 then
return false
end if
return true
end function
-------------------------------------------------------------------------------
It looks a bit scarey but I will try to explain each part.
The parameters:
x1 is the X co-ordinate of left edge of Box 1
y1 is the Y co-ordinate of the top edge of Box 1
w1 is the width (in pixels) of box 1
h1 is the height (in pixels) of box 1
x2 is the X co-ordinate of left edge of Box 2
y2 is the Y co-ordinate of the top edge of Box 2
w2 is the width (in pixels) of box 2
h2 is the height (in pixels) of box 2
if x1 + w1 < x2:
if the x co-ordinate of box 1's left edge, plus the width of box 1, is less than x co-ordinate of box 2's left edge then
(if the right side of box 1 is left of the left edge of box 2)
there is no collision.
if y1 + h1 < y2:
if the y co-ordinate of box 1's bottom edge, plus the height of box 1, is less than y co-ordinate of box 2's top edge then
(if the bottom edge of box 1 is above the top edge of box 2)
there is no collision.
if x2 + w2 < x1:
if the x co-ordinate of box 2's left edge, plus the width of box 2, is less than x co-ordinate of box 1's left edge then
(if the right side of box 2 is left of the left edge of box 1)
there is no collision.
if y2 + h2 < y1:
if the y co-ordinate of box 2's top edge, plus the height of box 2 if less than y co-ordinate of box 1's top edge then
(if the bottom edge of box 2 is above the top edge of box 1)
there is no collision.
Any other condition means that there must be an overlap of boxes and a collision has occurred.
'=====================================================================
' Sample of AABB collision. Box#2, is controlled by the mouse. When a collision occurs the circles will change.
'=====================================================================
xmax = 640
ymax = 480
title$ = "Axial Aligned Bounding box"
WindowOpen(1,title$,0,0,xmax,ymax,0)
CanvasOpen(1,xmax,ymax,0,0,xmax,ymax,0)
collision = 0
function collide(box1left, box1right, box1top, box1bottom, box2left, box2right, box2top, box2bottom)
if (box1bottom < box2top) or (box1top > box2bottom) or (box1left > box2right) or (box1right < box2left) then
collision = 0
else
collision = 1
end if
return collision
end function
box1top = 190
box1bottom = 290
box1left = 270
box1right = 370
do
ClearCanvas
box2left = mousex()-50
box2top = mousey()-50
box2right = box2left+100
box2bottom = box2top+100
setColor(rgb(255,128,0))
box(box2left,box2top,box2right,box2bottom)
collide(box1left, box1right, box1top, box1bottom, box2left, box2right, box2top, box2bottom)
if collision = 1 then
' fill both boxes
setColor(rgb(255,255,0))
boxfill(box1left,box1top,box1right,box1bottom)
setColor(rgb(255,128,0))
boxfill(box2left,box2top,box2right,box2bottom)
else
' Draw empty boxes
setColor(rgb(255,255,0))
box(box1left,box1top,box1right,box1bottom)
setColor(rgb(255,128,0))
box(box2left,box2top,box2right,box2bottom)
end if
update()
loop until key(k_escape) = 1
'===========================================================
Circular Bounding: The simplest description would be; Knowing the center co-ordinates of each of the circles and ensuring the distance between the centers are less than the sum of the two radii.
The following few lines of code will calculate the distance between two circles.
circle1radius = 100
circl2radius = 50
dx = circle1X - circle2X
dy = circle1Y - circle2Y
distance = sqr(dx * dx + dy * dy)
if distance < circle1radius + circle2radius then
collison = true
end if
'=========================================================================
' Sample of circular collision. Circle#2, is controlled by the mouse. When a collision occurs the circles will change.
'=========================================================================
xmax = 640
ymax = 480
title$ = "Circular Collision"
WindowOpen(1,title$,0,0,xmax,ymax,0)
CanvasOpen(1,xmax,ymax,0,0,xmax,ymax,0)
' circ1 x/y centre of circle 1
' circ2 x/y center of circle 2
' r1 radius of circle 1
' r2 radius of circle 2
collision = 0
function collide(circ1x, circ1y, circ2x, circ2y, r1, r2)
' Calculate difference between centres
distX = circ1x - circ2x
distY = circ1y - circ2y
' Get distance using Pythagoras
dist = sqrt((distX * distX) + (distY * distY))
if dist <= (r1 + r2) then
collision = 1
else
collision = 0
end if
return collision
end function
circ1x = 320
circ1y = 240
r1 = 100
r2 = 50
distX =0
distY =0
dist = 0
do
circ2x = mousex()
circ2y = mousey()
ClearCanvas
collide(circ1x, circ1y, circ2x, circ2y, r1, r2)
if collision = 1 then
setColor(rgb(255,255,0))
circlefill(circ1x, circ1y, r1)
setColor(rgb(255,128,0))
circlefill(circ2x, circ2y, r2)
else
setColor(rgb(255,255,0))
circle(circ1x, circ1y, r1)
setColor(rgb(255,128,0))
circle(circ2x, circ2y, r2)
end if
update()
loop until key(k_escape) = 1
'======================================================
These collision system are perfect if both objects are either rectangular or circular.
But what about a simple game of Pong?
The paddle is rectangular and the ball is circular. Can AABB be used to check the collision between the ball and the paddle? In short, yes, it can. But the detection would not be as perfect, say if the ball, was a square.
AABB is expecting rectangular shapes. The circular ball would be treated as a square. Imagine a ball drawn inside a square that has the same width and height as the ball. There will be 4 'voids' in the corners of the square. Areas where the circle does not occupy. There would be a potential of a "near miss" being registered as a collision. When one of the "corners" of the ball would overlap the paddle... However, if the ball was small enough, the chance of a "near miss" collision would be reduced.
But, yes, AABB can still be used in pong.
I hope that this is useful. As usual, if you find any mistakes or methods of improvement, just let me know.
When two objects "overlap", or try to occupy the same space, a collision occurs and the game or program will have the necessary instructions to react to a collision... eg: Bullet object 'overlaps' an enemy object... Boom! Score updated. Next enemy...
Some Basic dialects have a collision detection system 'built in', however, RCBasic does not. But, all is 'not' lost, "we have the technology"... lol
There are several 'types' of collision systems. To name but a few: Axial Aligned Bounding Box and Circular Bounding.
Axial Aligned Bounding Box (AABB): This system is one of the 'cheapest', in regards to memory usage, collision system out there.
As the title aludes to... Boxes are the favoured shape. Mapping the co-ordinates of each box 'edge' or 'side' is far quicker than mapping every pixel on every side of every box.
--------------------------------------------------------------------------------
This is the function that will be used to 'detect' if box 1 is overlapping box 2.
"Overlap" is just function name. You can call it what you will.
function Overlap(x1, y1, w1, h1, x2, y2, w2, h2)
if x1 + w1 < x2 then
return false
end if
if y1 + h1 < y2 then
return false
end if
if x2 + w2 < x1 then
return false
end if
if y2 + h2 < y1 then
return false
end if
return true
end function
-------------------------------------------------------------------------------
It looks a bit scarey but I will try to explain each part.
The parameters:
x1 is the X co-ordinate of left edge of Box 1
y1 is the Y co-ordinate of the top edge of Box 1
w1 is the width (in pixels) of box 1
h1 is the height (in pixels) of box 1
x2 is the X co-ordinate of left edge of Box 2
y2 is the Y co-ordinate of the top edge of Box 2
w2 is the width (in pixels) of box 2
h2 is the height (in pixels) of box 2
if x1 + w1 < x2:
if the x co-ordinate of box 1's left edge, plus the width of box 1, is less than x co-ordinate of box 2's left edge then
(if the right side of box 1 is left of the left edge of box 2)
there is no collision.
if y1 + h1 < y2:
if the y co-ordinate of box 1's bottom edge, plus the height of box 1, is less than y co-ordinate of box 2's top edge then
(if the bottom edge of box 1 is above the top edge of box 2)
there is no collision.
if x2 + w2 < x1:
if the x co-ordinate of box 2's left edge, plus the width of box 2, is less than x co-ordinate of box 1's left edge then
(if the right side of box 2 is left of the left edge of box 1)
there is no collision.
if y2 + h2 < y1:
if the y co-ordinate of box 2's top edge, plus the height of box 2 if less than y co-ordinate of box 1's top edge then
(if the bottom edge of box 2 is above the top edge of box 1)
there is no collision.
Any other condition means that there must be an overlap of boxes and a collision has occurred.
'=====================================================================
' Sample of AABB collision. Box#2, is controlled by the mouse. When a collision occurs the circles will change.
'=====================================================================
xmax = 640
ymax = 480
title$ = "Axial Aligned Bounding box"
WindowOpen(1,title$,0,0,xmax,ymax,0)
CanvasOpen(1,xmax,ymax,0,0,xmax,ymax,0)
collision = 0
function collide(box1left, box1right, box1top, box1bottom, box2left, box2right, box2top, box2bottom)
if (box1bottom < box2top) or (box1top > box2bottom) or (box1left > box2right) or (box1right < box2left) then
collision = 0
else
collision = 1
end if
return collision
end function
box1top = 190
box1bottom = 290
box1left = 270
box1right = 370
do
ClearCanvas
box2left = mousex()-50
box2top = mousey()-50
box2right = box2left+100
box2bottom = box2top+100
setColor(rgb(255,128,0))
box(box2left,box2top,box2right,box2bottom)
collide(box1left, box1right, box1top, box1bottom, box2left, box2right, box2top, box2bottom)
if collision = 1 then
' fill both boxes
setColor(rgb(255,255,0))
boxfill(box1left,box1top,box1right,box1bottom)
setColor(rgb(255,128,0))
boxfill(box2left,box2top,box2right,box2bottom)
else
' Draw empty boxes
setColor(rgb(255,255,0))
box(box1left,box1top,box1right,box1bottom)
setColor(rgb(255,128,0))
box(box2left,box2top,box2right,box2bottom)
end if
update()
loop until key(k_escape) = 1
'===========================================================
Circular Bounding: The simplest description would be; Knowing the center co-ordinates of each of the circles and ensuring the distance between the centers are less than the sum of the two radii.
The following few lines of code will calculate the distance between two circles.
circle1radius = 100
circl2radius = 50
dx = circle1X - circle2X
dy = circle1Y - circle2Y
distance = sqr(dx * dx + dy * dy)
if distance < circle1radius + circle2radius then
collison = true
end if
'=========================================================================
' Sample of circular collision. Circle#2, is controlled by the mouse. When a collision occurs the circles will change.
'=========================================================================
xmax = 640
ymax = 480
title$ = "Circular Collision"
WindowOpen(1,title$,0,0,xmax,ymax,0)
CanvasOpen(1,xmax,ymax,0,0,xmax,ymax,0)
' circ1 x/y centre of circle 1
' circ2 x/y center of circle 2
' r1 radius of circle 1
' r2 radius of circle 2
collision = 0
function collide(circ1x, circ1y, circ2x, circ2y, r1, r2)
' Calculate difference between centres
distX = circ1x - circ2x
distY = circ1y - circ2y
' Get distance using Pythagoras
dist = sqrt((distX * distX) + (distY * distY))
if dist <= (r1 + r2) then
collision = 1
else
collision = 0
end if
return collision
end function
circ1x = 320
circ1y = 240
r1 = 100
r2 = 50
distX =0
distY =0
dist = 0
do
circ2x = mousex()
circ2y = mousey()
ClearCanvas
collide(circ1x, circ1y, circ2x, circ2y, r1, r2)
if collision = 1 then
setColor(rgb(255,255,0))
circlefill(circ1x, circ1y, r1)
setColor(rgb(255,128,0))
circlefill(circ2x, circ2y, r2)
else
setColor(rgb(255,255,0))
circle(circ1x, circ1y, r1)
setColor(rgb(255,128,0))
circle(circ2x, circ2y, r2)
end if
update()
loop until key(k_escape) = 1
'======================================================
These collision system are perfect if both objects are either rectangular or circular.
But what about a simple game of Pong?
The paddle is rectangular and the ball is circular. Can AABB be used to check the collision between the ball and the paddle? In short, yes, it can. But the detection would not be as perfect, say if the ball, was a square.
AABB is expecting rectangular shapes. The circular ball would be treated as a square. Imagine a ball drawn inside a square that has the same width and height as the ball. There will be 4 'voids' in the corners of the square. Areas where the circle does not occupy. There would be a potential of a "near miss" being registered as a collision. When one of the "corners" of the ball would overlap the paddle... However, if the ball was small enough, the chance of a "near miss" collision would be reduced.
But, yes, AABB can still be used in pong.
I hope that this is useful. As usual, if you find any mistakes or methods of improvement, just let me know.