CCSprite doesn't go invisible -iphone - iphone

in .h file
CCSprite *backwheels;
in .m file
backwheels = [CCSprite spriteWithFile:#"wheels_back.png"];
backwheels.position = ccp(400,120);
[self addChild:backwheels];
-(void) showGameOver {
backwheels.visible = false;
}
but when Game is Over backWheels still appears on scene..? !
any help ?!
NOTE:i have synthesized backWheels too,but still doesn't work for me.

I can give you a quick fix. This is not the best approach, the best one is to find out what exactly causes such a behavior, but i can't do that without seeing the rest of your code. Anyway this is how you can access backwheels sprite in showGameOver method. When you create the sprite make it this way:
backwheels = [CCSprite spriteWithFile:#"wheels_back.png"];
backwheels.position = ccp(400,120);
backwheels.tag = 100; // whatever integer value you wish
[self addChild:backwheels];
Then you retrieve it in showGameOver :
backwheels = [self getChildByTag:100];
backwheels.visible = false;
I believe it's gonna work.

You could always just change the opacity of the sprite i.e.
-(void) showGameOver {
backwheels.opacity = 0.0f;
}
And then when you want it to reappear change it to
backwheels.opacity = 1.0f;

Use Remove Child :
[self removeChild:backwheels cleanup:YES];

Related

Cocos2d NSMutable Array mutated while enumerated

I've been working on a game, and at a point I didn't have issues removing the enemy game objects (right now they are subclassed from CCSprite and I know that's not the best way)
But I'm not sure what I changed to make it crash when the program attempts to removeChild from _targets after they have been added to targetsToDelete.
I tried moving things around, I just don't know how I am adding or editing the array while its being created... Any help or advice would be great!
And actually if you had any pointers on how best to create game enemies, do you subclass NSObject or CCNode? I heard to divide them into component classes but I had no clue what they meant.
//Projectile Target collision
-(void)update:(ccTime)dt {
for (spygot *target in _targets) {
CGRect targetRect = CGRectMake(
target.position.x - (target.contentSize.width/2),
target.position.y - (target.contentSize.height/2),
target.contentSize.width,
target.contentSize.height);
//Collision Detection Player
CGRect playerRect2 = CGRectMake(
_controlledSprite.position.x - (_controlledSprite.contentSize.width/2),
_controlledSprite.position.y - (_controlledSprite.contentSize.height/2),
_controlledSprite.contentSize.width,
_controlledSprite.contentSize.height);
NSMutableArray *projectilesToDelete = [[NSMutableArray alloc] init];
for (Projectile *projectile in _projectiles)
{
NSMutableArray *targetsToDelete = [[NSMutableArray alloc] init];
CGRect projectileRect = CGRectMake(
projectile.position.x - (projectile.contentSize.width/2),
projectile.position.y - (projectile.contentSize.height/2),
projectile.contentSize.width,
projectile.contentSize.height);
BOOL monsterHit = FALSE;
if (CGRectIntersectsRect(projectileRect, targetRect))
{
NSLog(#"hit");
target.mhp = target.mhp - 1;
monsterHit = TRUE;
if (target.mhp <= 0)
{
[targetsToDelete addObject:target];
}
}
for (spygot *target in targetsToDelete)
{
[self removeChild:target cleanup:YES];
[_targets removeObject:target];
}
if (monsterHit)
{
[projectilesToDelete addObject:projectile];
}
[targetsToDelete release];
}
for (Projectile *projectile in projectilesToDelete)
{
[_projectiles removeObject:projectile];
[self removeChild:projectile cleanup:YES];
}
[projectilesToDelete release];
}
It looks like the code that you've pasted is all from within a for loop iterating over _targets. How does the variable target get initialized?
Usually when I get this sort of error it's because I have the code in a block or am in some other way on a nebulous thread. How sure are you that this bit of code is not running more than once at the same time?
You could try wrapping it in the following:
dispatch_async(dispatch_get_main_queue(), ^{
// do everything here.
});
As for advice about using CCSprite for your game enemy objects, my advice is fix it when it becomes a problem. Are you seeing issues with it right now? Premature optimization is almost as bad as doing it wrong in the first place. You'll know better at the end of the project how you should have done it earlier. ;)
I guess you know that you cannot remove elements from the array while you iterate over it. That is why you have targetsToDelete array.
But it looks to me that you do remove targets to soon.
Try this:
finish iterating the main loop and finish collecting targets to the targetsToDelete array and only after main loop is done remove the targets.

accessing instance variable in cocos2d scheduled method crashes

fresh to objC and cocos2d :)
i'm following "learn cocos2d game development with iOS5", in chapter4, there is a "DoodleDrop" game.
define some variable in GameScene.h like this
#interface GameScene : CCLayer
{
CCSprite *player;
CGPoint playerVelocity;
CCArray *spiders;
CGSize screenSize;
int dropedSpidersCount;
float duration;
}
+ (CCScene *)scene;
#end
in GameScene.m the init method looks like this
- (id)init
{
if (self = [super init]) {
duration = 4.0;
[self createPlayer];
[self createSpiders]; // spiders were inited here.
[self resetSpiders];
[self schedule:#selector(chooseSpider:) interval:0.7];
}
return self;
}
while in chooseSpider, i cannot access spiders, xcode broke
in other methods, spiders or duration just behave normally, why does this happens?
gist code added
https://gist.github.com/2940466
After inspecting your code, I suggest you to try this fix:
- (void)createSpiders
{
CCSprite *tempSpider = [CCSprite spriteWithFile:#"spider.png"];
CGSize spiderSize = [tempSpider texture].contentSize;
int spiderCount = screenSize.width / spiderSize.width;
spiders = [[CCArray arrayWithCapacity:spiderCount] retain];
for (int i = 0; i < spiderCount; i++) {
CCSprite *spider = [CCSprite spriteWithFile:#"spider.png"];
[self addChild:spider];
[spiders addObject:spider];
}
}
where the only difference is in the line:
spiders = [[CCArray arrayWithCapacity:spiderCount] retain];
Indeed, if you do not retain you spiders object, it will be autoreleased at the next run loop iteration.
OLD ANSWER:
Without seeing more code it is not possible to say exactly what is happening, but it seems that in the interval between creating the spiders and the actual execution of chooseSpiders, your spiders array gets deallocated.
As a quick try, I would suggest adding:
[spiders retain];
before calling
[self schedule:#selector(chooseSpider:) interval:0.7];
and see wether the crash keeps happening.
if you provide more code, it could be possible to help you further.

How to set ICarousel to slide one time for one one image

I am using ICarousel to make my Electronic Album. When you slide the album , the default setting by ICarousel is that it will move to some distance. What I need is slide one time for one one image only. I found ICarousel is not based on ScrollView , So I can not figure out how to achieve my purpose, is someone who know about it?
Updated answer with the more recent versions of iCarousel :
iCarousel now supports single-page swiping by setting
pagingEnabled=YES.
I would recommend turning off the native scrolling and attaching a PanGestureRecognizer that utilizes the scrollByNumberofItems method.
[iCarousel setScrollEnabled:NO];
Then inside your gestureRecognizer:
[iCarousel scrollByNumberOfItems:1 duration:0.25];
I tried this myself and it worked great.
It seems that you have to use another library called SwipeView, implemented by the same author.
The issue was found here.
https://github.com/nicklockwood/iCarousel/issues/247
I achieved that for type iCarouselTypeCoverFlow by setting:
//In ViewController.m
self.carousel.pagingEnabled = YES;
//In iCarousel.m change for smooth animation
-(void)scrollByOffset:(CGFloat)offset duration:(NSTimeInterbal)duration{
if (duration > 0.0)
{
_decelerating = NO;
_scrolling = YES;
_startTime = CACurrentMediaTime();
_startOffset = _scrollOffset;
// _scrollDuration = duration;
// set constant duration instead
_scrollDuration = 1.0;
_endOffset = _startOffset + offset;
if (!_wrapEnabled)
{
_endOffset = [self clampedOffset:_endOffset];
}
[_delegate carouselWillBeginScrollingAnimation:self];
[self startAnimation];
}
else
{
self.scrollOffset += offset;
}
}
Modify iCarousel source code iCarousel.m file may do this!
- (void)didPan:(UIPanGestureRecognizer *)panGesture {
......
case UIGestureRecognizerStateChanged: {
CGFloat translation = _vertical? [panGesture translationInView:self].y: [panGesture translationInView:self].x;
translation = translation * 0.35; // Add This line to change the really translation.
......
}
}
That solve my problem,Hope to help you!

Removing animation sprite frames from layer?

Let's say I have a character in a game and its class is like this.
#interface Player
{
CCSprite* stand;
CCAnimation* run;
}
-(void) playRunAction
{
// Create CCAnimate* object from CCAnimation object (run)
[self runAction:runAniate];
}
-(void) playStandAction
{
stand.visible = YES;
[self stopAllActions];
}
The player has ability to stand or run.
But one problem is, after playStandAction is called, stand animation is visible and running animation stopped, but one frame of running animation still there!
( Now you see 'stand sprite' AND 'one of running animation frame' together. )
How can I make running animation not visible?
P.s Can anyone throw me a better way of managing animation in one character? This is totally disaster as animations added.
-(void) playStandAction
{
//Make the animation object.visible = NO; here
stand.visible = YES;
[self stopAllActions];
}
and in
-(void) playRunAction
{
// Create CCAnimate* object from CCAnimation object (run)
//Make the animation object.visible = YES; here
stand.visible = NO;
[self runAction:runAniate];
}
Use method with parameter restoreOriginalFrame and pass it yes
I don't know which method you are calling for creating CCAnimate object...
Like this:
[CCAnimate actionWithAnimation:animation restoreOriginalFrame:YES]];
And don't call runAction on layer. I would prefer you to runAction on sprite itself...
You don't need to hide and show 2 different objects...
Hope this helps. :)

scaling a CCMenuItem in Cocos2d (Objective-C)

I'm trying to make a CCMenuItem that has scaled images. For example, I tried:
CCSprite* normalSprite = [CCSprite spriteWithFile:#"button_play.png"];
CCSprite* selectedSprite = [CCSprite spriteWithFile:#"button_play.png"];
selectedSprite.scale = 1.2;
CCMenuItem menuItem = [CCMenuItemSprite
itemFromNormalSprite:normalSprite
selectedSprite:selectedSprite
target:self
selector:#selector(onPlay:)];
But it looks like CCMenuItemSprite ignores the scale of the underlying sprites. Is there a way to do this (aside from just creating scaled versions of the underlying images)? Thanks.
Thyrgle is correct about how CCMenuItem works.
However, there certainly is a way to do what you want. All you need to do is subclass CCMenuItem and override the selected and unselected methods to achieve what you want. In fact, I'm pretty sure you could just cut and paste the code from CCMenuItemLabel, because scaling the item to 1.2 is exactly what it does. (In fact, it does it better, since it animates the scale change.)
-(void) selected
{
// subclass to change the default action
if(isEnabled_) {
[super selected];
[self stopActionByTag:kZoomActionTag];
CCAction *zoomAction = [CCScaleTo actionWithDuration:0.1f scale:1.2f];
zoomAction.tag = kZoomActionTag;
[self runAction:zoomAction];
}
}
-(void) unselected
{
// subclass to change the default action
if(isEnabled_) {
[super unselected];
[self stopActionByTag:kZoomActionTag];
CCAction *zoomAction = [CCScaleTo actionWithDuration:0.1f scale:1.0f];
zoomAction.tag = kZoomActionTag;
[self runAction:zoomAction];
}
}
CCMenuItemImage Class is also available for displaying image with its scale in CCMenu.Please Check this link http://www.cocos2d-iphone.org/forum/topic/8310
[mainMenu alignItemsVerticallyWithPadding:15.0f];
No there is not another way. The thing is that menuItem is only acknowledging the files part of the sprites. It is not looking at other properties such as the scale property.