SKSpriteNode弹跳我在Swift中没有创建的东西

时间:2016-03-28 15:02:27

标签: ios swift sprite-kit

我试图从屏幕顶部做一个方形的下降。但当它下降一半时,它会一直从屏幕上反弹。我没有在屏幕中间创建一个对象。我无法理解为什么它会在屏幕中间弹跳。

以下是运行代码的视频的链接:http://sendvid.com/enm9l1np

以下是代码:

import SpriteKit

class GameScene: SKScene, SKPhysicsContactDelegate {

     var animator : UIDynamicAnimator?
     let BlueSquare = SKSpriteNode()
     let RedSquare = SKSpriteNode()
    var scorenumber = 0
    var Ground = SKSpriteNode()

    override func didMoveToView(view: SKView) {
        /* Setup your scene here */
        physicsWorld.gravity = CGVector(dx: 1.0, dy: -9.0)

        let borderBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
        // 2. Set the friction of that physicsBody to 0
        borderBody.friction = 0
        // 3. Set physicsBody of scene to borderBody
        self.physicsBody = borderBody





        let width = UInt32(self.frame.size.width)

        let X = arc4random() % width


        Ground = SKSpriteNode(imageNamed: "Ground")
        Ground.setScale(1.0)
        Ground.position = CGPoint(x: self.frame.width / 2, y: 5)
        Ground.physicsBody = SKPhysicsBody(rectangleOfSize: Ground.size)
        Ground.physicsBody!.affectedByGravity = false
        Ground.physicsBody!.dynamic = false

        Ground.zPosition = 3

        self.addChild(Ground)


        //INizialize
        animator = UIDynamicAnimator(referenceView: self.view!)

        //Add Gravity

        //animator?.addBehavior(gravity, sprite)




        BlueSquare.size = CGSize(width: 100, height: 100)
        BlueSquare.position = CGPoint(x: CGFloat(X), y: 1000)
        BlueSquare.physicsBody?.affectedByGravity = true
        BlueSquare.physicsBody?.dynamic = false
        BlueSquare.name = "bluecube"
        BlueSquare.physicsBody = SKPhysicsBody(circleOfRadius: 20)
        BlueSquare.color = SKColor.blueColor()
       // BlueSquare.physicsBody?.velocity = CGVectorMake(0, 0)

        //BlueSquare.physicsBody?.applyImpulse(CGVectorMake(0, -90))
        self.addChild(BlueSquare)

        let X2 = arc4random() % width
        RedSquare.size = CGSize(width: 100, height: 100)
        RedSquare.position = CGPoint(x: CGFloat(X2), y: 1000)
        RedSquare.physicsBody?.affectedByGravity = true
        RedSquare.physicsBody?.dynamic = true
        RedSquare.name = "redcube"
        RedSquare.physicsBody = SKPhysicsBody(circleOfRadius: 20)
        RedSquare.hidden = false

        RedSquare.color = SKColor.redColor()

        self.addChild(RedSquare)




        var gameTimer = NSTimer!()
       gameTimer = NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: "spawning1", userInfo: nil, repeats: true)

    }



    func spawning1() {


    }

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
       /* Called when a touch begins */

        for touch in touches {
           // let location = touch.locationInNode(self)
            let currentPoint = touch.locationInNode(self)
            let currentNode = nodeAtPoint(currentPoint)
            let nodeName: String? = currentNode.name


            if nodeName == "bluecube" {
                BlueSquare.hidden = true

                score()
            }

            if nodeName == "redcube" {
                RedSquare.hidden = true

                score()
            }

        }
    }

    func score () {
        scorenumber++
        print(scorenumber)
    }

    override func update(currentTime: CFTimeInterval) {
        /* Called before each frame is rendered */
       if CGRectIntersectsRect(RedSquare.frame, Ground.frame) {
        RedSquare.position = CGPoint(x: RedSquare.position.x, y: RedSquare.position.y + 10)
        }
    }
}

1 个答案:

答案 0 :(得分:2)

你的代码有点混乱,所以让我们来看看

1)首先在你的GameViewController.swift中你应该在调用第一个场景之前设置这个属性

 skView.showsPhysics = true 

帮助您在测试时直观地看到您的物理身体。

2)不要在SpriteKit游戏中使用NSTimers,而是使用SKActions.waitForDuration。

let timerAction1 = SKAction.waitForDuration(0.5)
let timerAction2 = SKAction.runBlock(spawning1)
let timerSequence = SKAction.sequence([timerAction1, timerAction2])
runAction(SKAction.repeatActionForever(timerSequence))

如果你需要在gamePlay中的某个时刻使计时器无效,而不是简单地给runAction一个键

  runAction(SKAction.repeatActionForever(timerSequence), withKey: "SpawnTimer")

而不是像这样删除它

 removeActionForKey("SpawnTimer")

乍一看这可能看起来更像代码,但相信我,它是spriteKit游戏的更好方法。暂停场景时,NSTimers不会暂停,否则可能会导致场景转换问题。最好尽可能多地使用spriteKit API。

3)在一些精灵上,你强行解开物理身体

 ....physicsBody!.affectedByGravity....

使用?代替。

....physicsBody?.affectedByGravity....

一般来说,当你处理选项时,在Swift中,就像本例中的physicsBody一样,总是使用?只要编译器也允许你。

4)在你的某些身体上,你在实际给对象物理身体

之前设置了物理属性
    BlueSquare.physicsBody?.affectedByGravity = true
    BlueSquare.physicsBody?.dynamic = false
    BlueSquare.physicsBody = SKPhysicsBody(circleOfRadius: 20) // WRONG SPOT

看起来应该是这样的

    BlueSquare.physicsBody = SKPhysicsBody(circleOfRadius: 20)
    BlueSquare.physicsBody?.affectedByGravity = true
    BlueSquare.physicsBody?.dynamic = false

现在针对实际问题我相信你的问题与你的场景大小有关。如果您没有缩放场景以适应设备,那么您给场景的物理边界将不会达到预期的大小。默认场景大小(GameScene.sks)为1024x768(iPad纵向分辨率)。您的游戏处于横向模式和iPhone上,因此您的场景将被裁剪/拉伸。 要阅读有关场景比例模式的更多信息,请查看这些文章

http://blog.infinitecortex.com/2014/01/spritekit-understanding-skscene-scalemode/

https://www.raywenderlich.com/49695/sprite-kit-tutorial-making-a-universal-app-part-1

我最近就场景大小回答了类似的问题,它也可能对你有帮助

How to change SKscene size

如果您正在学习swift,那么作为另一个侧面提示,遵循文档是一个好习惯,例如,像BlueSquare这样的属性不应该以大写字母开头。只有类,结构和协议应以大写字母开头。

希望这有帮助