How to add a CCsprite to layer from array - objective-c

Hi guys I really need some help, I have been stuck in this part of my game for over a week now and I can't seem to get past this issue, So have look at my code below,
#import "HelloWorldLayer.h"
#import "AppDelegate.h"
#implementation HelloWorldLayer
+(CCScene *) scene
{
// 'scene' is an autorelease object.
CCScene *scene = [CCScene node];
// 'layer' is an autorelease object.
HelloWorldLayer *layer = [HelloWorldLayer node];
// add layer as a child to scene
[scene addChild: layer];
// return the scene
return scene;
}
-(id) init
{
// always call "super" init
// Apple recommends to re-assign "self" with the "super's" return value
if( (self=[super init]) ) {
moles = [[NSMutableArray alloc] init];
winSize = [[CCDirector sharedDirector]winSize];
CCSprite *mole1 = [CCSprite spriteWithFile:#"lightsabericonblue.png"];
[self starCreateCurrentLevel:mole1];
}
return self;
}
-(void)starCreateCurrentLevel:(CCSprite *)mole1{
starCountCurrentLevel = 10;
for (int i = 0; i < starCountCurrentLevel;) {
[moles addObject:mole1];
starCountCurrentLevel--;
}
[self schedule:#selector(tryPopMoles:) interval:1];
}
- (void)tryPopMoles:(ccTime)dt {
if(moles.count != 0){
for (CCSprite *mole in moles) {
if (arc4random() % moles.count == 0) {
if (mole.numberOfRunningActions == 0) {
[self popMole:mole];
}
}
}
}else if(moles.count == 0){
NSLog(#"No More Moles To Spawn");
[self unschedule:#selector(tryPopMoles:)];
}
}
- (void) popMole:(CCSprite *)mole {
mole.position = ccp(150, 150);
[self addChild:mole];
}
- (void) dealloc
{
[moles release];
moles = nil;
[super dealloc];
}
#end
When I run this code i get the following error, * Assertion failure in -[HelloWorldLayer addChild:z:tag:], /Users/....../libs/cocos2d/CCNode.m:335.
I when i add the child in the init method its fine but I don't want to do that, I want to be able to call the try pop mole which will then call the pop mole based on if there is anymore sprites left in the array, I have a feeling I am missing something or doing something wrong.
UPDATE -
#import "HelloWorldLayer.h"
#import "AppDelegate.h"
#pragma mark - HelloWorldLayer
CGSize winSize;
int enemyX;
int enemyY;
int randomAngleY;
int randomAngleX;
int winSizeX;
int winSizeY;
int minDuration = 1;
int maxDuration = 4.0;
int rangeDuration;
int actualDuration;
int starCountCurrentLevel;
int test = 0;
#implementation HelloWorldLayer
+(CCScene *) scene
{
CCScene *scene = [CCScene node];
HelloWorldLayer *layer = [HelloWorldLayer node];
[scene addChild: layer];
return scene;
}
-(id) init
{
if( (self=[super init]) ) {
moles = [[NSMutableArray alloc] init];
winSize = [[CCDirector sharedDirector]winSize];
[self starCreateCurrentLevel];
}
return self;
}
-(void)starCreateCurrentLevel{
starCountCurrentLevel = 10;
for (int i = 0; i < starCountCurrentLevel;) {
[moles addObject:[CCSprite spriteWithFile:#"lightsabericonblue.png"]];
starCountCurrentLevel--;
}
[self schedule:#selector(tryPopMoles:) interval:3];
}
- (void)tryPopMoles:(ccTime)dt {
NSMutableArray *tempArray = [NSMutableArray arrayWithArray:moles];
for (int randomIndex = tempArray.count -1; randomIndex < tempArray.count; randomIndex--) {
CCSprite * sprite = (CCSprite *)[tempArray objectAtIndex:randomIndex];
//CCSprite *sprite = [tempArray objectAtIndex:randomIndex];
[self popMole:sprite];
NSLog(#"Enemy Added");
[tempArray removeObject:sprite];
}
if([tempArray count] == 0){
NSLog(#"No More Moles To Spawn");
[self unschedule:#selector(tryPopMoles:)];
}
}
- (void) popMole:(CCSprite *)sprite {
winSizeX = winSize.width - sprite.contentSize.width + 25;
winSizeY = winSize.height - 25 - sprite.contentSize.height + 17;
randomAngleX = arc4random() % winSizeX;
randomAngleY = arc4random() % winSizeY;
enemyX = arc4random() % winSizeX ;
enemyY = arc4random() % winSizeY;
rangeDuration = maxDuration - minDuration;
actualDuration = (arc4random() % rangeDuration) + minDuration;
sprite.position = ccp(enemyX, enemyY);
[self addChild:sprite];
}
- (void) dealloc
{
[moles release];
moles = nil;
[super dealloc];
}
#end

You're only creating the sprite once, but trying to add it several times. (Remember, these are pointers to objects, so you're always referring to exactly the same sprite.) If you want 10 versions of the same sprite (at different positions, scales, speeds, whatever), you'll need to create the sprite (via the creator method) 10 times. You can do a copy on the original one, or just create it on the fly:
-(void)starCreateCurrentLevel:(CCSprite *)mole1{
starCountCurrentLevel = 10;
for (int i = 0; i < starCountCurrentLevel;) {
//[moles addObject:mole1];
// ^^ You're adding the same sprite (meaning same pointer reference) again and again. Try this instead:
[moles addObject:[CCSprite spriteWithFile:#"lightsabericonblue.png"]];
starCountCurrentLevel--;
}
Of course, now you don't need to pass mole1 into your method. You may (depending on your need) consider passing in a spriteFrameName or something.

Related

Objective C - NSMutableSet not working properly

I have an NSMutableSet that I am trying to add labels to. After each label added, I check the set's count and it comes back as 0. Any help will be appreciated
In my .h file:
#interface MainMenu : CCLayerColor {
NSMutableSet* letters;
}
In my .m file:
-(void)initiateLetters{
//Grab the window size
CGSize size = [[CCDirector sharedDirector] winSize];
int i;
for(i=0;i<100;i++){
CCLabelTTF *label;
int r = rand() % 35 + 60;
char c = (char) r;
label = [CCLabelTTF labelWithString:[NSString stringWithFormat:#"%c",c] fontName:#"Courier" fontSize:30];
[label setColor:ccc3(0,0,0)];
[label setOpacity:255/2];
//Generate a random number for the x variable, y will be 0
int x = (arc4random() % (int)size.width);
int y = size.height+(arc4random() % 50)+25;
[label setPosition:ccp(x,y)];
[self addChild:label];
[letters addObject:label];
//Here's what's printing 0:
printf("%lu",[letters count]);
}
}
You have to instantiate the set before you can add things to it. You can do that in an overridden implementation of init:
- (id)init
{
self = [super init];
if (self) {
letters = [[NSMutableSet alloc] init];
}
return self;
}
…or at the beginning of your initiateLetters method:
- (void)initiateLetters
{
letters = [[NSMutableSet alloc] init];
...
Instead, the code you posted is simply sending addObject: to nil, which does nothing.
the array is probably nil. Did you create it in the class init method ?
something like
-(id) init {
if (self = [super init]){
// ...
letters = [[NSMutableSet set] retain]; // not using ARC
// ...
}
return self;
}
and of course
-(void) dealloc {
// ...
[letters release]; // not using ARC
[super dealloc];
}

The animation just run one time?

The problems is the animation just run one time then cannot repeat again. Do I need to add one more NSTimer in somewhere ?
Anything I missing ? Looking for help and advice. Thanks a lot !
And here is the code.
First, in ViewController.h & ViewController.m
#interface ViewController : UIViewController {
GameView* gameView;
}
- (void)viewDidLoad
{
[super viewDidLoad];
if(gameView == nil) {
gameView = [[GameView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
gameView.backgroundColor = [UIColor clearColor];
}
[self.view addSubview:gameView];
[[AppEngine sharedInstance] addSnow:CGPointMake((random() % 320),(random() % -20))];
[[AppEngine sharedInstance] addSnow:CGPointMake((random() % 320),(random() % -20))];
[[AppEngine sharedInstance] addSnow:CGPointMake((random() % 320),(random() % -20))];
[[AppEngine sharedInstance] addSnow:CGPointMake((random() % 320),(random() % -20))];
[[AppEngine sharedInstance] addSnow:CGPointMake((random() % 320),(random() % -20))];
}
In the GameView.h & .m
#interface GameView : UIView <UIAccelerometerDelegate>{
CADisplayLink* displayLink;
}
-(void) timeStep;
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
displayLink = [CADisplayLink displayLinkWithTarget:self selector:#selector(timeStep)];
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}
return self;
}
-(void) timeStep {
[[AppEngine sharedInstance] timeStep];
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect {
[[UIImage imageNamed:#"Christmas.jpg"] drawInRect:CGRectMake(0,0,320,480)]; // set the background image
CGContextRef context = UIGraphicsGetCurrentContext();
for(MySnow* snowObject in [AppEngine sharedInstance].snowObjectArray)
{
CGContextSaveGState(context);
CGContextTranslateCTM(context, snowObject.x, snowObject.y);
NSString *imagePath = [NSString stringWithFormat:#"snowflake0%d.png",snowObject.type];
[[UIImage imageNamed: imagePath] drawInRect:CGRectMake(-16,-16,32,32)];
CGContextRestoreGState(context);
}
}
Third, in the snow.h & m
#interface MySnow : NSObject
{
float x,y;
float vx, vy;
float rotSpeed;
float rotation;
int type;
}
#property (nonatomic) float x,y;
#property (nonatomic) float vx, vy, rotSpeed,rotation;
#property (nonatomic) int type;
-(id) initWithStartPoint:(CGPoint) startPoint withType:(int) type;
-(void) timeStep;
#implementation MySnow
#synthesize x,y,vx,vy,rotation,rotSpeed,type;
-(id) initWithStartPoint:(CGPoint) startPoint withType:(int) _type {
self = [super init];
if(self) {
x = startPoint.x;
y = startPoint.y;
vx = RANDOM_FLOAT() * 1 + 0.1;
vy = RANDOM_FLOAT() * 2 + 0.1;
type = _type;
}
return self;
}
-(void) timeStep {
y += vy;
}
Finally, in AppEngine.h & m
#interface AppEngine : NSObject {
NSMutableArray* snowObjectArray;
float ax, ay;
}
#property (readonly) NSMutableArray* snowObjectArray;
#property (nonatomic) float ax,ay;
+(AppEngine*) sharedInstance;
+(void) destoryInstance;
-(void) timeStep;
-(void) addSnow:(CGPoint) point;
static AppEngine* _sharedEngine;
#implementation AppEngine
#synthesize snowObjectArray;
#synthesize ax,ay;
+(AppEngine*) sharedInstance {
if(_sharedEngine == nil)
_sharedEngine = [[AppEngine alloc] init];
return _sharedEngine;
}
+(void) destoryInstance {
if(_sharedEngine != nil) {
_sharedEngine = nil;
}
}
-(id) init {
self = [super init];
if(self) {
snowObjectArray = [[NSMutableArray alloc] init];
}
return self;
}
-(void) addSnow:(CGPoint) point {
int type = (arc4random() % 9) + 1; // random snow image 01 to 09
MySnow* snowObject = [[MySnow alloc] initWithStartPoint:point withType:type];
[snowObjectArray addObject:snowObject];
}
-(void) timeStep {
NSMutableArray* removeArray = [NSMutableArray array];
for(MySnow* item in snowObjectArray) {
[item timeStep];
if(item.y > 400 || item.y < -100)
[removeArray addObject:item];
}
[snowObjectArray removeObjectsInArray:removeArray];
[removeArray removeAllObjects];
}
Is this your code? Can you explain how it starts the animation?
It looks to me like the AppEngine's timeStep method has code that specifically deletes each item in the snowObjectsArray once it reaches some boundary. However, if this is your code, why don't you understand what it does?
EDIT: OK, so this is from a lecture.
If you want the animation to continue, here's what I would do:
Take the last block of code from your viewDidLoad method (the code that creates and adds snow objects) and put it in a separate method. Make viewDidLoad call that method. Let's call the method makeItSnow.
Then, at the end of your AppEngine timeStep method, if the object count in snowObjectArray drops to 0, call makeItSnow.
That approach would make a set of snowflakes start at the top, fall down and disappear, and then another group of snowflakes start. If you want a continuous stream of snowflakes to fall, then change the timeStep method to count the number of snowflake objects it deletes, and at the end of the method add that many snowflakes back to the array. That would cause your program to add a new snowflake as each one disappears.
Yet another approach would be to add a repeating timer to AppEngine, and make that timer create another snowflake. That would keep adding snowflakes on a regular interval.

Objective-c [Xcode] CCAnimation not working, cocos2d

i have two animations declared in the player class, and i want to run then from another class but i can't here's my code (If you can't read it here it's on pastebin: http://pastebin.com/iy0eFMWL):
player.h
#interface Player : CCSprite {
CCAnimate *animationOllie;
CCRepeatForever *repeatNormal;
}
player.m:
#implementation Player
-(id)initWithFile:(NSString *)filename
{
if (self = [super initWithFile:filename]) {
self.velocity = ccp(0.0, 0.0);
CCAnimation *ollie = [CCAnimation animation];
[ollie setDelayPerUnit:0.05f];
[ollie addSpriteFrameWithFilename:#"ollie1.png"];
[ollie addSpriteFrameWithFilename:#"ollie2.png"];
animationOllie = [CCAnimate actionWithAnimation:ollie];
CCAnimation *normal = [CCAnimation animation];
[normal setDelayPerUnit:0.05f];
[normal addSpriteFrameWithFilename:#"normal1.png"];
[normal addSpriteFrameWithFilename:#"normal2.png"];
CCAnimate *animationNormal = [CCAnimate actionWithAnimation:normal];
repeatNormal = [CCRepeatForever actionWithAction:animationNormal];
[self runAction:repeatNormal];
}
return self;
}
-(void)animateThePlayer {
[self stopAction:repeatNormal];
[self runAction:animationOllie];
}
And in the GameScene Class:
GameScene.h:
#interface GamePlayLayer : CCLayerColor {
float yVel;
}
GameScene.m:
#import "Player.h"
#interface GamePlayLayer()
{
Player *player;
}
#end
#implementation GamePlayLayer
-(id) init
{
if( (self=[super initWithColor:ccc4(255,255,255,255)] )) {
player = [[Player alloc] initWithFile:#"normal1.png"];
[self addChild:player];
self.isTouchEnabled = YES;
player.position = ccp(85,70);
[self schedule:#selector(update:)];
}
return self;
}
-(void)update:(ccTime)dt {
if (player.position.y > 70) {
yVel -= 0.1;
}
else {
if (yVel != 5.5) {
yVel = 0;
player.position = ccp(player.position.x, 70);
}
}
player.position = ccp(player.position.x, player.position.y + yVel);
}
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
yVel = 5.5;
[player animateThePlayer];
}
And that's it, it builds fine, and everything works but when i click the layer it crashes and i get this message:
0x1df609b: movl 8(%edx), %edi Thread 1: EXC_BAD_ACCESS (code=2,
address=0xf
What can i do? Thanks in advance
The first thing - you try to use autoreleased object. animationOllie will be released after your init method.
The second mistake is that you cannot reuse actions. When you need to run action, you have to recreate it.

What is the proper way to implement animation in a CCSprite subclass?

in my game I made a subclass of CCSprite (cocos2d) for my enemies.
Because I want control over animation, from within every instance of this subclass, I had to translate my animation code in my main class, which loads
the enemies, to this subclass.
I found this rather hard but.... after some time it magically started to work.
Unfortunately after creating and setting properties in this subclass I started to have weird crashes. Because they are in cocosDenshion and other places which have nothing to do with my
enemy class and after a research in depth in my code and on the net, I'm convinced its some kind of data corruption and I'm almost completely certain its because I did my enemie class with his animation code completely the wrong way.
To be honest, I cannot even wrap my mind around what is going on here anymore and how this actually works :S...I'm completely stuck. any help is much appreciated!
So my main questions would be: What is the proper way to implement animation in a CCSprite subclass ? / what am I doing wrong here?
simplified my code here: (it triggers the animation every 2 seconds to show how I want
to use it)
#import "cocos2d.h"
#interface Npc : CCSprite
{
CCAction *_runAnimation;
NSString* name;
int strength;
}
#property (nonatomic, retain) CCAction *runAnimation;
#property int strength;
#property (nonatomic, retain) NSString* name;
- (Npc*)loadAnimation;
- (void)animate;
#end
#import "Npc.h"
#implementation Npc
#synthesize runAnimation = _runAnimation;
#synthesize name;
#synthesize strength;
-(id) initWithTexture:(CCTexture2D*)texture rect:(CGRect)rect
{
if( (self=[super initWithTexture:texture rect:rect]))
{
}
return self;
}
- (Npc*)loadAnimation
{
int lastFrame = 11;
NSString *creatureFile = #"vis 1";
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:
[NSString stringWithFormat:#"%#.plist", creatureFile]];
CCSpriteBatchNode* sheet = [CCSpriteBatchNode batchNodeWithFile:
[NSString stringWithFormat:#"%#.png", creatureFile]];
self = [Npc spriteWithTexture:sheet.texture];
NSMutableArray* animFrames = [[NSMutableArray alloc] init];
for (int x = 0; x < lastFrame; x++)
{
[animFrames addObject:
[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:
[NSString stringWithFormat:#"%# %d.png", creatureFile, x]]];
}
CCAnimation* anim = [CCAnimation animationWithFrames: animFrames delay: 0.1];
self.runAnimation = [CCAnimate actionWithAnimation:anim restoreOriginalFrame:NO];
[self runAction:_runAnimation];
return self;
}
- (void)animate
{
[self runAction:self.runAnimation];
}
- (void)dealloc
{
[super dealloc];
[name release];
}
#end
#import "HelloWorldLayer.h"
#import "Npc.h"
#implementation HelloWorldLayer
+(CCScene *) scene
{
CCScene *scene = [CCScene node];
HelloWorldLayer *layer = [HelloWorldLayer node];
[scene addChild: layer];
return scene;
}
-(id) init
{
if( (self=[super init]))
{
timer = 0;
creatureTemp = [Npc spriteWithFile:#"Icon.png"];
creature = [creatureTemp loadAnimation];
creature.position = ccp(100,100);
[self addChild:creature];
[self schedule:#selector(nextFrame:)];
}
return self;
}
- (void)nextFrame:(ccTime)dt
{
timer += dt;
if (timer > 2.)
{
[creature animate];
timer = 0.;
}
}
- (void) dealloc
{
[super dealloc];
}
#end
-------------------EDIT--------------------
I changed my code with help of a tutorial by Ray Wenderlich: http://www.raywenderlich.com/3888/how-to-create-a-game-like-tiny-wings-part-1
this is I think much closer to what it should be. Unfortunately it still crashes on my iphone (not the simulator) on SimpleAudioEngine (which I implement right) so I still do something wrong.
on top of the Npc class:
#synthesize batchNode = _batchNode;
the init of the Npc class:
-(id) initNpc
{
if( (self=[super initWithSpriteFrameName:#"vis 1 0.png"]))
{
_normalAnim = [[CCAnimation alloc] init];
NSMutableArray* animFrames = [[NSMutableArray alloc] init];
int lastFrame = 11;
for (int x = 0; x < lastFrame; x++)
{
[animFrames addObject:
[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:
[NSString stringWithFormat:#"vis 1 %d.png", x]]];
}
_normalAnim = [CCAnimation animationWithFrames: animFrames delay: 0.1];
self.runAnimation = [CCAnimate actionWithAnimation:_normalAnim restoreOriginalFrame:NO];
}
return self;
}
and the init of the HelloWorldLayer
-(id) init
{
if( (self=[super init]))
{
timer = 0;
_batchNode = [CCSpriteBatchNode batchNodeWithFile:#"vis 1.png"];
[self addChild:_batchNode];
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"vis 1.plist"];
creature = [[[Npc alloc] initNpc] autorelease];
creature.position = ccp(200,200);
[_batchNode addChild:creature];
[self schedule:#selector(nextFrame:)];
[[SimpleAudioEngine sharedEngine] preloadEffect:#"super1.mp3"];
}
return self;
}
You're reassigning self in loadAnimation:
self = [Npc spriteWithTexture:sheet.texture];
At that point I stopped reading the code. Since self already is an instance of the Npc class you have to ask yourself why you're doing this in an Npc instance method like loadAnimation.
So, I got it....here is the code:
Npc.h:
#import "cocos2d.h"
#interface Npc : CCSprite
{
CCAction *_runAnimation;
CCAnimation *_normalAnim;
CCAnimate *_normalAnimate;
}
#property (nonatomic, retain) CCAction *runAnimation;
- (void)animate;
- (id)initNpc;
#end
Npc.m
#synthesize runAnimation = _runAnimation;
#synthesize batchNode = _batchNode;
-(id) initNpc
{
if( (self=[super initWithSpriteFrameName:#"vis 1 0.png"]))
{
_normalAnim = [[CCAnimation alloc] init];
NSMutableArray* animFrames = [[NSMutableArray alloc] init];
int lastFrame = 7;
for (int x = 0; x < lastFrame; x++)
{
[animFrames addObject:
[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:
[NSString stringWithFormat:#"vis 1 %d.png", x]]];
}
_normalAnim = [CCAnimation animationWithFrames: animFrames delay: 0.1];
self.runAnimation = [CCAnimate actionWithAnimation:_normalAnim restoreOriginalFrame:NO];
}
return self;
}
- (void)animate
{
[self runAction:_runAnimation];
}
in the HelloWorldLayer.m
-(id) init
{
if( (self=[super init]))
{
_batchNode = [CCSpriteBatchNode batchNodeWithFile:#"vis 1.png"];
[self addChild:_batchNode];
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"vis 1.plist"];
timer = 0;
creature = [[[Npc alloc] initNpc] autorelease];
creature.position = ccp(200,200);
[_batchNode addChild:creature];
[self schedule:#selector(nextFrame:)];
}
return self;
}
- (void)nextFrame:(ccTime)dt
{
timer += dt;
if (timer > 2.)
{
[creature animate];
timer = 0.;
}
}
And about the weird crashes in cocosDenshion. That is also solved...it turned out to be a known bug in SimpleAudioEngine where it threw exceptions only when I had an exception breakpoint active. Workaround: made a class for my sound and if I need a exception breakpoint, I comment out the sound...
-- have to say, I do would prefer the:
_batchNode = [CCSpriteBatchNode batchNodeWithFile:#"vis 1.png"];
[self addChild:_batchNode];
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"vis 1.plist"];
inside the Npc class, but that is too advanced oop for me. If anybody knows that, let me know...would be great to know actually, to understand oop better.
But it is not strictly necessary...

Strange Crash, No Debugger Clues

I am currently running this Block of code in my Level1.m file, this is the scene for the first level of my game.
#import "BankerL1.h"
#import "GameOverScene.h"
#import "BankerGameWin1.h"
// HelloWorldLayer implementation
#implementation BankerL1Layer
#synthesize label = _label;
#synthesize Banker = _Banker;
#synthesize WalkAction = _WalkAction;
#synthesize MoveAction = _MoveAction;
+(CCScene *) scene
{
// 'scene' is an autorelease object.
CCScene *scene = [CCScene node];
// 'layer' is an autorelease object.
BankerL1Layer *layer = [BankerL1Layer node];
// add layer as a child to scene
[scene addChild: layer];
// return the scene
return scene;
}
// on "init" you need to initialize your instance
-(id) init
{
// always call "super" init
// Apple recommends to re-assign "self" with the "super" return value
if( (self=[super init])) {
CGSize winSize = [[CCDirector sharedDirector] winSize];
CCSprite *background = [CCSprite spriteWithFile:#"Ninja Menu Background.png"];
background.position = ccp(winSize.width/2, winSize.height/2);
[self addChild:background z:-1];
CCLabelTTF *Levelcounter = [CCLabelTTF labelWithString:#"Level 1" fontName:#"Marker Felt" fontSize:40];
Levelcounter.position = ccp(winSize.width * 0.80,winSize.height * 0.92);
[self addChild: Levelcounter];
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile: #"GreenorcSpriteSheet_default.plist"];
CCSpriteBatchNode *spriteSheet = [CCSpriteBatchNode batchNodeWithFile:#"GreenorcSpriteSheet_default.png"];
[self addChild:spriteSheet];
NSMutableArray *walkAnimFrames = [NSMutableArray array];
for(int i = 1; i <=6; ++i) {
[walkAnimFrames addObject: [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName: [NSString stringWithFormat:#"Greenorc%d.png", i]]];
}
CCAnimation *walkAnim = [CCAnimation animationWithFrames:walkAnimFrames delay:0.1f];
self.Banker = [CCSprite spriteWithSpriteFrameName:#"Greenorc1.png"];
_Banker.position = ccp(winSize.width/2, (winSize.height/2)-190);
self.WalkAction = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:walkAnim restoreOriginalFrame:NO]];
//[_Banker runAction:_WalkAction];
[spriteSheet addChild:_Banker];
self.isTouchEnabled = YES;
_targets = [[NSMutableArray alloc] init];
}
return self;
}
- (void) onEnter
{
// First, call super if you override this. ALWAYS.
[super onEnter];
[self schedule:#selector(gameLogic:) interval:1.5];
[self scheduleUpdate]; // use this instead of schedule: if it's for an update method.
}
//Implements the Callback function above
-(void)gameLogic:(ccTime)dt {
[self addTarget];
}
-(void)spriteMoveFinished:(id)sender {
CCSprite *sprite = (CCSprite *)sender;
[self removeChild:sprite cleanup:YES];
if (sprite.tag == 1) { // target
[_targets removeObject:sprite];
GameOverScene *gameOverScene = [GameOverScene node];
[gameOverScene.layer.label setString:#"You Lose :["];
[[CCDirector sharedDirector] replaceScene:gameOverScene];
} else if (sprite.tag == 2) { // projectile
[_targets removeObject:sprite];
}
}
//Adds the "targets" or in this case enemies, to the scene and spawns/moves them
-(void)addTarget {
CCSprite *target = [CCSprite spriteWithFile:#"seeker.png"
rect:CGRectMake(0, 0, 40, 40)];
target.tag = 1;
[_targets addObject:target];
// Determine where to spawn the target along the X axis
CGSize winSize = [[CCDirector sharedDirector] winSize];
int minX = target.contentSize.height/2;
int maxX = winSize.height - target.contentSize.height/2;
int rangeX = maxX - minX;
int actualX = (arc4random() % rangeX) + minX;//Randomizes the place it will spawn on X- Axis
// Create the target slightly off-screen along the top edge,
// and along a random position along the Y axis as calculated above
target.position = ccp(actualX, winSize.height + (target.contentSize.height/2));
[self addChild:target];
// Determine speed of the target
int minDuration = 2.0;
int maxDuration = 5.0;
int rangeDuration = maxDuration - minDuration;
int actualDuration = (arc4random() % rangeDuration) + minDuration;//Speed is randomized between 2 and 5
// Create the actions
id actionMove = [CCMoveTo actionWithDuration:actualDuration
position:ccp(actualX, -target.contentSize.height/2)];
id actionMoveDone = [CCCallFuncN actionWithTarget:self
selector:#selector(spriteMoveFinished:)];
[target runAction:[CCSequence actions:actionMove, actionMoveDone, nil]];
}
//WHEN THE THINGS COLLIDE, THEY DISSAPEAR
- (void)update:(ccTime)dt {
CGSize winSize = [[CCDirector sharedDirector] winSize];
NSMutableArray *targetsToDelete = [[NSMutableArray alloc] init];
for (CCSprite *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);
BOOL playerHit = FALSE;
for (CCSprite *player in _targets) {
CGRect playerRect = CGRectMake(
player.position.x - (player.contentSize.width/2),
player.position.y - (player.contentSize.height/2),
player.contentSize.width,
player.contentSize.height);
if (CGRectIntersectsRect(playerRect, targetRect)) {
//[targetsToDelete addObject:target];
playerHit = TRUE;
[targetsToDelete addObject:target];
break;
}
}
for (CCSprite *target in targetsToDelete) {
[_targets removeObject:target];
[self removeChild:target cleanup:YES];
_targetsDestroyed++;
[_label setString:[NSString stringWithFormat:#""]];
if (_targetsDestroyed > 30) {
GameWinScene *gameWinScene = [GameWinScene node];
_targetsDestroyed = 0;
[[CCDirector sharedDirector] replaceScene:gameWinScene];
} else{
NSString *killcounttext = [NSString stringWithFormat:#"Catches: %i", _targetsDestroyed];
self.label = [CCLabelTTF labelWithString:killcounttext fontName:#"Zapfino" fontSize:20];
_label.color = ccc3(225,225,225);
_label.position = ccp(winSize.width * 0.20,winSize.height * 0.92);
[self addChild:_label];
}
}
if (targetsToDelete.count > 0) {
[targetsToDelete addObject:target];
}
[targetsToDelete release];
}
for (CCSprite *target in targetsToDelete) {
[_targets removeObject:target];
[self removeChild:target cleanup:YES];
//[[SimpleAudioEngine sharedEngine] playEffect:#"ProjectileHit.wav"];
}
[targetsToDelete release];
}
-(void) registerWithTouchDispatcher
{
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0
swallowsTouches:YES];
}
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
return YES;
}
-(void) ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event {
CGPoint touchLocation = [touch locationInView: [touch view]];
touchLocation = [[CCDirector sharedDirector] convertToGL: touchLocation];
touchLocation = [self convertToNodeSpace:touchLocation];
float bankerVelocity = 320.0/2.0;
CGPoint moveDifference = ccpSub(touchLocation, _Banker.position);
float distanceToMove = ccpLength(moveDifference);
float moveDuration = distanceToMove / bankerVelocity;
if (moveDifference.x < 0) {
_Banker.flipX = NO;
} else {
_Banker.flipX = YES;
}
[_Banker stopAction:_MoveAction];
if (!_Moving) {
[_Banker runAction:_WalkAction];
}
self.MoveAction = [CCSequence actions:
[CCMoveTo actionWithDuration:moveDuration position:touchLocation],
[CCCallFunc actionWithTarget:self selector:#selector(bearMoveEnded)],
nil];
[_Banker runAction:_MoveAction];
_Moving = TRUE;
}
-(void)bearMoveEnded {
[_Banker stopAction:_WalkAction];
_Moving = FALSE;
}
// on "dealloc" you need to release all your retained objects
- (void) dealloc
{
// in case you have something to dealloc, do it in this method
// in this particular example nothing needs to be released.
// cocos2d will automatically release all the children (Label)
self.Banker = nil;
self.WalkAction = nil;
// don't forget to call "super dealloc"
[super dealloc];
}
#end
The scene starts and everything works fine except as soon as a target is added (this is what I think is happeneing) the game freezes and crashes.
I don't know if the target being added is what is causing the crash, but it seems that whenever it is time for the target to come on, it crashes.
There is nothing in the debugger that says the game crashed, Xcode things the game is still running even though it is frozen. Please help :/ thanks
retain the _targets array in the init method like this: _targets = [[[NSMutableArray alloc] init] retain];