Diego Benítez
Diego Benítez

Reputation: 185

How to move sprite with a joystick within a certain limit?

I want to make it so that the player can move with a joystick but cant go out of the circle. I made the joystick but I don't know how to do the other stuff. There is an example in the image below and also my code. Hope someone can help me, thanks.

class GameScene: SKScene {

    var circuloPrincipal = SKSpriteNode(imageNamed: "circulo")
    var circuloFondo = SKSpriteNode(imageNamed: "circuloFondo")
    let base = SKSpriteNode(imageNamed: "circuloFondo")
    let ball = SKSpriteNode(imageNamed: "circulo")
    var stickActive:Bool = false



    override func didMoveToView(view: SKView) {
        /* Setup your scene here */

        base.size = CGSize(width: 100, height: 100)
        base.alpha = 0.3
        base.zPosition = 2.0
        base.position = CGPoint(x: frame.width / 2, y: frame.height / 2 - 310)
        self.addChild(base)

        ball.size = CGSize(width: 50, height: 50)
        ball.color = circuloPrincipal.color
        //ball.alpha = 0
        ball.zPosition = 3.0
        ball.position = base.position
        self.addChild(ball)

        circuloPrincipal.size = CGSize(width: 35, height: 35)
        circuloPrincipal.position = CGPoint(x: frame.width / 2, y: frame.height / 2)
        self.addChild(circuloPrincipal)
        circuloPrincipal.color =  UIColor(red: 0.75, green: 0.75, blue: 0.75, alpha: 1.0)
        circuloPrincipal.colorBlendFactor = 1.0
        circuloPrincipal.zPosition = 3.0
    }

    override func touchesBegan(touches: Set<UITouch>, withEvent event:     UIEvent?) {


        for touch in touches {
            let location = touch.locationInNode(self)

            if (CGRectContainsPoint(ball.frame, location)) {

                stickActive = true
            }else {

                stickActive = false

            }

        }
    }

    override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
        for touch in touches {
            let location = touch.locationInNode(self)

            if (stickActive == true) {


            let v = CGVector(dx: location.x - base.position.x, dy: location.y - base.position.y)
            let angle = atan2(v.dy, v.dx)
            let deg = angle * CGFloat(180 / M_PI)
            print(deg + 180)

            let lenght:CGFloat = base.frame.size.height / 2 - 20
            let xDist: CGFloat = sin(angle - 1.57079633) * lenght
            let yDist: CGFloat = cos(angle - 1.57079633) * lenght

            ball.position = CGPointMake(base.position.x - xDist, base.position.y + yDist)

            if (CGRectContainsPoint(base.frame, location)) {

                ball.position = location
            }else {

                ball.position = CGPointMake(base.position.x - xDist, base.position.y + yDist)

            }


            } // termina stickActive

        }

    }

    override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
        if (stickActive == true) {

            let move: SKAction = SKAction.moveTo(base.position, duration: 0.2)
            move.timingMode = .EaseOut

            ball.runAction(move)

        }
    }

Upvotes: 2

Views: 429

Answers (1)

Steve Ives
Steve Ives

Reputation: 8134

Look into SKConstraint - you can set a constraint that a node cannot move further than a specified distance from another node. You'd set this 'other' node to the centre of the area that your player is limited to. Sprite-Kit will automatically move your node back should it go to far. As this is being in the game loop at 60fps before the node is redrawn after it's moved, you won't get any weird 'jumping' effects.

https://developer.apple.com/reference/spritekit/skconstraint

That documentation is a bit lacking compared to some of the other SK documentation. Here's and example that make a green rectangle 'follow' a yellow triangle within a specified distance:

let distanceRange = SKRange(lowerLimit: 200, upperLimit: 400)
let distanceConstraint = SKConstraint.distance(distanceRange, toNode: yellowTriangle)  
greenRect.constraints = [distanceConstraint]

The constraints property of an SKNode (greenRect) is an array, so if you also want an orientation constraint (to keep greenRect facing the yellow triangle, for example), you would code something like this:

let orientRange = SKRange(lowerLimit: 0.0, upperLimit: 0.0)
let orientConstraint = SKConstraint.orientToNode(yellowTriangle, offset: orientRange)
greenRect.constraints = [orientatConstraint, distanceConstraint]

For your particular example, you might want to set the constraint as:

let distanceRange = SKRange(lowerLimit: 0, upperLimit: limitcircle.size/2)
 let distanceConstraint = SKConstraint.distance(distanceRange, toPoint: limitCircle.position)
player.constraints = [distanceConstraint]

This assumes that the circle from which the player cannot move is an SKNode called limitcircle and it's anchor point is set to (0.5, 0.5) i,e, it's center. The above code would constrain the player to a distance of between 0 and 1/2 the width of the circle (i.e. it's radius) from a point at the center of the circle.

Upvotes: 1

Related Questions