1

I've made a simple Screensaver using SWIFT 3 and SpriteKit.

I can get the scene to display but when I try to apply the texture atlas and animate it I get a red X with the animation instead of the actual image.

The debugger has the following error:

2016-12-15 09:35:29.131724 ScreenSaverEngine[1819:52037] Texture Atlas 'Flyers' cannot be found.

I'm stumped -- is it not possible to use texture atlas within SpriteKit that runs within a screensaver?

More details about the project:

  • created a texture atlas using TexturePacker -- confirmed the texture atlas works within iOS test SpriteKit app.
  • using example SWIFT3 code from the TexturePacker site.

UPDATE 12/15/16: Rickster mentioned that the bundle.main of a screensaver/plugin is not my bundle but the host apps bundle. Thus, my issue is I'm trying to load the assets from the screensaverengine.app bundle instead of my own and well, that will give me a "cannot be found".

I believe in Flyer.swift (see code below), I need to reference and load the Flyers.atlasc from my bundle. Anyone know how that syntax needs to look?

From what I gather, I need to reference my app bundle somehow here:

// load texture atlas
let textureAtlas = SKTextureAtlas(named: "Flyers") // << This is trying to find it in the screensaverengine.app bundle and not where it actually lives in my bundle.

Code:

import SpriteKit
import Cocoa

class GameScene: SKScene
{
    let sheet = Flyers()
    var sequence: SKAction?

    override var acceptsFirstResponder: Bool { return false }

    override func didMove(to view: SKView)
    {
        self.resignFirstResponder()
        self.isUserInteractionEnabled=false

        /* Setup your scene here */
        backgroundColor = (NSColor.black)

        // in the first animation CapGuy walks from left to right, in the second one he turns from right to left
        let fly = SKAction.animate(with: sheet.flyer(), timePerFrame: 0.033)

        // to walk over the complete iPad display, we have to repeat the animation
        let flyAnim = SKAction.repeat(fly, count: 6)

        // we define two actions to move the sprite from left to right, and back;
        let moveRight = SKAction.moveTo(x: 900, duration: flyAnim.duration)
        let moveLeft  = SKAction.moveTo(x: 100, duration: flyAnim.duration)

        // as we have only an animation with the CapGuy walking from left to right, we use a 'scale' action
        // to get a mirrored animation.
        let mirrorDirection = SKAction.scaleX(to: -1, y:1, duration:0.0)
        let resetDirection  = SKAction.scaleX(to: 1,  y:1, duration:0.0);

        // Action within a group are executed in parallel:
        let flyAndMoveRight = SKAction.group([resetDirection,  flyAnim, moveRight]);
        let flyAndMoveLeft  = SKAction.group([mirrorDirection, flyAnim, moveLeft]);

        // now we combine the walk+turn actions into a sequence, and repeat it forever
        sequence = SKAction.repeatForever(SKAction.sequence([flyAndMoveRight, flyAndMoveLeft]));

        // each time the user touches the screen, we create a new sprite, set its position, ...
        let sprite = SKSpriteNode(texture: sheet.flyer1())
        sprite.position = CGPoint(x: 100.0, y: CGFloat(arc4random() % 100) + 200.0)

        // ... attach the action with the walk animation, and add it to our scene
        sprite.run(sequence!)
        addChild(sprite)



    }


    override func update(_ currentTime: CFTimeInterval)
    {
        /* Called before each frame is rendered */
        /*self.backgroundColor = NSColor(calibratedHue: 0.0, saturation: 0.0, brightness: CGFloat(0.5 + (sin(currentTime) * 0.5)), alpha: 1.0)*/
    }
}

Here is the Flyers.swift code:

// ---------------------------------------
// Sprite definitions for 'Flyers'
// Generated with TexturePacker 4.3.1
//
// http://www.codeandweb.com/texturepacker
// ---------------------------------------

import SpriteKit


class Flyers {

    // sprite names
    let FLYER1 = "flyer1"
    let FLYER2 = "flyer2"
    let FLYER3 = "flyer3"
    let FLYER4 = "flyer4"
    let TOAST  = "toast"


    // load texture atlas
    let textureAtlas = SKTextureAtlas(named: "Flyers")


    // individual texture objects
    func flyer1() -> SKTexture { return textureAtlas.textureNamed(FLYER1) }
    func flyer2() -> SKTexture { return textureAtlas.textureNamed(FLYER2) }
    func flyer3() -> SKTexture { return textureAtlas.textureNamed(FLYER3) }
    func flyer4() -> SKTexture { return textureAtlas.textureNamed(FLYER4) }
    func toast() -> SKTexture  { return textureAtlas.textureNamed(TOAST) }


    // texture arrays for animations
    func flyer() -> [SKTexture] {
        return [
            flyer1(),
            flyer2(),
            flyer3(),
            flyer4(),
            flyer3(),
            flyer2()
        ]
    }


}

I have a Flyers.atlasc generated by TexturePacker imported into the project as a blue folder.

enter image description here

Mavro
  • 571
  • 8
  • 19
  • Some code definitely needed. Not entirely sure what you're on about in this "to use texture atlas within SpriteKit that lives within a screensave?" question. – Confused Dec 15 '16 at 07:32
  • OK -- I just edited the question with more details and some code... hope that helps. – Mavro Dec 15 '16 at 17:43
  • Where are `sheet` and `sheet.flyer1()` defined and initialized? Most likely you have code that's looking for resources in the "main" bundle — when you're a screensaver or other plugin, `Bundle.main` is *not* "your" bundle, it's the hosting' app's bundle. – rickster Dec 15 '16 at 20:05
  • @rickster I expanded the code portion above to show the GameScene class and Flyers.swift where you can see how/where the sheet it defined. – Mavro Dec 15 '16 at 20:45
  • when you say "within a screensaver", I'm lost. Where is this screensaver coming from? How is it inside SpriteKit? – Confused Dec 15 '16 at 21:38
  • @Confused as rickster mentioned, the screensaverengine.app bundle.main is not my bundle, its the screensaverengine app's bundle... I am trying now to figure out how to make it so the code pulls from my bundle not the screensavernegine.app bundle which obviously my texture atlas doesn't exist in that one. – Mavro Dec 15 '16 at 21:42
  • Could you link to this thing? I have no idea what you're both talking about. – Confused Dec 15 '16 at 21:47
  • @Confused I'm looking at some old obj-c screen saver code I wrote years ago and see that I had to do the following to get access to the bundle resources and I believe I need to do the same here -- but have never used SpriteKit and SWIFT much so this is a bit foreign to me... OLD CODE: thisBundle = [NSBundle bundleForClass:[self class]]; fileName=[[NSString alloc ] initWithFormat:@"flyer%d", flyerNum]; picturePath = [thisBundle pathForResource:fileName ofType:@"png"]; flyerImage= [[NSImage alloc ] initWithContentsOfFile:picturePath]; – Mavro Dec 15 '16 at 21:54
  • argh... ok. I know nothing about that kind of thing. You need someone really knowledgeable and genuinely smart... like @rickster ! File handling and all that inane, fiddly, contrived mess is far beyond my wee little mind. – Confused Dec 15 '16 at 23:36

0 Answers0