Cocos2d Random object from array not being called - iphone

I have created an array which stores either red, yellow, or green (3, 2, or 1) based on what the user hits. I want the code to choose a random number in the array and display the corresponding color on the screen. However, when the code runs, the program always chooses the last entered color and only shows that color.
Code:
-(void)CreateEnemy:(ccTime)dt{
CCSprite *Enemy;
int a;
if (colorArray != nil) {
a = arc4random()% [colorArray count];
}
int y = [[colorArray objectAtIndex:a] integerValue];
if (y == 1) {
Enemy = [CCSprite spriteWithFile:#"GreenBall.png"];
int x = arc4random()%320;
Enemy.position = ccp(x, 530);
id action = [CCMoveTo actionWithDuration:3 position:ccp(x, -30)];
[Enemy runAction:[CCSequence actions:action, [CCCallFuncN actionWithTarget:self selector:#selector(spriteMoveFinished:)], nil]];
[enemyArray addObject:Enemy];
[self addChild:Enemy z:2 tag:1];
NSLog(#"Green Enemy Attack!!");
}
else if (y == 2) {
Enemy = [CCSprite spriteWithFile:#"YellowBall.png"];
int x = arc4random()%320;
Enemy.position = ccp(x, 530);
id action = [CCMoveTo actionWithDuration:3 position:ccp(x, -30)];
[Enemy runAction:[CCSequence actions:action, [CCCallFuncN actionWithTarget:self selector:#selector(spriteMoveFinished:)], nil]];
[enemyArray addObject:Enemy];
[self addChild:Enemy z:2 tag:1];
NSLog(#"Yellow Enemy Attack!!");
}
else if (y == 3) {
Enemy = [CCSprite spriteWithFile:#"RedBall.png"];
int x = arc4random()%320;
Enemy.position = ccp(x, 530);
id action = [CCMoveTo actionWithDuration:3 position:ccp(x, -30)];
[Enemy runAction:[CCSequence actions:action, [CCCallFuncN actionWithTarget:self selector:#selector(spriteMoveFinished:)], nil]];
[enemyArray addObject:Enemy];
[self addChild:Enemy z:2 tag:1];
NSLog(#"Red Enemy Attack!!");
}
}
Y should be a randomly chosen color, but it never is.

In:
if (colorArray != nil) {
a = arc4random()% [colorArray count];
}
int y = [[colorArray objectAtIndex:a] integerValue];
what is most likely happening is that [colorArray count] has not the value you expect it to have, so that arc4random only returns 0 (or a limited set of values).
If you add an NSLog trace just before calculating the value for a, you can assess the value for [colorArray count].

Related

Animation in cocos2d crashes

I am having trouble with my game, it was running fine until i tried to add the animation, now whenever i go to shoot it crashes my game and i cant work out what is wrong with my animation code. Below i will put in all the code that causes the ninja star to shoot but as i said i believe the error is in the animation.
ccsprite Projectile is what gets shoot and what im trying to animate
- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
if (StrategyBullet > 0) {
//SOME IF STATEMENTS
if (Strategyscore == 47) {
StrategyBullet = StrategyBullet +5;
}
if (Strategyscore == 97) {
StrategyBullet = StrategyBullet +5;
}
if (Strategyscore == 197) {
StrategyBullet = StrategyBullet +10;
}
// Choose one of the touches to work with
UITouch *touch = [touches anyObject];
CGPoint location = [self convertTouchToNodeSpace:touch];
// Set up initial location of projectile
CGSize winSize = [[CCDirector sharedDirector] winSize];
CCSprite *projectile = [CCSprite spriteWithFile:#"ninja star 1.png"];
[self addChild:projectile z:2];
{
NSString *animationName = #"UNIQUE_ANIMATION_NAME";
CCAnimation* animation = nil;
animation = [[CCAnimationCache sharedAnimationCache] animationByName:animationName];
if(!animation)
{
NSMutableArray *animFrames = [NSMutableArray array];
for( int i=1;i<=5;i++)
{
NSString* path = [NSString stringWithFormat:#"ninja star %d.png", i];
CCTexture2D* tex = [[CCTextureCache sharedTextureCache] addImage:path];
CGSize texSize = tex.contentSize;
CGRect texRect = CGRectMake(0, 0, texSize.width, texSize.height);
CCSpriteFrame* frame = [CCSpriteFrame frameWithTexture:tex rect:texRect];
[animFrames addObject:frame];
}
animation = [CCAnimation animationWithSpriteFrames:animFrames];
animation.delayPerUnit = 0.175f;
animation.restoreOriginalFrame = YES;
[[CCAnimationCache sharedAnimationCache] addAnimation:animation name:animationName];
}
if(animation)
{
CCAnimate *animAction = [CCAnimate actionWithAnimation:animation];
[projectile runAction:animAction];
}
}
projectile.position = ccp(20, winSize.height/2);
// Determine offset of location to projectile
CGPoint offset = ccpSub(location, projectile.position);
// Bail out if you are shooting down or backwards
if (offset.x <= 0) return;
// Ok to add now - we've double checked position
[self addChild:projectile];
int realX = winSize.width + (projectile.contentSize.width/2);
float ratio = (float) offset.y / (float) offset.x;
int realY = (realX * ratio) + projectile.position.y;
CGPoint realDest = ccp(realX, realY);
// Determine the length of how far you're shooting
int offRealX = realX - projectile.position.x;
int offRealY = realY - projectile.position.y;
float length = sqrtf((offRealX*offRealX)+(offRealY*offRealY));
float velocity = 480/1; // 480pixels/1sec
float realMoveDuration = length/velocity;
// collison stuff
projectile.tag = 2;
[_projectiles addObject:projectile];
StrategyBullet --;
[StrategyBulletLabel setString:[NSString stringWithFormat:#"%d", StrategyBullet]];
// Move projectile to actual endpoint
[projectile runAction:
[CCSequence actions:
[CCMoveTo actionWithDuration:realMoveDuration position:realDest],
[CCCallBlockN actionWithBlock:^(CCNode *node) {
[node removeFromParentAndCleanup:YES];
// CCCallBlockN in ccTouchesEnded
[_projectiles removeObject:node];
}],
nil]];
}
}
The crash is because you addChild projectile twice (my best guess). The rest looks ok, although i tend to use sprite sheets for animations as opposed to file-based frames as you do.

Infinite scrolling on a sprite(Parallax)

I am a newbie to the world of cocos2d i am developing my first tutorial and facing one problem
my problem is i have an image (1024 X 320) and my orientation is landscape i need to move that image continuously from right to left for this purpose i have used space shooter tutorial by Ray(Thanks to him) but the image doesn't seem to be appearing again and again.
my code is..
-(id) init
{
if( (self=[super init])) {
CGSize screenSize = [CCDirector sharedDirector].winSize;
// 1) Create the CCParallaxNode
backgroundNode = [CCParallaxNode node];
[self addChild:backgroundNode z:-1];
// 2) Create the sprites we'll add to the CCParallaxNode
Back = [CCSprite spriteWithFile:#"bg_front_spacedust.png"];
//Back.position=ccp(screenSize.width/2, screenSize.height/2);
Back.rotation = -90;
Back1 = [CCSprite spriteWithFile:#"bg_front_spacedust.png"];
Back1.rotation = -90;
// 3) Determine relative movement speeds for space dust and background
CGPoint dustSpeed = ccp(0.1, 0.1);
// 4) Add children to CCParallaxNode
[backgroundNode addChild:Back z:0 parallaxRatio:dustSpeed positionOffset:ccp(screenSize.width/2, screenSize.height/2)];
NSLog(#"back.content width is...%f",Back.contentSize.width);
[backgroundNode addChild:Back1 z:1 parallaxRatio:dustSpeed positionOffset:ccp(screenSize.width/2, screenSize.height*2)];
// 5) Enable updates
[self scheduleUpdate];
}
return self;
}
- (void)update:(ccTime)dt {
// 1) Update background position
CGPoint backgroundScrollVel = ccp(0,-1000);
backgroundNode.position = ccpAdd(backgroundNode.position, ccpMult(backgroundScrollVel, dt));
// 2) Check for background elements moving offscreen
NSArray *spaceDusts = [NSArray arrayWithObjects:Back, Back1, nil];
for (CCSprite *spaceDust in spaceDusts) {
if ([backgroundNode convertToWorldSpace:spaceDust.position].x < -spaceDust.contentSize.width) {
[backgroundNode incrementOffset:ccp(2*spaceDust.contentSize.width,0) forChild:spaceDust];
}
}
}
please help me out of this
Thanks in advance.
try this one
if (backgroundNode.position.y <-screenSize.height*2)
backgroundNode.position = ccp(0,0);
As init method is called only once the approach you are doing will be done only one time you need to again set the Position of the backgroundNode to 0 in your update method.
here the multiple may vary
Try this code it is creating a paralax moving from bottom to top change CGPointMake(0, 1.0) to this CGPointMake(1.0,0) in paraNode addChild line.
-(id) init
{
// always call "super" init
// Apple recommends to re-assign "self" with the "super's" return value
if( (self=[super init]) )
{
float yPos =0.0;
NSMutableString *fileNameString = [[NSMutableString alloc]initWithCapacity:0];
if (IS_IPHONE_5)
{
[fileNameString appendString:#"Background-568h.png"];
yPos= 560.0;
}
else
{
[fileNameString appendString:#"Background.png"];
yPos= 470.0;
}
background1 = [CCSprite spriteWithFile:fileNameString];
background1.tag = 1;
background1.anchorPoint = CGPointMake(0,0);
background2 = [CCSprite spriteWithFile:fileNameString];
background2.tag = 2;
background2.anchorPoint = CGPointMake(0,0);
background3 = [CCSprite spriteWithFile:fileNameString];
background3.tag = 3;
background3.anchorPoint = CGPointMake(0,0);
background4 = [CCSprite spriteWithFile:fileNameString];
background4.tag = 4;
background4.anchorPoint = CGPointMake(0,0);
paraNode = [CCParallaxNode node];
[paraNode addChild:background1 z:1 parallaxRatio:CGPointMake(0, 1.0) positionOffset:CGPointMake(0, 0)];
[paraNode addChild:background2 z:2 parallaxRatio:CGPointMake(0, 1.0) positionOffset:CGPointMake(0, -yPos)];
[paraNode addChild:background3 z:3 parallaxRatio:CGPointMake(0, 1.0) positionOffset:CGPointMake(0, -yPos*2)];
[paraNode addChild:background4 z:4 parallaxRatio:CGPointMake(0, 1.0) positionOffset:CGPointMake(0, -yPos*3)];
[self addChild:paraNode z:-1 tag:123];
[self updateFrameRate:0.7 andYposition:yPos];
[fileNameString release];
fileNameString = nil;
}
return self;
}
-(void)updateFrameRate:(float)speedValue andYposition:(float)yposToSet
{
move1 = [CCMoveBy actionWithDuration:speedValue position:CGPointMake(0, yposToSet)];
move2 = [CCMoveBy actionWithDuration:0.0 position:CGPointMake(0, -yposToSet)];
move3 = [CCMoveBy actionWithDuration:0.0 position:CGPointMake(0, 0)];
CCSequence* sequence = [CCSequence actions:move1,move2,move3, nil];
CCRepeatForever* repeat = [CCRepeatForever actionWithAction:sequence];
[paraNode runAction:repeat];
}

how to change image of moving ccsprite using timer

I have around 10 sprite of same image and these are moving, i want to change the image(2 images) of all sprite alternatively by using timer.
I am using following code but its not working for me
CCSprite *target = [CCSprite spriteWithFile:#"images1.png" rect:CGRectMake(0, 0, 120, 140)];
// Determine where to spawn the target along the Y axis
winSize = [[CCDirector sharedDirector] winSize];
int minY = target.contentSize.height/2;
int maxY = (winSize.height/2) - target.contentSize.height/2;
int rangeY = maxY - minY;
int actualY = (arc4random() % rangeY) ;
// Create the target slightly off-screen along the right edge,
// and along a random position along the Y axis as calculated above
target.position = ccp(winSize.width + (target.contentSize.width/2), actualY);
[self addChild:target];
// Determine speed of the target
int minDuration = 2.0;
int maxDuration = 4.0;
int rangeDuration = maxDuration - minDuration;
int actualDuration = (arc4random() % rangeDuration) + minDuration;
id delayTime1 = [CCDelayTime actionWithDuration:1.0f];
id calFun1 = [CCCallBlock actionWithBlock:^{
//HERE SET BLUE TEXTURE..
[target setTexture:[[CCSprite spriteWithFile:#"image1.png"]texture]];
}];
id delayTime2 = [CCDelayTime actionWithDuration:1.0f];
id calFun2 = [CCCallBlock actionWithBlock:^{
//HERE SET RED TEXTURE..
[target setTexture:[[CCSprite spriteWithFile:#"image2.png"]texture]];
}];
// Create the actions
id actionMove = [CCMoveTo actionWithDuration:actualDuration*2.5 position:ccp(-target.contentSize.width/2, actualY)];
id actionMoveDone = [CCCallFuncN actionWithTarget:self selector:#selector(spriteMoveFinished:)];
id sequece = [CCSequence actions:delayTime1, calFun1, delayTime2, calFun2,actionMove, actionMoveDone, nil];
id repeate = [CCRepeatForever actionWithAction:sequece];
[target runAction:repeate];
But by using this code only one image is continuously showing on sprite. The image is not changing.
Try this
-(CCSpriteFrame *)getImageWithName:(NSString *)image{
CCSprite *sprite=[CCSprite spriteWithFile:image];
CCSpriteFrame *frame=[CCSpriteFrame frameWithTexture:sprite.texture rect:CGRectMake(0, 0, sprite.contentSize.width, sprite.contentSize.height)];
return frame;
}
Then
[target setDisplayFrame:[self getImageWithName:#"image1"]];
[target setDisplayFrame:[self getImageWithName:#"image2"]];

Adding a game over scene

I want to add this game over scene to this game that I am trying to do for my homework, and I seem to not have it where if you kill the target the game over scene will pop up. I tried putting my code in every line and see if it will finally work but no it didn't. So now I have to ask for some help.
. m file
- (void)addTarget10 {
Boss *target10 = nil;
if ((arc4random() % 2) == 0) {{
target10 = [WeakAndFastBoss9 boss9];
}} else {
target10 = [WeakAndFastBoss9 boss9];
}
[[SimpleAudioEngine sharedEngine] playEffect:#"lastboss.mp3"];
// Determine where to spawn the target along the Y axis
CGSize winSize = [[CCDirector sharedDirector] winSize];
int minY = target10.contentSize.height/2;
int maxY = winSize.height - target10.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
target10.position = ccp(winSize.width + (target10.contentSize.width/2), actualY);
[self addChild:target10 ];
// Determine speed of the target
int minDuration = target10.minMoveDuration;
int maxDuration = target10.maxMoveDuration;
int rangeDuration = maxDuration - minDuration;
int actualDuration = (arc4random() % rangeDuration) + minDuration;
// Create the actions
id actionMove = [CCMoveTo actionWithDuration:actualDuration position:ccp(- target10.contentSize.width/2, actualY)];
id actionMoveDone = [CCCallFuncN actionWithTarget:self
selector:#selector(spriteMoveFinished9:)];
[target10 runAction:[CCSequence actions:actionMove, actionMoveDone, nil]];
target10.tag = 1;
[_targets addObject:target10];
}
-(void)gameLogicboss9:(ccTime)dt {
[self unschedule:_cmd];
[self addTarget10];
}
- (void)updateboss9:(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:target1];
bossHit = TRUE;
Boss *boss = (Boss *)target1;
boss.hp--;
if (boss.hp <= 0 ) {
[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];
}
[targetsToDelete release];
}
-(void)spriteMoveFinishedboss9:(id)sender {
CCSprite *sprite = (CCSprite *)sender;
[self removeChild:sprite cleanup:YES];
if (sprite.tag == 1) { // target
[_targets removeObject:sprite];
} else if (sprite.tag == 2) { // projectile
[_projectiles removeObject:sprite];
} }
This the game over scene I want to add when target 10/ boss 9 is killed
GameOverScene *gameOverScene = [GameOverScene node];
[gameOverScene.layer.label setString:#"You Lose"];
[[CCDirector sharedDirector] replaceScene:gameOverScene];
Right now my other game over scene is when the sprite is moved passed screen.If you need me to answer any questions feel free to ask.
For scene replace you try this for your game code..
First Add this code to your GameOverScene class
+(CCScene *) scene
{
// 'scene' is an autorelease object.
CCScene *scene = [CCScene node];
// 'layer' is an autorelease object.
GameOverScene *layer = [GameOverScene node];
// add layer as a child to scene
[scene addChild: layer];
// return the scene
return scene;
}
Make your GameOverClass is subclass of CCLayer,
Than when You want to change scene do this
[[CCDirector sharedDirector] replaceScene:[GameOverScene scene]];
Ok, so you have to create a new scene. This can simple be done using File->New File and make it a subclass of NSObject. You then change the subclass to an CCLayer. As a test, you can just copy your code from the hello world layer. Next, just import the new class in your helloworld layer class and create a instance of it. Then in a method use [[CCDirector sharedDirector] replaceScene:sceneName];
You can use this site for more info, its very helpful, just read through it and you will find your answer:http://www.raywenderlich.com/352/how-to-make-a-simple-iphone-game-with-cocos2d-tutorial

i want my falling sprites to dissapear half way down the screen

im new to programming, i have been experimenting with cocos2d, heres the problem, i have made a simple game, device in portrait, it has falling sprites, and i want the sprite to disappear when the position of the top of the sprite < screen.height/2 how can this be done?
heres some code you may be interested in:
this is the falling sprite, it falls from the top of the screen to the bottom
-(void)addRock {
CCSprite *rock = [CCSprite spriteWithFile:#"rock.png"
rect:CGRectMake(0, 0, 27, 40)];
// Determine where to spawn the target along the X axis
CGSize winSize = [[CCDirector sharedDirector] winSize];
int minX = rock.contentSize.width/2;
int maxX = winSize.width - rock.contentSize.width/2;
int rangeX = maxX - minX;
int actualX = (arc4random() % rangeX) + minX;
// Create the target slightly off-screen along the right edge,
// and along a random position along the X axis as calculated above
rock.position = ccp(actualX, 500);
[self addChild:rock];
// Determine speed of the target
int actualDuration = spriteDuration;//speed of sprite
// Create the actions
id actionMove = [CCMoveTo actionWithDuration:actualDuration position:ccp(actualX,-winSize.height+ rock.contentSize.height)];
id actionMoveDone = [CCCallFuncN actionWithTarget:self selector:#selector(spriteMoveFinished:)];
[rock runAction:[CCSequence actions:actionMove, nil]];
}
when the sprite move has finished
-(void)spriteMoveFinished:(id)sender {
CCSprite *sprite = (CCSprite *)sender;
[self removeChild:sprite cleanup:YES];
}
To fade your sprite out halfway of the Animation you can use CCSpawn to combine the falling animation with the fadeOut. But as you want it to fade out after a given time, you need to create a Sequence of CCDelayTime and CCFadeOut.
double fadeStart = 0.5;
id wait = [CCDelayTime actionWithDuration: actualDuration * fadeStart];
id fadeOut = [CCFadeOut actionWithDuration: actualDuration * (1.0 - fadeStart)];
id waitThenFade = [CCSequence actions: wait, fadeOut, nil];
id actionMove = ...;
id fullAnimation = [CCSpawn actions:actionMove, waitThenFade, nil];
[rock runAction:[CCSequence actions:fullAnimation, actionMoveDone, nil]];
In case you want the fading to start earlier or later you simply have to move the fadeStart value. 0 will start immediately, 1 will actually not fade, so better pick a value in between.
Maybe something like this?
CGSize size = [[CCDirector sharedDirector] winSize];
CCSprite* img = [[CCSprite alloc] initWithFile:#"yourSprite.png"];
img.position = ccp(size.width/2,size.height + img.boundingBox.size.height/2);
[img runAction:[CCSequence actions:
[CCMoveTo actionWithDuration:3 position:ccp(img.position.x,size.height/2 - img.boundingBox.size.height/2)],
[CCFadeOut actionWithDuration:1],
[CCCallFuncN actionWithTarget:nil selector:#selector(spriteMoveFinished:)],
nil]];