Swift + Física: cálculo del ángulo incorrecto en la colisión

Tengo una simple aplicación SpriteKit con panetworkinges y una bola. Ambas configuraciones con un SKPhysicsBody .

Cuando aplico una fuerza en una dirección, espero que la bola se refleje en la panetworking con el mismo ángulo cuando colisiona, pero en dirección opuesta.

Pero a veces veo que el ángulo es extraño. physicsBody mucho con todas las properties de physicsBody , pero no pude solucionarlo. A veces las primeras reflexiones se ven bien, pero luego la tercera o la sexta ya veces la primera reflexión está en un ángulo incorrecto.

Leí de diferentes publicaciones, las personas son un poco autocálculo de la "dirección correcta". Pero no puedo imaginar que el motor SpriteKits physic no sea capaz de hacerlo.

Mira mi image adjunta para entender lo que quiero decir. ¿Alguien puede ayudar en esto? No quiero comenzar a jugar con Box2d para Swift, ya que parece que será muy difícil para mí integrarme en Swift.

SpriteKit expexted y lo que realmente está sucediendo

Este es el physicsWorld init en mi file GameScene.swift donde se agregan todos mis elementos a:

 self.physicsWorld.gravity = CGVectorMake(0, 0) 

Agregar todo mi código sería demasiado, así que agrego las piezas importantes. Espero que sea suficiente para analizar. Todos los elementos como la pelota, las panetworkinges son SKSpriteNode

Este es el código physicsBody para la pelota:

 self.physicsBody = SKPhysicsBody(circleOfRadius: Constants.Config.playersize+self.node.lineWidth) self.physicsBody?.restitution = 1 self.physicsBody?.friction = 0 self.physicsBody?.linearDamping = 1 self.physicsBody?.allowsRotation = false self.physicsBody?.categoryBitMask = Constants.Config.PhysicsCategory.Player self.physicsBody?.collisionBitMask = Constants.Config.PhysicsCategory.Wall | Constants.Config.PhysicsCategory.Enemy self.physicsBody?.contactTestBitMask = Constants.Config.PhysicsCategory.Wall | Constants.Config.PhysicsCategory.Enemy 

Este es el cuerpo físico de las panetworkinges:

 el = SKSpriteNode(color: UIColor.blueColor(), size: CGSize(width: Constants.Config.wallsize, height: Constants.Config.wallsize)) el.physicsBody = SKPhysicsBody(rectangleOfSize: CGSize(width: Constants.Config.wallsize, height: Constants.Config.wallsize)) el.physicsBody?.dynamic = false el.physicsBody?.categoryBitMask = Constants.Config.PhysicsCategory.Wall el.physicsBody?.collisionBitMask = Constants.Config.PhysicsCategory.Player el.physicsBody?.contactTestBitMask = Constants.Config.PhysicsCategory.Player 

Al final, acabo de llamar a la function applyImpulse en las bolas physicsBody para que se mueva en la simulación física.

También revise mi segunda image / gif adjunta. Muestra el problema de colisión de bordes con una aplicación skphysics simple sin ninguna parametrización especial. solo un rectángulo con una bola dentro y un vector aplicado como impulso.

introduzca la descripción de la imagen aquí

Aquí está mi código completo que no funciona con la solución de appzYourLife.

 class GameScene: SKScene { private var ball:SKShapeNode! override func didMoveToView(view: SKView) { let screen = UIScreen.mainScreen().bounds let p = UIBezierPath() p.moveToPoint(CGPointMake(0,0)) p.addLineToPoint(CGPointMake(screen.width,0)) p.addLineToPoint(CGPointMake(screen.width, screen.height)) p.addLineToPoint(CGPointMake(0,screen.height)) p.closePath() let shape = SKShapeNode(path: p.CGPath) shape.physicsBody = SKPhysicsBody(edgeLoopFromPath: p.CGPath) shape.physicsBody?.affectedByGravity = false shape.physicsBody?.dynamic = false shape.strokeColor = UIColor.blackColor() self.addChild(shape) ball = SKShapeNode(circleOfRadius: 17) ball.name = "player" ball.position = CGPoint(x: 20, y: 20) ball.fillColor = UIColor.yellowColor() ball.physicsBody = SKPhysicsBody(circleOfRadius: 17) ball.physicsBody?.angularDamping = 0 ball.physicsBody?.linearDamping = 0 ball.physicsBody?.restitution = 1 ball.physicsBody?.friction = 0 ball.physicsBody?.allowsRotation = false self.addChild(ball) self.ball.physicsBody?.applyImpulse(CGVector(dx: 2.4, dy: 9.7)) } 

Acabo de darme count de que la masa y la densidad de mi sprite de bola son nulas. ¿Por qué eso? Incluso configurarlo se mantiene en cero.

 Since i cannot imagine this is some unknown bug in SpriteKits physics engine, i very hope someone can help me here as this is a full stopper for me. 

Es un error (conocido) en el motor físico SpriteKits. Pero a veces, simplemente jugar con los valores hará que este error desaparezca, por ejemplo, intente cambiar la velocidad de la pelota (incluso por un valor pequeño) cada vez que golpee la panetworking.

Aquí se enumeran otras soluciones: la física de SpriteKit en Swift: la pelota se desliza contra la panetworking en lugar de reflejarse

(El mismo problema que el tuyo, ya desde 2014, aún no está arreglado …)

SpriteKit está funcionando bien

Creé un proyecto simple y está funcionando bien.

introduzca la descripción de la imagen aquí

El problema

Como @Sulthan ya sugirió en un comentario, creo que el problema en su código es esta línea

 el.physicsBody = SKPhysicsBody(rectangleOfSize: CGSize(width: Constants.Config.wallsize, height: Constants.Config.wallsize)) 

Aquí, en lugar de crear el borde físico de tu escena, estás creando un cuerpo de física rectangular que se superpone al cuerpo de la Física de la Ball produce comportamientos poco realists.

Para crear el borde de la física de mi escena, simplemente usé esto

 physicsBody = SKPhysicsBody(edgeLoopFromRect: frame) 

Código completo

Por cierto, este es el código completo de mi proyecto.

 class GameScene: SKScene { override func didMoveToView(view: SKView) { let ball = Ball() ball.position = CGPoint(x:frame.midX, y:frame.midY) addChild(ball) physicsBody = SKPhysicsBody(edgeLoopFromRect: frame) ball.physicsBody!.applyImpulse(CGVector(dx:50, dy:70)) physicsWorld.gravity = CGVector(dx:0, dy:0) } } class Ball: SKSpriteNode { init() { let texture = SKTexture(imageNamed: "ball") super.init(texture: texture, color: .clearColor(), size: texture.size()) let physicsBody = SKPhysicsBody(circleOfRadius: texture.size().width/2) physicsBody.restitution = 1 physicsBody.friction = 0 physicsBody.linearDamping = 0 physicsBody.allowsRotation = false self.physicsBody = physicsBody } requinetworking init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } } 

También utilicé scene.scaleMode = .ResizeFill dentro de GameViewController.swift .