I am trying to take a particle effect in my Cocos2d project. Particle effect shows good. But I am confused when I put the particle showing function into a thread as follows, it only shows tiny dark squares instead of the right texture. thanx in advance.
// thread caller
[self performSelectorInBackground:#selector(showParticleThrd:) withObject:nil];
// it works good when i call it directly
-(void) showParticleThrd{
CCParticleSystem * system = [[ParticleEffectSelfMade alloc] initWithTotalParticles:1];
[aLayer removeChildByTag:R_TAG cleanup:YES];
system.position = ccp(self.position.x,self.position.y);
[self.parent addChild:system z:R_ORDER tag:R_TAG];
[system release];
}
You can not modify anything cocos2d related in a background thread. Cocos2d requires you to make changes to nodes in the main thread, where the OpenGL context was created.
Related
I use this code to show game over menu after _hero sprite and _enemy sprite collide :
if (CGRectIntersectsRect(_hero.boundingBox,_enemy.boundingBox)) {
CCActionCallFunc *_callShowMenu=[CCActionCallFunc actionWithTarget:self selector:#selector(showMenu)];
[self runAction:_callShowMenu];
// EDIT : I also remove both sprites when collision happens.
[_hero removeFromParent];
[_enemy removeFromParent];
}
In _callShowMenu I just stop all actions and show a sprite with half transparent black background image and buttons.
Sometimes when collision happens, it seems to me, that _callShowMenu is called twice, because
background is completely black, like there is the same image behind. Has anyone had a similar problem? (Mostly background image is half-transparent, as it should be).
EDIT:
-(void)showMenu{
[[CCDirector sharedDirector] pause];
CCSprite *_halfTransparentBackground=[CCSprite spriteWithImageNamed:#"halfTransparentBackground.png"];
_halfTransparentBackground.position=ccp(160, 280);
[self addChild:_blackBack z:5];
}
I found a solution using BOOL. Actually everyone uses BOOL in this case, so I don't need to reinvent the wheel.
BOOL doNotCallMeTwice;
Somewhere in the didLoad method:
doNotCallMeTwice=NO;
In the collision detection method:
if (doNotCallMeTwice==NO) {
[self showMenu];
}
And finally:
-(void)showMenu{
doNotCallMeTwice=YES;
}
Possibly, showMenu was called twice(or much more times),because collision detection is in the update method.
I am trying to launch a physics object after loading a game scene, something similar to https://www.makegameswith.us/tutorials/getting-started-with-spritebuilder/creating-two-levels/
The code I have is something like this
- (void)didLoadFromCCB {
// tell this scene to accept touches
self.userInteractionEnabled = TRUE;
[self launchObject];
}
- (void) launchObject {
CCNode* object = [CCBReader load:#"Object"];
// Apply force to it
}
The problem is if I add a sleep method in didLoadFromCCB before launching the object or the first line in the launchObject, the game scene itself is loading only after that many seconds (say after clicking play) and immediately launches, but I want the game scene to load and after n seconds the physics object is launched.
I can easily solve this problem by using
- (void)update:(CCTime)delta
by setting some conditions for launch, but the question is, is that the right approach. I don't want to complicate update method to hold multiple if/else stuff and use it beyond what it's intended for, especially if there is another best way to do it.
I tried different solutions posted in this forum but didn't help my case.
CCActionCallBlock *call=[CCActionCallBlock actionWithBlock:^
{
NSLog(#"***********done");
}];
[self runAction:call];
Is not working if i put it in another node, and add this node to my main scene .
It only works in my main scene, and not in any other layer added to that scene .
why ?
I just tried it and it works for me, have you called [super onEnter] on your scene?
If that does not work please a bit more code please.
Anyone that can give any hint of the smartest way to do a main loop animation? I don't want to use CCAnimation because I want to control the animations frame by frame.
Shall I store the sprite rect (relative to the sprite sheet) for each individual frame in an array, and then look up the suiting rect in each animation step? I tried to find out how this is done in CCAnimation, but I didn't succeed...
How to get the rect for each frame at initialization?
How to set the rect at each animation step?
Do I need to use CCSpriteBatchNode? I guess not, eh?
Cannot crealry understand, why you don't want to use CCAnimation, but anyway, to get answer for your questions you can check creation code of the CCSprite instance. Then, check creation of CCSpriteFrame instance. There you will find the answer for at least your first question.
Actually if you just want to manage animation frames differently from CCAnimate, you can just store array of CCSpriteFrames and show them as you want(in CCAnimate action these frames are just changed one by one in equal time intervals).
And if you do not want to show more than one frame of your animation, there is no difference will you use CCSpriteBatchNode or not. It saves a lot of processor time if you need to draw several parts of one texture, as it draws them in one draw call instead of send draw message to all of these sprites.
As you want animate sprite frame by frame I think using CCSpriteBatchNode would be a better option as it give you frame by frame access of animation.Making plist of sprites using any tool like "Zwoptex" will give an efficient way to animate using CCSpriteBatchNode.
Hope you know the animation using plist file with CCSpriteBatchNode.
I did the following with inspiration from Morions answer:
In the game tick function:
_animationFrames.legFrame = (_animationFrames.legFrame + 1) % _animationFrames.legFrames.count;
[_legs setDisplayFrame: [_animationFrames.legFrames objectAtIndex: _animationFrames.legFrame]];
And in the init function:
CCSpriteBatchNode *spriteSheet = [CCSpriteBatchNode
batchNodeWithFile:#"Player.png"];
[self addChild:spriteSheet];
_animationFrames.legFrames = [[NSMutableArray array] retain];
for(int i = 0; i <= 15; ++i)
{
[_animationFrames.legFrames addObject:
[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:
[NSString stringWithFormat:#"Player_legs-%d.png", i]]];
}
_legs = [CCSprite spriteWithSpriteFrameName:#"Player_legs-0.png"];
[_sprite addChild: spriteSheet];
[spriteSheet addChild:_legs z:1];
In cocos2D I currently have a very simple particle emitter initialized like this:
turnEmitter = [[CCParticleFlower alloc] init];
turnEmitter.texture = [[CCTextureCache sharedTextureCache] addImage:#"Pocket.png"];
[self addChild:turnEmitter z:1];
turnEmitter.scale = 0.7f;
turnEmitter.positionType = kCCPositionTypeFree;
It is simply added directly to the gameplay layer.
This emitter follows a sprite around the screen in this way (happens in the update method):
turnEmitter.position = turnEmblem.position;
Now the problem is that the tail of particles left behind the emitter moves with the emitter, instead of released particles simply staying in the position they were released, which gives a really weird and stupid looking effect.
What I want to do is have the particles not follow the emitter at all after they have been spawned, unfortunately I have been unable to find any way of doing so.
As you can see from the code above I have already searched around, and found people which suggests changing the positionType property of the emitter, although I have tried all the possibilities and it does not solve the problem.
Does anyone have any ideas as to what this might be?
You may want to try changing the "emitterMode" as well to "kCCPositionTypeFree". I had a similar issue where i had the emitter as a child of a CCNode. The CCNode was being rotated, but the particles and emitter wasn't. In the same way it looked stupid because the illusion of rotation was ruined. I need to set the following on my emitter:
emitter.emitterMode = kCCPositionTypeRelative;
emitter.positionType = kCCPositionTypeRelative;