Last active
August 5, 2019 02:51
-
-
Save SupremeTechnopriest/404572f53b22782f89d1dc704c81a144 to your computer and use it in GitHub Desktop.
Simple overlap system
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import intersects from 'intersects' | |
import { polygonRotate } from 'geometric' | |
const categoryCheck = (c1, c2) => c1.collidesWith.some(category => c2.categories.includes(category)) | |
const reducePoints = points => points.reduce((resultArray, item, index) => { | |
const chunkIndex = Math.floor(index / 2) | |
if (!resultArray[chunkIndex]) resultArray[chunkIndex] = [] // start a new chunk | |
resultArray[chunkIndex].push(item) | |
return resultArray | |
}, []) | |
const flattenPoints = points => points.reduce((resultArray, item) => { | |
return resultArray.concat(item) | |
}, []) | |
export default function (modngn) { | |
const { engine, services: { spatial } } = modngn | |
let nearby | |
return (position, rotation, collider, id) => { | |
nearby = spatial.broadphase(position) | |
const c1 = [] | |
const c1Name = collider.shape | |
if (collider.active) { | |
switch (collider.shape) { | |
case 'circle': | |
c1.push(position.x) // xc | |
c1.push(position.y) // yc | |
c1.push(collider.radius) // rc | |
break | |
case 'box': | |
c1.push(position.x) // xb | |
c1.push(position.y) // yb | |
c1.push(collider.width) // wb | |
c1.push(collider.height) // hb | |
break | |
case 'polygon': | |
// Get new rotation | |
const poly = polygonRotate( | |
reducePoints(collider.points), | |
rotation.radians * (Math.PI / 180), | |
[ collider.offset.x || 0, collider.offset.y || 0 ] | |
) | |
c1.push(flattenPoints(poly)) // points | |
break | |
default: | |
} | |
nearby.forEach((id2) => { | |
// Test each collider type | |
const colliders = modngn.getAddress('components.engine.collider.composure.components', []) | |
colliders.forEach(colliderName => { | |
const collider2 = engine.getComponent(id2, colliderName) | |
if (!collider2) return | |
if (id === id2) return | |
const c2 = [] | |
const c2Name = collider2.shape.charAt(0).toUpperCase() + collider2.shape.slice(1) | |
if (collider2.active) { | |
const position2 = engine.getComponent(id2, 'POSITION') | |
const rotation2 = engine.getComponent(id2, 'ROTATION') | |
switch (collider2.shape) { | |
case 'circle': | |
c2.push(position2.x) // xc | |
c2.push(position2.y) // yc | |
c2.push(collider2.radius) // rc | |
break | |
case 'box': | |
c2.push(position2.x) // xb | |
c2.push(position2.y) // yb | |
c2.push(collider2.width) // wb | |
c2.push(collider2.height) // hb | |
break | |
case 'polygon': | |
// Rotate the polygon | |
const poly = polygonRotate( | |
reducePoints(collider2.points), | |
rotation2.radians * (Math.PI / 180), | |
[ collider2.offset.x || 0, collider2.offset.y || 0 ] | |
) | |
c2.push(flattenPoints(poly)) // points | |
break | |
default: | |
} | |
if (categoryCheck(collider, collider2)) { | |
if (intersects[`${c1Name}${c2Name}`](...c1.concat(c2))) { | |
// Emit overlap event | |
engine.emit('overlap', id, id2, collider.name, collider2.name) | |
// Notify other systems via components with whatever stateful data is needed later | |
engine.addComponent(id, 'OVERLAP', { with: id2 }) | |
engine.addComponent(id2, 'OVERLAP', { with: id }) | |
} | |
} | |
} | |
}) | |
}) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment