moving pacman in swift

1.1k views Asked by At

i am brand new to swift and i am trying to program a pacman. i am trying to move the pacman to the direction of the swipe, so far i have managed to move it to the edges of the screen, the problem is that when i try to move it not from the edge of the screen but in the middle of the swipe action, it just goes to the edge of the screen and moves to the swipe direction, here is the code for one direction:

    var x = view.center.x
    for var i = x; i > 17; i--
    {
        var origin: CGPoint = self.view.center
        var move = CABasicAnimation(keyPath:"position.x")
        move.speed = 0.13
        move.fromValue = NSValue(nonretainedObject: view.center.x)
        move.toValue = NSValue(nonretainedObject: i)
        view.layer.addAnimation(move, forKey: "position")
        view.center.x = i
    }

the thing is that i know the problem which is when i swipe to the direction that i want the for loop will not wait for the animation to stop but it will finish the loop in less than a second and i need sort of delay here or other code.

1

There are 1 answers

0
cjnevin On BEST ANSWER

This was an interesting question, so I decided to make an example in SpriteKit. There isn't any collision detection, path finding or indeed even paths. It is merely an example of how to make 'Pac-Man' change direction when a swipe occurs.

I have included the GameScene below:

class GameScene: SKScene {
    enum Direction {
        case Left
        case Right
        case Up
        case Down
    }
    lazy var openDirectionPaths = [Direction: UIBezierPath]()
    lazy var closedDirectionPaths = [Direction: UIBezierPath]()
    lazy var wasClosedPath = false
    lazy var needsToUpdateDirection = false
    lazy var direction = Direction.Right
    lazy var lastChange: NSTimeInterval = NSDate().timeIntervalSince1970

    var touchBeganPoint: CGPoint?
    let pacmanSprite = SKShapeNode(circleOfRadius: 15)

    override func didMoveToView(view: SKView) {
        let radius: CGFloat = 15, diameter: CGFloat = 30, center = CGPoint(x:radius, y:radius)
        func createPaths(startDegrees: CGFloat, endDegrees: CGFloat, inout dictionary dic: [Direction: UIBezierPath]) {
            var path = UIBezierPath(arcCenter: center, radius: radius, startAngle: startDegrees.toRadians(), endAngle: endDegrees.toRadians(), clockwise: true)
            path.addLineToPoint(center)
            path.closePath()
            dic[.Right] = path
            for d: Direction in [.Up, .Left, .Down] {
                path = path.pathByRotating(90)
                dic[d] = path
            }
        }
        createPaths(35, 315, dictionary: &openDirectionPaths)
        createPaths(1, 359, dictionary: &closedDirectionPaths)
        pacmanSprite.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
        pacmanSprite.fillColor = UIColor.yellowColor()
        pacmanSprite.lineWidth = 2
        if let path = openDirectionPaths[.Right] {
            pacmanSprite.path = path.CGPath
        }
        pacmanSprite.strokeColor = UIColor.blackColor()
        self.addChild(pacmanSprite)
        updateDirection()

        // Blocks to stop 'Pacman' changing direction outside of a defined path?
        //375/25 = 15 width
        //666/37 = 18 height
    }

    override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
        touchBeganPoint = positionOfTouch(inTouches: touches)
    }

    override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {
        if let touchStartPoint = touchBeganPoint,
            touchEndPoint = positionOfTouch(inTouches: touches) {
                if touchStartPoint == touchEndPoint {
                    return
                }
                let degrees = atan2(touchStartPoint.x - touchEndPoint.x,
                    touchStartPoint.y - touchEndPoint.y).toDegrees()
                var oldDirection = direction
                switch Int(degrees) {
                case -135...(-45):  direction = .Right
                case -45...45:      direction = .Down
                case 45...135:      direction = .Left
                default:            direction = .Up
                }
                if (oldDirection != direction) {
                    needsToUpdateDirection = true
                }
        }
    }

    override func touchesCancelled(touches: Set<NSObject>!, withEvent event: UIEvent!) {
        touchBeganPoint = nil
    }

    override func update(currentTime: CFTimeInterval) {
        /* Called before each frame is rendered */
        if let nodes = self.children as? [SKShapeNode] {
            for node in nodes {
                let p = node.position
                let s = node.frame.size
                //let s = node.size
                if p.x - s.width > self.size.width {
                    node.position.x = -s.width
                }
                if p.y - s.height > self.size.height {
                    node.position.y = -s.height
                }
                if p.x < -s.width {
                    node.position.x = self.size.width + (s.width / 2)
                }
                if p.y < -s.height {
                    node.position.y = self.size.height + (s.height / 2)
                }
                if needsToUpdateDirection || NSDate().timeIntervalSince1970 - lastChange > 0.25 {
                    if let path = wasClosedPath ? openDirectionPaths[direction]?.CGPath : closedDirectionPaths[direction]?.CGPath {
                        node.path = path
                    }
                    wasClosedPath = !wasClosedPath
                    lastChange = NSDate().timeIntervalSince1970
                }
                updateDirection()
            }
        }
    }

    // MARK:- Helpers

    func positionOfTouch(inTouches touches: Set<NSObject>) -> CGPoint? {
        for touch in (touches as! Set<UITouch>) {
            let location = touch.locationInNode(self)
            return location
        }
        return nil
    }

    func updateDirection() {
        if !needsToUpdateDirection {
            return
        }
        pacmanSprite.removeActionForKey("Move")
        func actionForDirection() -> SKAction {
            let Delta: CGFloat = 25
            switch (direction) {
            case .Up:
                return SKAction.moveByX(0.0, y: Delta, duration: 0.1)
            case .Down:
                return SKAction.moveByX(0.0, y: -Delta, duration: 0.1)
            case .Right:
                return SKAction.moveByX(Delta, y: 0.0, duration: 0.1)
            default:
                return SKAction.moveByX(-Delta, y: 0.0, duration: 0.1)
            }
        }
        let action = SKAction.repeatActionForever(actionForDirection())
        pacmanSprite.runAction(action, withKey: "Move")
        needsToUpdateDirection = false
    }
}

The repository can be found here

I have added the MIT license, so you can fork this repository if you wish. I hope this helps.