Skip to content

Instantly share code, notes, and snippets.

@SupremeTechnopriest
Last active August 5, 2019 02:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SupremeTechnopriest/404572f53b22782f89d1dc704c81a144 to your computer and use it in GitHub Desktop.
Save SupremeTechnopriest/404572f53b22782f89d1dc704c81a144 to your computer and use it in GitHub Desktop.
Simple overlap system
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