Problems with cocos2d schedule method selectors - objective-c

I have the following code (that should be correct):
- (void) loadIntro:(ccTime)unused {
[[GameManager sharedGameManager] runWithSceneID:kIntroScene]; // fade to the intro screen
}
- (void) loadAppScreen {
CCSprite *commodoreScreenLoaded = [CCSprite spriteWithFile:#"CommodoreLoadedApp.png"];
useBackgroundImage(commodoreScreenLoaded);
[self addChild:commodoreScreenLoaded];
}
- (void) ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView: [touch view]];
// location = [[CCDirector sharedDirector] convertToGL:location];
CGRect mySurface = (CGRectMake(100, 100, 320, 480));
if (CGRectContainsPoint(mySurface, location)) {
//[[CCDirector sharedDirector] stopAnimation];
play(#"InsertGameCartridge.wav");
[self removeChild:commodoreScreen cleanup:YES];
[self loadAppScreen];
[self schedule:#selector(loadIntro:) interval:2.5f]; // <-- Right here!
}
But when I run it, it logs a really weird error:
2012-07-29 12:21:41.186 Apocanaut[7299:707] *** Assertion failure in -[CCTimer initWithTarget:selector:interval:repeat:delay:],/Users/chris/src/Apps/Games/Apocanaut/Apocanaut/libs/cocos2d/CCScheduler.m:111
2012-07-29 12:21:41.190 Apocanaut[7299:707] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Signature not found for selector - does it have the following form? -(void) name: (ccTime) dt'
EDIT:
It seems to be coming from a method in the GameManager class, which I've implemented a scene called runWithSceneID:
- (void) runWithSceneID:(SceneTypes)sceneID {
SceneTypes oldScene = currentScene;
currentScene = sceneID;
id sceneToRun = nil;
switch (sceneID) {
case kMenuScene:
sceneToRun = [MenuScene node];
break;
case kCommodoreScene:
sceneToRun = [CommodoreScene node];
break;
case kIntroScene:
sceneToRun = [IntroScene node];
break;
default:
CCLOG(#"No scene ID to load");
return;
break;
}
if (sceneToRun == nil) {
currentScene = oldScene;
return;
}
if ([[CCDirector sharedDirector] runningScene] == nil) {
[[CCDirector sharedDirector] runWithScene:sceneToRun];
} else {
[[CCDirector sharedDirector] replaceScene:
[CCTransitionFade transitionWithDuration:kStandardTransitionDuration scene:sceneToRun]];
}
}

Not certain why it makes a difference, but in certain cases this has solved some really opaque bugs of this nature for me. Declare your method in a private category as such (MPBattleSequencer is one of my scenes, use your own class):
#interface MPBattleSequencer (private)
// snip-x-snip
-(void) loadIntro:(ccTime)unused;
#end

Related

Implementing Game Center with Sprite Kit

I'm unable to implement Game Center into my SpriteKit game.
Most tutorials I've screen require a ViewDidLoad which my game does not have.
I am unable to find correct code to Authenticate my game, or it could be that I have the correct code but am placing it in the wrong area of my application.
Currently I have placed the Authentication in the initWithSize:
#import <GameKit/GameKit.h>
#interface GameScene ()
...
#implementation GameScene
...
-(id)initWithSize:(CGSize)size { /* Setup your scene here */
if (self = [super initWithSize:size]) {
self.anchorPoint = CGPointMake(0.5,0.5);
self.physicsWorld.contactDelegate = self;
...
...
**(I HAVE BEEN PLACING AUTHENTICATE CODE FOUND ON INTERNET HERE, BUT NOTHING FOUND TO BE WORKING)**
}
return self;
}
The below code is where I have a UILabel node called "Leaderboards" where I want my player to be able to click, and enable the user to login to game center and view the leaderboards, along with his own score.
(When clicked currently, it says "Game Center Unavailable, Player not signed in", and then after clicking OK, the user is unable to return to the game, but is left with the game screen frozen?)
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:location];
//if fire button touched, bring the rain
if ([node.name isEqualToString:#"LBButtonNode"]) {
NSLog(#"leader boards opened");
GKLeaderboardViewController *leaderboardController = [[GKLeaderboardViewController alloc] init];
if (leaderboardController != NULL)
{
leaderboardController.timeScope = GKLeaderboardTimeScopeAllTime;
leaderboardController.leaderboardDelegate = self;
GKGameCenterViewController *gameCenterController = [[GKGameCenterViewController alloc] init];
if (gameCenterController != nil)
{
gameCenterController.viewState = GKGameCenterViewControllerStateLeaderboards;
UIViewController *vc = self.view.window.rootViewController;
[vc presentViewController: gameCenterController animated: YES completion:nil];
}
}
}
else if(!self.isStarted) {
[self start];
}
else if (self.isGameOver) {
[self clear];
}
else if (self.isStarted) {
[hero jump];
}
}
How do I correctly implement the Game Center feature using SpriteKit?

Dealloc gives warnings

I am practicing making a simple app that switches scenes with a scene controller (state manager) class.
I created my scene:
+(CCScene *) scene
{
CCScene *scene = [CCScene node];
GameMenu *layer = [GameMenu node];
[scene addChild: layer];
return scene;
}
-(id)init{
if ((self = [super init])){
self.isTouchEnabled = YES;
CGSize winSize = [[CCDirector sharedDirector] winSize];
gameMenuLabel = [CCLabelTTF labelWithString:#"This is the Main Menu. Click to Continue" fontName:#"Arial" fontSize:13];
gameMenuLabel.position = ccp(winSize.width/2, winSize.height/1.5);
[self addChild:gameMenuLabel];
}
return self;
}
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(#"ccTouchesBegan: called from MainMenu object");
[[StateManager sharedStateManager] runSceneWithID:kGamePlay];
}
-(void)dealloc{
[gameMenuLabel release];
gameMenuLabel = nil;
[super dealloc];
}
#end
But I keep getting this warning: https://dl.dropbox.com/u/1885149/Screen%20Shot%202012-10-06%20at%205.23.43%20PM.png (probably not much help, but figured I would link the screenshot.
I think it has something to do with the dealloc. If I comment out the dealloc in my scene, I do not get this warning. Any help would be greatly appreciated, thanks.
This is my statemanager's method for switching scenes:
-(void)runSceneWithID:(SceneTypes)sceneID {
SceneTypes oldScene = currentScene;
currentScene = sceneID;
id sceneToRun = nil;
switch (sceneID) {
case kSplashScene:
sceneToRun = [SplashScene node];
break;
case kGameMenu:
sceneToRun = [GameMenu node];
break;
case kGamePlay:
sceneToRun = [GamePlay node];
break;
case kGameOver:
sceneToRun = [GameOver node];
break;
default:
CCLOG(#"Unknown ID, cannot switch scenes");
return;
break;
}
if (sceneToRun == nil) {
// Revert back, since no new scene was found
currentScene = oldScene;
return;
}
if ([[CCDirector sharedDirector] runningScene] == nil) {
[[CCDirector sharedDirector] runWithScene:sceneToRun];
} else {
[[CCDirector sharedDirector] replaceScene:sceneToRun];
}
}
You should give a retain property to gameMenuLabel like this
#property (nonatomic, retain) CCLabelTTF* gameMenuLabel; //in .h file
And write this....
self.gameMenuLabel = [CCLabelTTF labelWithString:#"This is the Main Menu. Click to Continue" fontName:#"Arial" fontSize:13];
instead of this...
gameMenuLabel = [CCLabelTTF labelWithString:#"This is the Main Menu. Click to Continue" fontName:#"Arial" fontSize:13];
The problem is that you are giving an autoreleased object to gameMenuLabel and then releasing again that object in the dealloc section. Hence, the crash.

cocos2d ccTintTo, implementing an endless changing color label

Instead of writing all those lines at the init method of HelloWorldLayer :
CCTintTo* tint1 = [CCTintTo actionWithDuration:2 red:255 green:0 blue:0];
CCTintTo* tint2 = [CCTintTo actionWithDuration:2 red:0 green:0 blue:255];
....
CCSequence* sequence = [CCSequence actions:tint1, tint2, nil];
[label runAction:sequence];
I tried to make the label change color forever but got stucked:
I don't know where to place the relavant commands+ dealing with the integers x,y,z
I tried to do the randomize process at the update method,but didn't have any access to the label, any ideas?
// HelloWorldLayer.h
// Essentials
//
// Created by Steffen Itterheim on 14.07.10.
// Copyright Steffen Itterheim 2010. All rights reserved.
//
#import "cocos2d.h"
#interface HelloWorld : CCLayer
{
CCTintTo* tint1;
CCSequence* sequence1;
// CCLabelTTF* label; even tried property
}
// returns a Scene that contains the HelloWorld as the only child
+(id) scene;
#end
//
// HelloWorldLayer.m
// Essentials
//
// Created by Steffen Itterheim on 14.07.10.
// Copyright Steffen Itterheim 2010. All rights reserved.
//
#import "HelloWorldScene.h"
#import "MenuScene.h"
integer_t x;
integer_t y;
integer_t z;
#implementation HelloWorld
+(id) scene
{
CCScene* scene = [CCScene node];
CCLayer* layer = [HelloWorld node];
[scene addChild:layer];
return scene;
}
-(id) init
{
if ((self = [super init]))
{
CCLOG(#"init %#", self);
// enable touch input
self.isTouchEnabled = YES;
CGSize size = [[CCDirector sharedDirector] winSize];
// add the "touch to continue" label
CCLabelTTF* label = [CCLabelTTF labelWithString:#"Touch Screen For Awesome" fontName:#"AmericanTypewriter-Bold" fontSize:30];
label.position = CGPointMake(size.width / 2, size.height / 8);
[self addChild:label];
[self schedule:#selector(update:) interval:1/60.0f];
/*
tint1 = [CCTintTo actionWithDuration:2 red:x green:y blue:z];
sequence1 = [CCSequence actions:tint1, nil ];
id goaction=[CCRepeatForever actionWithAction:sequence1];
[label runAction:goaction];
*/
}
return self;
}
-(void) registerWithTouchDispatcher
{
// call the base implementation (default touch handler)
[super registerWithTouchDispatcher];
//[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:INT_MIN+1 swallowsTouches:YES];
}
-(void) update:(ccTime)delta
{
x=(integer_t )(CCRANDOM_0_1()*255); y=(integer_t )(CCRANDOM_0_1()*255); z=(integer_t )(CCRANDOM_0_1()*255);
tint1 = [CCTintTo actionWithDuration:2 red:x green:y blue:z ];
sequence1 = [CCSequence actions:tint1, nil ];
[HelloWorld.label runAction:goaction]; //property label not found on object of type 'HelloWorld'
}
// Touch Input Events
-(CGPoint) locationFromTouches:(NSSet *)touches
{
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [touch locationInView: [touch view]];
return [[CCDirector sharedDirector] convertToGL:touchLocation];
}
-(void) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
}
-(void) ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
CGPoint location = [self locationFromTouches:touches];
CCLOG(#"touch moved to: %.0f, %.0f", location.x, location.y);
}
-(void) ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
// the scene we want to see next
CCScene* scene = [MenuScene scene];
CCTransitionSlideInR* transitionScene = [CCTransitionSlideInR transitionWithDuration:3 scene:scene];
[[CCDirector sharedDirector] replaceScene:transitionScene];
}
-(void) ccTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
}
-(void) dealloc
{
CCLOG(#"dealloc: %#", self);
// always call [super dealloc] at the end of every dealloc method
[super dealloc];
}
#end
If you want the tint color to be random for each time, then you cannot use CCTintTo directly inside CCRepeatForever. You need to re-randomize the RGB values for each CCTintTo action. Thus you need to embed the randomization process inside the action by using block. Here is how:
// do this in init method
__block void (^changeTint)(CCNode*) = [[^(CCNode *node) {
GLubyte x = (integer_t)(CCRANDOM_0_1()*255), y = (integer_t)(CCRANDOM_0_1()*255), z = (integer_t)(CCRANDOM_0_1()*255);
[node runAction:[CCSequence actionOne:[CCTintTo actionWithDuration:2 red:x green:y blue:z]
two:[CCCallBlockN actionWithBlock:changeTint]]];
} copy] autorelease];
changeTint(label);
You should look at CCRepeatForever action. As the name implies, it will repeat the action it points to forever. So you should remove your update method where you are changing the colors, and return to the CCSequence code that you had, and embed that in a CCRepeatForever action:
CCTintTo* tint1 = [CCTintTo actionWithDuration:2 red:255 green:0 blue:0];
CCTintTo* tint2 = [CCTintTo actionWithDuration:2 red:0 green:0 blue:255];
....
CCSequence* sequence = [CCSequence actions:tint1, tint2, nil];
CCAction* repeat = [CCRepeatForever actionWithAction:sequence];
[label runAction:repeat];

UIViewController stops receiving touch events on UIWebView

I am working on a magazine viewer and I have to use UIWebView for pages because of html5 interactive contents. First I tried uiwebviews in a UIScrollView but scrollview was too slow on sliding pages.
So now I am trying to write my own scrollview-like code. I have a MainView.xib, a view controller (Viewer) and extended UIWindow class (TouchCapturingWindow) that I take from here : http://wyldco.com/blog/2010/11/how-to-capture-touches-over-a-uiwebview/
when I try to slide pages fast, there is no problem but when I touch and slowly slide by not pulling my finger, "Viewer" view controller stops receiving touch events and so pages stop moving. I am logging TouchCapturingWindow, it still sending events. I searched many information and tutorials but I couldn't make it work. How can I make it continuously receive touch events?
I uploaded a simple Xcode project that contains only this part of my project. You can download here : http://testdergi.mysys.com/touchEvents.zip
When you run project, you should first download pages (180Kb) by tapping "Download Pages" button, then tap the "Open Viewer" button.
You can also look over the code below :
TouchCapturingWindow.h :
#interface TouchCapturingWindow : UIWindow {
NSMutableArray *views;
#private
UIView *touchView;
}
- (void)addViewForTouchPriority:(UIView*)view;
- (void)removeViewForTouchPriority:(UIView*)view;
#end
TouchCapturingWindow.m :
#implementation TouchCapturingWindow
- (void)dealloc {
}
- (void)addViewForTouchPriority:(UIView*)view {
if ( !views ) views = [[NSMutableArray alloc] init];
[views addObject:view];
}
- (void)removeViewForTouchPriority:(UIView*)view {
if ( !views ) return;
[views removeObject:view];
}
- (void)sendEvent:(UIEvent *)event {
//get a touch
UITouch *touch = [[event allTouches] anyObject];
//check which phase the touch is at, and process it
if (touch.phase == UITouchPhaseBegan) {
for ( UIView *view in views ) {
//if ( CGRectContainsPoint([view frame], [touch locationInView:[view superview]]) ) {
NSLog(#"TouchCapturingWindow --> TouchPhaseBegan");
touchView = view;
[touchView touchesBegan:[event allTouches] withEvent:event];
break;
}
}
else if (touch.phase == UITouchPhaseMoved) {
NSLog(#"TouchCapturingWindow --> TouchPhaseMoved");
if ( touchView ) {
[touchView touchesMoved:[event allTouches] withEvent:event];
}
else
{
NSLog(#"touch view is nil");
}
}
else if (touch.phase == UITouchPhaseCancelled) {
NSLog(#"TouchCapturingWindow --> TouchPhaseCancelled");
if ( touchView ) {
[touchView touchesCancelled:[event allTouches] withEvent:event];
touchView = nil;
}
}
else if (touch.phase == UITouchPhaseEnded) {
NSLog(#"TouchCapturingWindow --> TouchPhaseEnded");
if ( touchView ) {
[touchView touchesEnded:[event allTouches] withEvent:event];
touchView = nil;
}
}
//we need to send the message to the super for the
//text overlay to work (holding touch to show copy/paste)
[super sendEvent:event];
}
#end
Viewer.h :
#interface Viewer : UIViewController{
int currentPage;
int totalPages;
IBOutlet UIView *pagesView;
int lastTchX;
int difference;
BOOL hasMoved;
int touchBeganSeritX;
}
- (IBAction)backBtnClicked:(id)sender;
- (void)loadImages;
- (void)animationDidStop;
- (void)loadSinglePage:(int)pageNo;
#property (nonatomic, retain) IBOutlet UIView *pagesView;
#end
Viewer.m :
#interface Viewer ()
#end
#implementation Viewer
#synthesize pagesView;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (IBAction)backBtnClicked:(id)sender
{
[self.navigationController popViewControllerAnimated:YES];
}
- (void)loadImages
{
for(UIView *subView in pagesView.subviews)
{
[subView removeFromSuperview];
}
currentPage = 1;
totalPages = 12;
for(int count = 1; count <= 12; count++)
{
[self loadSinglePage:count];
}
}
- (void)loadSinglePage:(int)pageNo
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory , NSUserDomainMask, YES);
NSString *cachesDir = [paths objectAtIndex:0];
NSString *pagesDir = [NSString stringWithFormat:#"%#/pages", cachesDir];
int pageX = (pageNo - 1) * 768;
UIWebView *aPageWebView = [[UIWebView alloc] init];
[aPageWebView setFrame:CGRectMake(pageX, 0, 768, 1024)];
aPageWebView.backgroundColor = [UIColor clearColor];
aPageWebView.opaque = YES;
[aPageWebView setClearsContextBeforeDrawing:YES];
aPageWebView.clipsToBounds = NO;
[aPageWebView setScalesPageToFit:YES];
NSString *hamData = [NSString stringWithFormat:#"<!DOCTYPE html><html><head><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"user-scalable=yes, width=1024, height=1365, maximum-scale=1.0\"><style type=\"text/css\">body {margin:0; padding:0;}</style></head><body bgcolor=\"#508CCF\"><div id=\"touchable\" style=\"top:0px; left:0px; width:1024px; height:1365px; background-image:url(%#.jpg)\"></div></body></html>", [[NSNumber numberWithInt:pageNo] stringValue]];
[aPageWebView loadHTMLString:hamData baseURL:[NSURL fileURLWithPath:pagesDir isDirectory:YES]];
aPageWebView.scrollView.bounces = NO;
[aPageWebView.scrollView setMaximumZoomScale:1.3333f];
[aPageWebView.scrollView setMinimumZoomScale:1.0f];
aPageWebView.scrollView.zoomScale = 1.0f;
[aPageWebView setMultipleTouchEnabled:YES];
[pagesView addSubview:aPageWebView];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(#"touchesBegan");
UITouch *myTouch = [[event allTouches] anyObject];
int curTchX = [myTouch locationInView:self.view].x;
lastTchX = curTchX;
hasMoved = NO;
touchBeganSeritX = pagesView.frame.origin.x;
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(#"Viewer : .....moved");
hasMoved = YES;
UITouch *myTouch = [[event allTouches] anyObject];
int curTchX = [myTouch locationInView:self.view].x;
difference = curTchX - lastTchX;
int newX = (pagesView.frame.origin.x + difference);
if(newX <= 0)
{
[pagesView setFrame:CGRectMake((pagesView.frame.origin.x + difference), 0, pagesView.frame.size.width, 1024)];
}
lastTchX = curTchX;
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(#"touchesEnded");
if(hasMoved == YES)
{
hasMoved = NO;
int curSeritX = pagesView.frame.origin.x;
curSeritX = curSeritX / (-1);
int newX = 0;
if(difference < 0) //Sağa geçilecek
{
if((currentPage + 1) <= totalPages)
{
currentPage++;
}
}
else //Sola geçilecek
{
if((currentPage - 1) >= 1)
{
currentPage--;
}
}
newX = (currentPage - 1)*768*(-1);
[UIView animateWithDuration:0.2f
delay:0.0f
options:UIViewAnimationOptionCurveEaseOut
animations:^{
// Do your animations here.
[pagesView setFrame:CGRectMake(newX, 0, pagesView.frame.size.width, pagesView.frame.size.height)];
}
completion:^(BOOL finished){
if (finished) {
// Do your method here after your animation.
}
}];
}
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(#"touchesCancelled");
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
#end
I am answering my own question. I found something after a hard work. I changed "(void)sendEvent:(UIEvent *)event" method like the code below. I saw that use of "[super sendEvent:event];" after UITouchPhaseMoved phase is problematic.
- (void)sendEvent:(UIEvent *)event {
//we need to send the message to the super for the
//text overlay to work (holding touch to show copy/paste)
//[super sendEvent:event];
//get a touch
UITouch *touch = [[event allTouches] anyObject];
//check which phase the touch is at, and process it
if (touch.phase == UITouchPhaseBegan) {
for ( UIView *view in views ) {
//if ( CGRectContainsPoint([view frame], [touch locationInView:[view superview]]) ) {
NSLog(#"TouchCapturingWindow --> TouchPhaseBegan");
touchView = view;
[touchView touchesBegan:[event allTouches] withEvent:event];
break;
}
[super sendEvent:event];
}
else if (touch.phase == UITouchPhaseMoved) {
NSLog(#"TouchCapturingWindow --> TouchPhaseMoved");
if ( touchView ) {
[touchView touchesMoved:[event allTouches] withEvent:event];
int curTchX = [touch locationInView:self].x;
NSLog(#"curTchX : %d", curTchX);
}
else
{
NSLog(#"touch view is nil");
}
}
else if (touch.phase == UITouchPhaseCancelled) {
NSLog(#"TouchCapturingWindow --> TouchPhaseCancelled");
if ( touchView ) {
[touchView touchesCancelled:[event allTouches] withEvent:event];
touchView = nil;
}
[super sendEvent:event];
}
else if (touch.phase == UITouchPhaseEnded) {
NSLog(#"TouchCapturingWindow --> TouchPhaseEnded");
if ( touchView ) {
[touchView touchesEnded:[event allTouches] withEvent:event];
touchView = nil;
}
[super sendEvent:event];
}
//we need to send the message to the super for the
//text overlay to work (holding touch to show copy/paste)
}
But the new problem is; if I add a video in a web page, and try to forward the video with its slider, page is moving. I have to find a way to detect if user taps on a video.

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];