2016-03-15 2 views
1

Я пытаюсь создать столкновение между экземпляром SKShapeNode и краями экрана, но по какой-то причине ShapeNode по-прежнему выходит за пределы экрана. Я реализовал код, который, как мне кажется, должен заботиться о столкновении, но я новичок в SpriteKit, поэтому я не совсем уверен. Вот фрагмент кода:iOS SpriteKit столкновение с краями экрана не работает

// 
// GameScene.swift 
// SpriteKitTest 
// 
// Created by 580380 on 3/10/16. 
// Copyright (c) 2016 580380. All rights reserved. 
// 

import SpriteKit 
import UIKit 
import CoreMotion 

class GameScene: SKScene { 

    //MARK: - Global variables 
    let motionManager = CMMotionManager() 
    var circleNode = SKShapeNode() 
    var destX : CGFloat = 0.0 
    var destY : CGFloat = 0.0 

    enum Collision :UInt32 { 
     case ball = 1 
     case wall = 2 
    } 
    //MARK: - Sprite kit functionality 
    override func didMoveToView(view: SKView) { 

     backgroundColor = UIColor.whiteColor() 
     createCircleNode() 
     moveCircleNode() 
     self.addChild(circleNode) 
    } 

    //Setup and configuring the SKShapeNode object 
    private func createCircleNode() { 
     circleNode.path = UIBezierPath(arcCenter: CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame)), radius: 20, startAngle: 0, endAngle: CGFloat(2*M_PI), clockwise: true).CGPath 
     circleNode.fillColor = UIColor.redColor() 
     circleNode.strokeColor = UIColor.blueColor() 
     circleNode.lineWidth = 1 
    } 

    private func moveCircleNode() { 
     circleNode.physicsBody = SKPhysicsBody() 
     circleNode.physicsBody?.dynamic = true 
     circleNode.physicsBody?.affectedByGravity = false 
     if motionManager.accelerometerAvailable { 
      motionManager.accelerometerUpdateInterval = 0.1 
      motionManager.startAccelerometerUpdatesToQueue(NSOperationQueue.mainQueue(), withHandler: { (data, error) -> Void in 
       self.destX = self.circleNode.position.x + CGFloat(data!.acceleration.x*100) 
       self.destY = self.circleNode.position.y + CGFloat(data!.acceleration.y*200) 
      }) 
     } 
     self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame) 
     self.physicsBody!.dynamic = true 
     self.physicsBody!.affectedByGravity = false 
     self.physicsBody!.categoryBitMask = Collision.wall.rawValue 
     self.physicsBody!.collisionBitMask = Collision.ball.rawValue 
    } 

    override func update(currentTime: NSTimeInterval) { 
     let destXAction = SKAction.moveToX(destX, duration: 0.1) 
     let destYAction = SKAction.moveToY(destY, duration: 0.1) 
     self.circleNode.runAction(destXAction) 
     self.circleNode.runAction(destYAction) 
    } 
} 

Любая идея, где я мог бы пойти не так?

ответ

1

Основная проблема здесь Я предполагаю, что игровая сцена никогда не набирает свой размер.

В вашей GameViewController добавьте строку scene.size = skView.bounds.size под let skView = self.view as! SKView.

Это позволит установить размер вашей сцены правильно, так что теперь ваш шар должен столкнуться с вашим краем экрана ... однако, когда вы установили путь circleNode, то, как вы его реализовали, со смещением вашего круга на половину размера экран.

Если вы хотите, чтобы ваш круг появлялся в середине экрана, лучшим решением было бы иметь circleNode = SKShapeNode(circleOfRadius: 20) вместо circleNode.path = UIBezierPath(arcCenter: CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame)), radius: 20, startAngle: 0, endAngle: CGFloat(2*M_PI), clockwise: true).CGPath. Затем установите его в центр с помощью circleNode.position = CGPointMake(frame.width/2, frame.height/2).

Это должно решить вашу проблему в целом, однако вы можете заметить, что мяч может исчезнуть через край экрана. Чтобы это исправить, изменить способ обновления на что-то вроде этого

func clamp(value: CGFloat, min: CGFloat, max: CGFloat) -> CGFloat { 
    if value > max { 
     return max 
    } 
    if value < min { 
     return min 
    } 
    return value 
} 


override func update(currentTime: NSTimeInterval) { 
    let ballRadius: CGFloat = 10 
    destX = clamp(destX, min: ballRadius, max: frame.width - ballRadius) 
    destY = clamp(destY, min: ballRadius, max: frame.height - ballRadius) 

    let destXAction = SKAction.moveToX(destX, duration: 0.1) 
    let destYAction = SKAction.moveToY(destY, duration: 0.1) 
    self.circleNode.runAction(destXAction) 
    self.circleNode.runAction(destYAction) 
} 

Это сделает это так, мяч никогда не должны пытаться выходить за пределы экрана. Я также предложил бы добавить circleNode.physicsBody?.usesPreciseCollisionDetection = true, чтобы ваши столкновения были более точными.

Смежные вопросы