1

Despite reading through much of Apple's docs and reading through their forums and watching their WWDC videos, I seem to have missed the steps required to utilise the texture packing and performance of Sprite Kit for making many large-ish Sprites.

Imagine 100 different sprite images, for 100 different sprites. If each image is 256x256 pixels, they're going to take up more than one SpriteSheet at 2048x2048. And let's imagine that's the limit, rather than 4096x4096, just so it's understood that more than one spritesheet is going to be required.

There might be as many as 20 different sprites on screen at any given time. So performance is a consideration.

How to import these images and then create these sprites in the manner SpriteKit intends for its texture packing and performance considerations of in game use?

Just a specific link to Apple recommended absolute steps will be fine. I must have just skimmed right over it.

Apple's new docs go this far:

enter image description here

Which completely fails to convey:

  1. Import folder, or images?
  2. Import to WHERE within the project?
  3. Load and reference them, how?
Confused
  • 6,048
  • 6
  • 34
  • 75
  • Have you used TexturePacker (https://www.codeandweb.com/texturepacker)? What are the distinction between the sprites? for example are they all one character? All disparate items? – Mobile Ben Oct 05 '16 at 18:41
  • No. I want to do it exactly the way Apple is suggesting SpriteKit prefers it to be done. – Confused Oct 05 '16 at 18:41
  • @MobileBen all disparate items. Not same character, not animations. – Confused Oct 05 '16 at 18:42
  • @MobileBen over the years I've seen many comments in the Apple forums suggesting different ways to do it, and talking about various bugs. I've only recently started using SpriteKit due to the many bugs its apparently had in the past. I want to know the right way to use it, as per their ideals and intentions, but am having trouble finding their documentation for the processes of importing many images for this sort of use. Much of their discussions are about animated sprites with exhaustive amounts of animation. Not this particularly diverse approach with lots of different sprites. – Confused Oct 05 '16 at 18:45
  • I can try and answer this a little bit later, however I cannot vouch that it is the "SpriteKit/Apple way". I typically deal with a lot of assets. My scenes are easily in the hundreds of objects, with textures of differing sizes. I did get this working with SpriteKit in rev 1 of the engine, but I have since been in the process of rewriting the engine to stop using SK because I find the SDK cumbersome/slow/buggy for what I do. The method, however should work regardless of the underlying implementation (which some mods). – Mobile Ben Oct 05 '16 at 18:50
  • THANK YOU!!! I'm much more slowly reading through the docs, for what they are. Saddened to hear SK is still buggy and slow. I'm here, at this point in the docs "Creating a Texture Atlas: Xcode can automatically build texture atlases for you from a collection of images. The process is described in detail in Texture Atlas Help"... where there is no link to the imaginary "Texture Atlas Help" section... – Confused Oct 05 '16 at 18:52
  • Btw SK is certainly fine for most people. So you shouldn't be overly worried by my statements. For the types of games I build it doesn't work well. I tried to build a game using it and in the end was forced to rewrite. I'd say I am perhaps an exception in this case due to my needs. – Mobile Ben Oct 05 '16 at 19:17
  • I hope so. I'm less than most people, so should qualify ;) – Confused Oct 05 '16 at 19:27
  • 1
    Do you experiencing actual performance issues or you are doing premature optimization here? ;) The thing is that if you organize your textures into atlas, in most cases SpriteKit will do the rest and it will be performant. You can test what is optimal for you though, one big atlas, or few smaller. If you use big atlas, then you will end up with small number of draw calls, but you will have big memory impact, and vice versa. Comments are short for talking more, but you can read this answer because it based on some serious testing :) http://stackoverflow.com/a/37119708/3402095 – Whirlwind Oct 05 '16 at 20:44
  • That's a great link, but I'm miles behind that. I'm at the early stages of ... How do I organise into atlases? How do I import them so that they're organised into atlases? How do I then reference/load them so that I'm getting the benefits of these atlases? – Confused Oct 05 '16 at 20:48
  • 1
    @Confused Also following some basic rules / techniques like pooling - creating a pool of sprites once, then reuse them will help with performance. Also, there are catches like this that should be kept in mind : http://stackoverflow.com/a/30448038/3402095 – Whirlwind Oct 05 '16 at 20:48
  • Another wonderful link, thank you! – Confused Oct 05 '16 at 20:49
  • added an image from the apple docs that leaves me with only questions... @Whirlwind – Confused Oct 05 '16 at 20:51
  • @Confused There are two (or even more) ways you can create texture atlases. One would be like from the picture. You create .atlas folder, put images in it and add it to the project by simple dragging or using File->... command. The other way, is a new way and I have partially described it here : http://stackoverflow.com/a/35410364/3402095 It is a simple thing really. Just search SO, there are many examples about how to create/use atlases... if you are still stuck (or having performance issues), let me know. – Whirlwind Oct 05 '16 at 21:17
  • I'm specifically looking for the way that's best from the point of view of Apple and their take on how they optimised/intend SpriteKit to be used. – Confused Oct 05 '16 at 21:23
  • But then there's loading textures, into Sprites, correctly, again, as per Apple's thoughts on this, with regards SK. I'm kind of baffled I can't find their "best practices" for this in SK. I think I suck at reading. – Confused Oct 05 '16 at 21:24
  • The texture atlas creation works pretty magically for me in SpriteKit, but I wanted to know more about how and when the atlas images (sprite sheets) are generated. If you're curious, here are a couple details: 1) You can see the atlases being compiled in the "Compile Texture Atlases" step of your build (select your target in Xcode and then "Build Phases"); 2) The script that does the compiling is called TextureAtlas and can be run from the command line (no args to get a usage message). On my machine it's located in (/Applications/Xcode.app/Contents/Developer/usr/bin/TextureAtlas. – Karl Voskuil Oct 06 '16 at 14:08
  • I agree. It's exactly like magic. Unknown things happen, and then boom, a result. At this point I'm dumping a folder (with drag-n-drop) into Xcode, never certain if I'm dragging it to the right spot (of many possible tree levels) and then hoping it works. It seems to be working, but beyond that, it's magic! – Confused Oct 06 '16 at 14:20
  • As to running things from a command line, with all due respect, I have never understood any fascination or interest in this aspect of doing something in a GUI environment. To my way of thinking, if something needs a command line, post 1986, then something is very wrong with the design and implementation. – Confused Oct 06 '16 at 14:22
  • Which is not to say @KarlVoskuil, that your help isn't greatly appreciated. That a script, somewhere, somehow related to Xcode, is doing something with images, is very intriguing and revealing. I'm further appalled at Apple's inability to articulate how best to do things in their own tools for their own platform. – Confused Oct 06 '16 at 14:23
  • Texture atlas creation isn't really magic. The "rule" seems to be that any Folder Reference (blue) with the .atlas extension will be treated as a texture atlas. This would mean any image file is a sub-texture in the atlas. It's an arbitrary rule, but when you're the maker of the IDE, you can choose the rules :). – Mobile Ben Oct 06 '16 at 22:04
  • I chuckled deeply at the cheeky smile at the end. He who has the gold... – Confused Oct 06 '16 at 22:06
  • Also, don't underestimate the power/need of command line. Every game I've worked on has used command line. Even tools which had GUI interfaces for level layout where all backed by ... wait for it ... command line tools. Event TextureAtlas is an example. It's not a symptom of bad design. Food for thought. Apple's agenda is to lower the skill level needed to make a game and to lock your code to their platform. As such, they need tools that will be accessible to most. Their tools are sufficient in the minimal sense. – Mobile Ben Oct 06 '16 at 22:08
  • There's a taint that scares me. Whenever using something badly designed, I feel that if I don't complain (loudly) and pointlessly, some of the bad design might rub off on me, and become tolerable. The fear is this will make me less critical in my own design endeavours. And it's criticism of self and one's own production efforts that makes a good designer, I think. Not sure that's applicable or understandable to programmers, they seem to take whatever's given to them... including Android ;) – Confused Oct 06 '16 at 22:10
  • Most people choose to use Apple's tools like the scene editor, texture atlas gen, because it's there. It must work right? But for everything? They are giving you a hammer. It's your choice if every problem looks like a nail. Command line tools and other tools provide you freedom in creating newer data abstraction and also not necessarily being tied to the platform. – Mobile Ben Oct 06 '16 at 22:10
  • Lol, "they seem to take whatever's given to them". Or they make their own solutions if necessary ;) – Mobile Ben Oct 06 '16 at 22:11
  • Reinventing the wheel seems to be, unfortunately, one of the habits of programmers. Odd for a community scared of bike shedding ;) – Confused Oct 06 '16 at 22:12
  • Ahh, the cynic in you. The question one should ask is whether it's NIH or a genuine need. For example, I don't use Apple's TextureAtlas tool, but is that re-inventing the wheel? Perhaps. But there is other meta I need with my texture(eg. data I have to pass along to the renderer). I cannot get that from the Apple tools. Say I wanted to use their tool. Now I'm forced to encode that data out of band and find another way to load it. So is the re-inventing the wheel? Or recognizing I need a screwdriver? Building more product helps one discern whether you're being NIH or not. And even still .... ;) – Mobile Ben Oct 06 '16 at 22:18
  • Yes... and then there's the matter of coding speed and performance, stability and maintainability of your code. It might be that you can make it so fast it's quicker than searching for alternatives or adapting what's there. And your code might well be good enough to exceed expectations in other areas. I'm constrained by a coding speed of a about 1 line per day. – Confused Oct 06 '16 at 22:23
  • Now, for instance, I have to go learn whether I should do logic in the GameScene for touchesBegun on all sprites, or make a touchesbegun within each sprite, and shelve a little logic out to each of them to deal with when/if they're touched. – Confused Oct 06 '16 at 22:25
  • And, of course, there's nowhere that even begins to discuss this kind of design thinking because it's not something that coders seem to talk about. They seem to do both, or arbitrarily pick one, or have a residual of wisdom that permits them to make a wise choice. All 2 types of people that shouldn't communicate about this, they do. The wise ones don't seem to write or publish their thinking. – Confused Oct 06 '16 at 22:26
  • Eventually you'll hit 2 lines a day. I'd say don't worry fully about the "right way". I realize some will have my head for saying that. But I think learning through trial and error is part of learning to get better at any skill. Once you're done, you can always then look back and determine was your technique "correct" (there are many ways to solve the problems). Most beginners aren't making large projects. Although I'm sure at the time they seem large. That's the perfect time for trial and error. – Mobile Ben Oct 06 '16 at 23:05
  • This idea that "trial and error" is a normal way to learn something with paradigms and processes is unique to coding. Just about every other serious form of endeavour builds from diverse arrays of orthodoxy and collective wisdom, and prides itself in how it collates and presents it for newcomers. SO is about the best programming has, and it's NOTHING like that. – Confused Oct 06 '16 at 23:10
  • Actually, there are a lot of other things where trial and error works. Sports. Even things like medicine, although we don't like to think it is the case. Most trades have a collective wisdom available. However, many times when learning people don't always follow/read/learn the collective wisdom ... and hence trial and error can be a means to better understanding. – Mobile Ben Oct 06 '16 at 23:26
  • Can be? Yes. Is part of learning? Yes. Predominant in any other activity? No. But in programming it's (through a cultural phenomenon) the predominant way. Sport's best players do massive previsualisation and restrict the potential of trial through error maniacally. The more complex and/or dangerous the sport, the more previsualisation and learning is done. Injury to recovery is a finite loop. The NFL provides better training than the military of most countries. Every movement is scientifically previsualised and performed. All with a degree of discipline that's awe inspiring, at the very least. – Confused Oct 06 '16 at 23:37
  • Pre-visualized? Yes, but you'll notice the importance of physical reps for players like QB. These reps are "trial and error" to help build muscle memory, processing of the speed of the game, variations, etc. Perhaps trial and error is a poor term. Iteration? Take a player that reads the playbook (collective wisdom) but doesn't get the reps (trial and error). They typically have issues executing. Same goes for getting the reps but not reading the playbook. The players that transcend are the ones that work their craft and learn the relationship between the reps and the wisdom. – Mobile Ben Oct 07 '16 at 00:28
  • Reps have little to do with trial and error, nor iterative development. The goal is absolute. Reps are about refinement of highly described, nuanced and absolutely previsualised (by a coach) activities. Somebody already knows exactly how to do them, and how they want them done, and where everyone should be. Improving football playing ability and programming have few parallels, this aint one. Refinement of a subset of footballing activity to external criteria (a perfectly articulated desire for pre-existing, preconceived and previsualised performances) certainly isn't one of them. – Confused Oct 07 '16 at 00:36
  • But you're completely missing the point. You're looking for a way to justify trial-and-error being the dominant means of learning programming. As I've said, trial and error being part of programming culture is a result of a problem in programming's culture, not an ideal way to teach, learn or create community. It is, in fact, not teaching, the slowest form of learning and does not create community. These guys doing play-pass reps are being subject to a type of teaching and discipline that simply doesn't exist in programming, and has nothing to do with trial and error, nor iteration. – Confused Oct 07 '16 at 00:44
  • how do we take this to a chat, before someone(s) (other than us) lose their minds? – Confused Oct 07 '16 at 00:46
  • You're conflating ideas. I'm not trying to justify T/E being what you say is the dominate means of learning programming. I'm just merely pointing out that T/E, iteration, reps, are all similar. Humans make mistakes and need a way to assimilate goals, actions, or what have you into reproducible results. Some people are better at doing this naturally, other need reps or whatever you want to call it. Whether or not a goal is in mind, if your rep doesn't end up with the result, what is it? How do you correct it? You get "feedback". How do you see if you've corrected it? You try to do it again. – Mobile Ben Oct 07 '16 at 00:52
  • Your (very good) description of an iterative feedback loop perfectly describes why trial and error isn't teaching, is the slowest form of learning (for everyone) and doesn't build community from which further acceleration of learning and development can stem. – Confused Oct 07 '16 at 01:21

