Last active
March 6, 2023 00:14
-
-
Save pmark/15da413c72aa000a2680bf43f06731a7 to your computer and use it in GitHub Desktop.
Revisions
-
pmark revised this gist
Mar 6, 2023 . 1 changed file with 72 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,72 @@ import OctopusKit // Define the available AI behaviors enum AIBehavior { case none case seek(target: Entity) case flee(target: Entity) case wander case followPath(path: GKPath) } // Define the monster AI component class MonsterAIComponent: OKComponent { var behaviorType: AIBehavior = .none { didSet { // Remove any existing behavior components entity?.removeComponents(ofType: BehaviorComponent.self) // Add the appropriate behavior component based on the behavior type switch behaviorType { case .none: break case .seek(let target): entity?.addComponent(BehaviorComponent(behavior: GKSeekBehavior(target: target.node))) case .flee(let target): entity?.addComponent(BehaviorComponent(behavior: GKFleeBehavior(target: target.node))) case .wander: entity?.addComponent(BehaviorComponent(behavior: GKRandomWalkBehavior())) case .followPath(let path): entity?.addComponent(BehaviorComponent(behavior: GKFollowPathBehavior(path: path, maxPredictionTime: 1.0, forward: true))) } } } override func update(deltaTime seconds: TimeInterval) { // Update any existing behavior components entity?.updateBehaviorComponents(deltaTime: seconds) } } extension MonsterAIComponent { enum AIBehavior { case randomMovement case followPlayer case patrol case custom(GKBehavior) } func setBehavior(_ behaviorType: AIBehavior) { if let oldBehavior = entity.component(ofType: MonsterAIComponent.self) { entity.removeComponent(oldBehavior) } switch behaviorType { case .randomMovement: let behavior = RandomMovementBehaviorComponent() entity.addComponent(behavior) case .followPlayer: let behavior = FollowPlayerBehaviorComponent() entity.addComponent(behavior) case .patrol: let behavior = PatrolBehaviorComponent() entity.addComponent(behavior) case .custom(let behavior): let behaviorComponent = CustomBehaviorComponent(behavior: behavior) entity.addComponent(behaviorComponent) } } } -
pmark revised this gist
Mar 5, 2023 . 2 changed files with 65 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,28 @@ class PlayerControlComponent: OKComponent { override var requiredComponents: [AnyClass] { return [OKPhysicsBodyComponent.self] } override func didAddToEntity() { guard let entity = entity else { return } // Set up a pan gesture recognizer to control the player let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(panGesture(_:))) entity.scene?.view?.addGestureRecognizer(panRecognizer) } @objc func panGesture(_ recognizer: UIPanGestureRecognizer) { guard let physicsBodyComponent = entity?.component(ofType: OKPhysicsBodyComponent.self) else { return } // Calculate the velocity based on the pan gesture let translation = recognizer.translation(in: recognizer.view) let velocity = CGVector(dx: translation.x, dy: translation.y) // Apply the velocity to the physics body physicsBodyComponent.physicsBody?.velocity = velocity } } This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,37 @@ import OctopusKit class PlayerEntity: OKEntity { override func awake(from system: OKComponentSystem) { // Add a physics body to the player let physicsBodyComponent = OKPhysicsBodyComponent(circleOfRadius: 32) addComponent(physicsBodyComponent) // Add a player control system to handle user input let playerControlComponent = PlayerControlComponent() addComponent(playerControlComponent) // Add a sprite component to display the player let spriteComponent = OKSpriteComponent(texture: SKTextureAtlas.spriteNode(named: "player", in: "game").texture) addComponent(spriteComponent) } } class MonsterEntity: OKEntity { override func awake(from system: OKComponentSystem) { // Add a physics body to the monster let physicsBodyComponent = OKPhysicsBodyComponent(circleOfRadius: 32) addComponent(physicsBodyComponent) // Add a monster AI system to handle behavior let monsterAIComponent = MonsterAIComponent() addComponent(monsterAIComponent) // Add a sprite component to display the monster let spriteComponent = OKSpriteComponent(texture: SKTextureAtlas.spriteNode(named: "monster", in: "game").texture) addComponent(spriteComponent) } } -
pmark created this gist
Mar 5, 2023 .There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,46 @@ import Foundation import SpriteKit class Level { let tileSet: SKTileSet let mapSize: CGSize let tileSize: CGSize let tileData: [[Int]] init(jsonData: Data) throws { let json = try JSONSerialization.jsonObject(with: jsonData, options: []) guard let jsonDict = json as? [String: Any], let tileSetName = jsonDict["tileset"] as? String, let tileSet = SKTileSet(named: tileSetName), let mapSizeDict = jsonDict["mapSize"] as? [String: CGFloat], let mapWidth = mapSizeDict["width"], let mapHeight = mapSizeDict["height"], let tileSizeDict = jsonDict["tileSize"] as? [String: CGFloat], let tileWidth = tileSizeDict["width"], let tileHeight = tileSizeDict["height"], let tileDataArray = jsonDict["tileData"] as? [[Int]] else { throw NSError(domain: "com.example.TileMapDemo", code: 0, userInfo: [NSLocalizedDescriptionKey: "Invalid JSON data"]) } self.tileSet = tileSet self.mapSize = CGSize(width: mapWidth, height: mapHeight) self.tileSize = CGSize(width: tileWidth, height: tileHeight) self.tileData = tileDataArray } func createTileMapNode() -> SKTileMapNode { let tileMapNode = SKTileMapNode(tileSet: tileSet, columns: Int(mapSize.width), rows: Int(mapSize.height), tileSize: tileSize) for row in 0..<Int(mapSize.height) { for col in 0..<Int(mapSize.width) { let tileGID = tileData[row][col] let tileDefinition = tileSet.tileDefinition(forGID: UInt32(tileGID)) tileMapNode.setTileGroup(tileDefinition?.tileGroup, forColumn: col, row: row) } } return tileMapNode } } This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,9 @@ extension SKTextureAtlas { static func spriteNode(named name: String, in atlasName: String) -> SKSpriteNode { let atlas = SKTextureAtlas(named: atlasName) let texture = atlas.textureNamed(name) return SKSpriteNode(texture: texture) } } let sprite = SKTextureAtlas.spriteNode(named: "MySpriteImage", in: "MySprites") This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,38 @@ import OctopusKit import SpriteKit class GameScene: OKScene { override func didMove(to view: SKView) { // Load tile map let tileMap = SKTileMapNode() addChild(tileMap) // Create character entity let character = OKEntity() character.addComponent(OKSpriteNodeComponent(node: SKSpriteNode(imageNamed: "character"))) character.addComponent(OKPhysicsBodyComponent(physicsBody: SKPhysicsBody(rectangleOf: character.spriteNode.size))) character.addComponent(OKControlledPathComponent()) entityManager.add(character) // Create camera entity let camera = OKEntity() camera.addComponent(OKCameraComponent(focusEntity: character)) camera.addComponent(OKTopDownCameraComponent()) entityManager.add(camera) // Add virtual joystick let joystick = OKJoystickControlComponent() joystick.position = CGPoint(x: size.width - joystick.frame.width / 2 - 10, y: joystick.frame.height / 2 + 10) joystick.style = .circular joystick.movement = .full360 joystick.velocityMultiplier = 5.0 joystick.addHandler(for: .inputEvent) { inputEvent in if let joystickEvent = inputEvent as? OKJoystickEvent { character.component(ofType: OKControlledPathComponent.self)?.velocity = joystickEvent.velocity } } addChild(joystick.node) } } This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,41 @@ import Foundation import SpriteKit class TileSetLoader { static func loadTileSet(from jsonData: Data) throws -> SKTileSet { let json = try JSONSerialization.jsonObject(with: jsonData, options: []) guard let jsonDict = json as? [String: Any], let tileDataArray = jsonDict["tiles"] as? [[String: Any]] else { throw NSError(domain: "com.example.TileMapDemo", code: 0, userInfo: [NSLocalizedDescriptionKey: "Invalid JSON data"]) } let tileDefinitions = try tileDataArray.map { tileData in try createTileDefinition(from: tileData) } let tileSet = SKTileSet(tileGroups: [], tileSetType: .grid) for definition in tileDefinitions { tileSet.add(definition) } return tileSet } private static func createTileDefinition(from tileData: [String: Any]) throws -> SKTileDefinition { guard let id = tileData["id"] as? Int, let textureName = tileData["texture"] as? String, let texture = SKTexture(imageNamed: textureName) else { throw NSError(domain: "com.example.TileMapDemo", code: 0, userInfo: [NSLocalizedDescriptionKey: "Invalid tile data"]) } let tileDefinition = SKTileDefinition(texture: texture, size: texture.size()) tileDefinition.userData = NSMutableDictionary() tileDefinition.userData?.setValue(id, forKey: "id") return tileDefinition } }