Skip to content

Commit

Permalink
feat: propagate collision events to every parent classes
Browse files Browse the repository at this point in the history
  • Loading branch information
Gugustinette committed Aug 22, 2024
1 parent 1390215 commit fbce531
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 16 deletions.
15 changes: 15 additions & 0 deletions apps/playground-3d/src/classes/MyCustomCube.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { FCube } from '@fibbojs/3d'
import type { FComponent3dOptions, FScene3d } from '@fibbojs/3d'

/**
* Used to demonstrate that collisions are working with "FCube" even if the class is extended.
*/
export default class MyCustomCube extends FCube {
constructor(scene: FScene3d, options?: FComponent3dOptions) {
super(scene, options)
}

onFrame(delta: number) {
super.onFrame(delta)
}
}
27 changes: 19 additions & 8 deletions apps/playground-3d/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { FKeyboard } from '@fibbojs/event'
import Duck from './classes/Duck'
import GltfCube from './classes/GltfCube'
import './style.css'
import MyCustomCube from './classes/MyCustomCube'

(async () => {
// Initialize the scene
Expand Down Expand Up @@ -76,20 +77,30 @@ import './style.css'
const angle = i * Math.PI / 4
const x = Math.cos(angle) * 4
const z = Math.sin(angle) * 4
const cube = new FCube(scene)
cube.setPosition(x, 3, z - 17)
cube.initRigidBody({
// First one gets a sphere collider, the others get a cube collider
shape: i === 0 ? F3dShapes.SPHERE : F3dShapes.CUBE,
})
// Create cube variable
let cube
if (i === 0) {
// First one is an instance of MyCustomCube
cube = new MyCustomCube(scene)
cube.setPosition(x, 3, z - 17)
cube.initRigidBody({
// First one gets a sphere collider, the others get a cube collider
shape: F3dShapes.SPHERE,
})
}
else {
cube = new FCube(scene)
cube.setPosition(x, 3, z - 17)
cube.initRigidBody()
}
scene.addComponent(cube)
}

/**
* Add collision events
*/
capsule.onCollisionWith(GltfCube, () => {
console.log('Cube collided with a GltfCube !')
capsule.onCollisionWith(FCube, () => {
console.log('Cube collided with a FCube !')
})
capsule.onCollisionWith(sphere, () => {
console.log('Cube collided with the sphere!')
Expand Down
39 changes: 31 additions & 8 deletions packages/core/src/FComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,19 +89,42 @@ export abstract class FComponent {
* ```
*/
emitCollisionWith(classOrObject: any) {
let eventKey = ''
// If the classOrObject is an object, use the class name + ID
if (classOrObject instanceof FComponent) {
eventKey = `${classOrObject.constructor.name}@${classOrObject.__ID__}`
const eventKey = `${classOrObject.constructor.name}@${classOrObject.__ID__}`

// Check if the event key exists and call the callbacks
if (this.__CALLBACKS_ON_COLLISION__[eventKey]) {
this.__CALLBACKS_ON_COLLISION__[eventKey].forEach((callback) => {
callback()
})
}
}
// Else, it should be a class, use the class name
else {
eventKey = classOrObject.name
}
// Check if the event key exists and call the callbacks
if (this.__CALLBACKS_ON_COLLISION__[eventKey]) {
this.__CALLBACKS_ON_COLLISION__[eventKey].forEach((callback) => {
callback()
// Get the prototype chain for a given class
const getPrototypeChain = (obj: any) => {
const protoChain = []
let currentProto = obj.prototype
while (currentProto) {
protoChain.push(currentProto.constructor.name)
currentProto = Object.getPrototypeOf(currentProto)
}
return protoChain
}
// Get the prototype chain for the classOrObject
const thisChain = getPrototypeChain(classOrObject)

/**
* For each class in the prototype chain, check if there are any callbacks.
* If there are, call them.
*/
thisChain.forEach((className) => {
if (this.__CALLBACKS_ON_COLLISION__[className]) {
this.__CALLBACKS_ON_COLLISION__[className].forEach((callback) => {
callback()
})
}
})
}
}
Expand Down

0 comments on commit fbce531

Please sign in to comment.