1 Answers1

2

So let me see if I can reasonably answer your question. Please keep in mind that while I have used SpriteKit, I'm not a big fan of it. And when I did use it, I did not use any of the tools Apple provided (eg. SKTextureAtlas, sks files, etc). Nevertheless, this should still be applicable. Best practices as per Apple? I have no idea.

Question: Import folder, or images?

If you use Xcode's means of generating atlases, you Add Files... to your project a folder named XYZ.atlas, where XYZ will be the texture name. This folder contains all of your textures which will be in the atlas.

Question: Import to WHERE within the project?

Just has to be in your project. But you should have some organization Group hierarchy in your project file.

Question: Load and reference them, how?

An example of loading would be something like (yeah, I know boo, Obj-C):

self.myTextureAtlas = [SKTextureAtlas atlasNamed:@"MyTexture"];

Inevitably, you will want access to the actual textures and you'll need to do something like:

self.tex0 = [self.myTextureAtlas textureNamed:@"tex0"];

A good tutorial is here: https://www.raywenderlich.com/45152/sprite-kit-tutorial-animations-and-texture-atlases

Here is also a screenshot that shows the .atlas folder. It also shows a couple of tool generated atlas files.

enter image description here

So here you can see I have 2 Groups which are references to folder MyTexture.atlas and ProgressBar.atlas. In game, they will be called MyTexture and ProgressBar.

