109 lines
2.7 KiB
Plaintext
109 lines
2.7 KiB
Plaintext
var collision2d = {}
|
|
|
|
collision2d.body = function(config) {
|
|
var c = config || {}
|
|
return {
|
|
type: c.type || 'aabb',
|
|
width: c.width || 0,
|
|
height: c.height || 0,
|
|
radius: c.radius || 0,
|
|
offset: c.offset || {x: 0, y: 0},
|
|
layer: c.layer || 0,
|
|
mask: c.mask || 0xFFFF
|
|
}
|
|
}
|
|
|
|
function body_center(body, pos) {
|
|
return {
|
|
x: pos.x + body.offset.x,
|
|
y: pos.y + body.offset.y
|
|
}
|
|
}
|
|
|
|
function test_aabb_aabb(a, ap, b, bp) {
|
|
var ac = body_center(a, ap)
|
|
var bc = body_center(b, bp)
|
|
var ahw = a.width * 0.5
|
|
var ahh = a.height * 0.5
|
|
var bhw = b.width * 0.5
|
|
var bhh = b.height * 0.5
|
|
return abs(ac.x - bc.x) < ahw + bhw && abs(ac.y - bc.y) < ahh + bhh
|
|
}
|
|
|
|
function test_circle_circle(a, ap, b, bp) {
|
|
var ac = body_center(a, ap)
|
|
var bc = body_center(b, bp)
|
|
var dx = ac.x - bc.x
|
|
var dy = ac.y - bc.y
|
|
var r = a.radius + b.radius
|
|
return dx * dx + dy * dy < r * r
|
|
}
|
|
|
|
function test_aabb_circle(aabb, ap, circ, cp) {
|
|
var ac = body_center(aabb, ap)
|
|
var cc = body_center(circ, cp)
|
|
var hw = aabb.width * 0.5
|
|
var hh = aabb.height * 0.5
|
|
var cx = max(ac.x - hw, min(cc.x, ac.x + hw))
|
|
var cy = max(ac.y - hh, min(cc.y, ac.y + hh))
|
|
var dx = cc.x - cx
|
|
var dy = cc.y - cy
|
|
return dx * dx + dy * dy < circ.radius * circ.radius
|
|
}
|
|
|
|
collision2d.test = function(a, a_pos, b, b_pos) {
|
|
if (a.layer & b.mask == 0 || b.layer & a.mask == 0)
|
|
return false
|
|
|
|
if (a.type == 'aabb' && b.type == 'aabb')
|
|
return test_aabb_aabb(a, a_pos, b, b_pos)
|
|
if (a.type == 'circle' && b.type == 'circle')
|
|
return test_circle_circle(a, a_pos, b, b_pos)
|
|
if (a.type == 'aabb' && b.type == 'circle')
|
|
return test_aabb_circle(a, a_pos, b, b_pos)
|
|
if (a.type == 'circle' && b.type == 'aabb')
|
|
return test_aabb_circle(b, b_pos, a, a_pos)
|
|
return false
|
|
}
|
|
|
|
collision2d.overlap = function(body, pos, others) {
|
|
var results = []
|
|
var i = 0
|
|
var other = null
|
|
for (i = 0; i < length(others); i++) {
|
|
other = others[i]
|
|
if (collision2d.test(body, pos, other.body, other.pos))
|
|
push(results, other)
|
|
}
|
|
return results
|
|
}
|
|
|
|
collision2d.overlap_point = function(point, bodies) {
|
|
var results = []
|
|
var i = 0
|
|
var b = null
|
|
var c = null
|
|
var hw = 0
|
|
var hh = 0
|
|
var dx = 0
|
|
var dy = 0
|
|
for (i = 0; i < length(bodies); i++) {
|
|
b = bodies[i]
|
|
c = body_center(b.body, b.pos)
|
|
if (b.body.type == 'aabb') {
|
|
hw = b.body.width * 0.5
|
|
hh = b.body.height * 0.5
|
|
if (abs(point.x - c.x) < hw && abs(point.y - c.y) < hh)
|
|
push(results, b)
|
|
} else if (b.body.type == 'circle') {
|
|
dx = point.x - c.x
|
|
dy = point.y - c.y
|
|
if (dx * dx + dy * dy < b.body.radius * b.body.radius)
|
|
push(results, b)
|
|
}
|
|
}
|
|
return results
|
|
}
|
|
|
|
return collision2d
|