Stop SKAction that RepeatsForever - Sprite Kit
The method is supposed to be called on the node which the SKAction is running on.
Change
[self removeActionForKey:@"animation1"];
to
[sprite removeActionForKey:@"animation1"];
swift spritekit : How to stop a runBlock?
So you are naming an object "noObject" and an action "stop"? :)
Anyway, you should use a group
and a few sequence
actions.
The idea
This code
self.runAction(SKAction.waitForDuration(5), completion: {
print("slide02")
})
can also be written this way
let action1 = SKAction.sequence([SKAction.waitForDuration(5), SKAction.runBlock { print("slide02") }])
Solution
Given a sprite
let sprite = SKSpriteNode()
and 4 actions
let action0 = SKAction.runBlock { print("slide01") }
let action1 = SKAction.sequence([SKAction.waitForDuration(5), SKAction.runBlock { print("slide02") }])
let action2 = SKAction.sequence([SKAction.waitForDuration(8), SKAction.runBlock { print("slide03") }])
let action3 = SKAction.sequence([SKAction.waitForDuration(6), SKAction.runBlock { print("slide06") }])
we can group the actions like this
let group = SKAction.group([action0, action1, action2, action3])
Now we can run the action with a key
sprite.runAction(group, withKey: "group")
and stop it
sprite.removeActionForKey("group")
How to stop SKAction called on DidMove when a variable changes
You can use a property observer for this kind of tasks:
var i = 50{
didSet{
if i < 18{
spriteNode.removeAction(forKey: "key")
}
}
}
This means that everytime i
is set to another value, the didSet block is called.
How to stop a audio SKAction?
You can't stop audio from playing when run from SKAction.
You will need another engine to run your background music.
Try AVAudioPlayer - it is really easy and straightforward to use. Something like this will work:
First import header and add new property to your scene or view controller:
#import <AVFoundation/AVFoundation.h>
@interface AudioPlayerViewController : UIViewController {
@property (strong, nonatomic) AVAudioPlayer *audioPlayer;
}
After this in viewDidLoad or in didMoveToView method of scene add following code:
- (void)viewDidLoad {
[super viewDidLoad];
NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/audiofile.mp3", [[NSBundle mainBundle] resourcePath]]];
NSError *error;
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
self.audioPlayer.numberOfLoops = -1;
if (!self.audioPlayer)
NSLog([error localizedDescription]);
else
[self.audioPlayer play];
}
Each time you need your music to stop, just call [self.audioPlayer stop];
When you need new music to play, put a new player into the property initialized with your new music piece.
Hope this helps.
Remove SKAction and restore node state
Thanks to the helpful comment and answer I came to my own solution. I think the state machine would be bit too heavy here. Instead I created a wrapper node, which main purpose is run the animation. It also has a state: isAimating
property. But, first of all, it allows to keep startAnimating()
and stopAnimating()
methods close to each other, incapsulated, so it's more difficult to mess up.
class ShowMoveAnimNode: SKNode {
let animKey = "showMove"
var isAnimating: Bool = false {
didSet {
guard oldValue != isAnimating else { return }
if isAnimating {
startAnimating()
} else {
stopAnimating()
}
}
}
private func startAnimating() {
let shortPeriod = 0.2
let scaleDown = SKAction.scale(by: 0.75, duration: shortPeriod)
let seq = SKAction.sequence([scaleDown,
scaleDown.reversed(),
scaleDown,
scaleDown.reversed(),
SKAction.wait(forDuration: shortPeriod * 6)])
let repeated = SKAction.repeatForever(seq)
run(repeated, withKey: animKey)
}
private func stopAnimating() {
removeAction(forKey: animKey)
xScale = 1
yScale = 1
}
}
Usage: just add everything that should be animated to this node. Works well with simple animations, like: fade, scale and move.
How can I slow down a SKSpriteNode that is running SKAction followPath for a slow motion effect using Sprite Kit?
Each node has a speed
property:
A speed modifier applied to all actions executed by a node and its
descendants.Discussion
The default value is 1.0, which means that all actions run
at their normal speed. If you set a different speed, time appears to
run faster or slower for all actions executed on the node and its
descendants. For example, if you set a speed value of 2.0, actions run
twice as fast.
You could set this to a value smaller than 1 to make the action run slower. You can even animate the speed to gradually slow down:
[mySprite runAction:[SKAction speedTo:0.5 duration:1.0]];
SKAction go to and stop at a specific frame
There is no action to play from frame x to y. But it's easy to replicate because the animate actions..
+ (SKAction *)animateWithTextures:(NSArray *)textures
timePerFrame:(NSTimeInterval)sec
.. take an array of textures as input. You either create the array just with the specific frame textures you want to play, or if you already have an array allFrames
with all textures you can get a new array with the desired frames like so if you wanted to play from frame 15 to end:
NSRange range = NSMakeRange(15, allFrames.count - 15);
NSArray* animFrames = [allFrames subarrayWithRange:range];
SKAction anim = [SKAction animateWithTextures:animFrames timePerFrame:0.1];
Stop SKAction after a certain amount of time
You are removing the wrong action. The action with key "enemy1" is:
SKAction.sequence([delay, actionMove, actionRemove])
which simply animates the enemy. Removing this only stops this sequence of actions temporarily. When addEnemy1
is called again, the sequence of action is added again.
The action that spawns the enemy is the action that you run on self
here:
run(SKAction.repeatForever(
SKAction.sequence([SKAction.run() { [weak self] in
self?.addEnemy1()
},
SKAction.wait(forDuration: 5.0)])))
Yo should give a key to that action instead:
...
},
SKAction.wait(forDuration: 5.0)])), withKey: "spawnEnemy")
and then remove that from self
:
removeAction(forKey: "spawnEnemy")
Related Topics
How to Access the Accelerometer from the Apple Watch
Changing Uipageviewcontroller's Page Programmatically Doesn't Update the Uipagecontrol
Custom Font Not Working in Wkwebview Swift
Reordering Uitableview Without Reorder Control
How to Detect Whether an iOS Device Is in Silent Mode or Not
How to Emulate Nfc Cards in iOS 13
Two Buttons Inside Hstack Taking Action of Each Other
App Is Not Showing in the Share Menu of Shared Options in Shared Extension in iOS8
Downcast from Any to a Protocol
iOS Application Using Facebook -- Rejected
Parse JSON Response with Afnetworking
Add Uiimage on Top of Another Uiimage
Detecting When App Is Becoming Active from Lockscreen VS Other on iOS7
How to Search for Any Uiwebview Component Usage Inside a Current Project
How to Detect Orientation in an App Extension