【问题标题】:Force the SKAction.move to be completed - swift强制完成 SKAction.move - swift
【发布时间】:2020-01-04 22:50:39
【问题描述】:

我正在使用 swift 和库 SpriteKit 创建一个蛇游戏。

要控制蛇的方向,用户必须在屏幕上滑动。要检查滑动的方向,我使用UISwipeGestureRecognizer

现在,我必须将GameViewController.swift 文件中的信息(滑动方向)传递给GameScene.swift 文件。为此,我声明了一个名为 movesConoller 的 4 项数组:

movesController[false, false, false, false]

如果用户向上滑动,数组的第一个元素变为真,如果他向下滚动,第二个元素变为真,第一个元素变为假......等等。

现在,在GameScene.swift 文件中,我必须说明如果玩家向上移动,Snake 必须做什么。 出于这个原因,我使用了另外 2 个变量:

var playerX:CGFloat = 0
var playerY:CGFloat = 0

然后我创建了这段代码

if movesController[0] == true {
   playerY += 56
}
if movesController[1] == true {
   playerY -= 56
}
if movesController[2] == true {
   playerX += 56
}
if movesController[3] == true {
   playerX -= 56
}

现在我创建运动

let startPoint = CGPoint(x: player.position.x, y: player.position.y )
let endPoint = CGPoint(x: playerX + player.position.x, y: playerY + player.position.y)
let moveIt = SKAction.move(to: endPoint, duration:0.1)
player.run(moveIt)

因此,每次执行程序时,playerXplayerY 变量都等于 0。然后,根据滑动的方向,将它们加减 56。 要移动蛇,我只是对头部说,在 0.1 秒内从他的 startPoint 移动到他的 endPoint

我添加的另一件事是尾巴。为了创建它,我使用了两个数组,snakeXsnakeY。 在这两个空数组(CGFloat 类型)中,我添加了蛇的前一个位置,然后,如果分数保持不变,则删除每个数组的最后一个元素。否则,最后一个元素不会被删除并保留在他的数组中。

用这个方法,当蛇吃苹果时,我让尾巴长出来。

但是头部在 0.1 秒内移动了 56 次。这意味着他在每次执行时移动了 8 个像素。因此,我必须每执行 7 次程序就将 X 和 Y 值添加到 snakeXsnakeY

这就是问题所在。如果玩家在程序执行完 7 次后在屏幕上滑动,尾巴的移动将是完美的。但是如果玩家在7执行之前刷过,就会有问题。假设蛇在向右移动,并且当程序执行第 4 次时玩家向上滑动。

//snakeX and snakeY values before the swipe
snakeX[168, 112, 56, 0] //all this numbers are multiple of 56
snakeY[224, 224, 224, 224] //the snake is moving right, the Y value doesn't change.

//snakeX and snakeY values after the swipe
snakeX[168 ,112 ,56 , 0] 
snakeY[248, 224, 224, 224] //look at the first element

248 不是 56 的倍数。蛇在第 4 次执行时向上移动,在第 3 次执行后,它的位置将被添加到数组中。但在 3 次执行中,他移动了 24 像素。 因此,我会得到这个错误

如您所见,尾巴并不是完美的角落。

蛇头没有完成 56 像素的移动。当我滑动时,它会离开他的动作并开始另一个动作。有什么方法可以告诉头部在做另一个动作之前总是完成他的动作?

【问题讨论】:

  • 您不允许在触发下一个动作之前完成最后一个动作,使用某种队列在前一个动作完成时触发下一个动作。 Run 有一个完成处理程序,你可以进入

标签: swift sprite-kit


【解决方案1】:

您正在尝试对基本上基于网格的游戏使用基于像素的方法,但也许这样的方法会奏效...

制作一个控制是否允许移动的变量:

var moveAllowed = true

使用该变量保护您的移动代码:

if moveAllowed {
  if movesController[0] == true {
    playerY += 56
  }
  ...
}

当您安排移动动作时,切换moveAllowed,并添加一个完成处理程序以在动作完成后将其切换回来:

...
moveAllowed = false
let moveIt = SKAction.move(to: endPoint, duration:0.1)
player.run(moveIt) { self.moveAllowed = true }

self.moveAllowed 可能只是 moveAllowed,具体取决于您的结构,但我无法从您的片段中分辨出来。)

编辑:我刚刚意识到,也许您正在基于player.position 设置snakeXsnakeY。这不是很清楚。在任何情况下,您都会使用相同的想法,但仅当moveAllowedtrue 时才从player.position 复制。基本上,该变量会告诉您操作是否仍在运行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-06
    • 2020-02-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多