Managing SKTextures for animations - sprite-kit

I'm wondering about the best way of managing my textures. In my current project they are all quite small, so it doesn't really matter, but I'm wondering if there is any best practice. I'm also working with the entity/component system (it's an experimental project).
So I have an animation component that I use to store all my animations related to that entity. I created a struct like that:
struct AnimationDefinition {
let animation: [SKTexture]
let timePerFrame: CGFloat
}
And I store animation definitions in a dictionnary property of my component so I can recall them by name later on. That part works really well. For now though, I have only a limited number of entities, but I plan on adding more as development goes on so the way I'm creating the animations might become messy because I'm creating all the textures in the entity's init(). So I'm pretty sure if I reuse that component in another project that uses large textures and more animations, it will slow down everything each time I create an entity.
So I thought about building a TextureManager who will create the textures at the beginning (if it becomes bigger i could make it regenerate itself at the beginning of each level with only the textures that will be used) and feed the arrays at will. Is that a good way to go?
Should I create the animation's SKAction right away and store that instead of the texture array?
Thanks for your opinions?

here are some resources, buried in there are some nuggets pertaining to what you want.
https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/SpriteKit_PG/DesigningGameswithSpriteKit/DesigningGameswithSpriteKit.html
https://developer.apple.com/videos/play/wwdc2014/608/
https://developer.apple.com/library/content/samplecode/DemoBots/Listings/DemoBots_SceneManager_swift.html

Related

What is the difference between storing data in plist vs setting up data in scene editor in Sprite Kit?

It may not appear to be a wise question to ask but I have confusion in mind which I want to clear. In Apple's 2d game framework Sprite kit, normally it is suggested to store data related to nodes in Plist and then retrieve when required in code. What i don't get is while using .sks scene editor you have opportunity to set and store data related to nodes in attributes inspector.Or I am misunderstanding it? What is the difference in both approaches or setting data related to nodes by using .sks scene editor through attribute inspector does not get stored anywhere and only accessible dynamically. I would appreciate if someone can state the clear difference between these two approaches. I have tried to look for it but could not get any help.
I've recently started using the Scene editor for all aspects of my game. Not just the scenes but to create complex SKSPriteNode objects, modular popups, etc. It has mostly been great, and a lot quicker than trying to layout the objects in code.
So if I could keep all of the data in the sks file even better.
Yes, you are correct you can set and store data relevant to the node in the scene editor. It's in the Attributes Inspector under User Data.
You can also store that info in a Plist file. However a big difference between the two methods is that if you store the data in the Plist file you have to then sort through the data and find the relevant data and bind it to the node. When using User Data the data is already bound to the node and goes with it, so you don't have to find it associate it later.
From Apple.
You use this property to store your own data in a node. For example,
you might store game-specific data about each node to use inside your
game logic. This can be a useful alternative to creating your own node
subclasses to hold game data. SpriteKit does not do anything with the
data stored in the node. However, the data is archived when the node
is archived.
Here is an example of how easy it is to access User Data stored from an sks file
if let userData = redVillian.userData {
if let hitPoints = userData.object(forKey: "hitPoints") as? Int {
redVillain.hitPoints = hitPoints
}
if let name = userData.object(forKey: "name") as? String {
redVillian.name = name
}
}
You can also set the User Data in code
redVillian.userData = ["hitPoints": 5, "name" : "Herbert"]
or modify it in code
redVillian.userData?.setValue("Eleanor", forKey: "name")
I think you should go simple on that matter. PLists are perfect to store data that is more general. Like game settings, etc. If you need to store data related directly to a node, then use the node's User Data.
It is important to understand that in a game where you have, let's say, spawning ennemies, you could/should store the information about the different ennemy types in a plist.
When the ennemies are spawned, they will have different attributes that will make them unique even though a bunch of them are of the same type. It could be color, health points, level, etc. If you need that data serialized and saved for later use, it should go in the user data.
Based on what I just said, I don't know, performance wise, if user data is very efficient when it comes to data that changes a lot (like health points, for instance). I feel like in that situation, using a custom class and adding properties to store that data might make things go faster, but in that case, if you need the data serialized, you will have to implement the NSCoding protocol.
Edit
Based on your comments here is some clarification:
If you are only working on your scene in xCode's scene editor, then you might not see the real difference between User Data and using a plist. If you never create sprites by code then it's not obvious.
Why plists?
If you create your characters by code, then it might be interesting to use plists to store the "model information". As you mentionned, the video presentation made by Apple about SpriteKit best practices is talking about storing information such as the anchor, the position, scale and the like in a plist. For example, if you are making a space ship game, you might want to have different spaceship models. They might have very different shapes and because of that you might not want them to rotate around the same point for it to look good. They will also have different textures and different stats (max health points, max shield, etc). In the plist you can then store things like that:
ship model 1
texture: ship1.png
anchor: (0.5, 0.5)
maxhealth: 100
maxshield: 100
...
ship model 2
texture: ship2.png
anchor: (0.2, 0.5)
maxhealth: 150
maxshield: 200
...
...
If you are working with a graphist, it's easy for him to edit a plist without getting involved with xCode. So when his graphics are ready, he can fill in the informations about the texture and the anchor (for example) by himself and let the game designer add the other stats, etc.
Then, if you create a ship in the code, simply retrieve the informations from the plist to create the new ship with all the correct settings.
Over time, the graphist can update the graphics and related info in the plist and you won't even need to recompile to test the new content. You can even use generic pictures (or a solid color when no picture is provided) to develop features before you even get the graphics material.
Why use UserData?
Your spaceships are created and you are fighting for your life. At some point, someome will get hurt and you will need to keep track of it. You could do it easily with variables, but then, it you want to use NSCoder to save your game state, you will have to do it by hand.
If you store specific information about a sprite, then UserData is the key. It's something that is specific to THAT node only. It will also get saved with all the rest when you use NSCoder to save your game state.
This is ponctual data. Health will greatly vary during the course of the game, but when you load your last save, you want the boss you were fighting to be hurt just like it was when you saved. So it's ponctual, but persistent. And it's related only to that node. So it makes sense to store it in the node itself.
Performances
As with anything you might worry about performance. If you have hundreds of sprites all getting hurt and healed non-stop, it might bottleneck if you update the userData all the time. If you ever get to that point, you might consider subclassing from the SKSpriteNode , adding a variable to keep track of the health and such and instead of dealing with the NSCoder stuff directly, simply commit the content of your variables to the userData when you need to save it.

Use one or multiple SKScenes for Level based Game

I'm making a level based game using SpriteKit. I would like to know the best practice for making level changes. I was originally using one Scene as my gameplay scene and when a level is completed, it removes all nodes in the scene and then adds the ones for the next level. I am using a background node that is persistent throughout the entire course of the game. I'm worried about memory because I don't think ARC will deallocate the nodes removed because the scene is persistent. Is this method ok or should I instantiate a new scene for when a level is changing?
The best practice is to separate game data and assets from game code. This way, you can make changes to stuff without having to recompile (and is handy if you are working with another person who doesn't code).
Here is what apple has to say about it at WWDC 2014:
When you transition between scenes, ARC will deallocate the prior scene, assuming you made no strong references to it. Since you're starting out it's unlikely you need to worry about this right now... it's mostly done with globals and closures, and you should be able to fix it if it becomes a problem (but likely won't).
You can use things like unowned self and weak var etc to ensure this doesn't happen when needed. Again this is a more advanced topic but it's good to be aware of them.
Really, making level changes is entirely up to you... if you want to make a state manager that swaps out stuff to one scene, you can certainly do that... or, you could make a bunch of scenes and transition to that. Again, the best practice here is separating game content from game code, not necessarily how you switch scenes.
Personally, I would used separate SKScenes-- because it's already built in with transitions, memory management--and you have the option of using the editor, and you get to give each scene it's own file if desired.
There is also GameplayKit which has a statemanager, in which case you could use one scene and have different states be the level.
here are some resources, buried in there are some nuggets pertaining to what you want.
https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/SpriteKit_PG/DesigningGameswithSpriteKit/DesigningGameswithSpriteKit.html
https://developer.apple.com/videos/play/wwdc2014/608/
https://developer.apple.com/library/content/samplecode/DemoBots/Listings/DemoBots_SceneManager_swift.html

Understanding scenes in Unity3d

I have some confusion with scenes in Unity3d and I was not able to find any resources about them.
When should scenes be used? For example in a platformer would every level have to be a different scene? Would the main menu be a scene?
Can one overlay scenes?
How do assets work between scenes? Are they attached to each individual scene and have to be reloaded every time. Can one specify when an asset is no longer needed?
How does one send data between scenes/interface between scenes?
I understand that this is a broad topic, but I didn't want to spam with multiple questions.
When should scenes be used? For example in a platformer would every
level have to be a different scene? Would the main menu be a scene?
There are no general rules about that. In theory you may have just one scene for the whole game.
How you organize your scenes is entirely up to you and often depends on the type of game you are creating.
I think that there are at least 3 features to be considered of using scenes:
they are a logical container for all pre-instantiated objects that might be useful to divide your game into multiple levels/sections.
You can serialize cross references between GameObjects and Components inside a scene (if GO A needs a ref to GO B, and they belong to the same scene, the reference can be serialized and you no longer need to find the referenced object at runtime)
When you load (not in an additive way) another scene, the resources already loaded into memory are automatically released
Can one overlay scenes?
Yes you can using LoadAdditive. Unfortunately, once 2 scenes are both loaded into memory there is no automatic way of distinguish objects belonging to one or the other. So if you load additive a second level environment, it's up to you to keep track of the previous environment and explicitly destroy it if you need to.
How do assets work between scenes? Are they attached to each
individual scene and have to be reloaded every time. Can one specify
when an asset is no longer needed?
As defaults every GameObject of a scene will be destroyed once the new scene is loaded (unless you use an additive scene loading). A way to make a GameObject survive across scenes is to mark it using DontDestroyOnLoad.
If you need to share a particular "configuration" of a GameObject, you can store it as a prefab, and reference it across scenes (but remember that once in a scene it's a prefab instance, so the GO shares with the prefab the initial serialized and not overriden properties, but 2 instances of the same prefab are different objects).
How does one send data between scenes/interface between scenes?
Several ways, depending on what kind of persistent data you want to share.
For a particular GameObject instance let the object survive using DontDestroyOnLoad.
If you have some configuration data that doesn't need to be attached to a specific GameObject you can consider storing a ScriptableObject inside the AssetDatabase and reference it.
If you have data that must persist across different game sessions you can consider storing them into PlayerPrefs.
There are 2 other ways that I don't like, but just to cite them:
Using a static field can sometimes help you in doing that, but it has several problems from my point of view
Save and load from disk (could be useful in several situations, but often it's a platform dependent way and you can have some trouble especially on different mobile platforms)
This is a broad topic btw, I hope this answer can be a quite decent overview.
When should scenes be used? For example in a platformer would every level have to be a different scene? Would the main menu be a scene?
There is no rule as to how many scenes you need to have in your game. However, scenes allow you to logically separate out parts of your game from the rest of it. You have to have a minimum of one scene.
By main menu, if you are referring to a canvas with your UI elements, it will be IN a scene and not a scene itself. Canvas is just another GameObject, that we mostly happen to use for showing game menus. I mostly create a Canvas GameObject, put a script by the name of "UIManager" and put DontDestroyOnLoad on it, so I have access to it in all scenes. Make it Singleton and I ensure that it is not duplicated.
Can one overlay scenes?
Yes, there is no restriction as to how many scenes you can load at a time. What purpose do you plan to overlay scenes though? Maybe there is a better way than loading additively.
How do assets work between scenes? Are they attached to each individual scene and have to be reloaded every time. Can one specify when an asset is no longer needed?
Assets are what you see in your 'project' hierarchy. I think you meant "GameObject"s in the scene, and if so, think of your gameobjects as entities with components (Entity-Component System). All entities in a scene get destroyed when its parent scene is destroyed until explicitly stated not to, using DontDestroyOnLoad in some component (a monobehavior in case of unity). The destroyed ones will get garbage collected.
So how they are loaded (or reloaded) depends on your implementation, on whether you are instantiating/destroying them time an again or if you put their instantiated prefabs in a cached object and retrieving later from it.
How does one send data between scenes/interface between scenes?
Heisen covered the ones I could think of. Just to add a little bit to it, it also depends on how you want to the architect your project. So if you had an underlying data structure to e.g. hold Commands, you are free to use it in any part of your project
Most games would be organised to have scenes for every level(including the main menu) but that is entirely up to you.
You can use the data from one scene to another if you save it in a text file or binary. There are a lot of tutorials on how to do this. I find documentation helps a lot.
Assets are universal in a project.
You can not overlay scenes.
When should scenes be used? For example in a platformer would every level have to be a different scene? Would the main menu be a scene?
When to use a scene is up to you. If you are just starting I would recommend using a different scene for each section of your game.
Can one overlay scenes?
Yes, using LoadSceneMode.Additive(). (LoadAdditive() is obsolete)
How do assets work between scenes? Are they attached to each individual scene and have to be reloaded every time. Can one specify when an asset is no longer needed?
By default, assets are deleted when using SceneManager.LoadScene(). However, if you use DontDestroyOnLoad(), the object will not be destroyed when entering new scenes. If you want to only keep an object through a few scenes instead of all, use Destroy() with some boolean logic.
How does one send data between scenes/interface between scenes? I understand that this is a broad topic, but I didn't want to spam with multiple questions.
You can send data through scenes by using the aforementioned DontDestroyOnLoad(), referencing the data on different scripts, using ScriptableObjects, using JSON Serialization, using StreamWriter(), using PlayerPrefs (Don't use for important information), the list goes on. I would personally recommend using ScriptableObjects for their accessibility, and StreamWriter() for it's encryption capabilities.

SpriteKit where to load texture atlases for thousands of sprites

In my game I have thousands of "tile" nodes which make up a game map (think simcity), I am wondering what the most frame-rate/memory efficient route for texturing and animating each node would be? There a a handful of unique tile "types" which each have their own texture atlas / animations, so making sure textures are being reused when possible is key.
All my tile nodes are children of a single map node, should the map node handle recognising a tile type and loading the necessary atlas & animations (e.g. by loading texture & atlas names from a plist?)
Alternatively, each tile type is a certain subclass. Would it be better for each SKSpriteNode tile to handle their own sprite atlas loading e.g. [tileInstance texturise]; (how does sprite kit handle this? would this method result in the same texture atlas being loaded into memory for each instance of a certain tile type?)
I have been scrounging the docs for a deeper explanation of atlases and texture reusage but I don't know what the typical procedure is for a scenario like this. Any help would be appreciated, thanks.
Memory first: there won't be any noticeable difference. You have to load the tile's textures, textures will account for at least 99% of the memory of the Map+Tiles and that's that.
Texture reuse: textures are being reused/cached automatically. Two sprites using the same texture will reference the same texture rather than each having its own copy of the texture.
Framerate/Batching: this is all about batching properly. Sprite Kit approaches batching children of a node by rendering them in the order they are added to the children array. As long as the next child node uses the same texture as the previous one, they will all be batched into one draw call. Possibly the worst thing you could do is to add a sprite, a label, a sprite, a label and so on. You'll want to add as many sprites using the same texture in consecutive order as is possible.
Atlas Usage: here's where you can win the most. Commonly developers try to categorize their atlases, which is the wrong way to go about it. Instead of creating one atlas per tile (and its animations), you'll want to create as few texture atlases as possible, each containing as many tiles as possible. On all iOS 7 devices a texture atlas can be 2048x2048 and with the exception of iPhone 4 and iPad 1 all other devices can use textures with up to 4096x4096 pixels.
There are exceptions to this rule, say if you have such a large amount of textures that you can't possibly load them all at once into memory on all devices. In that case use your best judgement to find a good compromise on memory usage vs batching efficiency. For example one solution might be to create one or two texture atlases per each unique scene or rather "scenery" even if that means duplicating some tiles in other texture atlases for another scene. If you have tiles that almost always appear in any scenery it would make sense to put those in a "shared" atlas.
As for subclassing tiles, I'm a strong proponent to avoid subclassing node classes. Especially if the main reason to subclass them is to merely change which texture they are using/animating. A sprite already is a container of a texture, so you can as well change the sprite texture and animate it from the outside.
To add data or additional code to a node you can peruse its userData property by creating your own NSMutableDictionary and adding any object you need to it. A typical component-based approach would go like this:
SKSpriteNode* sprite = [SKSpriteNode spriteWithWhatever..];
[self addChild:sprite];
// create the controller object
sprite.userData = [NSMutableDictionary dictionary];
MyTileController* controller = [MyTileController controllerWithSprite:sprite];
[sprite.userData setObject: forKey:#"controller"];
This controller object then performs any custom code needed for your tiles. It could be animating the tile and whatever else. The only important bit is to make the reference to the owning node (here: sprite) a weak reference:
#interface MySpriteController
#property (weak) sprite; // weak is important to avoid retain cycle!
#end
Because the sprite retains the dictionary. The dictionary retains the controller. If the controller would retain the sprite, the sprite couldn't deallocate because there would still be a retaining reference to it - hence it will continue to retain the dictionary which retains the controller which retains the sprite.
The advantages of using a component-based approach (also favored by and implemented in Kobold Kit):
If properly engineered, works with any or multiple nodes. If what if some day you want a label, effect, shape node tile?
You don't need a subclass for every tile. Some tiles may be simple static sprites. So use simple static SKSpriteNode for those.
It lets you start/stop or add/remove individual aspects as needed. Even on tiles you didn't initially expect to have or need a certain aspect.
Components allow you to build a repertoire of functionality you're going to need often and possibly even in other projects.
Components make for better architecture. A classical OOP design mistake is to have Player and Enemy classes, then realize both need to be able to shoot arrows and equip armor. So you move the code to the root GameObject class, making the code available to all subclasses. With components you simply have an equipment and a shooting component add to those objects that need it.
The great benefit of component-based design is that you start developing individual aspects separately from other things, so they can be reused and added as needed. You'll almost naturally write better code because you approach things with a different mindset.
And from my own experience, once you modularize a game into components you get far fewer bugs and they're easier to solve because you don't have to look at or consider other component's code - unless used by a component but even then when one component triggers another you have a clear boundary, ie is the passed value still correct when the other component takes over? If not, the bug must be in the first component.
This is a good introduction on component-based design. The hybrid approach is certainly the way to go. Here are more resources on component based design but I strongly advice against straying from the path and looking into FRP as the "accepted answer's author" suggests - FRP is an interesting concept but has no real world application (yet) in game development.

RPG Game loop and class structure (cocos2D for iPhone)

I'm looking to make an RPG with Cocos2D on the iPhone. I've done a fair bit of research, and I really like the model Cocos2D uses for scenes. I can instantiate a scene, set up my characters etc. and it all works really nicely... what I have problems with is structuring a game loop and separating the code from the scenes.
For example, where do I put my code that will maintain the state of the game across multiple scenes? and do I put the code for events that get fired in a scene in that scene's class? or do I have some other class that separates the init code from the logic?
Also, I've read a lot of tutorials that mention changing scenes, but I've read none that talk about updating a scene - taking input from the user and updating the display based on that. Does that happen in the scene object, or in a separate display engine type class.
Thanks in advance!
It sounds like you might do well to read up on the Model-View-Controller pattern. You don't have to adhere slavishly to it (for example, in some contexts it makes sense to allow some overlap between Model and View), but having a good understanding of it will help you to build any program that has lots of graphical objects and logic controlling them, and the need to broadcast state or persist it to disc (game save), etc.
You also have to realize that cocos2d provides a good system for structuring the graphical scene graph and rendering it efficiently, but it doesn't provide a complete infrastructure for programming games. In that sense it's more of a graphics engine than a game engine. If you try to fit your game's architecture into the structure of cocos2d, you might not end up with the most maintainable result. Instead, you should treat cocos2d as what it is: a great tool to take care of your display and animation needs.
You should definitely have an object other than the scenes that maintain the game state, because otherwise where will all the state go when you switch between scenes? And within scenes/levels, you should simply try to use good Object Oriented design to have state distributed over objects of various classes. Each character object remembers its own state etc. Here you can see where MVC becomes useful: when you save the game to disc, you want to remember each character's health level, but probably not which exact frame index the sprite animation was showing. So you need to distinguish between the sprite and the character (model) itself. That said, as I mentioned before, for game objects that don't have a lot of logic attached to them, or which don't need to be saved, it might be ok to just fuse the Model and View together into one class (basically by subclassing CCSprite).
To pull off MVC the way it's supposed to be, you should also learn the basics of Key-Value Observing. (And you'd do well to use this replacement for Apple's interface.) In more intensely real-time games, techniques like this might be too slow, but since you're making a RPG (good choice for starting out) you could probably sacrifice performance for a more maintainable architecture.
The game scene (which is just another cocos2d sprite) plays the role of Controller, in terms of the MVC pattern. It doesn't draw anything itself, but tells everything else to draw itself based on inputs and state. It's tempting to put all kinds of logic and functionality into the game scene, but when you notice that it swells, you should ask yourself how you could separate that functionality into other classes. Analyze which type of functionality you're implementing. Is it to do with data and state (Model)? Or is it about animation and rendering (View)? Or is it about connecting logic with rendering (in which case you should try to make the View observe the Model directly)?
The game scene/Controller is basically a dispatch center, which takes input events (from the user or from sprites reporting that they've hit something, for example) and decides what to do with them: it might tell one or several of the Model objects to update themselves in some way, or it might just trigger an animation in some other sprites, for example.
In a real-time game, you'd have a "tick" or "step" method in the scene which tells all objects to update themselves. This method (the game loop) is the heart of the program and is run every time a new frame is drawn. (In modern game engines there's a lot of multi-threading but let's not think about that.) But in your case, you might want to create a module that can "play the game" completely separate from the game scene. Imagine creating a program that can play chess through the terminal, using only text input. If you create the whole game system in that manner, and then connect it to the graphics engine through a small and clean interface, you'll have a really maintainable app with lots of reusable code for future projects!
Some good rules of thumb: the model (data) shouldn't know anything about sprites or display states; the view (sprites) shouldn't contain any of the game's actual logic (the game rules) but only know how to do simple things like moving and bouncing and reporting to the scene if something complicated happens. Whenever possible, the view should react to changes in the model directly, without the controller having to interfere.