diff --git a/SDPhysicsEngine/Sources/SDPhysicsEngine/GameScene.swift b/SDPhysicsEngine/Sources/SDPhysicsEngine/GameScene.swift index a258c3d1..e0a090b7 100644 --- a/SDPhysicsEngine/Sources/SDPhysicsEngine/GameScene.swift +++ b/SDPhysicsEngine/Sources/SDPhysicsEngine/GameScene.swift @@ -1,11 +1,19 @@ import SpriteKit -public class GameScene: SKScene, SDScene { +public class GameScene: SKScene { public var sceneDelegate: SDSceneDelegate? private var lastUpdateTime: TimeInterval? + private var objectMap: [SKNode: SDObject] = [:] + + override public func sceneDidLoad() { + super.sceneDidLoad() + + physicsWorld.contactDelegate = self + } + override public func update(_ currentTime: TimeInterval) { super.update(currentTime) @@ -19,8 +27,34 @@ public class GameScene: SKScene, SDScene { sceneDelegate?.update(self, deltaTime: deltaTime) } +} +extension GameScene: SDScene { public func addObject(_ object: SDObject) { + guard objectMap[object.node] == nil else { + return + } + + objectMap[object.node] = object addChild(object.node) } } + +extension GameScene: SKPhysicsContactDelegate { + public func didBegin(_ contact: SKPhysicsContact) { + guard let skNodeA = contact.bodyA.node, + let skNodeB = contact.bodyB.node else { + return + } + + guard let objectA = objectMap[skNodeA], + let objectB = objectMap[skNodeB] else { + fatalError("Unknown node in game scene") + } + + sceneDelegate?.contactOccured( + objectA: objectA, + objectB: objectB + ) + } +} diff --git a/SDPhysicsEngine/Sources/SDPhysicsEngine/Object/SDObject.swift b/SDPhysicsEngine/Sources/SDPhysicsEngine/Object/SDObject.swift index 7eb44ce6..3549ee9a 100644 --- a/SDPhysicsEngine/Sources/SDPhysicsEngine/Object/SDObject.swift +++ b/SDPhysicsEngine/Sources/SDPhysicsEngine/Object/SDObject.swift @@ -1,15 +1,20 @@ import SpriteKit +public typealias SDObjectId = UUID + public class SDObject { + public let id: SDObjectId let node: SKNode var innerRotation: CGFloat = 0 public init() { + id = UUID() node = SKNode() } init(node: SKNode) { + self.id = UUID() self.node = node } diff --git a/SDPhysicsEngine/Sources/SDPhysicsEngine/Object/SDPhysicsBody.swift b/SDPhysicsEngine/Sources/SDPhysicsEngine/Object/SDPhysicsBody.swift index b3f26a22..9c1f1a4d 100644 --- a/SDPhysicsEngine/Sources/SDPhysicsEngine/Object/SDPhysicsBody.swift +++ b/SDPhysicsEngine/Sources/SDPhysicsEngine/Object/SDPhysicsBody.swift @@ -36,4 +36,19 @@ public class SDPhysicsBody { get { body.isDynamic } set { body.isDynamic = newValue } } + + public var categoryBitMask: UInt32 { + get { body.categoryBitMask } + set { body.categoryBitMask = newValue } + } + + public var contactTestMask: UInt32 { + get { body.contactTestBitMask } + set { body.contactTestBitMask = newValue } + } + + public var collisionBitMask: UInt32 { + get { body.collisionBitMask } + set { body.collisionBitMask = newValue } + } } diff --git a/SDPhysicsEngine/Sources/SDPhysicsEngine/SDSceneDelegate.swift b/SDPhysicsEngine/Sources/SDPhysicsEngine/SDSceneDelegate.swift index e1e4dba3..cfd9d76b 100644 --- a/SDPhysicsEngine/Sources/SDPhysicsEngine/SDSceneDelegate.swift +++ b/SDPhysicsEngine/Sources/SDPhysicsEngine/SDSceneDelegate.swift @@ -1,4 +1,5 @@ public protocol SDSceneDelegate: AnyObject { func update(_ scene: SDScene, deltaTime: Double) + func contactOccured(objectA: SDObject, objectB: SDObject) } diff --git a/star-dash/star-dash.xcodeproj/project.pbxproj b/star-dash/star-dash.xcodeproj/project.pbxproj index 89de32f5..d3eacdaa 100644 --- a/star-dash/star-dash.xcodeproj/project.pbxproj +++ b/star-dash/star-dash.xcodeproj/project.pbxproj @@ -29,6 +29,8 @@ 14E2478E2BA22FCE0071FFC0 /* MoveEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14E2478D2BA22FCE0071FFC0 /* MoveEvent.swift */; }; 14E247932BA2CA920071FFC0 /* DequeModule in Frameworks */ = {isa = PBXBuildFile; productRef = 14E247922BA2CA920071FFC0 /* DequeModule */; }; 14E247952BA2CB480071FFC0 /* EventManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14E247942BA2CB480071FFC0 /* EventManager.swift */; }; + 4604BBD52BA819C70078B84C /* InventoryComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4604BBD42BA819C70078B84C /* InventoryComponent.swift */; }; + 4604BBD92BA81C940078B84C /* InventorySystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4604BBD82BA81C940078B84C /* InventorySystem.swift */; }; 461148912BA1CDBF0073E7E1 /* SystemManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 461148902BA1CDBF0073E7E1 /* SystemManager.swift */; }; 461148932BA1D04B0073E7E1 /* System.swift in Sources */ = {isa = PBXBuildFile; fileRef = 461148922BA1D04B0073E7E1 /* System.swift */; }; 461148962BA1D53D0073E7E1 /* PositionSystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 461148952BA1D53D0073E7E1 /* PositionSystem.swift */; }; @@ -39,7 +41,6 @@ 46D418162BA5CBD60091A38B /* Collidable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D418152BA5CBD60091A38B /* Collidable.swift */; }; 46D418182BA5CD840091A38B /* Player+Collidable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D418172BA5CD840091A38B /* Player+Collidable.swift */; }; 46D4181A2BA5CDBD0091A38B /* CollisionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D418192BA5CDBD0091A38B /* CollisionHandler.swift */; }; - 46D4181C2BA5CDC70091A38B /* SeparationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D4181B2BA5CDC70091A38B /* SeparationHandler.swift */; }; 46D4181E2BA5D2620091A38B /* Monster+Collidable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D4181D2BA5D2620091A38B /* Monster+Collidable.swift */; }; 46D418202BA5D3420091A38B /* Collectible+Collidable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D4181F2BA5D3420091A38B /* Collectible+Collidable.swift */; }; 46D418222BA5D4E60091A38B /* Obstacle+Collidable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D418212BA5D4E60091A38B /* Obstacle+Collidable.swift */; }; @@ -144,6 +145,8 @@ 14D14B722BA5A3CD00386C3B /* RemoveEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoveEvent.swift; sourceTree = ""; }; 14E2478D2BA22FCE0071FFC0 /* MoveEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoveEvent.swift; sourceTree = ""; }; 14E247942BA2CB480071FFC0 /* EventManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventManager.swift; sourceTree = ""; }; + 4604BBD42BA819C70078B84C /* InventoryComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InventoryComponent.swift; sourceTree = ""; }; + 4604BBD82BA81C940078B84C /* InventorySystem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InventorySystem.swift; sourceTree = ""; }; 461148902BA1CDBF0073E7E1 /* SystemManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SystemManager.swift; sourceTree = ""; }; 461148922BA1D04B0073E7E1 /* System.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = System.swift; sourceTree = ""; }; 461148952BA1D53D0073E7E1 /* PositionSystem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PositionSystem.swift; sourceTree = ""; }; @@ -154,7 +157,6 @@ 46D418152BA5CBD60091A38B /* Collidable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Collidable.swift; sourceTree = ""; }; 46D418172BA5CD840091A38B /* Player+Collidable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Player+Collidable.swift"; sourceTree = ""; }; 46D418192BA5CDBD0091A38B /* CollisionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollisionHandler.swift; sourceTree = ""; }; - 46D4181B2BA5CDC70091A38B /* SeparationHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparationHandler.swift; sourceTree = ""; }; 46D4181D2BA5D2620091A38B /* Monster+Collidable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Monster+Collidable.swift"; sourceTree = ""; }; 46D4181F2BA5D3420091A38B /* Collectible+Collidable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Collectible+Collidable.swift"; sourceTree = ""; }; 46D418212BA5D4E60091A38B /* Obstacle+Collidable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Obstacle+Collidable.swift"; sourceTree = ""; }; @@ -315,6 +317,7 @@ 14970F532BA8163300CC1E8A /* ScoreSystem.swift */, 461148952BA1D53D0073E7E1 /* PositionSystem.swift */, 461148972BA1E41F0073E7E1 /* PhysicsSystem.swift */, + 4604BBD82BA81C940078B84C /* InventorySystem.swift */, ); path = Systems; sourceTree = ""; @@ -337,7 +340,6 @@ 46D418152BA5CBD60091A38B /* Collidable.swift */, 46D418172BA5CD840091A38B /* Player+Collidable.swift */, 46D418192BA5CDBD0091A38B /* CollisionHandler.swift */, - 46D4181B2BA5CDC70091A38B /* SeparationHandler.swift */, 46D4181D2BA5D2620091A38B /* Monster+Collidable.swift */, 46D4181F2BA5D3420091A38B /* Collectible+Collidable.swift */, 46D418212BA5D4E60091A38B /* Obstacle+Collidable.swift */, @@ -451,6 +453,7 @@ 4E630F2D2B9F81850008F887 /* HealthComponent.swift */, 4E630F2F2B9F83DE0008F887 /* SpriteComponent.swift */, 4E630F312B9F887C0008F887 /* PhysicsComponent.swift */, + 4604BBD42BA819C70078B84C /* InventoryComponent.swift */, ); path = Components; sourceTree = ""; @@ -734,6 +737,7 @@ 4E630F2A2B9F7EF60008F887 /* PositionComponent.swift in Sources */, 46D418132BA5C9930091A38B /* Floor.swift in Sources */, E64361152BA4C2CD003850FD /* GameBridge.swift in Sources */, + 4604BBD92BA81C940078B84C /* InventorySystem.swift in Sources */, 14E247952BA2CB480071FFC0 /* EventManager.swift in Sources */, 4E630EF82B9F7E070008F887 /* SceneDelegate.swift in Sources */, 14970F542BA8163300CC1E8A /* ScoreSystem.swift in Sources */, @@ -760,9 +764,9 @@ 14970F502BA814D500CC1E8A /* ScoreComponent.swift in Sources */, 143AA3912BA4D7AC009C28E7 /* MonsterDeathEvent.swift in Sources */, E64361102BA4C2CD003850FD /* SpriteModule.swift in Sources */, + 4604BBD52BA819C70078B84C /* InventoryComponent.swift in Sources */, 46B8C09A2BA328D900498705 /* GameEngine.swift in Sources */, 461148982BA1E41F0073E7E1 /* PhysicsSystem.swift in Sources */, - 46D4181C2BA5CDC70091A38B /* SeparationHandler.swift in Sources */, 4E630F2E2B9F81850008F887 /* HealthComponent.swift in Sources */, 4E86605C2BA095460035530D /* Monster.swift in Sources */, 145F2C802BA203B400457549 /* Event.swift in Sources */, diff --git a/star-dash/star-dash/Constants/PhysicsConstants.swift b/star-dash/star-dash/Constants/PhysicsConstants.swift index 0958bdea..913ad3c0 100644 --- a/star-dash/star-dash/Constants/PhysicsConstants.swift +++ b/star-dash/star-dash/Constants/PhysicsConstants.swift @@ -24,10 +24,10 @@ struct PhysicsConstants { static let player = CollisionCategory.max ^ CollisionCategory.player static let monster = CollisionCategory.player | CollisionCategory.tool static let collectible = CollisionCategory.player - static let obstacle = CollisionCategory.player - static let tool = CollisionCategory.player | CollisionCategory.monster - static let wall = CollisionCategory.player | CollisionCategory.monster - static let floor = CollisionCategory.player | CollisionCategory.monster + static let obstacle = CollisionCategory.player | CollisionCategory.monster | CollisionMask.tool + static let tool = CollisionCategory.max ^ CollisionCategory.collectible ^ CollisionCategory.tool + static let wall = CollisionCategory.player | CollisionCategory.monster | CollisionCategory.tool + static let floor = CollisionCategory.player | CollisionCategory.monster | CollisionCategory.tool } struct Dimensions { diff --git a/star-dash/star-dash/Events/ContactEvents/PlayerMonsterContactEvent.swift b/star-dash/star-dash/Events/ContactEvents/PlayerMonsterContactEvent.swift index 97f89642..179d1d20 100644 --- a/star-dash/star-dash/Events/ContactEvents/PlayerMonsterContactEvent.swift +++ b/star-dash/star-dash/Events/ContactEvents/PlayerMonsterContactEvent.swift @@ -8,19 +8,39 @@ import Foundation class PlayerMonsterContactEvent: Event { - let timestamp: Date - let entityId: EntityId + var entityId: EntityId - let monsterEntityId: EntityId + let timestamp: Date + let monsterId: EntityId - init(from playerEntityId: EntityId, on monsterEntityId: EntityId) { + init(from playerId: EntityId, on monsterId: EntityId) { self.timestamp = Date.now - entityId = playerEntityId - self.monsterEntityId = monsterEntityId + self.entityId = playerId + self.monsterId = monsterId } func execute(on target: EventModifiable) { - // TODO: Determine if player is directly on top of monster. - // Trigger PlayerAttackMonsterEvent and MonsterAttackPlayerEvent accordingly + guard let positionSystem = target.system(ofType: PositionSystem.self), + let physicsSystem = target.system(ofType: PhysicsSystem.self) else { + return + } + + guard let playerPosition = positionSystem.getPosition(of: entityId), + let monsterPosition = positionSystem.getPosition(of: monsterId) else { + return + } + + guard let playerSize = physicsSystem.getSize(of: entityId), + let monsterSize = physicsSystem.getSize(of: monsterId) else { + return + } + + let isPlayerAbove = playerPosition.y - (playerSize.height / 2) >= monsterPosition.y + (monsterSize.height / 2) + + if isPlayerAbove { + target.add(event: PlayerAttackMonsterEvent(on: monsterId)) + } else { + target.add(event: MonsterAttackPlayerEvent(from: monsterId, on: entityId)) + } } } diff --git a/star-dash/star-dash/Events/MonsterEvents/MonsterAttackPlayerEvent.swift b/star-dash/star-dash/Events/MonsterEvents/MonsterAttackPlayerEvent.swift index 4b1b1661..9e8939f6 100644 --- a/star-dash/star-dash/Events/MonsterEvents/MonsterAttackPlayerEvent.swift +++ b/star-dash/star-dash/Events/MonsterEvents/MonsterAttackPlayerEvent.swift @@ -8,20 +8,39 @@ import Foundation class MonsterAttackPlayerEvent: Event { + private static let damageImpulse = CGVector(dx: 500, dy: 0) + let timestamp: Date let entityId: EntityId + let monsterId: EntityId - init(on entityId: EntityId) { + init(from monsterId: EntityId, on entityId: EntityId) { timestamp = Date.now self.entityId = entityId + self.monsterId = monsterId } func execute(on target: EventModifiable) { - guard let healthSystem = target.system(ofType: HealthSystem.self) else { + guard let healthSystem = target.system(ofType: HealthSystem.self), + let positionSystem = target.system(ofType: PositionSystem.self), + let physicsSystem = target.system(ofType: PhysicsSystem.self) else { + return + } + + guard let monsterPosition = positionSystem.getPosition(of: monsterId), + let playerPosition = positionSystem.getPosition(of: entityId) else { return } + healthSystem.applyHealthChange(to: entityId, healthChange: GameConstants.HealthChange.attackedByMonster) + let isMonsterToRight = monsterPosition.x > playerPosition.x + let impulse = isMonsterToRight + ? MonsterAttackPlayerEvent.damageImpulse * -1 + : MonsterAttackPlayerEvent.damageImpulse + + physicsSystem.applyImpulse(to: entityId, impulse: impulse) + if !healthSystem.hasHealth(for: entityId) { target.add(event: PlayerDeathEvent(on: entityId)) } diff --git a/star-dash/star-dash/Events/MonsterEvents/PlayerAttackMonsterEvent.swift b/star-dash/star-dash/Events/MonsterEvents/PlayerAttackMonsterEvent.swift index 6c64dd91..cf3f836c 100644 --- a/star-dash/star-dash/Events/MonsterEvents/PlayerAttackMonsterEvent.swift +++ b/star-dash/star-dash/Events/MonsterEvents/PlayerAttackMonsterEvent.swift @@ -8,6 +8,8 @@ import Foundation class PlayerAttackMonsterEvent: Event { + private static let attackImpulse = CGVector(dx: 0, dy: 400) + let timestamp: Date let entityId: EntityId @@ -17,10 +19,13 @@ class PlayerAttackMonsterEvent: Event { } func execute(on target: EventModifiable) { - guard let healthSystem = target.system(ofType: HealthSystem.self) else { + guard let healthSystem = target.system(ofType: HealthSystem.self), + let physicSystem = target.system(ofType: PhysicsSystem.self) else { return } + healthSystem.applyHealthChange(to: entityId, healthChange: GameConstants.HealthChange.attackedByPlayer) + physicSystem.applyImpulse(to: entityId, impulse: PlayerAttackMonsterEvent.attackImpulse) if !healthSystem.hasHealth(for: entityId) { target.add(event: MonsterDeathEvent(on: entityId)) diff --git a/star-dash/star-dash/GameBridge/GameBridge.swift b/star-dash/star-dash/GameBridge/GameBridge.swift index 815171f2..a71662ba 100644 --- a/star-dash/star-dash/GameBridge/GameBridge.swift +++ b/star-dash/star-dash/GameBridge/GameBridge.swift @@ -6,6 +6,7 @@ class GameBridge { var scene: SDScene var entitiesMap: [EntityId: SDObject] + var objectsMap: [SDObjectId: EntityId] var modules: [SyncModule] var creationModule: CreationModule? @@ -14,6 +15,7 @@ class GameBridge { self.scene = scene modules = [] entitiesMap = [:] + objectsMap = [:] registerModules() } @@ -43,6 +45,10 @@ class GameBridge { } } + func entityId(of objectId: SDObjectId) -> EntityId? { + objectsMap[objectId] + } + private func registerModule(_ module: SyncModule) { modules.append(module) } @@ -73,6 +79,7 @@ class GameBridge { return } entitiesMap[entity.id] = newObject + objectsMap[newObject.id] = entity.id modules.forEach { $0.create(for: newObject, from: entity) diff --git a/star-dash/star-dash/GameBridge/SyncModule/PhysicsModule.swift b/star-dash/star-dash/GameBridge/SyncModule/PhysicsModule.swift index 21432119..c7207ba3 100644 --- a/star-dash/star-dash/GameBridge/SyncModule/PhysicsModule.swift +++ b/star-dash/star-dash/GameBridge/SyncModule/PhysicsModule.swift @@ -18,6 +18,9 @@ class PhysicsModule: SyncModule { physicsComponent.velocity = body.velocity // physicsComponent.force = body.force physicsComponent.affectedByGravity = body.affectedByGravity + physicsComponent.categoryBitMask = body.categoryBitMask + physicsComponent.contactTestMask = body.contactTestMask + physicsComponent.collisionBitMask = body.collisionBitMask } func sync(object: SDObject, from entity: Entity) { @@ -30,6 +33,9 @@ class PhysicsModule: SyncModule { body.velocity = physicsComponent.velocity // body.force = physicsComponent.force body.affectedByGravity = physicsComponent.affectedByGravity + body.categoryBitMask = body.categoryBitMask + body.contactTestMask = body.contactTestMask + body.collisionBitMask = body.collisionBitMask } func create(for object: SDObject, from entity: Entity) { diff --git a/star-dash/star-dash/GameEngine/Collision/Collectible+Collidable.swift b/star-dash/star-dash/GameEngine/Collision/Collectible+Collidable.swift index 45b86c30..684518bd 100644 --- a/star-dash/star-dash/GameEngine/Collision/Collectible+Collidable.swift +++ b/star-dash/star-dash/GameEngine/Collision/Collectible+Collidable.swift @@ -37,36 +37,4 @@ extension Collectible: Collidable { func collideWithFloor(_ floor: Floor) -> Event? { nil } - - func separates(from collidable: Collidable) -> Event? { - collidable.separatesFromCollectible(self) - } - - func separatesFromPlayer(_ player: Player) -> Event? { - SeparationHandler.between(player: player, collectible: self) - } - - func separatesFromMonster(_ monster: Monster) -> Event? { - nil - } - - func separatesFromCollectible(_ collectible: Collectible) -> Event? { - nil - } - - func separatesFromObstacle(_ obstacle: Obstacle) -> Event? { - nil - } - - func separatesFromTool(_ tool: Tool) -> Event? { - nil - } - - func separatesFromWall(_ wall: Wall) -> Event? { - nil - } - - func separatesFromFloor(_ floor: Floor) -> Event? { - nil - } } diff --git a/star-dash/star-dash/GameEngine/Collision/Collidable.swift b/star-dash/star-dash/GameEngine/Collision/Collidable.swift index 3e677e45..0e09ed0f 100644 --- a/star-dash/star-dash/GameEngine/Collision/Collidable.swift +++ b/star-dash/star-dash/GameEngine/Collision/Collidable.swift @@ -14,13 +14,4 @@ protocol Collidable { func collideWithTool(_ tool: Tool) -> Event? func collideWithWall(_ wall: Wall) -> Event? func collideWithFloor(_ floor: Floor) -> Event? - - func separates(from collidable: Collidable) -> Event? - func separatesFromPlayer(_ player: Player) -> Event? - func separatesFromMonster(_ monster: Monster) -> Event? - func separatesFromCollectible(_ collectible: Collectible) -> Event? - func separatesFromObstacle(_ obstacle: Obstacle) -> Event? - func separatesFromTool(_ tool: Tool) -> Event? - func separatesFromWall(_ wall: Wall) -> Event? - func separatesFromFloor(_ floor: Floor) -> Event? } diff --git a/star-dash/star-dash/GameEngine/Collision/CollisionHandler.swift b/star-dash/star-dash/GameEngine/Collision/CollisionHandler.swift index d108a5e5..a68a222a 100644 --- a/star-dash/star-dash/GameEngine/Collision/CollisionHandler.swift +++ b/star-dash/star-dash/GameEngine/Collision/CollisionHandler.swift @@ -9,11 +9,11 @@ import Foundation struct CollisionHandler { static func between(player: Player, monster: Monster) -> Event? { - nil + PlayerMonsterContactEvent(from: player.id, on: monster.id) } static func between(player: Player, collectible: Collectible) -> Event? { - nil + PickupCollectibleEvent(by: player.id, collectibleEntityId: collectible.id) } static func between(player: Player, obstacle: Obstacle) -> Event? { @@ -43,4 +43,20 @@ struct CollisionHandler { static func between(monster: Monster, floor: Floor) -> Event? { nil } + + static func between(monster: Monster, obstacle: Obstacle) -> Event? { + nil + } + + static func between(tool: Tool, floor: Floor) -> Event? { + nil + } + + static func between(tool: Tool, wall: Wall) -> Event? { + nil + } + + static func between(tool: Tool, obstacle: Obstacle) -> Event? { + nil + } } diff --git a/star-dash/star-dash/GameEngine/Collision/Floor+Collidable.swift b/star-dash/star-dash/GameEngine/Collision/Floor+Collidable.swift index 43076bc4..ee161294 100644 --- a/star-dash/star-dash/GameEngine/Collision/Floor+Collidable.swift +++ b/star-dash/star-dash/GameEngine/Collision/Floor+Collidable.swift @@ -27,7 +27,7 @@ extension Floor: Collidable { } func collideWithTool(_ tool: Tool) -> Event? { - nil + CollisionHandler.between(tool: tool, floor: self) } func collideWithWall(_ wall: Wall) -> Event? { @@ -37,36 +37,4 @@ extension Floor: Collidable { func collideWithFloor(_ floor: Floor) -> Event? { nil } - - func separates(from collidable: Collidable) -> Event? { - collidable.separatesFromFloor(self) - } - - func separatesFromPlayer(_ player: Player) -> Event? { - SeparationHandler.between(player: player, floor: self) - } - - func separatesFromMonster(_ monster: Monster) -> Event? { - SeparationHandler.between(monster: monster, floor: self) - } - - func separatesFromCollectible(_ collectible: Collectible) -> Event? { - nil - } - - func separatesFromObstacle(_ obstacle: Obstacle) -> Event? { - nil - } - - func separatesFromTool(_ tool: Tool) -> Event? { - nil - } - - func separatesFromWall(_ wall: Wall) -> Event? { - nil - } - - func separatesFromFloor(_ floor: Floor) -> Event? { - nil - } } diff --git a/star-dash/star-dash/GameEngine/Collision/Monster+Collidable.swift b/star-dash/star-dash/GameEngine/Collision/Monster+Collidable.swift index 8d6edb22..c7f88f7d 100644 --- a/star-dash/star-dash/GameEngine/Collision/Monster+Collidable.swift +++ b/star-dash/star-dash/GameEngine/Collision/Monster+Collidable.swift @@ -23,7 +23,7 @@ extension Monster: Collidable { } func collideWithObstacle(_ obstacle: Obstacle) -> Event? { - nil + CollisionHandler.between(monster: self, obstacle: obstacle) } func collideWithTool(_ tool: Tool) -> Event? { @@ -31,42 +31,10 @@ extension Monster: Collidable { } func collideWithWall(_ wall: Wall) -> Event? { - nil + CollisionHandler.between(monster: self, wall: wall) } func collideWithFloor(_ floor: Floor) -> Event? { - nil - } - - func separates(from collidable: Collidable) -> Event? { - collidable.separatesFromMonster(self) - } - - func separatesFromPlayer(_ player: Player) -> Event? { - SeparationHandler.between(player: player, monster: self) - } - - func separatesFromMonster(_ monster: Monster) -> Event? { - nil - } - - func separatesFromCollectible(_ collectible: Collectible) -> Event? { - nil - } - - func separatesFromObstacle(_ obstacle: Obstacle) -> Event? { - nil - } - - func separatesFromTool(_ tool: Tool) -> Event? { - SeparationHandler.between(monster: self, tool: tool) - } - - func separatesFromWall(_ wall: Wall) -> Event? { - nil - } - - func separatesFromFloor(_ floor: Floor) -> Event? { - nil + CollisionHandler.between(monster: self, floor: floor) } } diff --git a/star-dash/star-dash/GameEngine/Collision/Obstacle+Collidable.swift b/star-dash/star-dash/GameEngine/Collision/Obstacle+Collidable.swift index 79745db8..30bfeac8 100644 --- a/star-dash/star-dash/GameEngine/Collision/Obstacle+Collidable.swift +++ b/star-dash/star-dash/GameEngine/Collision/Obstacle+Collidable.swift @@ -15,7 +15,7 @@ extension Obstacle: Collidable { } func collideWithMonster(_ monster: Monster) -> Event? { - nil + CollisionHandler.between(monster: monster, obstacle: self) } func collideWithCollectible(_ collectible: Collectible) -> Event? { @@ -27,7 +27,7 @@ extension Obstacle: Collidable { } func collideWithTool(_ tool: Tool) -> Event? { - nil + CollisionHandler.between(tool: tool, obstacle: self) } func collideWithWall(_ wall: Wall) -> Event? { @@ -37,36 +37,4 @@ extension Obstacle: Collidable { func collideWithFloor(_ floor: Floor) -> Event? { nil } - - func separates(from collidable: Collidable) -> Event? { - collidable.separatesFromObstacle(self) - } - - func separatesFromPlayer(_ player: Player) -> Event? { - SeparationHandler.between(player: player, obstacle: self) - } - - func separatesFromMonster(_ monster: Monster) -> Event? { - nil - } - - func separatesFromCollectible(_ collectible: Collectible) -> Event? { - nil - } - - func separatesFromObstacle(_ obstacle: Obstacle) -> Event? { - nil - } - - func separatesFromTool(_ tool: Tool) -> Event? { - nil - } - - func separatesFromWall(_ wall: Wall) -> Event? { - nil - } - - func separatesFromFloor(_ floor: Floor) -> Event? { - nil - } } diff --git a/star-dash/star-dash/GameEngine/Collision/Player+Collidable.swift b/star-dash/star-dash/GameEngine/Collision/Player+Collidable.swift index 1c467323..27006202 100644 --- a/star-dash/star-dash/GameEngine/Collision/Player+Collidable.swift +++ b/star-dash/star-dash/GameEngine/Collision/Player+Collidable.swift @@ -37,36 +37,4 @@ extension Player: Collidable { func collideWithFloor(_ floor: Floor) -> Event? { CollisionHandler.between(player: self, floor: floor) } - - func separates(from collidable: Collidable) -> Event? { - collidable.separatesFromPlayer(self) - } - - func separatesFromPlayer(_ player: Player) -> Event? { - nil - } - - func separatesFromMonster(_ monster: Monster) -> Event? { - SeparationHandler.between(player: self, monster: monster) - } - - func separatesFromCollectible(_ collectible: Collectible) -> Event? { - SeparationHandler.between(player: self, collectible: collectible) - } - - func separatesFromObstacle(_ obstacle: Obstacle) -> Event? { - SeparationHandler.between(player: self, obstacle: obstacle) - } - - func separatesFromTool(_ tool: Tool) -> Event? { - SeparationHandler.between(player: self, tool: tool) - } - - func separatesFromWall(_ wall: Wall) -> Event? { - SeparationHandler.between(player: self, wall: wall) - } - - func separatesFromFloor(_ floor: Floor) -> Event? { - SeparationHandler.between(player: self, floor: floor) - } } diff --git a/star-dash/star-dash/GameEngine/Collision/SeparationHandler.swift b/star-dash/star-dash/GameEngine/Collision/SeparationHandler.swift deleted file mode 100644 index bb78d0be..00000000 --- a/star-dash/star-dash/GameEngine/Collision/SeparationHandler.swift +++ /dev/null @@ -1,46 +0,0 @@ -// -// SeparationHandler.swift -// star-dash -// -// Created by Ho Jun Hao on 16/3/24. -// - -struct SeparationHandler { - // TODO: Add appropriate events - - static func between(player: Player, monster: Monster) -> Event? { - nil - } - - static func between(player: Player, collectible: Collectible) -> Event? { - nil - } - - static func between(player: Player, obstacle: Obstacle) -> Event? { - nil - } - - static func between(player: Player, floor: Floor) -> Event? { - nil - } - - static func between(player: Player, wall: Wall) -> Event? { - nil - } - - static func between(player: Player, tool: Tool) -> Event? { - nil - } - - static func between(monster: Monster, tool: Tool) -> Event? { - nil - } - - static func between(monster: Monster, wall: Wall) -> Event? { - nil - } - - static func between(monster: Monster, floor: Floor) -> Event? { - nil - } -} diff --git a/star-dash/star-dash/GameEngine/Collision/Tool+Collidable.swift b/star-dash/star-dash/GameEngine/Collision/Tool+Collidable.swift index 05aab3c6..91227ced 100644 --- a/star-dash/star-dash/GameEngine/Collision/Tool+Collidable.swift +++ b/star-dash/star-dash/GameEngine/Collision/Tool+Collidable.swift @@ -23,7 +23,7 @@ extension Tool: Collidable { } func collideWithObstacle(_ obstacle: Obstacle) -> Event? { - nil + CollisionHandler.between(tool: self, obstacle: obstacle) } func collideWithTool(_ tool: Tool) -> Event? { @@ -31,42 +31,10 @@ extension Tool: Collidable { } func collideWithWall(_ wall: Wall) -> Event? { - nil + CollisionHandler.between(tool: self, wall: wall) } func collideWithFloor(_ floor: Floor) -> Event? { - nil - } - - func separates(from collidable: Collidable) -> Event? { - collidable.separatesFromTool(self) - } - - func separatesFromPlayer(_ player: Player) -> Event? { - SeparationHandler.between(player: player, tool: self) - } - - func separatesFromMonster(_ monster: Monster) -> Event? { - SeparationHandler.between(monster: monster, tool: self) - } - - func separatesFromCollectible(_ collectible: Collectible) -> Event? { - nil - } - - func separatesFromObstacle(_ obstacle: Obstacle) -> Event? { - nil - } - - func separatesFromTool(_ tool: Tool) -> Event? { - nil - } - - func separatesFromWall(_ wall: Wall) -> Event? { - nil - } - - func separatesFromFloor(_ floor: Floor) -> Event? { - nil + CollisionHandler.between(tool: self, floor: floor) } } diff --git a/star-dash/star-dash/GameEngine/Collision/Wall+Collidable.swift b/star-dash/star-dash/GameEngine/Collision/Wall+Collidable.swift index 876d77c8..0d180122 100644 --- a/star-dash/star-dash/GameEngine/Collision/Wall+Collidable.swift +++ b/star-dash/star-dash/GameEngine/Collision/Wall+Collidable.swift @@ -27,7 +27,7 @@ extension Wall: Collidable { } func collideWithTool(_ tool: Tool) -> Event? { - nil + CollisionHandler.between(tool: tool, wall: self) } func collideWithWall(_ wall: Wall) -> Event? { @@ -37,36 +37,4 @@ extension Wall: Collidable { func collideWithFloor(_ floor: Floor) -> Event? { nil } - - func separates(from collidable: Collidable) -> Event? { - collidable.separatesFromWall(self) - } - - func separatesFromPlayer(_ player: Player) -> Event? { - SeparationHandler.between(player: player, wall: self) - } - - func separatesFromMonster(_ monster: Monster) -> Event? { - SeparationHandler.between(monster: monster, wall: self) - } - - func separatesFromCollectible(_ collectible: Collectible) -> Event? { - nil - } - - func separatesFromObstacle(_ obstacle: Obstacle) -> Event? { - nil - } - - func separatesFromTool(_ tool: Tool) -> Event? { - nil - } - - func separatesFromWall(_ wall: Wall) -> Event? { - nil - } - - func separatesFromFloor(_ floor: Floor) -> Event? { - nil - } } diff --git a/star-dash/star-dash/GameEngine/Components/InventoryComponent.swift b/star-dash/star-dash/GameEngine/Components/InventoryComponent.swift new file mode 100644 index 00000000..56388055 --- /dev/null +++ b/star-dash/star-dash/GameEngine/Components/InventoryComponent.swift @@ -0,0 +1,24 @@ +// +// InventoryComponent.swift +// star-dash +// +// Created by Ho Jun Hao on 18/3/24. +// + +import DequeModule +import Foundation + +typealias InventoryQueue = Deque + +class InventoryComponent: Component { + var inventory: Deque + + init(id: ComponentId, entityId: EntityId, inventory: Deque) { + self.inventory = inventory + super.init(id: id, entityId: entityId) + } + + convenience init(entityId: EntityId) { + self.init(id: UUID(), entityId: entityId, inventory: InventoryQueue()) + } +} diff --git a/star-dash/star-dash/GameEngine/Components/PhysicsComponent.swift b/star-dash/star-dash/GameEngine/Components/PhysicsComponent.swift index e8907dcf..b6138970 100644 --- a/star-dash/star-dash/GameEngine/Components/PhysicsComponent.swift +++ b/star-dash/star-dash/GameEngine/Components/PhysicsComponent.swift @@ -12,7 +12,9 @@ class PhysicsComponent: Component { var mass: CGFloat = .zero var velocity: CGVector = .zero var force: CGVector = .zero - var collisionMask: UInt32? + var categoryBitMask: UInt32 = 0xFFFFFFFF + var contactTestMask: UInt32 = 0x0 + var collisionBitMask: UInt32 = 0xFFFFFFFF var affectedByGravity = false var size: CGSize? diff --git a/star-dash/star-dash/GameEngine/Entities/GameEntities/Collectible.swift b/star-dash/star-dash/GameEngine/Entities/GameEntities/Collectible.swift index ed3419d7..bb0d7c39 100644 --- a/star-dash/star-dash/GameEngine/Entities/GameEntities/Collectible.swift +++ b/star-dash/star-dash/GameEngine/Entities/GameEntities/Collectible.swift @@ -23,7 +23,7 @@ class Collectible: Entity { func setUpAndAdd(to: EntityManager) { let positionComponent = PositionComponent(entityId: self.id, position: self.position, rotation: .zero) let physicsComponent = PhysicsComponent(entityId: self.id, size: PhysicsConstants.Dimensions.collectible) - physicsComponent.collisionMask = PhysicsConstants.CollisionMask.collectible + physicsComponent.collisionBitMask = PhysicsConstants.CollisionMask.collectible to.add(entity: self) to.add(component: positionComponent) diff --git a/star-dash/star-dash/GameEngine/Entities/GameEntities/Floor.swift b/star-dash/star-dash/GameEngine/Entities/GameEntities/Floor.swift index 2a566e23..f757960f 100644 --- a/star-dash/star-dash/GameEngine/Entities/GameEntities/Floor.swift +++ b/star-dash/star-dash/GameEngine/Entities/GameEntities/Floor.swift @@ -24,7 +24,7 @@ class Floor: Entity { func setUpAndAdd(to: EntityManager) { let positionComponent = PositionComponent(entityId: self.id, position: self.position, rotation: .zero) let physicsComponent = PhysicsComponent(entityId: self.id, size: PhysicsConstants.Dimensions.floor) - physicsComponent.collisionMask = PhysicsConstants.CollisionMask.floor + physicsComponent.collisionBitMask = PhysicsConstants.CollisionMask.floor to.add(entity: self) to.add(component: positionComponent) diff --git a/star-dash/star-dash/GameEngine/Entities/GameEntities/Monster.swift b/star-dash/star-dash/GameEngine/Entities/GameEntities/Monster.swift index 8b8c4068..1f3cef06 100644 --- a/star-dash/star-dash/GameEngine/Entities/GameEntities/Monster.swift +++ b/star-dash/star-dash/GameEngine/Entities/GameEntities/Monster.swift @@ -24,7 +24,7 @@ class Monster: Entity { let positionComponent = PositionComponent(entityId: self.id, position: self.position, rotation: .zero) let healthComponent = HealthComponent(entityId: self.id, health: GameConstants.InitialHealth.monster) let physicsComponent = PhysicsComponent(entityId: self.id, size: PhysicsConstants.Dimensions.monster) - physicsComponent.collisionMask = PhysicsConstants.CollisionMask.monster + physicsComponent.collisionBitMask = PhysicsConstants.CollisionMask.monster physicsComponent.affectedByGravity = true to.add(entity: self) diff --git a/star-dash/star-dash/GameEngine/Entities/GameEntities/Obstacle.swift b/star-dash/star-dash/GameEngine/Entities/GameEntities/Obstacle.swift index 80ed27c5..117a8460 100644 --- a/star-dash/star-dash/GameEngine/Entities/GameEntities/Obstacle.swift +++ b/star-dash/star-dash/GameEngine/Entities/GameEntities/Obstacle.swift @@ -23,7 +23,7 @@ class Obstacle: Entity { func setUpAndAdd(to: EntityManager) { let positionComponent = PositionComponent(entityId: self.id, position: self.position, rotation: .zero) let physicsComponent = PhysicsComponent(entityId: self.id, size: PhysicsConstants.Dimensions.obstacle) - physicsComponent.collisionMask = PhysicsConstants.CollisionMask.obstacle + physicsComponent.collisionBitMask = PhysicsConstants.CollisionMask.obstacle to.add(entity: self) to.add(component: positionComponent) diff --git a/star-dash/star-dash/GameEngine/Entities/GameEntities/Player.swift b/star-dash/star-dash/GameEngine/Entities/GameEntities/Player.swift index f575be90..02080128 100644 --- a/star-dash/star-dash/GameEngine/Entities/GameEntities/Player.swift +++ b/star-dash/star-dash/GameEngine/Entities/GameEntities/Player.swift @@ -26,7 +26,9 @@ class Player: Entity { let positionComponent = PositionComponent(entityId: self.id, position: self.position, rotation: .zero) let healthComponent = HealthComponent(entityId: self.id, health: GameConstants.InitialHealth.player) let physicsComponent = PhysicsComponent(entityId: self.id, size: PhysicsConstants.Dimensions.player) - physicsComponent.collisionMask = PhysicsConstants.CollisionMask.player + physicsComponent.categoryBitMask = 1 << 2 + physicsComponent.contactTestMask = 1 << 1 + physicsComponent.collisionBitMask = PhysicsConstants.CollisionMask.player physicsComponent.affectedByGravity = true let spriteComponent = SpriteComponent(entityId: self.id, image: "", textureAtlas: "", size: .zero) let scoreComponent = ScoreComponent(entityId: self.id, score: 0) diff --git a/star-dash/star-dash/GameEngine/Entities/GameEntities/Tool.swift b/star-dash/star-dash/GameEngine/Entities/GameEntities/Tool.swift index 02be37c4..411810bd 100644 --- a/star-dash/star-dash/GameEngine/Entities/GameEntities/Tool.swift +++ b/star-dash/star-dash/GameEngine/Entities/GameEntities/Tool.swift @@ -23,7 +23,7 @@ class Tool: Entity { func setUpAndAdd(to: EntityManager) { let positionComponent = PositionComponent(entityId: self.id, position: self.position, rotation: .zero) let physicsComponent = PhysicsComponent(entityId: self.id, size: PhysicsConstants.Dimensions.tool) - physicsComponent.collisionMask = PhysicsConstants.CollisionMask.tool + physicsComponent.collisionBitMask = PhysicsConstants.CollisionMask.tool to.add(entity: self) to.add(component: positionComponent) diff --git a/star-dash/star-dash/GameEngine/Entities/GameEntities/Wall.swift b/star-dash/star-dash/GameEngine/Entities/GameEntities/Wall.swift index c419c093..c5fe61a4 100644 --- a/star-dash/star-dash/GameEngine/Entities/GameEntities/Wall.swift +++ b/star-dash/star-dash/GameEngine/Entities/GameEntities/Wall.swift @@ -23,7 +23,7 @@ class Wall: Entity { func setUpAndAdd(to: EntityManager) { let positionComponent = PositionComponent(entityId: self.id, position: self.position, rotation: .zero) let physicsComponent = PhysicsComponent(entityId: self.id, size: PhysicsConstants.Dimensions.wall) - physicsComponent.collisionMask = PhysicsConstants.CollisionMask.wall + physicsComponent.collisionBitMask = PhysicsConstants.CollisionMask.wall to.add(entity: self) to.add(component: positionComponent) diff --git a/star-dash/star-dash/GameEngine/GameEngine.swift b/star-dash/star-dash/GameEngine/GameEngine.swift index 31350e77..85ce2475 100644 --- a/star-dash/star-dash/GameEngine/GameEngine.swift +++ b/star-dash/star-dash/GameEngine/GameEngine.swift @@ -25,10 +25,15 @@ class GameEngine { eventManager.executeAll(on: self) } - // TODO: after events are ready - func handleCollision(_ entityOne: EntityId, _ entityTwo: EntityId) {} + func handleCollision(_ entityOneId: EntityId, _ entityTwoId: EntityId) { + guard let entityOne = entity(of: entityOneId) as? Collidable, + let entityTwo = entity(of: entityTwoId) as? Collidable, + let event = entityOne.collides(with: entityTwo) else { + return + } - func handleSeparation(_ entityOne: EntityId, _ entityTwo: EntityId) {} + eventManager.add(event: event) + } private func setUpSystems() { systemManager.add(PositionSystem(entityManager, dispatcher: self)) diff --git a/star-dash/star-dash/GameEngine/Systems/InventorySystem.swift b/star-dash/star-dash/GameEngine/Systems/InventorySystem.swift new file mode 100644 index 00000000..bcac2918 --- /dev/null +++ b/star-dash/star-dash/GameEngine/Systems/InventorySystem.swift @@ -0,0 +1,40 @@ +// +// InventorySystem.swift +// star-dash +// +// Created by Ho Jun Hao on 18/3/24. +// + +import Foundation + +class InventorySystem: System { + var isActive: Bool + var dispatcher: EventModifiable? + var entityManager: EntityManager + + init(_ entityManager: EntityManager, dispatcher: EventModifiable? = nil) { + self.isActive = true + self.entityManager = entityManager + self.dispatcher = dispatcher + } + + func enqueueItem(for entityId: EntityId, with powerupEntityId: EntityId) { + guard let inventoryComponent = getInventoryComponent(of: entityId) else { + return + } + + inventoryComponent.inventory.append(powerupEntityId) + } + + func dequeueItem(for entityId: EntityId) -> EntityId? { + guard let inventoryComponent = getInventoryComponent(of: entityId) else { + return nil + } + + return inventoryComponent.inventory.removeFirst() + } + + private func getInventoryComponent(of entityId: EntityId) -> InventoryComponent? { + entityManager.component(ofType: InventoryComponent.self, of: entityId) + } +} diff --git a/star-dash/star-dash/GameEngine/Systems/PhysicsSystem.swift b/star-dash/star-dash/GameEngine/Systems/PhysicsSystem.swift index 0df8d50b..de4730b9 100644 --- a/star-dash/star-dash/GameEngine/Systems/PhysicsSystem.swift +++ b/star-dash/star-dash/GameEngine/Systems/PhysicsSystem.swift @@ -58,6 +58,18 @@ class PhysicsSystem: System { physicsComponent.velocity += (impulse / physicsComponent.mass) } + func getSize(of entityId: EntityId) -> CGSize? { + guard let physicsComponent = getPhysicsComponent(of: entityId) else { + return nil + } + + guard physicsComponent.shape == .rectangle else { + return nil + } + + return physicsComponent.size + } + private func getPhysicsComponent(of entityId: EntityId) -> PhysicsComponent? { entityManager.component(ofType: PhysicsComponent.self, of: entityId) } diff --git a/star-dash/star-dash/GameEngine/Systems/PositionSystem.swift b/star-dash/star-dash/GameEngine/Systems/PositionSystem.swift index cc51c7d1..7c6f3f3d 100644 --- a/star-dash/star-dash/GameEngine/Systems/PositionSystem.swift +++ b/star-dash/star-dash/GameEngine/Systems/PositionSystem.swift @@ -34,6 +34,14 @@ class PositionSystem: System { positionComponent.setRotation(rotation: newRotation) } + func getPosition(of entityId: EntityId) -> CGPoint? { + guard let positionComponent = getPositionComponent(of: entityId) else { + return nil + } + + return positionComponent.position + } + private func getPositionComponent(of entityId: EntityId) -> PositionComponent? { entityManager.component(ofType: PositionComponent.self, of: entityId) } diff --git a/star-dash/star-dash/ViewController.swift b/star-dash/star-dash/ViewController.swift index 3c1896d1..9ad17acc 100644 --- a/star-dash/star-dash/ViewController.swift +++ b/star-dash/star-dash/ViewController.swift @@ -51,6 +51,8 @@ class ViewController: UIViewController { let platform = SDObject() platform.physicsBody = SDPhysicsBody(rectangleOf: CGSize(width: 200, height: 50)) platform.physicsBody?.isDynamic = false + platform.physicsBody?.categoryBitMask = 1 << 1 + platform.physicsBody?.contactTestMask = 1 << 2 platform.position = CGPoint(x: scene.size.width / 2, y: scene.size.height / 2 - 400) scene.addObject(platform) @@ -69,4 +71,14 @@ extension ViewController: SDSceneDelegate { gameEngine?.update(by: deltaTime) gameBridge?.syncFromEntities() } + + func contactOccured(objectA: SDObject, objectB: SDObject) { + guard let entityA = gameBridge?.entityId(of: objectA.id), + let entityB = gameBridge?.entityId(of: objectB.id) else { + return + } + + print("contact \(objectA) - \(objectB)") + gameEngine?.handleCollision(entityA, entityB) + } }