Delay before beginning animation of NSView (AppKit) - swift

The following code from here shows how to do a fade-out for NSView in Swift:
NSAnimationContext.runAnimationGroup({ context in
context.duration = 1
self.view.animator().alphaValue = 0
}, completionHandler: {
self.view.isHidden = true
self.view.alphaValue = 1
})
I am using this code to display a status notification -> i.e. the text appears, stays for around a few seconds, and then fades out. Is there a way to delay the start of the fade out to accomplish this?

Is there a way to delay the start of the fade out to accomplish this?
One way is to use NSTimer to run your animation after whatever delay you choose. For example, you could pass a block containing your code to +scheduledTimerWithTimeInterval:repeats:block:, and once the interval expires the block will run.

Related

Increase Node Speed with SKPhysicsBody linearDamping Swift 4

I have the below class being called from my GameScene
func update(_ currentTime: TimeInterval)
Since it's being called there, my class is being called every second which leads me to this. I currently have my self.physicsBody?.linearDamping = 0.6 but how would I increase that number so I can also increase the speed? I was going to use another Timer till I realized my SKSpriteNode class is being called every second. Not too sure how to go about this, any ideas? I basically want to decrease that number every 2.0 seconds without letting the update function get in the way.
Any time you want to do something at regular time intervals in a sprite-Kit game, you can implement this as follows:
First declare 2 properties (in your class but outside all the function definitions)
var timeOfLastThing: CFTimeInterval = 0.0
var timePerThing: CFTimeInterval = 2.0 // How often to do the thing
( if the thing you want to do every 2 seconds is spawn a monster, then you might call these timeOfLastMonsterSpawn and timePerMonsterSpawn, but it's up to you)
Then, in Update, check to see if the timePerThing has been exceeded. If so, call your doThing function which does what you need it to and then reset the time since the last call:
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
if (currentTime - timeOfLastThing > timePerThing) {
doThing()
self.timeOfLastThing = currentTime
}
}
func doThing() {
// Your spawn code here
}
The advantage of making the doThing a separate function (as opposed to it being in line in update())is that you can call it from didMoveToView or any other place to spawn objects outside of the normal time-controlled cycle.
You can change the value of timePerThing as necessary to control the rate at which things happen.
You could also look into creating an SKAction that runs doThing at specified time intervals, but I think to change the rate at which objects are spawned, you'll have to delete and re-create the SKAction, which you could do this in a setter for timePerThing.
You shouldn't really use NSTimer in SpriteKit, as the SpriteKit engine will be unaware of what the timer is doing and can't control it (one example is that the timer keeps running and doing stuff even if you set the scene to paused).

How can i synchronize AVCaptureDevice setFocusModeLockedWithLensPosition call

I want to synchronize setFocusModeLockedWithLensPosition, setWhiteBalanceModeLockedWithDeviceWhiteBalanceGains and setExposureModeCustomWithDuration calls.
Is there a logic order to call thoses functions ?
What i want to do is to start Running session when i am sure that focus, balance and exposure are properly set (i want to set values, not in automatic)
I have tried to lock the configuration, then call the 3 functions, then unlock, then startRunning on session. I put nil in the 3 completion handler parameters.
What i see in this case is that my image preview is not pretty (kind of blue filter). I have to wait before having a good image quality. What i want is to display the image only when it is good. I want do be notified.
So i tried to cascade my 3 calls with completion handler. in some cases, the completion handler is not called. I suppose this is when i want to put my lens position to 0.4 and the current lens position is 0.4.
So i don't know which is the best method.
Thanks
You can set your camera options in completion handler like this. It will wait till focus has been set to set exposure and the same principle will work with white balance and exposure. You can read more about camera setting here.
var AVCGains:AVCaptureWhiteBalanceGains = AVCaptureWhiteBalanceGains()
AVCGains.redGain = 1.0;
AVCGains.greenGain = 1.0;
AVCGains.blueGain = 1.0;
self.camera?.focusMode = .locked
self.camera?.exposureMode = .locked
self.camera?.whiteBalanceMode = .locked
self.camera?.setFocusModeLockedWithLensPosition(focus_point, completionHandler: {(timestamp:CMTime) -> Void in
print("Focus applied")
self.camera?.setExposureModeCustomWithDuration(CMTimeMake(1,10), iso: 100, completionHandler: {(timestamp:CMTime) -> Void in
print("Exposure applied")
self.camera?.setWhiteBalanceModeLockedWithDeviceWhiteBalanceGains(AVCGains, completionHandler: {(timestamp:CMTime) -> Void in
print("White Balance applied")
// All settings have been applied, start running session
})
})
})

How to move a node for a given time?

