模拟寿司火车 - Swift SpriteKit
Simulating sushi train - Swift SpriteKit
我正在学习使用 SprikeKit 创建游戏,该游戏与寿司火车有关。
我有大约 20 个盘子沿着矩形路径移动,以模拟所有盘子都在移动的传送带上的外观。
我试过使用场景编辑器放置几个精灵节点并使它们像这样在方形路径上移动。
let dish_1 = self.childNode(withName: "dish_1");
let dish_2 = self.childNode(withName: "dish_2");
let square = UIBezierPath(rect: CGRect(x: 0, y: 0, width: 200, height: 200));
let followSquare = SKAction.follow(square.cgPath, asOffset: true, orientToPath: false, duration: 5.0);
dish_1?.run(SKAction.sequence([followSquare]))
dish_2?.run(SKAction.sequence([followSquare]))
目前,这两个盘子使用的是同一个方块,方块的位置是相对于每个盘子的,所以它们看起来像是在两条不同的矩形路径上,因为它们的起点不同。
这是模拟我想要的外观的合理方法吗?
我问这个的原因是为了让所有的菜看起来都在同一条路径上移动,我需要调整每道菜的 x、y 位置,就像 20 道菜一样。
我想知道是否可以使用物理套件,让一个矩形节点使所有盘子沿着路径移动,只要它们在矩形节点区域内。
asOffset
似乎不正确。根据 the documentation,这 与您想要的 完全相反。
If YES, the points in the path are relative offsets to the node’s starting position. If NO, the points in the node are absolute coordinate values.
将此设置为 true 将为每道菜提供自己的矩形路径,以遵循相对于其起始位置的坐标,如您在问题中所述:
v First dish
v Second dish
O--O-----.---.
| | | |
| | | |
'--'-----'---'
^^ Second dish's path
^^ First dish's path
相反,我想你需要在绝对坐标中设置传送带,然后将每道菜的起点初始化为不同的 - 再次在绝对坐标中 - 最后让每道菜遵循所述路径:
v First dish (starting point x=0; y=0)
v Second dish (starting point x=20; y=0)
O--O-----.
| |
| |
'--------'
^^ Single, absolute path
(如果你模拟的是寿司传送带,它们顺时针移动,上面的命名法 "first" 和 "second" 在技术上是倒退的。交换这个作为 reader.:-P)
好吧,我可能会以类似的方式完成它,我认为使用 SKAction.follow 是一个解决方案。
但是您可以对代码进行一些改进。第一个是你不需要把你的 SKAction 写成一个序列,因为它只由一个动作组成,所以你可以将你的代码简化为:
let squarePath = UIBezierPath(rect: CGRect(x: 0, y: 0, width: 200, height: 200))
let followAction = SKAction.follow(path: squarePath.cgPath, duration: 5.0)
dish?.run(followAction)
现在另一件重要的事情是,为了节省您的内存使用量,而不是每次(20 次)都重新创建一道菜,您可以在 [=16= 上使用 copy()
] 来创建它的许多不同副本。根据您需要实现的目标,您当然可以自定义每个副本,更改其颜色或位置等。这样效率会更高。
您可以像这样创建 SKSpriteNode 的副本:
import GameplayKit
if let dishCopy = dish?.copy() as? SKSpriteNode {
dishCopy.position = CGPoint(x: GKRandomDistribution(lowestValue: 0, highestValue: 200).nextInt(), y: GKRandomDistribution(lowestValue: 0, highestValue: 500).nextInt())
self.addChild(dishCopy)
}
对于每个菜品副本的位置,你当然可以调整到自己的值,但这里我使用了GameplayKit和它非常有用的随机值生成器。
更新:
如果您想在使用 copy() 的同时为每道菜设置唯一的名称,您有多种选择。
一种可能是使用您将递增的计数器生成唯一名称,另一种可能是在更新方法中使用 currentTime。
但另一种更优雅的方法是创建一个数组来存储所有副本。
在你的场景子类的顶部,像这样声明你的菜肴数组:
var dishes = [SKSpriteNode]()
目前,它仍然是空的,因此您需要在创建每个副本时将每个副本添加到数组中:
// Create (safely) a dish copy:
if let dishCopy = dish?.copy() as? SKSpriteNode {
// Add the dish copy to the dishes array:
dishes.append(dishCopy)
// And add the dish copy to the world node:
worldNode?.addChild(dishCopy)
}
如果你想创建很多这样的副本,你可以使用 for loop
,或者你可以使用 update(_ currentTime:)
方法,指定你想每 5 个创建一个新的寿司盘秒,例如 :).
好吧,如果您在任何时候需要访问这些副本中的任何一个,只需访问 dishes
数组即可。
例如,这就是删除所有副本的方式(如果将它添加到场景中,则必须处理原始菜肴):
// And just iterate through all of your dish copies:
for dish in dishes {
dish.removeFromParent()
// Do whatever you need here :)
}
它非常简单,它允许您完美地控制您添加到 worldNode
.
的所有对象 and/or 副本
如果您有任何其他问题,请告诉我,我很乐意为您提供帮助!
顺便说一句,今晚我真的会去你问题中提到的寿司店,那家有小火车的。真是巧合! :D
我正在学习使用 SprikeKit 创建游戏,该游戏与寿司火车有关。
我有大约 20 个盘子沿着矩形路径移动,以模拟所有盘子都在移动的传送带上的外观。
我试过使用场景编辑器放置几个精灵节点并使它们像这样在方形路径上移动。
let dish_1 = self.childNode(withName: "dish_1");
let dish_2 = self.childNode(withName: "dish_2");
let square = UIBezierPath(rect: CGRect(x: 0, y: 0, width: 200, height: 200));
let followSquare = SKAction.follow(square.cgPath, asOffset: true, orientToPath: false, duration: 5.0);
dish_1?.run(SKAction.sequence([followSquare]))
dish_2?.run(SKAction.sequence([followSquare]))
目前,这两个盘子使用的是同一个方块,方块的位置是相对于每个盘子的,所以它们看起来像是在两条不同的矩形路径上,因为它们的起点不同。
这是模拟我想要的外观的合理方法吗? 我问这个的原因是为了让所有的菜看起来都在同一条路径上移动,我需要调整每道菜的 x、y 位置,就像 20 道菜一样。
我想知道是否可以使用物理套件,让一个矩形节点使所有盘子沿着路径移动,只要它们在矩形节点区域内。
asOffset
似乎不正确。根据 the documentation,这 与您想要的 完全相反。
If YES, the points in the path are relative offsets to the node’s starting position. If NO, the points in the node are absolute coordinate values.
将此设置为 true 将为每道菜提供自己的矩形路径,以遵循相对于其起始位置的坐标,如您在问题中所述:
v First dish v Second dish O--O-----.---. | | | | | | | | '--'-----'---' ^^ Second dish's path ^^ First dish's path
相反,我想你需要在绝对坐标中设置传送带,然后将每道菜的起点初始化为不同的 - 再次在绝对坐标中 - 最后让每道菜遵循所述路径:
v First dish (starting point x=0; y=0) v Second dish (starting point x=20; y=0) O--O-----. | | | | '--------' ^^ Single, absolute path
(如果你模拟的是寿司传送带,它们顺时针移动,上面的命名法 "first" 和 "second" 在技术上是倒退的。交换这个作为 reader.:-P)
好吧,我可能会以类似的方式完成它,我认为使用 SKAction.follow 是一个解决方案。
但是您可以对代码进行一些改进。第一个是你不需要把你的 SKAction 写成一个序列,因为它只由一个动作组成,所以你可以将你的代码简化为:
let squarePath = UIBezierPath(rect: CGRect(x: 0, y: 0, width: 200, height: 200))
let followAction = SKAction.follow(path: squarePath.cgPath, duration: 5.0)
dish?.run(followAction)
现在另一件重要的事情是,为了节省您的内存使用量,而不是每次(20 次)都重新创建一道菜,您可以在 [=16= 上使用 copy()
] 来创建它的许多不同副本。根据您需要实现的目标,您当然可以自定义每个副本,更改其颜色或位置等。这样效率会更高。
您可以像这样创建 SKSpriteNode 的副本:
import GameplayKit
if let dishCopy = dish?.copy() as? SKSpriteNode {
dishCopy.position = CGPoint(x: GKRandomDistribution(lowestValue: 0, highestValue: 200).nextInt(), y: GKRandomDistribution(lowestValue: 0, highestValue: 500).nextInt())
self.addChild(dishCopy)
}
对于每个菜品副本的位置,你当然可以调整到自己的值,但这里我使用了GameplayKit和它非常有用的随机值生成器。
更新:
如果您想在使用 copy() 的同时为每道菜设置唯一的名称,您有多种选择。
一种可能是使用您将递增的计数器生成唯一名称,另一种可能是在更新方法中使用 currentTime。
但另一种更优雅的方法是创建一个数组来存储所有副本。
在你的场景子类的顶部,像这样声明你的菜肴数组:
var dishes = [SKSpriteNode]()
目前,它仍然是空的,因此您需要在创建每个副本时将每个副本添加到数组中:
// Create (safely) a dish copy:
if let dishCopy = dish?.copy() as? SKSpriteNode {
// Add the dish copy to the dishes array:
dishes.append(dishCopy)
// And add the dish copy to the world node:
worldNode?.addChild(dishCopy)
}
如果你想创建很多这样的副本,你可以使用 for loop
,或者你可以使用 update(_ currentTime:)
方法,指定你想每 5 个创建一个新的寿司盘秒,例如 :).
好吧,如果您在任何时候需要访问这些副本中的任何一个,只需访问 dishes
数组即可。
例如,这就是删除所有副本的方式(如果将它添加到场景中,则必须处理原始菜肴):
// And just iterate through all of your dish copies:
for dish in dishes {
dish.removeFromParent()
// Do whatever you need here :)
}
它非常简单,它允许您完美地控制您添加到 worldNode
.
如果您有任何其他问题,请告诉我,我很乐意为您提供帮助!
顺便说一句,今晚我真的会去你问题中提到的寿司店,那家有小火车的。真是巧合! :D