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