I have also included, just as an example the same atlases, but pre-built. You would not have both in your project, I only used it to show what including a pre-built would loo like. I generated them using TexturePacker. I'll get into why this may be a better option later on. TexturePacker also can create SpriteKit atlases instead of the atlas PNG.

In reality, an atlas is really just a texture with sub-textures are associated with it. The sub-textures are X/Y/W/H sections of the texture. The actual memory for the texture is "held" by the atlas. Understanding what an atlas is is a useful thing, because it allows you to think through how you would support it if you had to implement it yourself. Or enhance it.

Now let's go over how you would use this altogether to do something useful.And for this you're going to need a texture manager (aka TextureManager), sprite manager (aka SpriteManager) and a manifest of some sort.

The manifest is really some form of association between "sprite name" to atlas:sub texture pair. For example:

 {
  "progressbar": {
    "atlas": "ProgressBar",
    "subtexture": progressbarbacking"
  },
  "progressbarfillr": {
    "atlas": "ProgressBar",
    "subtexture": progressbarfillr"
  }
}

In this case it is some JSON, but you can have whatever format you want. When I build my games, I have a build assets phase which generates all my textures and from that, builds a manifest. This manifest tells me not only what textures exist, but is used later on to find the correct association of a "sprite name" to the actual atlas and sub texture. "sprite name" is just some name you have associated meaning. It could be "zombie" for example.

