如何重新启动Cocos2D应用程序



我正在制作一款游戏,除了重新启动按钮外,所有内容都有效。我希望游戏能够通过重启方法重新开始,即将所有内容加载到屏幕上并设置游戏玩法。然而,我得到一个错误说"终止应用程序由于未捕获的异常'NSInvalidArgumentException',原因:'-[HelloWorldLayer resetAll:]:无法识别的选择器发送到实例0x9142c70'"

下面是主类的代码(我假设你们不需要其他类,因为它们工作得很好):

    #import "HelloWorldLayer.h"
    #import "AppDelegate.h"
    #import "Block.h"
    #import "Character.h"
    @implementation HelloWorldLayer
    -(id) init{ //Init method
       if(self = [super initWithColor:ccc4(84,56,8,26)]){     //Initialise with a black background
        [self restart];
    }
    return self;
     }
    -(void) setUpMenus{
    moveRight = [CCMenuItemImage itemWithNormalImage:@"GoRightButton.png"     selectedImage:@"GoRightButtonSelected.png" target: self selector:@selector(moveRightMethod:)];
    moveLeft = [CCMenuItemImage itemWithNormalImage:@"GoLeftButton.png" selectedImage:@"GoLeftButtonSelected.png" target: self selector:@selector(moveLeftMethod:)];
    moveUp = [CCMenuItemImage itemWithNormalImage:@"GoUpButton.png" selectedImage:@"GoUpButtonSelected.png" target: self selector:@selector(moveUpMethod:)];
    moveDown = [CCMenuItemImage itemWithNormalImage:@"GoDownButton.png" selectedImage:@"GoDownButtonSelected.png" target: self selector:@selector(moveDownMethod:)];

    moveRight.position = ccp(player.image.position.x - 10, player.image.position.y);
    moveLeft.position = ccp(player.image.position.x - 80, player.image.position.y);
    moveUp.position = ccp(player.image.position.x - 40, player.image.position.y + 30);
    moveDown.position = ccp(player.image.position.x - 40, player.image.position.y - 30);
    myScore.position = ccp(player.image.position.x - 20, player.image.position.y + 100);
    mainMenu = [CCMenu menuWithItems:moveRight, moveLeft, moveUp, moveDown, nil];
    [self addChild: mainMenu];
  }
    -(void) enemyMoveTowardsPlayer{
    CGPoint playerPosition = player.image.position;
    [enemy moveToLocationEnemy:&playerPosition];
    }
     -(void) moveRightMethod: (id) sender{
    if(enemyExists == YES){
        [self enemyMoveTowardsPlayer];
    }
    if(player.image.position.x < 5000){
        [player move];
        [self changeBack];
    }
    }
