我正在开发一款即将完成的游戏,但我遇到了一个我无法自行解决的问题(说实话,有多个问题,但是让其他问题保存一下)。
我的游戏组织如下:MainMenu - > GameScene - >暂停/ GAMEOVER Pause和GameOver菜单基本上只是由Sprite和Label节点组成的叠加层。
在游戏中,有一个玩家需要避免触及每隔x个时间产生的敌人。我通过重复一个永远运行代码块的SKAction来实现这一点。
当游戏暂停时(当点击暂停按钮时),它会将布尔值(isPaused)更改为YES,这会导致每个方法停止。它还消除了敌人产生的行动。
当游戏重新启动时,它会删除当前存在的所有内容并重新创建整个场景。
问题出在这里:每当我点击暂停按钮时,菜单就会出现,然后然后退出应用(只是背景并没有实际退出)并返回并按重新启动,敌人不会产生ergo动作不运行(节点计数不会上升,我检查)。
以下是一些代码:
我不会放入所有内容,所以如果你发现某些东西不存在,那么原始代码中就可能出现这种情况。
在GameScene.m中:
-(void)didMoveToView:(SKView *)view {
if (!self.contentCreated) {
[self createSceneContents];
self.contentCreated = YES;
}
}
-(void)createSceneContents {
self.isTouchingGround = NO;
self.isPaused = NO;
self.world = [SKNode node];
NSLog(@"likewhatever");
self.playerCategory = 1;
self.enemyCategory = 2;
self.edgeCategory = 4;
self.bottomCategory = 8;
self.playerScore = 0;
[GameDataHelper sharedGameData].score = 0;
self.physicsWorld.contactDelegate = self;
SKSpriteNode *bottom = [SKSpriteNode spriteNodeWithColor:[SKColor blackColor] size:CGSizeMake(self.frame.size.width, 10)];
bottom.position = CGPointMake(self.frame.size.width/2, 0);
bottom.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:bottom.size];
bottom.physicsBody.dynamic = NO;
bottom.physicsBody.restitution = 0;
bottom.physicsBody.categoryBitMask = self.bottomCategory;
bottom.physicsBody.contactTestBitMask = self.playerCategory | self.enemyCategory;
SKSpriteNode *left = [[SKSpriteNode alloc]init];
left.size = CGSizeMake(1, self.frame.size.height);
left.position = CGPointMake(0, self.frame.size.height/2);
left.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:left.size];
left.physicsBody.dynamic = NO;
left.physicsBody.restitution = 0;
SKSpriteNode *right = [[SKSpriteNode alloc]init];
right.size = CGSizeMake(1, self.frame.size.height);
right.position = CGPointMake(self.frame.size.width - 1, self.frame.size.height/2);
right.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:right.size];
right.physicsBody.dynamic = NO;
right.physicsBody.restitution = 0;
self.backgroundColor = [SKColor blackColor];
self.playerData = [[Player alloc]init];
self.customUnit = self.frame.size.width/7;
self.player = [self.playerData newPlayer:self.customUnit];
self.player.physicsBody.categoryBitMask = self.playerCategory;
self.player.physicsBody.contactTestBitMask = self.enemyCategory | self.edgeCategory | self.bottomCategory;
self.player.position = CGPointMake(CGRectGetMidX(self.frame), self.customUnit*5);
[self.playerData movementSetup];
[self createUI];
NSString *path = [NSString stringWithFormat:@"%@/gamemusic2.mp3", [[NSBundle mainBundle]resourcePath]];
NSURL *mainMusicURL = [NSURL fileURLWithPath:path];
self.mainMusicPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:mainMusicURL error:nil];
self.mainMusicPlayer.volume = 0.1;
self.mainMusicPlayer.numberOfLoops = -1;
[self.mainMusicPlayer play];
[self spawnObject];
[self addChild:self.world];
[self.world addChild:bottom];
[self.world addChild:self.player];
[self addChild:left];
[self addChild:right];
[self addChild:self.pause];
[self addChild:self.scoreLabelInGame];
[self addChild:self.actualScore];
}
-(void)createUI {
self.pause = [SKSpriteNode spriteNodeWithImageNamed:@"pausebutton.png"];
self.pause.size = CGSizeMake(self.customUnit,self.customUnit);
self.pause.name = @"pauseButton";
self.pause.position = CGPointMake(30, self.frame.size.height - 30);
self.pausedImage = [SKSpriteNode spriteNodeWithImageNamed:@"paused.png"];
self.pausedImage.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)*1.5);
self.restart = [SKLabelNode labelNodeWithFontNamed:@"Futura"];
self.restart.text = @"RESTART";
self.restart.fontSize = 25;
self.restart.position = CGPointMake(CGRectGetMidX(self.frame), self.pausedImage.position.y - self.pausedImage.position.y/5);
self.resume = [SKLabelNode labelNodeWithFontNamed:@"Futura"];
self.resume.text = @"RESUME";
self.resume.fontSize = 25;
self.resume.position = CGPointMake(self.restart.position.x, self.restart.position.y - self.customUnit);
self.scoreLabelInGame = [SKLabelNode labelNodeWithFontNamed:@"Futura"];
self.scoreLabelInGame.text = @"";
self.scoreLabelInGame.fontSize = 25;
self.scoreLabelInGame.position = CGPointMake(self.frame.size.width - 100, self.frame.size.height - 40);
self.actualScore = [SKLabelNode labelNodeWithFontNamed:@"Futura"];
self.actualScore.text = @"SCORE: 0";
self.actualScore.fontSize = 25;
self.actualScore.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeRight;
self.actualScore.position = CGPointMake(self.frame.size.width - 20, self.frame.size.height - 40);
self.deathImage = [SKSpriteNode spriteNodeWithImageNamed:@"youdied.png"];
self.deathImage.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)*1.5);
}
-(void)spawnObject {
NSLog(@"called");
if (self.isPaused == NO){
NSLog(@"notpaused");
self.spawningSpeed = 1.5;
self.enemyData = [[Enemy alloc]init];
SKAction *wait = [SKAction waitForDuration:self.spawningSpeed];
SKAction *run = [SKAction runBlock:^{
NSLog(@"spawned");
SKSpriteNode *aNewEnemy = [self.enemyData createEnemyWithSize:self.customUnit andWidth:self.frame.size.width andHeight:self.frame.size.height + self.player.position.y];
aNewEnemy.physicsBody.allowsRotation = NO;
aNewEnemy.physicsBody.categoryBitMask = self.enemyCategory;
aNewEnemy.physicsBody.collisionBitMask = self.enemyCategory | self.playerCategory | self.edgeCategory | self.bottomCategory;
aNewEnemy.physicsBody.contactTestBitMask = self.enemyCategory | self.playerCategory | self.edgeCategory | self.bottomCategory;
[self.world addChild:aNewEnemy];
}];
SKAction *action = [SKAction repeatActionForever:[SKAction sequence:@[wait,run]]];
[self runAction:action withKey:@"spawn"];
}
}
-(void)didBeginContact:(SKPhysicsContact *)contact {
if (self.isPaused == NO) {
SKPhysicsBody *firstBody, *secondBody;
if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask) {
firstBody = contact.bodyA;
secondBody = contact.bodyB;
}else {
firstBody = contact.bodyB;
secondBody = contact.bodyA;
}
if (firstBody.categoryBitMask == self.playerCategory && secondBody.categoryBitMask == self.bottomCategory) {
self.isTouchingGround = YES;
}
if (firstBody.categoryBitMask == self.playerCategory && secondBody.categoryBitMask == self.enemyCategory) {
self.isTouchingGround = YES;
if ([secondBody.node.name isEqualToString:@"fallingEnemy"] && self.player.position.y < secondBody.node.position.y) {
[self gameOver];
}
}
if (firstBody.categoryBitMask == self.enemyCategory && secondBody.categoryBitMask == self.enemyCategory) {
[self.enemyData changeBlock:firstBody.node];
[self.enemyData changeBlock:secondBody.node];
[self impactSound];
[self updateScore];
NSLog(@"Change1");
}
if (firstBody.categoryBitMask == self.enemyCategory && secondBody.categoryBitMask == self.bottomCategory) {
NSLog(@"Change2");
[self.enemyData changeBlock:firstBody.node];
[self impactSound];
[self updateScore];
}
}
}
-(void)pauseGame {
NSLog(@"Pausing...");
[self removeActionForKey:@"spawn"];
[self addChild:self.pausedImage];
[self addChild:self.restart];
[self addChild:self.resume];
NSString *path = [NSString stringWithFormat:@"%@/menu_music.mp3", [[NSBundle mainBundle]resourcePath]];
NSURL *pauseMusicURL = [NSURL fileURLWithPath:path];
self.pauseMusicPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:pauseMusicURL error:nil];
self.pauseMusicPlayer.numberOfLoops = -1;
[self.pauseMusicPlayer play];
[self.pause removeFromParent];
self.scoreLabelInGame.position = CGPointMake(self.restart.position.x, self.resume.position.y - self.customUnit);
self.actualScore.position = CGPointMake(self.restart.position.x, self.scoreLabelInGame.position.y - self.customUnit);
self.isPaused = YES;
[self.mainMusicPlayer pause];
}
-(void)restartGame {
[self removeAllChildren];
[self removeAllActions];
self.isPaused = NO;
[self.pauseMusicPlayer stop];
[self createSceneContents];
}
-(void)resumeGame {
self.isPaused = NO;
[self.pauseMusicPlayer stop];
[self spawnObject];
self.scoreLabelInGame.position = CGPointMake(self.frame.size.width - 100, self.frame.size.height - 40);
self.actualScore.position = CGPointMake(self.frame.size.width - 20, self.frame.size.height - 40);
[self.mainMusicPlayer play];
[self.restart removeFromParent];
[self.resume removeFromParent];
[self.pausedImage removeFromParent];
[self addChild:self.pause];
}
-(void)gameOver {
NSLog(@"Game Over");
GameDataHelper *gameData = [[GameDataHelper alloc]init];
[self removeActionForKey:@"spawn"];
[self addChild:self.restart];
[self addChild:self.deathImage];
SKAction *gameOverSound = [SKAction playSoundFileNamed:@"gameover_tune.mp3" waitForCompletion:NO];
[self runAction:gameOverSound];
NSString *path = [NSString stringWithFormat:@"%@/menu_music.mp3", [[NSBundle mainBundle]resourcePath]];
NSURL *pauseMusicURL = [NSURL fileURLWithPath:path];
self.pauseMusicPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:pauseMusicURL error:nil];
self.pauseMusicPlayer.numberOfLoops = -1;
[self.pauseMusicPlayer play];
[self.pause removeFromParent];
SKLabelNode *highScore = [SKLabelNode labelNodeWithFontNamed:@"Futura"];
NSString *highScoreText = [NSString stringWithFormat:@"HIGHSCORE: %ld",[GameDataHelper sharedGameData].highScore];
highScore.text = highScoreText;
highScore.fontSize = 25;
highScore.position = CGPointMake(self.frame.size.width/2, self.restart.position.y - (2*self.customUnit));
[self addChild:highScore];
self.scoreLabelInGame.position = CGPointMake(self.restart.position.x, self.resume.position.y - self.customUnit);
self.actualScore.position = CGPointMake(self.restart.position.x, self.scoreLabelInGame.position.y - self.customUnit);
self.isPaused = YES;
[self.mainMusicPlayer pause];
[gameData save];
}
在Enemy.m中:
-(SKSpriteNode *)createEnemyWithSize:(float)size andWidth:(float)width andHeight:(float)height {
self.enemy = [SKSpriteNode spriteNodeWithImageNamed:@"block.png"];
self.enemy.size = CGSizeMake(size - 5, size - 5);
self.enemy.name = @"fallingEnemy";
self.enemy.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(size - 3, size - 3)];
self.enemy.physicsBody.restitution = 0;
self.enemy.physicsBody.allowsRotation = NO;
int randomSection = arc4random_uniform(7);
switch (randomSection) {
case 0:
self.enemy.position = CGPointMake(2.5 + self.enemy.size.width/2, height-5);
break;
case 1:
self.enemy.position = CGPointMake(width/7 + self.enemy.size.width/2, height-5);
break;
case 2:
self.enemy.position = CGPointMake((width/7*2) + self.enemy.size.width/2, height-5);
break;
case 3:
self.enemy.position = CGPointMake((width/7*3) + self.enemy.size.width/2, height-5);
break;
case 4:
self.enemy.position = CGPointMake((width/7*4) + self.enemy.size.width/2, height-5);
break;
case 5:
self.enemy.position = CGPointMake((width/7*5) + self.enemy.size.width/2, height-5);
break;
case 6:
self.enemy.position = CGPointMake((width/7*6) + self.enemy.size.width/2, height-5);
break;
default:
break;
}
return self.enemy;
}
-(void)changeBlock:(SKNode *)block{
block.physicsBody.dynamic = NO;
block.name = @"staticEnemy";
}
答案 0 :(得分:0)
我遇到了一个非常类似的问题(并注意到你的其他问题属于类似的问题)。我幸运能够解决问题,并希望我能为您提供一些见解。
我的情况: 我正在创建一个基于物理的游戏,它使用粒子发射器和SKActions来处理游戏的某些方面。但是,我注意到这些&#34;打破了#34;从insactive返回时;这是粒子发射器没有显示任何东西,尽管在进入后台之前和之后所有属性都是相同的,并且SKActions即使在从非活动状态返回后被初始化也不起作用。和你一样,我使用了自定义&#34; isPaused &#34;变量以维持游戏状态。
我的解决方案: 更改&#34; isPaused &#34;的名称标记为&#34; gameIsPaused &#34;。
<强>为什么吗 我的研究让我相信它与场景对孩子的影响以及SpriteKit进入背景时的作用有所不同。虽然苹果公司并没有公开发生什么事情,但各种论坛似乎表明当应用程序处于非活动状态时,SpriteKit会自动暂停现场。
但是,让你自己的&#34; isPaused&#34;变量,我认为你正在踩到导致这些错误的一些引擎盖过程。
利用NSNotification中心(What is causing my SKAction timer to behave strangely?)的其他解决方案按预期工作,重命名&#34; isPaused &#34;标志。