SpriteKit中的攻击button

我对Xcode稍微有点新鲜,并且为我的课程制作了2D游戏。 现在我一直在button的问题。 我刚刚得到了解决scheme,为什么我的跳转button不起作用,但我也有一个攻击button。

我已经设置了button的代码在屏幕上,并按下时做图像更改。 但是,我不知道用什么代码来把播放器的图像更改为跳转animation。 我也不知道如何为它和敌人build立冲突,这样攻击animation就会被击中。

所以我的问题是,我怎样才能让button开始跳跃animation,我怎么能设置碰撞摧毁敌人击中?

这是我的代码到目前为止:

override func sceneDidLoad() { //Setup start button jumpButton = SKSpriteNode(texture: jumpButtonTexture) jumpButton.position = CGPoint(x: 1850, y: 130) jumpButton.size = CGSize(width: 200, height: 200) jumpButton.zPosition = 20 addChild(jumpButton) //Setup start button attackButton = SKSpriteNode(texture: attackButtonTexture) attackButton.position = CGPoint(x: 1550, y: 130) attackButton.size = CGSize(width: 200, height: 200) attackButton.zPosition = 20 addChild(attackButton) } override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { if let touch = touches.first { if selectedButton != nil { handleJumpButtonHover(isHovering: false) handleAttackButtonHover(isHovering: false) } if jumpButton.contains(touch.location(in: self)) { selectedButton = jumpButton handleJumpButtonHover(isHovering: true) } else if attackButton.contains(touch.location(in: self)) { selectedButton = attackButton handleAttackButtonHover(isHovering: true) } } } override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { if let touch = touches.first { if selectedButton == jumpButton { handleJumpButtonHover(isHovering: false) if (jumpButton.contains(touch.location(in: self))) { handleJumpButtonClick() } } else if selectedButton == attackButton { handleAttackButtonHover(isHovering: false) if (attackButton.contains(touch.location(in: self))) { handleAttackButtonClick() } } } selectedButton = nil } func handleJumpButtonHover(isHovering : Bool) { if isHovering { jumpButton.texture = jumpButtonPressedTexture } else { jumpButton.texture = jumpButtonTexture } } func handleAttackButtonHover(isHovering : Bool) { if isHovering { attackButton.texture = attackButtonPressedTexture } else { attackButton.texture = attackButtonTexture } } func handleJumpButtonClick() { self.playerNode.physicsBody?.velocity = CGVector(dx: 0, dy: 0) self.playerNode.physicsBody?.applyImpulse(CGVector(dx: 0, dy: 20)) } func handleAttackButtonClick() { } 

你的问题的前半部分很容易。 你只需要在该函数中设置你的播放器的新纹理,然后一旦animation完成,恢复到原来的播放器animation。 所以我build议在课程级创build这两个animation,并为默认animation分配一个键,并使用攻击动作的完成处理程序将其设置回去。

 class GameScene: SKScene { let frame2 = SKTexture(imageNamed: "Ttam2") let frame3 = SKTexture(imageNamed: "Ttam3") let frame4 = SKTexture(imageNamed: "Ttam4") let attackFrame1 = SKTexture(imageNamed: "Ttam1_ATTACK") let attackFrame2 = SKTexture(imageNamed: "Ttam2_ATTACK") var animation: SKAction! var attackAnination: SKAction! override func sceneDidLoad(){ animation = SKAction.repeatForever(SKAction.animate(with: [playerTexture, frame2, frame3, frame4], timePerFrame: 0.2)) attackAnimation = SKAction.animate(with: [attackFrame1,attackFrame2],timePerFrame: 0.2) playerNode.run(animation,withKey:"animate") } func handleAttackButtonClick(){ playerNode.removeAction(forKey:"animate") playerNode.run(attackAnimation,completion:{ self.playerNode.run(animation,withKey: "animate") }) } } 

至于你的下半场碰撞,你想使用的是contactTestBitmask 。 您将SKPhysicsContactDelegate添加到您的场景类,并设置您要注册联系人的节点的位掩码。 对于这个方面有很多问题和答案。 没有必要再回答我不认为。 如果你挂了,随时可以回来一个新的问题。

我已经写了一个小的“入门”项目,以简单的方式演示(我希望)很多概念 – 只需将代码放入一个新项目并运行即可:


这是一个简单的Sprite-Kit GameScene.swift。 创build一个新的空SpriteKit项目,并用此replaceGameScene.swift。 然后build立并运行。

点击屏幕上的任何对象使其移动。 检查日志和注释以查看哪些发生了碰撞,哪些发生了联系。

 // // GameScene.swift // bounceTest // // Created by Stephen Ives on 05/04/2016. // Copyright (c) 2016 Stephen Ives. All rights reserved. // import SpriteKit class GameScene: SKScene, SKPhysicsContactDelegate { let objectSize = 150 let initialImpulse: UInt32 = 300 // Needs to be proportional to objectSize //Physics categories let purpleSquareCategory: UInt32 = 1 << 0 let redCircleCategory: UInt32 = 1 << 1 let blueSquareCategory: UInt32 = 1 << 2 let edgeCategory: UInt32 = 1 << 31 let purpleSquare = SKSpriteNode() let blueSquare = SKSpriteNode() let redCircle = SKSpriteNode() override func didMove(to view: SKView) { physicsWorld.gravity = CGVector(dx: 0, dy: 0) //Create an boundary else everything will fly off-screen let edge = frame.insetBy(dx: 0, dy: 0) physicsBody = SKPhysicsBody(edgeLoopFrom: edge) physicsBody?.isDynamic = false //This won't move name = "Screen_edge" scene?.backgroundColor = SKColor.black // Give our 3 objects their attributes blueSquare.color = SKColor.blue blueSquare.size = CGSize(width: objectSize, height: objectSize) blueSquare.name = "shape_blueSquare" blueSquare.position = CGPoint(x: size.width * -0.25, y: size.height * 0.2) let circleShape = SKShapeNode(circleOfRadius: CGFloat(objectSize)) circleShape.fillColor = SKColor.red redCircle.texture = view.texture(from: circleShape) redCircle.size = CGSize(width: objectSize, height: objectSize) redCircle.name = "shape_redCircle" redCircle.position = CGPoint(x: size.width * 0.4, y: size.height * -0.4) purpleSquare.color = SKColor.purple purpleSquare.size = CGSize(width: objectSize, height: objectSize) purpleSquare.name = "shape_purpleSquare" purpleSquare.position = CGPoint(x: size.width * -0.35, y: size.height * 0.4) addChild(blueSquare) addChild(redCircle) addChild(purpleSquare) redCircle.physicsBody = SKPhysicsBody(circleOfRadius: redCircle.size.width/2) blueSquare.physicsBody = SKPhysicsBody(rectangleOf: blueSquare.frame.size) purpleSquare.physicsBody = SKPhysicsBody(rectangleOf: purpleSquare.frame.size) setUpCollisions() checkPhysics() } func setUpCollisions() { //Assign our category bit masks to our physics bodies purpleSquare.physicsBody?.categoryBitMask = purpleSquareCategory redCircle.physicsBody?.categoryBitMask = redCircleCategory blueSquare.physicsBody?.categoryBitMask = blueSquareCategory physicsBody?.categoryBitMask = edgeCategory // This is the edge for the scene itself // Set up the collisions. By default, everything collides with everything. redCircle.physicsBody?.collisionBitMask &= ~purpleSquareCategory // Circle doesn't collide with purple square purpleSquare.physicsBody?.collisionBitMask = 0 // purpleSquare collides with nothing // purpleSquare.physicsBody?.collisionBitMask |= (redCircleCategory | blueSquareCategory) // Add collisions with red circle and blue square purpleSquare.physicsBody?.collisionBitMask = (redCircleCategory) // Add collisions with red circle blueSquare.physicsBody?.collisionBitMask = (redCircleCategory) // Add collisions with red circle // Set up the contact notifications. By default, nothing contacts anything. redCircle.physicsBody?.contactTestBitMask |= purpleSquareCategory // Notify when red circle and purple square contact blueSquare.physicsBody?.contactTestBitMask |= redCircleCategory // Notify when blue square and red circle contact // Make sure everything collides with the screen edge and make everything really 'bouncy' enumerateChildNodes(withName: "//shape*") { node, _ in node.physicsBody?.collisionBitMask |= self.edgeCategory //Add edgeCategory to the collision bit mask node.physicsBody?.restitution = 0.9 // Nice and bouncy... node.physicsBody?.linearDamping = 0.1 // Nice and bouncy... } //Lastly, set ourselves as the contact delegate physicsWorld.contactDelegate = self } func didBegin(_ contact: SKPhysicsContact) { let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask switch contactMask { case purpleSquareCategory | blueSquareCategory: print("Purple square and Blue square have touched") case redCircleCategory | blueSquareCategory: print("Red circle and Blue square have touched") case redCircleCategory | purpleSquareCategory: print("Red circle and purple Square have touched") default: print("Unknown contact detected") } } override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { for touch in touches { let touchedNode = selectNodeForTouch(touch.location(in: self)) if let node = touchedNode { node.physicsBody?.applyImpulse(CGVector(dx: CGFloat(arc4random_uniform(initialImpulse)) - CGFloat(initialImpulse/2), dy: CGFloat(arc4random_uniform(initialImpulse)) - CGFloat(initialImpulse/2))) node.physicsBody?.applyTorque(CGFloat(arc4random_uniform(20)) - CGFloat(10)) } } } // Return the sprite where the user touched the screen func selectNodeForTouch(_ touchLocation: CGPoint) -> SKSpriteNode? { let touchedNode = self.atPoint(touchLocation) print("Touched node is \(touchedNode.name)") // let touchedColor = getPixelColorAtPoint(touchLocation) // print("Touched colour is \(touchedColor)") if touchedNode is SKSpriteNode { return (touchedNode as! SKSpriteNode) } else { return nil } } //MARK: - Analyse the collision/contact set up. func checkPhysics() { // Create an array of all the nodes with physicsBodies var physicsNodes = [SKNode]() //Get all physics bodies enumerateChildNodes(withName: "//.") { node, _ in if let _ = node.physicsBody { physicsNodes.append(node) } else { print("\(node.name) does not have a physics body so cannot collide or be involved in contacts.") } } //For each node, check it's category against every other node's collion and contctTest bit mask for node in physicsNodes { let category = node.physicsBody!.categoryBitMask // Identify the node by its category if the name is blank let name = node.name != nil ? node.name! : "Category \(category)" let collisionMask = node.physicsBody!.collisionBitMask let contactMask = node.physicsBody!.contactTestBitMask // If all bits of the collisonmask set, just say it collides with everything. if collisionMask == UInt32.max { print("\(name) collides with everything") } for otherNode in physicsNodes { if (node.physicsBody?.dynamic == false) { print("This node \(name) is not dynamic") } if (node != otherNode) && (node.physicsBody?.isDynamic == true) { let otherCategory = otherNode.physicsBody!.categoryBitMask // Identify the node by its category if the name is blank let otherName = otherNode.name != nil ? otherNode.name! : "Category \(otherCategory)" // If the collisonmask and category match, they will collide if ((collisionMask & otherCategory) != 0) && (collisionMask != UInt32.max) { print("\(name) collides with \(otherName)") } // If the contactMAsk and category match, they will contact if (contactMask & otherCategory) != 0 {print("\(name) notifies when contacting \(otherName)")} } } } } }