SpriteKit; How to loop a SKVideoNode? - sprite-kit

I am currently trying to play a video in a loop via SpriteKit. I know that I need AVFoundation and the AVPLayer() for this, however I don't know how to initialize and use this...
Could someone help me with this?
Here is my current code block:
let mapSeriallyVideo = SKVideoNode(fileNamed: "map_serially.mp4")
mapSeriallyVideo.position = CGPoint(x: 850, y: 1100)
addChild(mapSeriallyVideo)
mapSeriallyVideo.play()

Related

Scenekit / Spritekit remove node causing crash

What I'm try to do, is replicate some digital instrument gauge ...using Spritekit..
On my project I have to use a SpriteKit Scene as material for Scenekit SCNnode.
In order to do that I create a sub class of SKscene and and apply it as "material.diffuse.contents" of the SCNNode.
all working fine, I can see my SKscene as material of the SCNNode.
Here the issue:
I try to animate/replicate the correct indication of the instrument based of some value my app received from other source.
To do so, i decide to use the SKsceneDelegate and use the method "update(_ currentTime: TimeInterval)"
simply the update method look for the sknode of the green needle "fulcro" remove it , and make a new line calculating the angle and new coordinate for the new line.
override func update(_ currentTime: TimeInterval) {
guard let fulcroToRemove = self.childNode(withName: "fulcro") else {return}
fulcroToRemove.removeFromParent() // issue here...
let fulcro = SKNode()
fulcro.name = "fulcro"
fulcro.position = CGPoint(x: 300, y: 260)
let line = makeLine(startPos: CGPoint(x: 0, y: 0),
endPos: getCoordinate(angleDeg: getCurrentEGT()),
name: "EGT_LINE")
fulcro.addChild(line)
self.addChild(fulcro)
}
... if I try this SKscene itself in a project only with Spritekit all working fine.. I can see my needle increase the value correctly when the data source increase.
But if use the same SKscene as material of SceneKit getting the following error:
look like I'm removing something not correctly .. and I can see fulcroToRemove.removeFromParent() is the line trigger the error.
But why ??How I can remove the line to avoid the crash?

Sprite Kit Animations and Texture Atlases in Swift 4

Currently working on an application that requires a little bit of animations through an array of images. I've done tons of research online on how to resolve my issue but couldn't run into anything for Swift 4. Below is my code, it shows the first picture in the loop when I run the app but no animation at all. Everything looks fine, I don't see a problem with my code but maybe you guys can help. Appreciate it in advanced!
let atlas = SKTextureAtlas(named: “mypic”)
var TextureArray = [SKTexture]()
var person = SKSpriteNode()
override func didMove(to view: SKView) {
person = SKSpriteNode(imageNamed: "red_1.png")
person.size = CGSize(width: 150, height: 129)
person.position = CGPoint(x: 0, y: 0)
person = SKSpriteNode(imageNamed: atlas.textureNames[0])
for i in 1...atlas.textureNames.count {
let Name = "red_\(i).png"
TextureArray.append(SKTexture(imageNamed: Name))
}
self.addChild(person)
}
override func update(_ currentTime: TimeInterval) {
let myAnimation = SKAction.animate(with: TextureArray, timePerFrame: 0.1)
person.run(SKAction.repeatForever(myAnimation))
}
The animation action is placed in update, which is executed once every frame. So if the game runs at 60 FPS, update gets called 60 times in one second. This means that every second person gets 60 new myAnimation actions that it needs to run.
To fix this, consider placing the animation action somewhere else in your code, e.g. right after adding the person to the scene. Since this is a repeatForever action, the animation will run as you intended until either the action is removed from the node, or the node is removed from the scene.
Hope this helps!

Adding multiple instances of objects spritekit swift 3

I am trying to add multiple instances of my object (bullet) so the player can shoot the bullet and then shoot another bullet. I am using the following code but it is giving me a thread 1 signal sigbart error. Can someone please explain whats wrong with the code? Thanks!
let bulletmove = SKAction.moveTo(y: self.frame.height, duration: 2)
let bulletremove = SKAction.removeFromParent()
addChild(bullett)
bullett.run(SKAction.sequence([bulletmove, bulletremove]))
if you add an SKSprite multiple times it would an error would occur.
What you need to do is create an SKSpritenode to add each time. You can have a function to do create bullets eachtime
func addBullet(){
var bullet = SKSpriteNode(imagenamed: "bullet")
bullet.position = //Give the point of origin as CGPoint. Maybe same as the shooter..
addChild(bullet)
bullet.run(SKAction.moveTo(y: self.frame.height, duration: 2))
}
So each time you call addBullet(),maybe in touches began , you can create new bullet that moves to end of screen without a crash.
So main point is have var bullet = SKSpriteNode(imagenamed: "bullet") for each addChild.

Endless scrolling background