You use a TextureManager as your asynchronous loader. In addition, it is your inventory manager of all your textures. As an inventory manager, it will prevent you from double loading textures and also give you the correct reference to textures/atlases when requested (if they exist).

You would use the SpriteManager to create a new SKSpriteNode using the data from the manifest. For example:

SKSpriteNode *progressBar = [[SpriteManager sharedInstance] createSprite:@"progressbar"];

Here I've made it a singleton. Use whatever implementation you want. If you hate singletons, that is fine, this is just an example. You'll note that it returns a SKSpriteNode. I see a lot of people making subclasses from SKSpriteNodes. I never do this. To me, the graphic component is always a "has a". However, if you are doing an "is a", you can still do this. You just need to feed in the class you need. I'm considering the way of handling that out of scope for this question.

Now if you look at the manifest, you'll notice that progressbar is associated with an atlas named ProgressBar and a sub texture named progressbarbacking. To get the texture you need, you'd have some implementation code in SpriteManager like:

// NOTE the literal names would be variables which contained the unpacked association from progressbar
// literal strings are used to make the idea easier to follow
SKTextureAtlas *atlas = [[TextureMaanger sharedInstance] findAtlasNamed:@"ProgressBar"];
//Error check of course

SKTexture *tex = [atlas textureNamed:@"progressbarbacking"];
// Error check of course

SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithTexture:tex];

Or perhaps you would just have a call:

SKTexture *tex = [[TextureManager] sharedInstance] texNamed:@"progressbarbacking" atlas:@"ProgressBar"];
SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithTexture:tex];

And there you have it. A means to get sprites from atlases.

Best practices as per Apple? Dunno, but it is along the lines of what I do.

Some people will complain that there will be dictionaries involved and some of this will be "slow". And yes, there is a penalty for this. And reality, I don't use a dictionary for this either, but it is easier to get the idea across as the dictionary. Also keep in mind that I consider the usage of this to occur during loading phases and very little during game play, if at all. One of the tricks to performant games is pre-loading all or as much of the data you need prior to actual game play.

Oh, going to why I pre-build the atlases. So part of your question was organization of textures to atlas. And that is why. I like to see the generated atlas and understand what the size is and what is in it. Additionally it makes downloadable atlases easier.

As an optimization, you would want to try and put textures in which are all drawn relatively the same time. For example, it would make sense to have all HUD items in the same atlas versus mixing HUD with background.

Mobile Ben
  • 7,121
  • 1
  • 27
  • 43
  • A tiny portion of this I was slowly realising on my own... see my updates here: http://stackoverflow.com/questions/39811334/folder-of-images-create-and-fill-skshapenodes-1-of-each, but the rest is just absolutely fantastic, and I look forward to immediately refuelling on caffeine to grok and gain from your wonderful writing and intense insights. And your humour, sprinkled with disdain and criticisms of Sprite Kit (and Apple) are a breath of fresh air in a world full of yes-men and people seemingly afraid to objectively analyse anything from Apple. – Confused Oct 06 '16 at 03:20
  • Not a problem and let me know what is not clear. I made an earnest attempt to use SpriteKit. However I kept hitting issues like the lack of skew, the need for vertex shaders, performance, etc. Hence abandoning it. You've no doubt read other issues people have had. You should also have a healthy skepticism for what I've presented. After doing a few games you'll get a better understanding of what works and does not work for you. This is a bit of why I was mentioning in that other thread getting done. There is an experience one gains from completion, because all the ideas start "gel". – Mobile Ben Oct 06 '16 at 03:47
  • Yeah, I've read a LOT about SpriteKit over the years, and avoided it for a long time because of the many negative reviews of its many bugs and issues. Fortunately I'm not a programmer, so there's little chance I'll be pushing it hard. – Confused Oct 06 '16 at 03:50
  • Unfortunately that means I may well come back with some VERY stupid questions! – Confused Oct 06 '16 at 03:51
  • Lol, well you really can't say you're not a programmer as you seem to be programming a game. It's a learned skill. Iteration, asking questions, failing ... all part of the process. Everyone goes through it. – Mobile Ben Oct 06 '16 at 03:55
  • I'm a designer. Normally I work with programmers. Now I'm trying to work with me, myself and I. We're arguing. – Confused Oct 06 '16 at 04:03
  • More coffee .. or beer. That will take care of the arguments (or make it worse). – Mobile Ben Oct 06 '16 at 04:18