這是一個有趣的問題,所以我決定在SpriteKit一個例子。沒有任何碰撞檢測,路徑查找甚至路徑。這僅僅是當發生滑動時如何使'吃豆人'改變方向的一個例子。
我已經包含下面的GameScene:
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
}
}
存儲庫可以是found here
我已經加入了麻省理工學院的許可證,所以你可以,如果你想叉這個庫。我希望這有幫助。
你只是修改x軸,也是我沒有看到你在哪裏刷卡確定的方向,你剛纔似乎是從X迭代到17,並朝着那個方向只,而不是相反的方向。此外,你是否可以不移動5格,並使速度5 * 0.13朝你需要移動的方向移動?可能不需要在那裏循環。關於您對動畫繼續執行的評論,您可以從視圖的CALayer中刪除動畫,然後以不同的方向執行新動畫。 – cjnevin
感謝您的回覆,就像我說我只發佈其中一個方向(向左滑動)我只修改x軸,因爲我滑動到左側大小,所以y不應該被修改,我完成循環只是爲了節省視圖的x位置,但我看到它沒有幫助,我怎樣才能保存沒有循環的x位置?謝謝。 – Basil
您可以使用CGRectIntersection確定您當前最接近哪個方格,然後根據旅行方向選擇您正在旅行的方向。然後,在排隊滑動的新方向之前,允許完成此動畫(或替換動畫)。而且,Pacman在他的運動中是遞歸的,他應該總是朝着旅行的方向前進,這只是一個響應手勢而改變方向的問題。你夜晚以錯誤的方式接近這一點。 – cjnevin