I am trying to get my background to move endless from right to left.
My let:
let background = SKSpriteNode(imageNamed: "background")
let background2 = SKSpriteNode(imageNamed: "background")
my didMoveToView
background.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
background.zPosition = 2
background2.position = CGPointMake(CGRectGetMidX(self.frame)+(background.position.x/2),CGRectGetMidY(self.frame))
background2.zPosition = 2
background.setScale(2)
background2.setScale(2)
self.addChild(background)
self.addChild(background2)
var backgroundMovement = SKAction.moveByX(background.size.width, y: 0, duration: 1)
background.runAction(backgroundMovement, completion: {() -> Void in
self.background.position = CGPointZero
})
var backgroundMovement2 = SKAction.moveByX(background2.size.width, y: 0, duration: 1)
background2.runAction(backgroundMovement2, completion: {() -> Void in
self.background2.position = CGPointZero
})}
My update func is empty.
I have uploaded a picture of how it looks like when running on device: http://s18.postimg.org/kbn83tvmx/i_OS_Simulator_Screen_Shot_09_Aug_2015_23_33_39.png
The image is still on half of the screen, and the image does not move now either.
The reason your background only takes up half of the screen is because you are using the regular size of the image in pixels. You need to edit the xScale and yScale properties in order to make it make it bigger. What you need is:
background.setScale(2)
Next, to move the background sprites, use SKAction instead since you have more control over timing. The motion within update won't be consistant because, unless you have an algorithm to control exactly when update: is called, you will see that the movement speeds up or slows down. To move the background, use code that looks something like this after your didMoveToView method:
var backgroundMovement = SKAction.moveByX(background.size.x, y: 0, duration: someDuration)
background.runAction(background, completion: {() -> Void in
//place background image at start again
background.position = ...
})
Loop this code if you want the background to move continuously and edit it in any way you'd like to make it look better (like having both backgrounds move with SKAction). Hope this helps
I'm going to copy and paste my code from another game I've made. This code moves a background from right-left forever. I'll do best to explain this code.
func createBackground () {
var backgroundTexture = SKTexture(imageNamed: "bg")
var moveBackgroundByX = SKAction.moveByX(-backgroundTexture.size().width, y: 0, duration: backgroundSpeed)
var replaceBackground = SKAction.moveByX(backgroundTexture.size().width, y: 0, duration: 0)
var moveBackgroundForever = SKAction.repeatActionForever(SKAction.sequence([moveBackgroundByX, replaceBackground]))
for var i:CGFloat = 0; i < 3; i++ {
background = SKSpriteNode(texture: backgroundTexture)
background.position = CGPoint(x: backgroundTexture.size().width/2 + (backgroundTexture.size().width * i), y: CGRectGetMidY(self.frame))
background.size.height = self.frame.height
background.runAction(moveBackgroundForever)
movingObjects.addChild(background)
}
}
What you need to do is:
Move background (moveBackgroundByX). This moves the background in the X direction. You need to set a duration.
Replace background1 (replaceBackground).
Create an ACTION forever that moves background1, then replaces it automatically with NO delay.
Run a LOOP that decides how many backgrounds you will need. Maybe you might need more than 3.
Inside that loop, adjust the background.position.
Call runAction on your SKSpriteNode instance.
Add the new SKSpriteNode into your another SKView.
If you have any questions please let me know.

AVPlayer play SKVideoNode video ,I just can not control the playback

I am using the SpriteKit to play video,this is my code to create the SKVideoNode from AVPlayer:
func CreateVideoViewWithAVPlayer(player:AVPlayer)
{
video = SKVideoNode(AVPlayer: player)
let frameLayer=AVPlayerLayer(player: player)
//video?. = CGRectMake(0, 0, 100, 100)
video?.size = CGSize(width: 1024, height: 768)
println(player.currentItem)
video?.anchorPoint = CGPoint(x: 0, y: 0)
video?.position = CGPoint(x: 0, y: 0)
backgroundColor = SKColor.blackColor()
self.addChild(video!)
}
And I create a AVPlayer give the function:
let scene01 = GameScene(size: view.bounds.size)
scene01.CreateVideoViewWithAVPlayer(player!)
But When I call this "player.play()" ,I just show the first frame and not going any more. but if I use the "video" in the "CreateVideoViewWithAVPlayer" function ,It can play.
Another: if I use this code"
skView.presentScene(scene01)
//self.view.addSubview(skView)
(Comments the second) And user "player.play()" it can play (I can hear the sound).
But if I use this:
skView.presentScene(scene01)
self.view.addSubview(skView)
I also can see the first frame.and can not run anymore.
Is there something I do is wrong? Help Me! Thanks A lot.
For no reason. You just can't use AVPlayer to control SKVideoNode's play or pause. but you can control monitor its play state via AVPlayer.
To play or pause a SKVideoNode, you have to use
video.play() / video.pause() // (video you declared here is the instance of SKVideoNode)