cocos2d : CCsprite setVisible method not working - iphone

In an cocos 2d game i user 3 heart sprites to update lives of hero.If hero lost one life..one heart should be hided.
I use below code but its not working properly.please help me.
- (void)updateLives {
int i = _lives;
[self livess:(int)i];
}
- (void)livess:(int)ii {
CGSize winSize = [CCDirector sharedDirector].winSize;
heart1=[CCSprite spriteWithFile:#"heart.png"];
heart2=[CCSprite spriteWithFile:#"heart.png"];
heart3=[CCSprite spriteWithFile:#"heart.png"];
[heart1 setPosition:ccp(winSize.width/2*1.3, winSize.height * 0.9)];
[self addChild:heart1 z:0];
[heart2 setPosition:ccp(winSize.width/2*1.1, winSize.height * 0.9)];
[self addChild:heart2 z:0];
[heart3 setPosition:ccp(winSize.width/2*0.9, winSize.height * 0.9)];
[self addChild:heart3 z:0];
if (ii==3) {
NSLog(#"%d",ii);
}
else if (ii==2)
{
NSLog(#"%d",ii);
[heart3 setVisible:NO];
} else if (ii==1)
{
NSLog(#"%d",ii);
[heart3 setVisible:NO];
[heart2 setVisible:NO];
}
else
{
}
}
note:in above code..nslog is printing correct values ..for example 1,2

It should hide correctly from your code. However, if this updateLives is called inside the game loop, probably the reason you see it is not hided as you expected is the heart from the previous frame. Try
1) creating the heart1, heart2, heart3 once
2) in the update, don't create the sprite. i.e. keep only if... else part of your code there.
Hope it helps.

Related

Sprite jumping around when i use resumeSchedulerAndActions

Ok I am attempting some AI stuff here and I have been following some Ray Wenderlich tutorials. I have some strange behavior going on. Maybe I am just doing this all wrong... but here you go. When a sprite is within 75 pixels of the target it switches to the Defending AIState and i call pauseSchedulerAndActions and set it to a predetermined safe spot via getDefensePosition method. What I am trying to do is after 2 seconds resume the actions so the sprite will move around again. so I call resumeSchedulerAndActions. Now this just goes through the getDefenseMethod and it moves te sprite between these three places but this is the strange behavior i have two slog calls one before getDefenseMethod and one after the sprite is jumping around from the center of the screen then back to the new spawnPoint:
2013-03-04 20:08:14.897 10-8[2629:c07] before: {217.533, 177.32}
2013-03-04 20:08:14.898 10-8[2629:c07] spawnPoint 1
2013-03-04 20:08:14.899 10-8[2629:c07] after: {100, 100}
dont understand why it is doing that. Why does it not just start from the position it was in?
- (void)execute:(GangMembers *)player {
// Check if should change state
NSArray * enemies = [player.layer enemiesOutsideRange:75 ofPlayer:player];
if (enemies.count > 0) {
NSLog(#"outside range 75");
[player changeState:[[Attacking alloc] init]];
return;
}
[player.layer setPlayer:player attacking:NO];
// Make build decision
[player.layer unschedule:#selector(shoot:)];
[player pauseSchedulerAndActions];
NSLog(#"before: %#", NSStringFromCGPoint(player.position));
[self getDefensePosition];
player.position = spawnPoint;
NSLog(#"after: %#", NSStringFromCGPoint(player.position));
[player performSelector:#selector(resumeSchedulerAndActions) withObject:player afterDelay:2];
}
- (void)getDefensePosition {
// CGSize winSize = [CCDirector sharedDirector].winSize;
int spawnChoice = arc4random() % 3;
spawnPoint = ccp(100, 100);
if(spawnChoice == 0){
spawnPoint = ccp(100, 100);
NSLog(#"spawnPoint 1");
}
else if(spawnChoice == 1){
spawnPoint = ccp(100, 200);
NSLog(#"spawnPoint 2");
}
else {
spawnPoint = ccp(100, 300);
NSLog(#"spawnPoint 3");
}
}
FWIW, I suspect your player object has some CCMove type of actions (which you are pausing). Even though you change the position while paused, when the action resumes, the action sets the position to its current state (startPosition, endPosition, duration, time elapsed since start), which may be quite different from the position you set during the pause.
not certain of your object model/class structure, but something like this:
[player stopAllActions];
player.position = spawnPoint;
[player runAction: [CCSequence actions:
[CCDelayTime actionWithDuration:2.0],
[CCMoveTo actionWithDuration:arc4random()%5+1 position: randomPoint],
[CCCallBlock actionWithBlock:^{ [self performSelector:#selector(moveRandom:) withObject:s afterDelay:0.5]; }],
nil]
];
this way, you recreate a moveto action that will be executed from spawnPoint, and your player.position is not in contention with a running action. Written from memory, you mileage may vary :)

How do I get a particle effect to follow my sprite in cocos2d?

I want a snow particle effect to follow my sprite and I tried some methods but all that ends up happening is the snow will just stay still instead of following. I did this one tutorial (will post as soon as I find it) thats shows how it do it with fire but didn't work out at all. Any tutorials or suggestions will be appreciated. I believe i have to add some kind of code to the snippet part where it says create enemy off screen.
[self schedule:#selector(gameLogicboss:) interval:180 ];
[self schedule:#selector(updateboss:)];
-(void)addTarget1 {
Boss *target1 = nil;
if ((arc4random() % 2) == 0) {{
target1 = [WeakAndFastBoss boss];
}} else {
target1 = [WeakAndFastBoss boss];
}
// Determine where to spawn the target along the Y axis
CGSize winSize = [[CCDirector sharedDirector] winSize];
int minY = target1.contentSize.height/2;
int maxY = winSize.height - target1.contentSize.height/2;
int rangeY = maxY - minY;
int actualY = (arc4random() % rangeY) + minY;
// Create the target slightly off-screen along the right edge,
// and along a random position along the Y axis as calculated above
target1.position = ccp(winSize.width + (target1.contentSize.width/2), actualY);
[self addChild:target1 ];
// Determine speed of the target
int minDuration = target1.minMoveDuration;
int maxDuration = target1.maxMoveDuration;
int rangeDuration = maxDuration - minDuration;
int actualDuration = (arc4random() % rangeDuration) + minDuration;
// Create the actions
id actionMove = [CCMoveTo actionWithDuration:actualDuration position:ccp(-target1.contentSize.width/2, actualY)];
id actionMoveDone = [CCCallFuncN actionWithTarget:self
selector:#selector(spriteMoveFinished:)];
[target1 runAction:[CCSequence actions:actionMove, actionMoveDone, nil]];
target1.tag = 1;
[_targets addObject:target1];
}
-(void)gameLogicboss:(ccTime)dt {
[self addTarget1];
iterations_++;
}
- (void)updateboss:(ccTime)dt {
CGRect projectileRect = CGRectMake(projectile.position.x - (projectile.contentSize.width/2), projectile.position.y - (projectile.contentSize.height/2), projectile.contentSize.width, projectile.contentSize.height);
BOOL bossHit = FALSE;
NSMutableArray *targetsToDelete = [[NSMutableArray alloc] init];
for (CCSprite *target1 in _targets) {
CGRect target1Rect = CGRectMake(target1.position.x - (target1.contentSize.width/2), target1.position.y - (target1.contentSize.height/2), target1.contentSize.width, target1.contentSize.height);
if (CGRectIntersectsRect(projectileRect, target1Rect)) {
//[targetsToDelete addObject:target];
bossHit = TRUE;
Boss *boss = (Boss *)target1;
boss.hp--;
if (boss.hp <= 0) {
_score ++;
[targetsToDelete addObject:target1];
}
break;
}
}
for (CCSprite *target in targetsToDelete) {
[_targets removeObject:target];
[self removeChild:target cleanup:YES];
_projectilesDestroyed++;
if (_projectilesDestroyed > 2) {
}
}
if (bossHit) {
//[projectilesToDelete addObject:projectile];
[[SimpleAudioEngine sharedEngine] playEffect:#"explosion.caf"];
}
[targetsToDelete release];
}
-(void)spriteMoveFinishedboss:(id)sender {
CCSprite *sprite = (CCSprite *)sender;
[self removeChild:sprite cleanup:YES];
GameOverScene *gameOverScene = [GameOverScene node];
[gameOverScene.layer.label setString:#"You Lose"];
[[CCDirector sharedDirector] replaceScene:gameOverScene];
if (sprite.tag == 1) { // target
[_targets removeObject:sprite];
} else if (sprite.tag == 2) { // projectile
[_projectiles removeObject:sprite];
}
}
I Have found this, at CCParticleSystem.h
/** #typedef tCCPositionType
possible types of particle positions
/
typedef enum {
/* Living particles are attached to the world and are unaffected by emitter repositioning. */
kCCPositionTypeFree,
/** Living particles are attached to the world but will follow the emitter repositioning.
Use case: Attach an emitter to an sprite, and you want that the emitter follows the sprite.
*/
kCCPositionTypeRelative,
/** Living particles are attached to the emitter and are translated along with it. */
kCCPositionTypeGrouped,
you should set it like
myparticleSystem.positionType=kCCPositionTypeGrouped;
Hope it helps.
You don't need to update the particle emitter's position with the sprite.
You can add a particle system to the sprite as a child.
The particle system does need to be typed as such:
CCParticleSystem * booster = [CCParticleSystem particleWithFile:#"boosterParticles.plist"];
//customize your particles' options
//assuming you have a sprite defined as _motherShip
[_motherShip addChild:booster];
/*
* now that the particles are the _motherShip's child, you must remember
* to set the position relative to the mothership's origin...
*/
particles.position = ccp(15,0);
...So now whenever _motherShip.position changes, the booster will follow. It will even rotate with the ship.
Very simple logic without getting into code:
I spawn a sprite and give it a location (x, y).
For each sprite, I also spawn a CCParticleSystem, give it the required particle type, spawn rates etc.
The CCParticleSystem location is now set to be the same (x,y) location as the sprite, and it should get updated as the sprite's (x,y) location is update.
As the sprite and the CCParticleSystem move around, this location (x, y) is getting updates constantly at random in your schedule method per the interval step time.
Hope that makes sense.
I do this
vehicleParticleSystem = [CCParticleSystemQuad particleWithFile:#"vehicleParticle.plist"];
vehicleParticleSystem.position = ccp(_ship.position.x - _ship.contentSize.width/3, _ship.position.y - _ship.contentSize.height/3);
if (UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad) {
vehicleParticleSystem.scale = 0.5;
}
[self addChild:vehicleParticleSystem z:-1];
and update its position with this
- (void) updateParticleSystem:(ccTime)dt {
vehicleParticleSystem.position = ccp(_ship.position.x - _ship.contentSize.width/3, _ship.position.y - _ship.contentSize.height/3);
}
which is called in the -(void) update:(ccTime)dt method.
The ship is moved by the user via a joypad.
hope this helps. The positioning for the particle is slightly behind the vehicle for an engine effect.
Did you tried to update your particle position taking advantage of the update method?
I'm doing something like the following lines in one of my games and it works as I think you expect
-(void) update:(CCTime)delta{
_sprite.position = CGPointMake(newXPosition, newYPosition);
_fire.position = CGPointMake(_sprite.position.x, _sprite.position.y);
}
I hope it helps!

Cocos2D random sprite movement

As a very beginner in Cocos2D i´m trying to make an iPhone game where some cows move randomly around the screen. I used the code for moving the sprites from here: highoncoding.com/.../. I´m adding the sprites in the init method wia an addAnimal method:
-(void) addAnimal {
animal = [CCSprite spriteWithFile:#"cow.png"];
animal.position = [self generateRandomCoordinates];
[self addChild:animal];
[self startAnimation:animal];
}
My problem:
When i add more than one cow to my game, they move from that random spawn position to another random position and then the first cow stops and the other cow goes on correctly. The startAnimation command in the finishedMoving method goes always to the last sprite. That means i need better control over my sprites but how to da that right?
You can try to implement animal class, that will contain your sprite and incapsulate random movement. Smth like
#implementation Cow
- (id) init
{
self = [super init];
if( self != nil )
{
CCSprite* cowSprite = [CCSprite spriteWithFile:#"cow.png"];
[self addChild: cowSprite];
}
return self;
}
- (void) onEnter
{
[super onEnter];
[self makeRandomMovement];
}
- (void) makeRandomMovement
{
id randomMoveAction = // create your random move action here
id moveEndCallback = [CCCallFunc actionWithTarget: self selector: #selector(makeRandomMovement)];
id sequence = [CCSequence actionOne: randomMoveAction two: moveEndCallback];
[self runAction: sequence];
}
#end
In such way after ending random movement part, method makeRandomMovement will be called again to generate and start new random movement part.
then remake your addAnimal method to smth like
- (void) addAnimal
{
Cow* newCow = [Cow node];
[newCow setPosition: [self generateRandomPosition]];
[self addChild: newCow];
}

Sprite and its body don't act the same way to forces

So I created a body and filled it with a sprite. The problem is that if I apply a force on the body, the sprite goes higher than the body (which I can see from debug_draw). Any idea why this is happening?
UPDATE
- (void)tick:(ccTime) dt {
_world->Step(dt, 10, 10);
for(b2Body *b = _world->GetBodyList(); b; b=b->GetNext()) {
if (b->GetUserData() != NULL) {
CCSprite *playerData = (CCSprite *)b->GetUserData();
playerData.position = ccp(b->GetPosition().x * PTM_RATIO,
b->GetPosition().y * PTM_RATIO);
playerData.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle());
}
}
}
And here's how I call this in my init method:
[self schedule:#selector(tick:)];
The for loop which gets the User_Data is kept on repeating now and then so to update the position of the creature would be difficult.. Please move the sprites position in the tick method....
-(void) moveCreature
{
// Please use the position to set the directions. This is used to fall from upside down in Portrait mode
[spriteCreature setPosition:ccp(spriteCreature.position.x,spriteCreature.position.y-5)];
}
Now in the init method schedule the sprite
-(id) init
{
if((self = [super init]))
{
// Create your World and other stuffs
[self schedule:#selector(moveCreature)];
}
return self;
}
The above stuff would carry the sprite in the body n fall down...

Cocos2d game termination problem when a moving sprite goes inside the bounding box of a animating still sprite(a ball get into a hole)

Let me explain it in depth, when ever if(CGRectContainsPoint([hole1 boundingBox], ball1.position)) condition goes true, i do lots of stuffs, like unscheduled, a selector, destroying a ball body calling an animation (please refer Code below)etc. This work properly most of the time. But sometimes when ball is really near to hole(just touching the hole but but not enough to make the above condition true), or is been throws towards the hole really fast speed, then application got terminated. I have checked, by commenting many actions which are been performed in this section, but got nothing helpful, application keep terminating when some efforts are been done to make it terminate.
if(CGRectContainsPoint([hole1 boundingBox], ball1.position))
{
ballBody->SetLinearVelocity(b2Vec2(0.0f,0.0f));
ballBody->SetAngularVelocity(0.0f);
[self unschedule:#selector(tick:)];
self.isTouchEnabled = NO;
[self removeChild:ball1 cleanup:YES];
world->DestroyBody(ballBody);
// create the sprite sheet
CCSpriteSheet *spriteSheet;
GolfBallsAppDelegate *appDelegate = (GolfBallsAppDelegate *)[[UIApplication sharedApplication] delegate];
if([appDelegate.ballValue isEqualToString:#"cricketball"])
{
spriteSheet = [CCSpriteSheet spriteSheetWithFile:#"cricket_ball_strip.png"];
}
else if([appDelegate.ballValue isEqualToString:#"ironball"])
{
spriteSheet = [CCSpriteSheet spriteSheetWithFile:#"iron_ball_strip.png"];
}
else if([appDelegate.ballValue isEqualToString:#"golfball"])
{
spriteSheet = [CCSpriteSheet spriteSheetWithFile:#"golf_ball_strip.png"];
}
else if([appDelegate.ballValue isEqualToString:#"soccerball"])
{
spriteSheet = [CCSpriteSheet spriteSheetWithFile:#"soccer_ball_strip.png"];
}
else if([appDelegate.ballValue isEqualToString:#"basketball"])
{
spriteSheet = [CCSpriteSheet spriteSheetWithFile:#"basket_ball_strip.png"];
}
spriteSheet.position = ccp(hole1.position.x,60);
[self addChild:spriteSheet];
float frameWidth = 96;
float frameHeight = 84;
CCSprite *sprite = [CCSprite spriteWithTexture:spriteSheet.texture rect:CGRectMake(0, 0, frameWidth, frameHeight)];
[spriteSheet addChild:sprite];
//if(animation)
{
// create the animation
CCAnimation *spriteAnimation = [CCAnimation animationWithName:#"potting" delay:0.1f];
int frameCount = 0;
for (int x = 0; x < 6; x++)
{
// create an animation frame
CCSpriteFrame *frame = [CCSpriteFrame frameWithTexture:spriteSheet.texture rect:CGRectMake(x*frameWidth,0*frameHeight,frameWidth,frameHeight) offset:ccp(0,0)];
[spriteAnimation addFrame:frame];
frameCount++;
// stop looping after we've added 14 frames
if (frameCount == 6)
{
//[self removeChild:spriteSheet cleanup:YES];
break;
}
}
// create the action
CCAnimate *spriteAction = [CCAnimate actionWithAnimation:spriteAnimation];
//CCRepeatForever *repeat = [CCRepeatForever actionWithAction:spriteAction];
// run the action
[sprite runAction:spriteAction];
//[sprite runAction:repeat];
}
[self schedule:#selector(loading) interval:0.5];
[self schedule:#selector(holeFinish) interval:1];
//[self removeChild:spriteSheet cleanup:YES];
}
Any suggestion will be highly appreciated.
EDIT: What i found is, problem with folling lines [self removeChild:ball1 cleanup:YES];
world->DestroyBody(ballBody);
(MAY be). but as it not occurs always, (as I mentioned), thus it's being ridiculous.
I think your problem will be that you are trying to delete a body when the b2World is 'locked', (When the world is busy working out collisions).
Try flagging the object as ready for deletion, and deleting it at the start of your next loop:
Replace:
[self removeChild:ball1 cleanup:YES];
world->DestroyBody(ballBody);
with
ball1.isDead = YES;
And at the start of your next game loop:
for (Ball b in balls)
{
if (b.isDead)
world->DestroyBody(b.ballBody);
}