Alex Alex - 4 months ago 11
Swift Question

How to make an sprite bounce within an object?

I am trying to make a ball bounce within a circle so it cant get out of the circumference of the circle. Now the ball bounce in self.frame. How can I make the ball bounce within the circle?

let sceneBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
sceneBody.friction = 0
self.physicsBody = sceneBody

var ball = SKShapeNode(circleOfRadius: 9)
ball.fillColor = SKColor.whiteColor()
ball.position = view.center
ball.physicsBody = SKPhysicsBody(circleOfRadius: 9)
ball.physicsBody?.affectedByGravity = true
ball.physicsBody?.restitution = 1
ball.physicsBody?.linearDamping = 0
ball.zPosition = 3
self.addChild(ball)

circulo = SKSpriteNode(imageNamed: "circuloFondo2")
//Circle that I want the ball bounce within
circulo.size = CGSize(width:view.frame.size.width - padding , height: view.frame.size.width - padding)
circulo.color = UIColor(red: 0.15, green: 0.15, blue: 0.15, alpha: 1)
circulo.colorBlendFactor = 1
circulo.alpha = 0.35
circulo.position = view.center
self.addChild(circulo)
circulo.zPosition = 1

Answer

I've prepared a simple test project to explain how to do it:

import UIKit
import SpriteKit

class GameScene: SKScene, SKPhysicsContactDelegate {

    enum CollisionTypes: UInt32 {
        case Circle = 1
        case Ball = 2
        //case Enemy1 = 4
        //case Enemy2 = 8
        //case Enemy3 = 16
        //case EnemyBoss = 32
    }

    var circulo: SKSpriteNode!
    var padding: CGFloat = 40.0
    var center: CGPoint!

    override func didMoveToView(view: SKView) {

        self.physicsWorld.gravity = CGVectorMake(0, -6)
        self.physicsWorld.contactDelegate = self
        self.center = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidY(self.frame))

        // Prepare circle
        circulo = SKSpriteNode(imageNamed: "circuloFondo2.png")
        //Circle that I want the ball bounce within
        circulo.size = CGSize(width:view.frame.size.width - padding , height: view.frame.size.width - padding)
        let circlePath = UIBezierPath(arcCenter: self.center, radius: (view.frame.size.width - padding*2)/2, startAngle: CGFloat(0), endAngle:CGFloat(M_PI * 2), clockwise: true)
        circulo.color = UIColor(red: 0.15, green: 0.15, blue: 0.15, alpha: 1)
        circulo.colorBlendFactor = 1
        circulo.alpha = 1
        circulo.position = self.center
        circulo.zPosition = 1

        // Set physics
        let circuloBody = SKPhysicsBody.init(edgeLoopFromPath: circlePath.CGPath)
        self.physicsBody = circuloBody
        self.physicsBody!.affectedByGravity = false
        self.physicsBody!.usesPreciseCollisionDetection = true
        self.physicsBody!.dynamic = true
        self.physicsBody!.mass = 0
        self.physicsBody!.friction = 0
        self.physicsBody!.linearDamping = 0
        self.physicsBody!.angularDamping = 0
        self.physicsBody!.restitution = 1
        self.physicsBody!.categoryBitMask = CollisionTypes.Circle.rawValue
        self.physicsBody!.contactTestBitMask = CollisionTypes.Ball.rawValue
        //self.circulo.physicsBody!.collisionBitMask = 0

        self.addChild(circulo)


        //Prepare ball
        let ball = SKShapeNode(circleOfRadius: 9)
        ball.fillColor = SKColor.whiteColor()
        ball.position = self.center
        ball.zPosition = 1

        // Set physics
        ball.physicsBody = SKPhysicsBody(circleOfRadius: 9)
        ball.physicsBody!.affectedByGravity = true
        ball.physicsBody!.restitution = 0.8
        ball.physicsBody!.linearDamping = 0
        ball.physicsBody!.friction = 0.3
        ball.physicsBody?.dynamic = true
        ball.physicsBody!.mass = 0.5
        ball.physicsBody!.allowsRotation = true
        ball.physicsBody!.categoryBitMask = CollisionTypes.Ball.rawValue
        ball.physicsBody!.contactTestBitMask = CollisionTypes.Circle.rawValue
        //ball.physicsBody!.collisionBitMask = 0

        self.addChild(ball)

    }

    func didBeginContact(contact: SKPhysicsContact) {
        // elements
        if (contact.bodyA.categoryBitMask == CollisionTypes.Circle.rawValue &&
            contact.bodyB.categoryBitMask == CollisionTypes.Ball.rawValue) {
            print("contact between circle and ball")
        }
    }

The circuloFondo2 image:

enter image description here

A demo about the project:

enter image description here

In this answer you can see all the code to do it, but if you want you can download the project here

Comments