问题
I am attempting to generate a random X position for a simple object, in order to have it bounce back and forth inside the scene in a Swift SpriteKit game. The repeatForever action should generate a random value and then move the object (a circle) multiple times to different locations, left and right. However, it acts only one time. It is as if the random function, which works correctly, is called only one time, and the action then simply continues to move the object to the same position forever.
let circle = SKSpriteNode(imageNamed: "circle")
circle.run(SKAction.repeatForever(SKAction.move(to:
CGPoint(x: random(min: minCircleX, max: maxCircleX),
y: scene.size.height*0.5),
duration: 0.5)))
The circle moves only one time, to one position, and never seems to be moved after that. I suspect it is simply moving to the same position over and over. Thanks for any suggestions!
回答1:
OK, after multiple efforts, the following works:
let customAction = SKAction.customAction(withDuration: 1000)
{
circle, _ in
let newXLocation: CGPoint = CGPoint(x: random(min: minCircleX, max: maxCircleX),
y: scene.size.height*0.5)
circle.run(SKAction.move(to: newXLocation, duration: 0.5))
}
circle.run(customAction)
Dai was correct in suggesting an anonymous function. The SKAction method customAction allows for that. And then running the actual action inside the function insured that the movement was random every time. Thanks so much!
回答2:
Instead of repeat forever, use the completionblock to establish a new moveTo:
func newLocation(){
let newXLocation: CGPoint = CGPoint(x: random(min: minCircleX, max: maxCircleX),
y: scene.size.height*0.5)
circle.run(SKAction.move(to: newXLocation, duration: 0.5){
[weak self] in self?.newLocation()
}
}
What this does is upon finishing the moveTo, it will add a new moveTo and the next random location. The only "flaw" is it will start the next move during the same frame as the current move since this is being done in the action phase of the update. If you do not want this effect, then you need to store it in a block to be done during didFinishUpdate
var finishedUpdates = [()->()]()
func newLocation(){
let newXLocation: CGPoint = CGPoint(x: random(min: minCircleX, max: maxCircleX),
y: scene.size.height*0.5)
circle.run(SKAction.move(to: newXLocation, duration: 0.5){
[weak self] in
self?.finishedUpdates.append({weak self] in self?.newLocation()})
}
}
func didFinishUpdate()
{
finishedUpdates.forEach{$0()}
finishedUpdates = [()->()]() //Be sure to clear the array
}
My apologies in advance, this is written from memory alone, and may not be 100% syntactically correct
来源:https://stackoverflow.com/questions/57641747/why-doesnt-the-call-to-the-random-function-work-in-the-sequence