I wonder how to animate a node to which I assign a few seconds until next action takes place.
For example, if a button is pressed, a node begins to move for three seconds, and after the three seconds pass away, a picture or text appears on the screen.
Should I use NSTimer and NSTimerInterval?
Try to use this fairly simple approach that will help you to manage animation. This animation will take 3 seconds and at the end it will execute a completion handler.
UIView.animateWithDuration(3.0, animations: { () -> Void in
//animate object here
}) { (state: Bool) -> Void in
// hide animated object here
}

SpriteKit SKSequence to make UI Buttons appear

In a gameOverScene of my SpriteKit game, I have 3 buttons which appear on the screen.
I'm trying to make them "pop in", one after the other... I figured a neat way was to fade them in from 0 alpha to full.
I'm currently doing it like this:
//animate in buttons
restartButton.alpha = 0
shareButton.alpha = 0
exitButton.alpha = 0
let bringInUIButtons = SKAction.sequence([
SKAction.waitForDuration(1.0),
SKAction(restartButton.runAction(SKAction.fadeInWithDuration(0.3))),
SKAction.waitForDuration(1.0),
SKAction(shareButton.runAction(SKAction.fadeInWithDuration(0.3))),
SKAction.waitForDuration(1.0),
SKAction(exitButton.runAction(SKAction.fadeInWithDuration(0.3))),
])
runAction(bringInUIButtons)
But they all fade in at once... Even though, as part of my sequence I wait for a second in-between each Action.
I even tried this:
//animate in buttons
restartButton.alpha = 0
shareButton.alpha = 0
exitButton.alpha = 0
let bringInUIButtons = SKAction.sequence([
SKAction.waitForDuration(1.0),
SKAction(restartButton.runAction(SKAction.fadeInWithDuration(0.3))),
SKAction.waitForDuration(1.0),
SKAction(shareButton.runAction(SKAction.fadeInWithDuration(0.6))),
SKAction.waitForDuration(1.0),
SKAction(exitButton.runAction(SKAction.fadeInWithDuration(0.9))),
])
runAction(bringInUIButtons)
...and by changing the fade in duration, so each button takes longer to appear, but it doesn't look very good.
Am I using the waitForDuration incorrectly? I figured it would wait before starting the next action in the sequence?
How can I make the next button appear after the first?
I think the problem is that you're having each button run its own "fade in" action, which means they'll execute their actions in parallel. If you want them to appear one at a time in the scene, it's better to have the scene run the action. Here's my solution...
When you instantiate restartButton, shareButton, and exitButton, set their name properties as shown below:
restartButton.name = "restartButton"
shareButton.name = "shareButton"
exitButton.name = "exitButton"
You'll use these name properties to specify the button on which you want to run a "fade in" action using the runAction(_:onChildWithName:) method.
When it's time to fade the buttons in, use this set of actions:
let fadeIn = SKAction.fadeInWithDuration(1)
let wait = SKAction.waitForDuration(1)
let bringInRestartButton = SKAction.runAction(fadeIn, onChildWithName: "restartButton")
let bringInShareButton = SKAction.runAction(fadeIn, onChildWithName: "shareButton")
let bringInExitButton = SKAction.runAction(fadeIn, onChildWithName: "exitButton")
let bringInUIButtons = SKAction.sequence([
bringInRestartButton,
wait,
bringInShareButton,
wait,
bringInExitButton
])
runAction(bringInUIButtons)

SpriteKit: Cloning Nodes

So I would like to make a block of code that will run inside the sprite node every frame. The result would be me tapping and creating a bubble there that would then float up using sine. Is that possible to code into the bubble? Sorry if this seems vague, I'm just not sure what to call it. The closest thing I can think of it cloning and each clone runs the same script every frame. Anyways, Here's what I have now.
let bubble = SKSpriteNode(imageNamed:"bubble")
bubble.position.x = CGFloat(rand())*self.frame.width
bubble.position.y = -20
//Code for bubble to run each frame
self.addChild(bubble)
I think that what you are looking for is enumerateChildNodesWithName. When it is called, it will run the code it contains on every node with the name you put in it.
bubble.name = "bubble"
If you name bubble "bubble", all of its child nodes will also be named "bubble".
enumerateChildNodesWithName("bubble"){node, stop in
let bubbleChild:SKSpriteNode = node as! SKSpriteNode
//Run the code telling them what to do here. You should make it so that
//it can figure out how to move the node a slight amount based on its position
}
You could call this by putting it in a function that is called by a timer, and the timer should be called frequently, like every 0.017 seconds (Approximately 60 times a second) so that the motion is smooth. For example:
var timer = NSTimer.scheduledTimerWithTimeInterval(NSTimeInterval(0.017), target: self, selector: Selector("moveBubbles:"), userInfo: nil, repeats: true)
Then, to make a function that the timer calls:
func moveBubbles(timer: NSTimer!){
//enumerateChildNodesWithName here
}
There is more information on enumerateChildNodesWithName here, and more information on NSTimer here.