Issues with adding an array of moving sprites to screen? - cocos2d-iphone

In my program, I have created an NSMutable Array which contains a series of sprites that move across the screen (to the left)
However, while implemented in my code, they do not seem to appear on the screen simulator when tested.
Any ideas?
-(void) addBlocks
{
NSMutableArray *_blocks; blocktest=[CCSprite spriteWithFile:#"blocksquare.png"];
blocktest.tag = 1;
// add the block to the array of blocks
[_blocks addObject:blocktest];
blocktest.position=ccp(500,100);
id repeat2 =[CCRepeatForever actionWithAction:[CCSequence actions:
[CCMoveTo actionWithDuration:7 position:ccp(-180,100)],nil]];
[blocktest runAction:repeat2];
}

That's because you haven't added blocktest to your scene ( [self addChild:blocktest] ).
Adding it to _blocks, will work as a reference to fetch your sprites later, but will not add the sprites on any layer or scene, so you won't see them anywhere

Related

ccSpriteBatchNode child bounding box transformation

I'm using cocos2d 1.0.1.
I've created a CCSpriteBatchNode, it includes a CCSprite (let's name it parentLayer) which includes some X number of childs(CCSprites).
The problem is - when I rotate parentLayer all sprites (childs) correctly displayed, however bounding boxes are at the same place (where they've been before rotation), so world coordinates of those sprites won't be changed.
Off course, all of the above works great without CCSpriteBatchNode. But, I would like to use batch node due to amount of sprites involved.
The question is, is there any way to update bounding boxes & child positions correspondingly?
How many sprites are we talking about? I would just go with a fast enumeration call to rotate each one individually. I nave never noticed a performance hit when doing this, have you?
CCArray *listOfChildren = [parentLayer children];
for (CCSprite *sprite in listOfChildren) {
[sprite setRotation:someValue];
}

How to load sprites in cocos2d correctly?

my problem is:
I'm making a game for iOS using cocos2d and this game has lots of levels, so I'll have to create a loading scene to load my sprites for each level. ( like new backgrounds, monsters and other stuff )
But I have no idea about this, I'm adding all the Texture Packer Files (.plist and .pvr.ccz)
on the sharedSpriteFrameCache in the GameData.m.
Does anyone knows a good tutorial for this or can help me solve this?
Thanks!
So basically you want to know how to load and unload images as you see fit. How about
#implementation Level1
- (void) loadLevel
{
CCSpriteFrameCache* frameCache = [CCSpriteFrameCache sharedSpriteFrameCache];
CCTextureCache* textureCache = [CCTextureCache sharedTextureCache];
// Add the sprite frames. This will load the texture as well
[frameCache addSpriteFramesWithFile:#"monkey.plist"];
[frameCache addSpriteFramesWithFile:#"player.plist"];
[frameCache addSpriteFramesWithFile:#"enemy.plist"];
// Load other textures that are going to be used
_myBackgroundTexture = [textureCache addImage:#"background.png"];
}
- (void) unloadLevel
{
CCSpriteFrameCache* frameCache = [CCSpriteFrameCache sharedSpriteFrameCache];
CCTextureCache* textureCache = [CCTextureCache sharedTextureCache];
// Remove textures
[textureCache removeTexture:_myBackgroundTexture];
// Remove sprite frames. This will load the texture as well
[frameCache removeSpriteFramesFromFile:#"monkey.plist"];
[frameCache removeSpriteFramesFromFile:#"player.plist"];
[frameCache removeSpriteFramesFromFile:#"enemy.plist"];
// Though normally, id use frameCache removeUnusedSpriteFrames and
// textureCache removeUnusedTextures
}
...
#end
You can use the sprite by CCMenuItem and also by the Menu as you would require to click and move to that particular level.. The below is the code for adding the menu item image
CCMenuItem *m4 =[CCMenuItemImage itemFromNormalSprite:[CCSprite spriteWithSpriteFrameName:<#(NSString *)spriteFrameName#>]
selectedSprite:[CCSprite spriteWithSpriteFrameName:<#(NSString *)spriteFrameName#>]
disabledSprite:[CCSprite spriteWithSpriteFrameName:<#(NSString *)spriteFrameName#>]
target:self selector:#selector(MoveLeft)];
The above code gives the information you can use to display the sprite for the particular state of the menu. And the "MoveLeft" is the method selector which I have used to call the particular method.
At last you can add the m4 object to the CCMenu and get the desired output...
Hope it works for you.

Cocos2d iPhone. Scrollayer contentSize. Layers

I want to set the contentsize of scrollayer.
I have a scrollayer, it's CCLayer type and moving is set by ccTouchMove. I have one schedule for smoothing. BUT.
Problem is that scrolling layer is big like the whole display. I want to set the contentsize of scrollayer. Content in this layer will be scroll and showing ONLY in this layer. Not taking up the whole display. Something like this
Scrolling just in gray CCLayer (scrollayer) ....NOT WHOLE SCREEN.
Can you help me?
P.S.: Setting CCLayerColor and initWithColor:Width:Height: is not working. It just makes some stupid color box and it's moving too.
ok, honestly i would put the window frame at a higher z than the scrolling object ... if you dont you may have to crop and change sprite on the fly for the window content, nasty (at least that is the one way i could do this, without further research).
so :
// initialize this logic somewhere useful
CCNode scrollableContent;
CCSprite windowFrame;
BOOL isScrollPossible;
[self addChild:scrollableContent z:0];
[self addChild:windowFrame z:1];
// and in the touch delegate methods
-(void) ccTouchBegan:{
check if the touch happened in the window, if yes, scrolling is possible
}
-(void) ccTouchMoved:{
if (isScrollPossible) {
compute displacement
compute nextPosition for scrollableContent node;
if ( nextPosition in window ) {
// make scrollableContent follow touch
scrollableContent.position=nextPosition;
} else {
// stop any further scrolling until the next 'touch began'
isScrollPossible=NO;
}
} else {
// scroll not possible, do nothing
}
}
This is the basic idea. You may need clamping logic to prevent the creeping of scrollableContent beyond the edges of the window.
Edited for typos.
After trying desperately with masking and GL_SCISSOR, I settled on cutting a hole in the foreground and only moving the background object when onTouchMoved updated.
To see it in action, have a look at the Stats page of Angry Gran.

Animate Sprite From Tile Map

I would like to animate a sprite at a specific location on an isometric tilemap. I can animate a sprite on a given layer, but not when its a sprite from a tilemap. For example the following works just fine:
// make a frame cache
CCSpriteFrameCache *frameCache = [CCSpriteFrameCache sharedSpriteFrameCache];
[frameCache addSpriteFramesWithFile:#"spellanim.plist" textureFile:#"spellanim.pvr.ccz"];
// create a sprite
CCSprite *effectSprite = [CCSprite spriteWithSpriteFrameName:#"spell_strength__33.png"];
// set sprite at center of screen
CGSize screenSize = [[CCDirector sharedDirector] winSize];
effectSprite.position = CGPointMake(screenSize.width / 2, screenSize.height / 2);
// create animation using an animation helper (since animationWithName:delay:frames: will be deprecated)
CCAnimation *animation = [CCAnimation animationWithFrame:#"spell_strength__" frameCount:13 delay:0.3f startAt:33];
CCAnimate *animate = [CCAnimate actionWithAnimation:animation];
// run animation on sprite
[effectSprite runAction:animate];
// add sprite as a child of the layer
[self addChild:effectSprite];
Now the following does not work, I assume it has to do with how tile maps work (I get an assertion failure in CCSprite setTexture:):
// add one to x to offset the spell animation from the player
CGPoint tileCoord = CGPointMake(player.entityTileCoordinate.x + 1, player.entityTileCoordinate.y);
// get the effects layer from the tile map
CCTMXTiledMap *tileMap = (CCTMXTiledMap *)[[TileMapLayer sharedTileMapLayer] getChildByTag:TileMapNode];
CCTMXLayer *effectsLayer = [tileMap layerNamed:#"Effects"];
// get a sprite from the effects layer
CCSprite *effectSprite = [effectsLayer tileAt:CGPointMake(0, 0)];
// move the sprite to the desired location (this works just fine)
CGPoint pointPixel = [effectsLayer positionAt:tileCoord];
[effectSprite runAction:[CCMoveTo actionWithDuration:0.0f position:pointPixel]];
// now animate the sprite
CCSpriteFrameCache *frameCache = [CCSpriteFrameCache sharedSpriteFrameCache];
[frameCache addSpriteFramesWithFile:#"spellanim.plist" textureFile:#"spellanim.pvr.ccz"];
CCAnimation *animation = [CCAnimation animationWithFrame:#"spell_strength__" frameCount:13 delay:0.3f startAt:33];
CCAnimate *animate = [CCAnimate actionWithAnimation:animation];
[effectSprite runAction:animate];
My guess it is because the animation sprites aren't a part of the tile set for that layer of the tile map. Is there a way to dynamically add these animation sprites to some cache used to draw on that layer (basically modify the tile set at runtime)? Can I later then remove these sprites from that modified tile set? Is there still a 1024x1024 limitation when you modify a tileset at runtime?
At the end of the day I really want to be able to have an animated sprite move from one tile to another on the tile map but I'm just not sure how to do that in the most efficient way. It seems really clunky to have an effects layer on the tile map and a tile set with all spell animations (especially if you can't fit them in 1024x1024) as assembling an animation would be chaining together tile GID updates as the effect moves across the tile map.
I know I can do what I want when the layer isn't a part of a tilemap - I can animate and move a sprite using screen coordinates, but when what I know are tile coordinates, translating those to screen coordinates (if the tile is even visible on the screen) has evaded my understanding so far. How do you determine what tiles the screen can actually 'see'? What then is the pixel coordinate on the screen of a visible tile?
I appreciate any thoughts on how to go about this process.
what you guess is the real cuase of the problem, tile maps are created using spritebatchnode. spritebatchnode is just like a layer with higher performance that you can only add sprites to it but there is a single restriction all the sprites in a spritebatchnode must share their textures. so when you are trying to change a tile to show an animation you are trying to draw something from diffrent texture alongside other tiles (which have default tile texture) and it causes crashes or malfunctioning. i didn't test it myself but i think if you try putting all your frames in a same texture you put other tiles, the problem would be solved.

How to keep fps rate constant in cocos2d

I have 3 question.
How to keep fps rate constant(almost) in cocos2d.When lots of CCSprite created and removed within a small interval like (5-8) per second is it possible to keep frame rate lmost constant??
Is [self removeChild:sprite cleanup:YES] is enough or i should also use
CCTexture2D *texture = [sprite texture];
[[CCTextureCache sharedTextureCache] removeTexture: texture];
The following Part of code is responsible for my frame drop.How to accomplish same task in better way-
id fadeout = [CCFadeOut actionWithDuration:1.4f];
id call = [CCCallFunc
actionWithTarget:self
selector:#selector(RemoveSmashedSprite:)];
CCSequence* sequence= [CCSequence actions:fadeout, call, nil];
[smash runAction:sequence];
and
-(void)RemoveSmashedSprite:(id)sender
{
CCSprite *sp = (CCSprite *)sender;
[self removeChild:sp cleanup:YES];
}
This is called 5-8 times per second.So the frame rate goes down.Can any one help me.
I am guessing that the "smashed sprite" in question is probably one of a number of sprites visible on the screen, more than likely sharing the same texture (part of a sprite sheet perhaps, or all the same image, etc?).
If this is the case, I would recommend allocating the number of sprites your games requires to have on screen and rather than "destroy" (remove them, re-create them) you should "re-use them".
Store a reference to all the CCSprite's in an NSMutableArray, populate this array with the number of sprites you think is appropriate (how many sprites are removed per second? how many sprites are added per second? how many sprites are on the screen to start? - use the answers to these questions to determine the most appropriate size of your array).
Then, rather than removing the sprite as a child, simply [sprite setVisible: NO] to hide it, then ... when you need to display a new one on screen, use the next "available" (hidden) sprite in the array (keep track of the last "used" sprite with an index, and simply increment it by 1 to find the next "available". Once the index exceeds the bounds, reset it to 0 - at this point, that sprite should have been "smashed"). Once you have the next "available" sprite, change it's properties (position, scale, texture?, visibility) and apply any actions that are appropriate (don't forget to "stop all actions" on it when "smashing it" - this is what "cleanup: YES" does).
If your game does not allow you to go around in a "circle" like this, because the user decides what may or may not be visible by interacting with the sprites in a varied order then you can store a reference to the "smashed sprites" in a separate array (while keeping them in the original array as well - then you can just pick anyObject from the "unused" array, remove it from that array and then alter it as mentioned above).
This should reduce your frame rate drops dramatically, as you won't be creating and destroying sprites all the time.
Another thing that may be occurring is that you are using different images, and each image is stored separately (image1.png, image2.png, image3.png) and the creation/destruction of these is causing the textures to be removed and re-added ... to resolve this, create a sprite sheet and add the sprite sheet to the Texture Cache, then create your images with 'spriteFromSpriteCacheName:#"image1.png"'