2

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.

Basil
  • 23
  • 4
  • You are only modifying the x axis, also I don't see where you are determining the direction of swipe, you just seem to be iterating from x to 17 and moving in that direction only, not in the opposite direction. Furthermore, could you not just move 5 squares and make the speed 5*0.13 in the direction you need pacman to move? Probably no need for a loop there. Regarding your comment around the animations continuing execution, you can remove animations from the CALayer of your view, before executing new ones in a different direction. – cjnevin Jun 21 '15 at 10:24
  • thanks for the reply, like i said i posted only one of the directions (swiping left) i am only modifying the x axis because i am swiping to the left size so the y should not be modified, i done the loop only to save the x position of the view but i saw it didn't help, how can i save the x position without the loop ? thanks. – Basil Jun 21 '15 at 11:05
  • You could determine which squares you are currently closest to using CGRectIntersection, then based on the direction of travel choose the one in the direction you are travelling. You then allow this animation to complete (or replace the animation) before queueing the new direction of the swipe. Also, Pacman is recursive in his movement, he should always be moving in the direction of travel, it's just a matter of changing direction in response to gestures. You night be approaching this in the wrong way. – cjnevin Jun 21 '15 at 11:10
  • May I also suggest using SpriteKit? It has collision detection. – cjnevin Jun 21 '15 at 11:11
  • i am sorry but i didn't understand how can i move the imageview without completing the animation, i can move it now without the loop but the problem is that he will go back as soon as the animation will finish, is there any way to get the x from a moving imageview ? – Basil Jun 21 '15 at 11:19
  • i will look at the SpriteKit. – Basil Jun 21 '15 at 11:20
  • Using presentation layer: http://stackoverflow.com/a/1933755/4983386 – cjnevin Jun 21 '15 at 11:21
  • thank you very much, you helped me a lot :) – Basil Jun 21 '15 at 11:23
  • i can't get the current position of the image view while it's animating, i tried this- if (sender.direction != .Right) { pacMan.center = pacMan.layer.presentationLayer().position } – Basil Jun 21 '15 at 12:22

1 Answers1

0

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.

cjnevin
  • 311
  • 2
  • 8