cocos2d load random image from sprite sheet - ios

Ok so I am conceptualizing for a game I want to make and have played a little bit but ran in to a problem. I am learning iOS programming and learning cocos2d also.
I have about 20 images. They are all the same size 64x64. Basically they are grouped as 5 different shapes (square, circle, etc.) each in 5 different colors. What I want to be able to do, is randomly drop them down the screen in portrait. There will only ever be one per column falling. There can be duplicates across the screen, I actually want that. While it is random, I want to control the introduction of a new color.
I have been really racking my brain to figure out how to do this. As I said, I am pretty new to this so any help would be really great.
If I could be so bold, can any answers be in a format to "Explain it like I'm 5 I have only been doing this for about 1 year"

First, have a look at this tutorial about sprites sheets: it will show you how to create your sprite sheets and load them into memory.
(Since the tutorial aims at building an animation, you can skip points 4 and 5).
Now, if you have your sprite sheets in place, what you do to create a sprite is:
CCSprite* sprite = [CCSprite spriteWithSpriteFrameName:#"frameName.png"];
and then you can add it to your layer/scene.
About the random selection: you can keep a list of image names (say, an NSArray) and then randomly (i.e., use srand to generate a random index) select the #"frameName.png" value from it.

When using Cocos2D the best way to use sprites is with Sprite Sheets. That is, a combination of two type of files:
A plist file with all the coordinates of N sprites and all different data about the sprites, size, name, etc.
A png file with all the sprites
You can make a sprite sheet with different types of software, like:
Zwoptex
Sprite Helper
Sprite Packer
Sprite Master
Texture Packer
About performance, when using a sprite sheet you will need to use CCSpriteBatchNode, as the API documentation states (read here):
A CCSpriteBatchNode can reference one and only one texture (one image file, one texture atlas). Only the CCSprites that are contained in that texture can be added to the CCSpriteBatchNode. All CCSprites added to a CCSpriteBatchNode are drawn in one OpenGL ES draw call. If the CCSprites are not added to a CCSpriteBatchNode then an OpenGL ES draw call will be needed for each one, which is less efficient.
THe code to use Sprite Sheet:
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"sprite.plist"];
CCSpriteBatchNode *spriteSheet = [CCSpriteBatchNode batchNodeWithFile:#"sprite.png"];
[self addChild:spriteSheet];
Hope this helps.

Related

iOS: Can I use Texture Atlas already created with Adobe Animate?

I know that I can add sequences of individual images in Xcode, and let it create the Texture Atlas. This process is well-described in easily-searched venues. (Like this one.)
I am getting atlases from designers, created with Adobe Animate (v18.0) already combined into the full sheet, and moreover with the accompanying XML file describing the animation. (In which sub-images and display frames do not match 1:1, so it's hard to see how Xcode would figure that out.)
It's not clear to me from the SpriteKit docs whether/how to use these pre-defined Texture Atlases. Is this possible?
If you're getting pre-baked texture atlases, with externally-generated descriptions of where the sprites should get their textures, you'll probably have to create your sprites using SKTextures that you create using the init(rect:in:) initializer of a SKTexture.
You'll need to read the sprite's extents out of the XML file, and then create a texture out of the atlas. Then you can create a new SKTexture object that represents a part of the larger texture to act as your sprite's texture.
This is untested pseudocode, but it shows the process:
let spriteRect = (get the rect from the XML)
let atlas = SKTexture( imageNamed: "myTextureAtlas" )
let spriteTexture = SKTexture( rect:spriteRect, in:atlas )
let sprite = SKSpriteNode( texture:spriteTexture )
Once you have this process in place, you can animate the sprites using the usual methods, like setting up SKActions with a list of textures out of the texture atlas.

How to Render Many SpriteKit Nodes at Once?

I am using SpriteKit to render a large (20 x 20) dot grid that looks like this:
I'd like to highlight rows or columns based on user input. For example, I'd like to change rows 1-10 to a red color, or columns 5-15 to a blue color.
What is the most performant way to do this?
I've tried:
Naming each GridNode based on the column it's in (e.g. #"column-4). Then use enumerateChildNodesWithName: with the string as #"column-n", changing the color of each node (by changing SKShapeNode setFillColor:) in the enumerate block.
Giving all the columns a parent node associated with that column. Then telling the parent node to change its alpha (thus changing the alpha of all its children).
Making arrays for the different columns, then looping through each node and changing its color or alpha.
I've tried making the GridDot class an SKEffectNode with shouldRasterize: set to YES. I've tried both an SKShapeNode and a SKSpriteNode as its child. I've also tried taking away the SKEffectNode parent and just render an SKSpriteNode.
Each of these options makes my whole app lag and makes my framerate drop to ~10 FPS. What is the correct way to change the color/alpha of many nodes (without dropping frames)?
At its heart, the issue is rendering this many nodes, yes?
When I faced similar performance problems while using SKShapeNode I came up with this solution:
Create SKShapeNode with required path and color.
Use SKView's method textureFromNode:crop: to convert SKShapeNode to an SKTexture
Repeat steps 1,2 to create all required textures for a node.
Create SKSpriteNode from a texture
Use created SKSpriteNode in your scene instead of SKShapeNode
Change node's texture when needed using SKSpriteNode's texture property
If you have a limited set of collors for your dots, I think this aproach will fit fine for your task.
In contrast to #amobi's statement, 400 nodes is not a lot. For instance, I have a scene with ~400 nodes and a render time of 9.8ms and 9 draw calls.
If you have 400 draw calls though, you should try to reduce that number. To determine the amount of draw calls needed for each frame rendered, implement (some of) the following code. It is actually taken from my own SpriteKit app's ViewController class which contains the SpriteKit scene.
skView.showsFPS = YES;
skView.showsNodeCount = YES;
skView.showsDrawCount = YES;
Proposed solution
I recommend using SKView's ignoresSiblingOrder. This way, SKSpriteNodes with equal zPosition are drawn in one draw call, which (for as many nodes/draw you appear to have) is horribly efficient. Set this in the -viewDidLoad method of the SKView's ViewController.
skView.ignoresSiblingOrder = YES;
I see no reason to burden the GPU with SKEffectNodes in this scenario. They are usually a great way to tank your frame rate.
Final thoughts
Basic performance issues mean you have a CPU or a GPU bottleneck. It is difficult to guess which you're suffering from with the current information. You could launch the Profiler, but Xcode itself also provides valuable information when you are running your app in an attached device. FPS in the Simulator is not representative for device performance.

Create a level terrain similar to Tiny Wings using SpriteKit

I would like to create a textured terrain in SpriteKit similar to the one in the game Tiny Wings. Using cocos2d, I was able to follow Ray W's tutorial and get the look I wanted...
http://www.raywenderlich.com/32954/how-to-create-a-game-like-tiny-wings-with-cocos2d-2-x-part-1
Is plotting points to make triangles to fill with a repeating texture (or something similar) possible using SpriteKit?
Thanks in advance.
yeah you can create a game like tiny wing with sprite kit
step create serval CGMutablePath using http://dazchong.com/spritekit/ tool its a online SKPhysicsBody Path Generator and save them in a NSMutableArray array suppose you have only one level in your game for multiple level create multiple NSMutableArray array with multiple random saved CGMutablePath items
be sure all CGMutablePath have static physics body don't make it dynamic now
inside your init function add all paths one by one in a order that first path ends start of second path and so on make by this you can make a huge loop of serval path which are connecting with each other.
don't make more paths because too many physics body makes your game slow
now inside update function move all item of your array from right to left be sure
when you reach last item of your NSMutableArray array add it again at the begging of your looping algo.
-(void)update:(CFTimeInterval)currentTime {
}
make a tiny bird and give it a dynamic physics body
set collision and contact category of tiny bird as well as your loop paths
now inside didBeginContact function you can get contact between your tiny bird and path .now you can apply a little Impulse or you can get contact.collisionImpulse between your bird and path apply apply that value to the bird acc to your game
-(void)didBeginContact:(SKPhysicsContact *)contact
{
//contact
CGPoint contactPoint=CGPointMake(0, 0);
}
So it seems what I need to use (or at least I had in mind) are vertex shaders, but those are not currently supported in Spritekit. Right now, only fragment shaders are allowed from what I could find.
I did however see that you can create an SKShapeNode and set its texture property. The only problem with this is there is no option to "tile" that image throughout the SKShapeNode.
I did find this which seems to solve that issue (although I have not tried it out).
https://gist.github.com/man1/413642637ebd0b00fe2b
Seems like quite a work around!
In the end, I decided to use Cocos2d for this project as it supports both vertex and fragment shaders. With a bit of trial and error, I got it to work wonderfully.

Cocos2d 2.x: is there a way to achieve z layering across multiple sprite sheets?

I have 2 sprite sheets, one for the characters and HUD layer and one for the background. The "background sprite sheet" has an actual background part and a "foreground part" which should be layered in a z level above the characters.
Here comes the problem. Using CCSpriteBatchNode in order to optimize drawing performance I am forced to have two different CCSpriteBatchNodes of size 2048*2048 each in order to use the 2 sprite sheets.
Here is a brief "schematization" of the structure I would like to achieve:
z=0 background sheetBackground
z=1 characters sheetCharacters
z=2 foreground sheetBackground
sheetBackground -> spriteBatchNodeA
sheetCharacters -> spriteBatchNodeB
!!! Conflict -> sprites in a spriteBatchNode cannot be z-ordered in respect to sprites in another batch node !!
Unfortunately the z ordering of the sprites affects only the sprites within the same CCSpriteBatchNode and not the "global z order".
To overcome this problem the only way to me would be to have a sprite sheet of double size (4096*4096). I have found this github project CCBigImage that supports bigger files. Before I start changing my code structure I wanted to ask you if this would this be an accaptable solution or if there are other ways to achieve this.

Tiled 2d World Map Size Issue

Hey all, I am creating a 2D tile based XNA game. Basically the character can move any direction one tile at a time. I am using the Tiled map editor: http://www.mapeditor.org/ to create my map. I have not found any good tutorials or documentation on this yet.
Here is my issue:
I am attempting to load a very large world map into my game. Each gridspace is 32x32 pixels. The map itself is 1000x1000 gridspaces. At a first glimpse, this seems bad because of the size. When I loaded this WorldMap into my game XNA threw an out of memory error because the image was too large. I feel like I am approaching this from the wrong angle. Does anyone know a better way to handle a large world map? It would be nice to only load in what the character can see, that would be way more efficient however, that does not solve my problem of loading this huge image. Another idea would be a smaller image for each area but I am not sure how to do that since it's a world. Any ideas, tips, tutorials, I am sure this is a common issue that has been solved several times using several different solutions. Thank you!
When I was creating 2d XNA game I did:
My own format of binary map file. This file contains map name, map width and height in tiles etc and map array. It was simply byte array (byte[]) where each value corresponds to tile type.
Tile type. It's just simple class with some properties: movement cost (-1 if player can't move over this tile), which types of creatures can live in this tile, tile images etc.
Tile types db. It's just xml file contains tile types.
So, when game loads a level:
Load map and find in tile type db tiles which used in this map.
Load appropriate images for this tiles. Only once. It can be reused for different tiles with same type.
Draw only visible (for player) tiles with some reserve. As example draw only screen_width/tile_size_y*2 in width and screen_height/tile_size_y*2 in height. When player moves recalc visible tiles.

Resources