我正在制作游戏,除重启按钮外,一切正常。我希望游戏能够从重启方法重新开始,该方法将所有内容加载到屏幕上并设置游戏玩法。但是我得到一个错误,说“因未捕获的异常而终止应用程序'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
有什么想法?
杰克
答案 0 :(得分:0)
您似乎调用了一个类方法(+),您需要调用实例方法( - )。您只需要重置所有资源,但不需要重置整个对象。而且,作为一种类方法,您的+(void)resetAll
方法没有任何意义,因为它没有返回值。
我建议,您可以将所有资源初始化代码放在一个方法中,当您需要重新启动时,只需调用[self removeAllChildrenWithCleanup:]
并调用指定的resource-init方法。