-(void) moveLeftMethod: (id) sender{
    if(enemyExists == YES){
        [self enemyMoveTowardsPlayer];
    }
    if(player.image.position.x > 20){
        [player moveLeft];
        [self change];
    }
    }
    -(void) moveUpMethod: (id) sender{
    if(enemyExists == YES){
        [self enemyMoveTowardsPlayer];
    }
    if(player.image.position.y < 7000){
        [player moveUp];
        [self changeUp];
    }
    }
    -(void) moveDownMethod: (id) sender{
    if(player.image.position.y > -100){
        [player moveDown];
        [self changeDown];
    }
    if(enemyExists == YES){
        [self enemyMoveTowardsPlayer];
    }
    }
    -(void) callSpawnEnemy{
    CCSprite *enemyImage = [CCSprite spriteWithFile:@"Lizard_Sprite.png"];     //Enemy picture
    enemy = [[Character alloc] initWithImageAndNameAndProjectile:enemyImage     
     andAnotherParam:@"Enemy"];
    //Enemy instantiation
    enemy.image.position = ccp(100,400);
    [self addChild:enemy.image];            //Add the enemy image object
    enemyExists = YES;
}
     -(void)ccTouchesBegan:(NSSet*)touches withEvent:(UIEvent*)event{
    //CODE FOR HANDLING TOUCH EVENTS. THE BELOW CODE SIMPLY CREATES AND INSTANTIATES A TOUCH   OBJECT AND STORES THE LOCATION
    CGPoint touchLocation;
    for(UITouch *touch in touches ) {
        touchLocation = [touch locationInView: [touch view]];
        CGPoint prevLocation = [touch previousLocationInView: [touch view]];
        touchLocation = [[CCDirector sharedDirector] convertToGL: touchLocation];
        prevLocation = [[CCDirector sharedDirector] convertToGL: prevLocation];
        CGPoint diff = ccpSub(touchLocation,prevLocation);
        [self setPosition: ccpAdd(self.position, diff)];
    }
    //
    NSLog(@"%f", touchLocation.x);
    NSLog(@"%f",touchLocation.y);
}
-(void) change{                     //Code to change the image to a leftward facing sprite
    CCTexture2D* tex = [[CCTextureCache sharedTextureCache] addImage:@"PlayerSpriteLeftHugeV2.png"];
    [player.image setTexture: tex];
}  
-(void) changeBack{                 //Code to change the image to a rightward facing sprite
    CCTexture2D* tex = [[CCTextureCache sharedTextureCache] addImage:@"PlayerSpriteHugeV2.png"];
    [player.image setTexture: tex];
}
-(void) changeUp{                     //Code to change the image to a leftward facing sprite
    CCTexture2D* tex = [[CCTextureCache sharedTextureCache] addImage:@"PlayerSpriteUp.png"];
    [player.image setTexture: tex];
}
-(void) changeDown{                 //Code to change the image to a rightward facing sprite
    CCTexture2D* tex = [[CCTextureCache sharedTextureCache] addImage:@"PlayerSpriteDown.png"];
    [player.image setTexture: tex];
}
-(void) generate2dMap{                 //Method to generate a 130 by 80 block map (10400 blocks)
    for(int i = 20; i < 13000; i+=100){          //X coordinate. Increment by length of each block.
        for(int g = 20; g < 8000; g+=100){      //Y coordinate. Increment by length of each block.
            CGPoint p = CGPointMake(i, g);      //Point for the block. Changes every time the loop goes through
            int randNumber = rand() % 11;       //Random number to determine the block type
            if(randNumber < 1){             //Only 1 in 10 blocks should be gold blocks
                Block* gold = [[Block alloc] initWithTypePositionAndImage:@"Gold" andImageName:[CCSprite spriteWithFile:@"GoldBlockHuge.png"]];
                //Create a gold object and pass the appropriate information to the constructor
                [allBlocks addObject: gold];    //Add the gold object to the mutable array
                gold.image.position = p;        //Set the block image position to be the current location
                [self addChild:gold.image];    //Add the block image to the screen
            }
            else{   //More common. Should occur 9/10 times
            Block* dirt = [[Block alloc]
                           initWithTypePositionAndImage:@"Dirt" andImageName:[CCSprite spriteWithFile:@"DirtBlockHuge.png"]];
             //Create a dirt object and pass the appropriate information to the constructor
            [allBlocks addObject: dirt]; //Add the dirt object to the mutable array
            dirt.image.position = p;        //Set the block image position to be the current location
                [self addChild:dirt.image]; //Add the block image to the screen
            }
        }
    }
}
-(void) checkScore{            //Update the score. Set the score object to be the score primative from the player object
    [myScore setString:[NSString stringWithFormat:@"%d", player->score]];
    stringScore = myScore.string;
}
-(BOOL) checkForCollisions{     //Method to check for collision detection
    for(Block *b in allBlocks){ //Loop through all blocks to check if any have collided with the player image
        CGRect playerRect = CGRectMake(player.image.position.x, player.image.position.y, 90, 84);
        //Rectangle object for the player
        CGRect blockRect = CGRectMake(b.image.position.x, b.image.position.y, 50, 50);
        //Rectangle object for each block

        if(CGRectIntersectsRect(playerRect, blockRect)){        //If the block is in the state of intersecting the player
            amountOfBlocks++;
            collisionSprite = b;    //Set the collision object to be the block
            if([collisionSprite.type isEqualToString:@"Gold"]){ //If  it's collided with a gold object...
                [player incrementScoreBy:100];      //Then increment the score by 100
            }
            else if([collisionSprite.type isEqualToString:@"Bronze"]){
                [player incrementScoreBy:20];
            }
            else if([collisionSprite.type isEqualToString:@"Silver"]){
                [player incrementScoreBy:50];
            }
            else if([collisionSprite.type isEqualToString:@"Dirt"]){
                [player incrementScoreBy:2];
            }
            return YES;     //There has been a collision, and you should terminate this round of the method
        }
        if(enemyExists == YES){
            CGRect enemyRect = CGRectMake(enemy.image.position.x, enemy.image.position.y, 80,80);
            if(CGRectIntersectsRect(enemyRect, blockRect)){
                collisionSprite = b;
                enemyHitBlock = YES;
                return YES;
            }
            if(CGRectIntersectsRect(enemyRect, playerRect)){
                enemyHitPlayer = YES;
                return YES;
            }
        }
    }
    return NO;  //There has not been a collision, and you should terminate this round of the method
}
-(void) update: (ccTime) dt{       //Update method called on regular interval that checks for collisions, updates the score
    if(isDone == NO){
        if([self checkForCollisions]){      //Check for collisions
            [self removeChild:collisionSprite.image cleanup:YES]; //Remove the sprite if there has been a collision
            [allBlocks removeObject:collisionSprite];       //Remove the object if there has been a collision
            if(enemyExists == YES){
                if(enemyHitPlayer == YES){
                    [self removeChild:enemy.image cleanup:YES];
                    enemyHitPlayer = NO;
                    enemyExists = NO;
                }
                if(enemyHitBlock == YES){
                    [self removeChild:collisionSprite.image cleanup:YES]; //Remove the sprite if there has been a collision
                    enemyHitBlock = NO;
                }
            }
        }
        mainMenu.position = ccp(player.image.position.x - 10, player.image.position.y);
        myScore.position = ccp(player.image.position.x - 20, player.image.position.y + 100);
        if(enemyExists == NO){
            [self callSpawnEnemy];
        }
        [self checkScore];      //Update the score
        if([stringScore intValue] >= 200){
            [self endGame];
        }
    }
}
-(void) endGame{
    isDone = YES;
    endGameString = @"You reached the max score in ";
    stringBlockCount = [NSString stringWithFormat:@"%d blocks", amountOfBlocks];
    totalString = [endGameString stringByAppendingString:stringBlockCount];
    endGameMessage = [CCLabelTTF labelWithString:totalString fontName:@"Times New Roman" fontSize:20];
    CGSize winSize = [[CCDirector sharedDirector] winSize];
    CGPoint point = ccp(winSize.height/2,winSize.width/2);
    endGameMessage.position = point;
    [self stopAllActions];
    [self runAction:[CCFollow actionWithTarget:endGameMessage]];
    [self removeAllChildrenWithCleanup:YES];
    [self addChild: endGameMessage];
    restart = [CCMenuItemImage itemWithNormalImage:@"RestartButton.png" selectedImage:@"RestartButtonSelected.png" target: self selector:@selector(resetAll:)];
    restart.position = ccp(point.x - 500, point.y - 250);
    restartMenu = [CCMenu menuWithItems:restart, nil];
    [self addChild:restartMenu];
}
-(void) restart{
    [self removeAllChildrenWithCleanup:YES];
    NSLog(@"Got here");
    isDone = NO;
    amountOfBlocks = 0;
    allBlocks = [[NSMutableArray alloc] init];      //Instantiate array that holds all blocks
    collisionSprite = [[Block alloc] init];     //Instantiate object that holds the collision object
    enemyCollisionSprite = [[Character alloc] init];
    enemyHitBlock = NO;
    enemyHitPlayer = NO;
    [self generate2dMap];       //Generate the map
    self.isTouchEnabled = YES;  //Enable touch technology
    CCSprite *playerImage = [CCSprite spriteWithFile:@"PlayerSpriteHugeV2.png"];  //Player image object
    player = [[Character alloc] initWithImageAndNameAndProjectile:playerImage andAnotherParam:@"Player"];
    //Instantiate player object
    player.image.position = ccp(0,210);        //Set player image position
    //Set player projectile image position
    stringScore = [NSString stringWithFormat:@"%d", player->score];   //Score object
    myScore = [CCLabelTTF labelWithString:stringScore fontName:@"Times New Roman" fontSize:20];
    //CCLabel representation of score
    myScore.position = ccp(20,300);     //Set position of label score
    myScore.color = ccc3(255,255,255);  //Set color of label score
    [self addChild:myScore];        //Add the score object
    [self addChild:player.image];      //Add the player image object
    [self callSpawnEnemy];
    [self setUpMenus];
    [self moveForward];
    [self schedule:@selector(update:) interval:0.005];  //Schedule updating on 0.005 second intervals
}
+(void) resetAll{
    [[CCDirector sharedDirector] replaceScene:[HelloWorldLayer scene]];
}
-(void) moveForward{        //Method to move the camera forward
    [self runAction:[CCFollow actionWithTarget:player.image]];
}
+(CCScene*) scene{
    CCScene *scene = [CCScene node];
    HelloWorldLayer *layer = [HelloWorldLayer node];
    [scene addChild: layer];
    return scene;
}
-(void) dealloc{
    [super dealloc];
}
-(void) achievementViewControllerDidFinish:(GKAchievementViewController *)viewController{
    AppController *app = (AppController*) [[UIApplication sharedApplication] delegate];
    [[app navController] dismissModalViewControllerAnimated:YES];
}
-(void) leaderboardViewControllerDidFinish:(GKLeaderboardViewController *)viewController{
    AppController *app = (AppController*) [[UIApplication sharedApplication] delegate];
        [[app navController] dismissModalViewControllerAnimated:YES];
    }
    @end

任何想法吗?

杰克

似乎您在需要调用实例方法(-)的地方调用了类方法(+)。你只需要重置所有的资源,而不是整个对象。而且,作为一个类方法,你的+(void)resetAll方法是没有意义的,因为它没有返回值。

我建议,你可以把所有的资源初始化代码放到一个方法中,当你需要重启的时候,只需要调用[self removeAllChildrenWithCleanup:]并调用指定的资源初始化方法。

最新更新