Posts

Post not yet marked as solved
17 Replies
Once again thanks for the time you devoted helping me.I went in the addShape func and made all the tiles non-dynamic by default, then when naming the players tiles, I made these active.It works.The physics engin might get too busy if all of the tiles are active...
Post not yet marked as solved
17 Replies
extension GameScene: SKPhysicsContactDelegate { func didBegin(_ contact: SKPhysicsContact) { NSLog("SKPhysicsContact detected") if contact.bodyA.categoryBitMask == contact.bodyB.categoryBitMask { return } var player: SKPhysicsBody var that: SKPhysicsBody if contact.bodyA.categoryBitMask != PhysicsCategory.shape { player = contact.bodyA that = contact.bodyB } else { player = contact.bodyB that = contact.bodyA } if let o = that.node as? SKShapeNode, let p = player.node as? SKShapeNode { if (o.fillColor == p.fillColor) { NSLog("Collision between %@ and %@.", p.name!, o.name!) o.strokeColor = p.fillColor o.physicsBody?.categoryBitMask = p.physicsBody!.categoryBitMask if (p.physicsBody!.categoryBitMask == PhysicsCategory.me) { mySquares.append(o) for q in mySquares { propagate(shape: q) } } if (p.physicsBody!.categoryBitMask == PhysicsCategory.it) { hisSquares.append(o) for q in hisSquares { propagate(shape: q) } } } } } }
Post not yet marked as solved
17 Replies
Yes I did. The borders are relevant and rotate accordingly. I want to use the physics not to have to (re)code a massive matrix routine to determine which neighbours should or should not be affected...I tried to make the "unset" shapes to react to everything but their installation triggers a huge load of contacts. I also tested that the players' shapes NSLog their category bitmasks and it's also relevant.Strange.
Post not yet marked as solved
17 Replies
Excellent, I went further 🙂Now, I wonder why these Physics bodies: 2 adjacent squares do not generate an SKPhysicsContact when one rotates by .pi:Bitmasks: struct PhysicsCategory { static let none : UInt32 = 0 static let all : UInt32 = UInt32.max static let mine : UInt32 = 0b001 // 1 static let his : UInt32 = 0b010 // 2 static let us : UInt32 = 0b011 // 3 static let unset : UInt32 = 0b100 // 4 }Tiles: shape.physicsBody?.isDynamic = true shape.physicsBody?.categoryBitMask = PhysicsCategory.unset shape.physicsBody?.contactTestBitMask = PhysicsCategory.mine | PhysicsCategory.his shape.physicsBody?.collisionBitMask = PhysicsCategory.none shape.physicsBody?.usesPreciseCollisionDetection = true shape.isPaused = falsePlayer (a Tile which is customized): if (newName == "me") { s.physicsBody?.categoryBitMask = PhysicsCategory.mine } else { s.physicsBody?.categoryBitMask = PhysicsCategory.his } s.physicsBody?.contactTestBitMask = PhysicsCategory.unset s.physicsBody?.collisionBitMask = PhysicsCategory.none s.name = newNameWhatever I do, there's nothing in the logs involving a contact???
Post not yet marked as solved
17 Replies
Thanks, I will try and implement it other the week-end!Where did you find such ideas? It's not obvious it should be done this way in the Apple Developer Doc and I have been looking for days elsewhere...
Post not yet marked as solved
17 Replies
This is the intro of the game:1. The shapes start in a corner and spread out to form an array (perhaps in parallel, perhaps one-by-one).They all go simultaneously to their definite place. They however don't fadeAlpha which is kinda bugging me.Then for the first turn only, I want these to happen in parallel:2. One corner node to do some rotating.3. The second corner node to do some rotating.Once this is set the game can go on with one of the corners absorbing its neighbours by taking their colors, then the opponent and so on until one reaches more than 50%.I kicked off my SpriteKit approach using a Ray Wenderlich tutorial but it doesn't quite seem to work at me... many SKaction, even grouped don't work (even though they NSLog so)...I fixed the short wait which I indeed wanted to sequence after the group, but then it doesn't work because it just means that it starts after the others were started, but not completed.Do you have a typical working link to something like:run(SKAction.run { manythingsinparallel() }, completion: { otherthings() }...or maybe I should find ou how I could get a notification from all SKAction.group once it has completed all of its subtasks?Pity I don't find much around as I am lacking the right jargon to perform my searches...Thanks again.
Post not yet marked as solved
17 Replies
Thanks. I really value your friendly help.I want to:1) begin by placing a bunch of differently colored SKShapeNode objects on the SKScene. I'd cram there as much 32x32 CGSize as possible.2) The game will then begin by a pair of automatic turns:a) having my (lower-left corner shape) initialized (changing its color and actually turning around in order to contact the surrounding similarly colored shapes using SKPhysicsContactDelegate.didBegin() ) and take possession of themb) same for the computer opponent (upper right corner)3) At this point, the game may begin for real: either I or the computer play(s) and choose a color which cannot be the opponent's in order to chain-reaction all of his shapes to absorb even more similarly colored, unonwned surrounding ones.But then I am currently stuck because the inital tour doesn't quite take place: only my tile NSLogs me it has rotated but it actually doesn't.Bits of code: override func didMove(to view: SKView) { /* Set the scale mode to scale to fit the window */ scaleMode = .resizeFill // Set physics physicsWorld.gravity = .zero physicsWorld.contactDelegate = self backgroundColor = SKColor.darkGray label = SKLabelNode(fontNamed: "Chalkduster") label.text = "Color ZooZ 2" label.horizontalAlignmentMode = .center label.verticalAlignmentMode = .center label.color = SKColor.systemPink label.fontSize = 48 label.position = CGPoint(x: size.width/2, y: size.height/2) addChild(label) installShapes() } func installShapes() { X = size.width / (SIZE + SPACE) - 1 Y = size.height / (SIZE + SPACE) - 1 dX = (size.width - (X * (SIZE + SPACE))) / 1 dY = (size.height - (Y * (SIZE + SPACE))) / 1 NSLog("MIRKO display: %0.0f x %0.0f & Nb: %0.0f x %0.0f & dX: %0.0f / dY: %0.0f", size.width, size.height, X, Y, dX, dY) self.run(SKAction.run { for x in 0...Int8(self.X - 1) { for y in 0...Int8(self.Y - 1) { self.addShape(atX: x, andY: y) } } }, completion: { NSLog("End of installShapes, about to rename the player shapes") self.renameShape(from: "\(0).\(0)", to: "me") self.renameShape(from: "\(self.X-1).\(self.Y-1)", to: "him") }) } func renameShape(from oldName : String, to newName : String) { if let s = shapeByName(name: oldName) as SKShapeNode? { s.strokeColor = s.fillColor s.physicsBody?.categoryBitMask = PhysicsCategory.mine s.physicsBody?.contactTestBitMask = PhysicsCategory.unset s.physicsBody?.collisionBitMask = PhysicsCategory.none s.name = newName s.alpha = 1.0 propagate(shape: s) } } func addShape(atX x: Int8, andY y : Int8) { let shape = SKShapeNode(rectOf: CGSize(width: SIZE, height: SIZE), cornerRadius: SIZE / 4) shape.name = "\(x).\(y)" shape.position = CGPoint(x: 0, y: 0) let generator = ColorGenerator() shape.fillColor = generator.random() shape.strokeColor = UIColor.lightGray shape.lineWidth = BORDER shape.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: SIZE, height: SIZE)) shape.physicsBody?.isDynamic = false shape.physicsBody?.categoryBitMask = PhysicsCategory.unset shape.physicsBody?.contactTestBitMask = PhysicsCategory.mine | PhysicsCategory.his shape.physicsBody?.collisionBitMask = PhysicsCategory.none shape.physicsBody?.usesPreciseCollisionDetection = true shape.isPaused = false addChild(shape) let placeIt = SKAction.group( [SKAction.fadeAlpha(by: 0.5, duration: 2), SKAction.move(to: CGPoint(x: CGFloat(x) * (SIZE + SPACE) + dX, y: CGFloat(y) * (SIZE + SPACE) + dY), duration: 2), SKAction.wait(forDuration: 0.1)]) placeIt.timingMode = SKActionTimingMode.easeInEaseOut NSLog("moving %@", shape.name!) shape.run(placeIt, withKey: "placeIt \(shape.name!)") NSLog("%@ moved", shape.name!) } func shapeAt(x mX : Int8, y mY : Int8) -> SKShapeNode? { let allNodes = nodes(at: CGPoint(x: CGFloat(mX) * (SIZE + SPACE) + dX, y: CGFloat(mY) * (SIZE + SPACE) + dY)) for node in allNodes { if let o = node as? SKShapeNode { return o } } return nil } func shapeByName(name s:String) -> SKShapeNode? { if let c = childNode(withName: s) as? SKShapeNode { return c } return nil } func propagate(shape s : SKShapeNode) { NSLog("Propagating...") if s.isPaused { s.isPaused = false } let rotate = SKAction.rotate(toAngle: .pi, duration: 0.5) rotate.timingMode = SKActionTimingMode.easeInEaseOut NSLog("rotating") s.run(rotate, withKey: "rotate \(s.name!)") NSLog("rotated") }Which SKScene member funcion should I override for which part of the game init/turn, etc?Once again, thanks!
Post not yet marked as solved
17 Replies
Thanks, I am not sure this does help, except making me consider a shameful switch to the dreaded Unity Engine.Do you know where I could find some doc/examples about where to actually perform my SKActions? I thought these could all be performed from the SKScene.didMove method as they'd be sequentially performed in a single thread?