そのため、キャラクターのヘルスが 100 未満の場合 (テスト目的)、シーンを停止してゲーム オーバー シーンに移行するように設定しました。
if (playerDataManager.playerHealth < 100) {
[[CCDirector sharedDirector] replaceScene:[CCTransitionFade transitionWithDuration:3 scene: [GameLogic scene]]];
}
ただし、プレイヤーのヘルスが 100 を下回ると、新しいシーンに移動しますが、FPS は 60 から 5 に劇的に低下します。
のリストを取得すると、OpenGL error 0x0503 in -[EAGLView swapBuffers]
そのように約 40 秒間フリーズしたままになり、その後 FPS がフリーズして 60 に戻り、次のリストを取得します。2012-07-13 10:37:50.234 Tilegame[93513:10a03] cocos2d: removeChildByTag: child not found!
その後、通常どおりアプリを続行し、メイン メニューに戻って新しいゲームを開始し、エラーを再現します。
#import "HelloWorldLayer.h"
#import "Menu.h"
#import "SimpleAudioEngine.h"
#import "LogCabinMap.h"
#import "LogShedMap.h"
#import "SaveData.h"
#import "pauseM.h"
#import "Player.h"
#import "GameLogic.h"
CCSprite *player;
CGPoint newPos;
int joyDegrees;
// HelloWorldLayer implementation
@implementation HelloWorldLayer
@synthesize tileMap = _tileMap;
@synthesize background = _background;
@synthesize buildings = _buildings;
@synthesize meta = _meta;
@synthesize player = _player;
@synthesize foreground = _foreground;
@synthesize numCollected = _numCollected;
@synthesize hud = _hud;
-(void) animateEnemy:(CCSprite*)enemy {
//speed of the enemy
ccTime actualDuration = .2;
id actionMove;
int distanceFromPlayer = ccpDistance(player.position, enemy.position);
if (distanceFromPlayer < 200) { //Check whether enemy can "see" Ninja before moving towards him.
//rotate to face the player
CGPoint diff = ccpSub(player.position,enemy.position);
float angleRadians = atanf((float)diff.y / (float)diff.x);
float angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians);
float cocosAngle = -1 * angleDegrees;
if (diff.x < 0) {
cocosAngle += 180;
}
enemy.rotation = cocosAngle;
actionMove = [CCMoveBy actionWithDuration:actualDuration
position:ccpMult(ccpNormalize(ccpSub(player.position,enemy.position)),10)];
} else {
actionMove = [CCMoveBy actionWithDuration:actualDuration
position:ccpMult(ccpNormalize(ccpSub(player.position,enemy.position)),0)];
}
id actionMoveDone = [CCCallFuncN actionWithTarget:self
selector:@selector(enemyMoveFinished:)];
[enemy runAction:[CCSequence actions:actionMove, actionMoveDone, nil]];
}
// callback. starts another iteration of enemy movement.
- (void) enemyMoveFinished:(id)sender {
CCSprite *enemy = (CCSprite *)sender;
[self animateEnemy: enemy];
}
-(void)addEnemyAtX:(int)x y:(int)y {
CCSprite *enemy = [CCSprite spriteWithFile:@"enemy1.png"];
enemy.position = ccp(x, y);
[self addChild:enemy];
[self animateEnemy:enemy];
}
-(void)setViewpointCenter:(CGPoint) position {
CGSize winSize = [[CCDirector sharedDirector] winSize];
int x = MAX(position.x, winSize.width / 2);
int y = MAX(position.y, winSize.height / 2);
x = MIN(x, (_tileMap.mapSize.width * _tileMap.tileSize.width)
- winSize.width / 2);
y = MIN(y, (_tileMap.mapSize.height * _tileMap.tileSize.height)
- winSize.height/2);
CGPoint actualPosition = ccp(x, y);
CGPoint centerOfView = ccp(winSize.width/2, winSize.height/2);
CGPoint viewPoint = ccpSub(centerOfView, actualPosition);
self.position = viewPoint;
}
-(id) init
{
if( (self=[super init] )) {
[[SimpleAudioEngine sharedEngine] preloadEffect:@"pickup.caf"];
[[SimpleAudioEngine sharedEngine] preloadEffect:@"hit.caf"];
[[SimpleAudioEngine sharedEngine] preloadEffect:@"move.caf"];
//[[SimpleAudioEngine sharedEngine] playBackgroundMusic:@"TileMap.caf"];
self.isTouchEnabled = YES;
self.tileMap = [CCTMXTiledMap tiledMapWithTMXFile:@"TileMap.tmx"];
self.background = [_tileMap layerNamed:@"Background"];
self.foreground = [_tileMap layerNamed:@"Foreground"];
self.buildings = [_tileMap layerNamed:@"Buildings"];
self.meta = [_tileMap layerNamed:@"Meta"];
_meta.visible = NO;
CCTMXObjectGroup *objects = [_tileMap objectGroupNamed:@"Objects"];
NSAssert(objects != nil, @"'Objects' object group not found");
//NSMutableDictionary * padPoints = [objects objectNamed:@"pad"];
NSMutableDictionary * padPoints;
SaveData * SaveDataManager = [SaveData sharedSaveDataManager];
for (int i = 0; i < 20; i ++) {
for (padPoints in [objects objects]) {
if ([[SaveDataManager.padArray objectAtIndex: i] intValue] == 1 ){
if ([[padPoints valueForKey:@"pad"] intValue] == i){
int x = [[padPoints valueForKey:@"x"] intValue];
int y = [[padPoints valueForKey:@"y"] intValue];
self.player = [CCSprite spriteWithFile:@"man.png"];
_player.position = ccp(x+16,y+16);
//[self addChild:_player];
}
}
}
}
// iterate through objects, finding all enemy spawn points
// create an enemy for each one
NSMutableDictionary * spawnPoints;
for (spawnPoints in [objects objects]) {
if ([[spawnPoints valueForKey:@"Enemy"] intValue] == 2){
int x = [[spawnPoints valueForKey:@"x"] intValue];
int y = [[spawnPoints valueForKey:@"y"] intValue];
[self addEnemyAtX:x+=16 y:y+=64];
}
}
player = [CCSprite spriteWithFile:@"man.png"];
player.position= _player.position;
[_tileMap addChild:player z: 0];
// [self addChild:player z:10];
[self setViewpointCenter:player.position];
[self addChild:_tileMap z:-1];
[self scheduleUpdate];
}
return self;
}
- (CGPoint)tileCoordForPosition:(CGPoint)position {
int x = position.x / _tileMap.tileSize.width;
int y = ((_tileMap.mapSize.height * _tileMap.tileSize.height) - position.y) / _tileMap.tileSize.height;
return ccp(x, y);
}
-(void)setPlayerPosition:(CGPoint)position {
Player * playerDataManager = [Player playerSaveDataManager];
CGPoint tileCoord = [self tileCoordForPosition:position];
int tileGid = [_meta tileGIDAt:tileCoord];
int x = player.position.x;
int y = player.position.y;
if (tileGid) {
NSDictionary *properties = [_tileMap propertiesForGID:tileGid];
if (properties) {
NSString *collision = [properties valueForKey:@"Collidable"];
if (collision && [collision compare:@"True"] == NSOrderedSame) {
//[[SimpleAudioEngine sharedEngine] playEffect:@"hit.caf"];
if (joyDegrees > 45 && joyDegrees < 135){
player.position = ccp(x,y-1);
}
if (joyDegrees > 135 && joyDegrees < 225){
player.position = ccp(x+1,y);
}
if (joyDegrees > 225 && joyDegrees < 315){
player.position = ccp(x,y+1);
}
if ((joyDegrees > 315 && joyDegrees < 360) || (joyDegrees > -1 && joyDegrees < 45)){
player.position = ccp(x-1,y);
}
return;
}
NSString *collectable = [properties valueForKey:@"Collectable"];
if (collectable && [collectable compare:@"True"] == NSOrderedSame) {
[[SimpleAudioEngine sharedEngine] playEffect:@"pickup.caf"];
[_meta removeTileAt:tileCoord];
[_foreground removeTileAt:tileCoord];
self.numCollected += 1;
[_hud numCollectedChanged:_numCollected];
playerDataManager.playerHealth -= 10;
}
NSString *Gate = [properties valueForKey:@"Gate"];
if (Gate && [Gate compare:@"1"] == NSOrderedSame) {
SaveData * SaveDataManager = [SaveData sharedSaveDataManager];
//[SaveDataManager.padArray removeAllObjects];
for (int i = 0; i < 20; i ++) {
[SaveDataManager.padArray replaceObjectAtIndex:i withObject:[NSNumber numberWithInt:0]];
}
[SaveDataManager.padArray replaceObjectAtIndex:1 withObject:[NSNumber numberWithInt:1]];
//[[CCDirector sharedDirector] replaceScene:[LogCabinMap scene]];
[[CCDirector sharedDirector] pushScene:[LogCabinMap scene]];
}
if (Gate && [Gate compare:@"2"] == NSOrderedSame) {
SaveData * SaveDataManager = [SaveData sharedSaveDataManager];
//[SaveDataManager.padArray removeAllObjects];
for (int i = 0; i < 20; i ++) {
[SaveDataManager.padArray replaceObjectAtIndex:i withObject:[NSNumber numberWithInt:0]];
}
[SaveDataManager.padArray replaceObjectAtIndex:1 withObject:[NSNumber numberWithInt:1]];
//[[CCDirector sharedDirector] replaceScene:[LogShedMap scene]];
[[CCDirector sharedDirector] pushScene:[LogShedMap scene]];
}
}
}
//[[SimpleAudioEngine sharedEngine] playEffect:@"move.caf"];
player.position = position;
}
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
return YES;
}
-(void) update:(ccTime)deltaTime {
[self setPlayerPosition:newPos];
[self setViewpointCenter:player.position];
}
// 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.tileMap = nil;
self.background = nil;
self.foreground = nil;
self.buildings = nil;
self.meta =nil;
self.player = nil;
player = nil;
self.hud = nil;
// don't forget to call "super dealloc"
[super dealloc];
}
@end
@implementation HelloWorldHud
@synthesize background;
@synthesize background2;
@synthesize health;
@synthesize baseScaleFactor;
+(CCScene *) scene
{
// 'scene' is an autorelease object.
CCScene *scene = [CCScene node];
// 'layer' is an autorelease object.
HelloWorldHud *layer = [HelloWorldHud node];
// add layer as a child to scene
[scene addChild: layer z:2];
HelloWorldLayer *hud = [HelloWorldLayer node];
[scene addChild: hud z:1];
//layer.hud = hud;
// return the scene
return scene;
}
-(void)initJoystick {
SneakyJoystickSkinnedBase *joystickBase = [[[SneakyJoystickSkinnedBase alloc] init] autorelease];
joystickBase.backgroundSprite = [CCSprite spriteWithFile:@"JoyB.png"];
joystickBase.thumbSprite = [CCSprite spriteWithFile:@"JoyS.png"];
joystickBase.joystick = [[SneakyJoystick alloc] initWithRect: CGRectMake(0, 0, 128, 128)];
joystickBase.position = ccp(55, 55);
[self addChild:joystickBase];
leftJoystick = [[joystickBase.joystick retain] autorelease];
}
-(void) update:(ccTime)deltaTime {
Player *playerDataManager = [Player playerSaveDataManager];
CGPoint scaledVelocity = ccpMult(leftJoystick.velocity, 100);
CGPoint newPosition = ccp(player.position.x + scaledVelocity.x * deltaTime, player.position.y + scaledVelocity.y * deltaTime);
if (leftJoystick.velocity.x == 0 && leftJoystick.velocity.y == 0 ){
if (!playerDataManager.standStill) {
[player stopAllActions];
playerDataManager.walkUp = FALSE;
playerDataManager.walkDown = FALSE;
playerDataManager.walkRight = FALSE;
playerDataManager.walkLeft = FALSE;
playerDataManager.standStill = TRUE;
[player runAction:playerDataManager.standAction];
}
}
if (leftJoystick.degrees > 45 && leftJoystick.degrees < 135){
if (!playerDataManager.walkUp) {
[player stopAllActions];
playerDataManager.walkUp = TRUE;
playerDataManager.walkDown = FALSE;
playerDataManager.walkRight = FALSE;
playerDataManager.walkLeft = FALSE;
playerDataManager.standStill = FALSE;
[player runAction:playerDataManager.walkUpAction];
}
}
if (leftJoystick.degrees > 135 && leftJoystick.degrees < 225){
if (!playerDataManager.walkLeft) {
[player stopAllActions];
playerDataManager.walkUp = FALSE;
playerDataManager.walkDown = FALSE;
playerDataManager.walkRight = FALSE;
playerDataManager.walkLeft = TRUE;
playerDataManager.standStill = FALSE;
[player runAction:playerDataManager.walkLeftAction];
}
}
if (leftJoystick.degrees > 225 && leftJoystick.degrees < 315){
if (!playerDataManager.walkDown) {
[player stopAllActions];
playerDataManager.walkUp = FALSE;
playerDataManager.walkDown = TRUE;
playerDataManager.walkRight = FALSE;
playerDataManager.walkLeft = FALSE;
playerDataManager.standStill = FALSE;
[player runAction:playerDataManager.walkDownAction];
}
}
if (((leftJoystick.degrees > 315 && leftJoystick.degrees < 360) && (leftJoystick.velocity.x != 0 && leftJoystick.velocity.y != 0 )) || ((leftJoystick.degrees > -1 && leftJoystick.degrees < 45) && (leftJoystick.velocity.x != 0 && leftJoystick.velocity.y != 0 ))){
if (!playerDataManager.walkRight) {
[player stopAllActions];
playerDataManager.walkUp = FALSE;
playerDataManager.walkDown = FALSE;
playerDataManager.walkRight = TRUE;
playerDataManager.walkLeft = FALSE;
playerDataManager.standStill = FALSE;
[player runAction:playerDataManager.walkRightAction];
}
}
float scaleFactor = playerDataManager.playerHealth/baseScaleFactor;
health.scaleX = playerDataManager.playerHealth/1;
newPos = newPosition;
joyDegrees = leftJoystick.degrees;
if (playerDataManager.playerHealth < 100) {
[[CCDirector sharedDirector] replaceScene:[CCTransitionFade transitionWithDuration:3 scene: [GameLogic scene]]];
[[CCDirector sharedDirector] replaceScene: [GameLogic scene]];
}
}
-(void) scroll:(ccTime)dt
{
//move 30*dt px vertically
if (background.position.y<background2.position.y){
background.position = ccp(background.contentSize.width/2, background.position.y - 225*dt);
background2.position = ccp(background2.contentSize.width/2, background.position.y+background.contentSize.height);
}else{
background2.position = ccp(background2.contentSize.width/2, background2.position.y- 225*dt);
background.position = ccp(background.contentSize.width/2, background2.position.y+background2.contentSize.height);
}
//reset offscreen position
if (background.position.y <-background.contentSize.height/2)
{
background.position = ccp(background.contentSize.height/2,background2.position.y+background2.contentSize.height);
}else if (background2.position.y < -background2.contentSize.height/2)
{
background2.position = ccp(background2.contentSize.height/2, background.position.y+background.contentSize.height);
}
}
-(id) init
{
if ((self = [super init])) {
CGSize size = [CCDirector sharedDirector].winSize;
background = [CCSprite spriteWithFile:@"rain.png"];
background2 = [CCSprite spriteWithFile:@"rain.png"];
[background.texture setAliasTexParameters];
[background2.texture setAliasTexParameters];
//position background sprites
background.position = ccp(background.contentSize.height/2,background.contentSize.width/2);
background2.position = ccp(size.width,0);
//schedule to move background sprites
//[self schedule:@selector(scroll:)];
//adding them to the main layer
//[self addChild:background z:-1];
//[self addChild:background2 z:-1];
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"GUI.plist"];
CCSpriteBatchNode *GUISpriteSheet = [CCSpriteBatchNode batchNodeWithFile:@"GUI.png"];
[self addChild:GUISpriteSheet];
CCSprite * healthBar = [CCSprite spriteWithSpriteFrameName:@"bar.png"];
CCSprite * cap = [CCSprite spriteWithSpriteFrameName:@"cap.png"];
CCSprite * endCap = [CCSprite spriteWithSpriteFrameName:@"endcap.png"];
health = [CCSprite spriteWithSpriteFrameName:@"red.png"];
healthBar.anchorPoint = ccp(0,1);
health.anchorPoint = ccp(0,1);
cap.anchorPoint = ccp(0,1);
endCap.anchorPoint = ccp(0,1);
healthBar.position = ccp(1 , size.height);
healthBar.scaleX = 25;
cap.position = ccp(0 , size.height);
int width = [healthBar boundingBox].size.width;
endCap.position = ccp(width , size.height);
health.position = ccp(1, size.height-2);
baseScaleFactor = width;
health.scaleX = baseScaleFactor;
[self addChild:healthBar];
[self addChild:cap];
[self addChild:endCap];
[self addChild:health];
CGSize winSize = [[CCDirector sharedDirector] winSize];
label = [CCLabelTTF labelWithString:@"0" dimensions:CGSizeMake(50, 20)
alignment:UITextAlignmentRight fontName:@"Verdana-Bold"
fontSize:18.0];
label.color = ccc3(0,0,0);
int margin = 10;
label.position = ccp(winSize.width - (label.contentSize.width/2)
- margin, label.contentSize.height/2 + margin);
[self addChild:label];
CCMenuItemFont * pause = [CCMenuItemFont itemFromString:@"Pause" target:self selector:@selector(pause:)];
CCMenu *menu = [CCMenu menuWithItems: pause, nil];
pause.position = ccp(206,142);
[self addChild:menu];
CCSprite *pix = [CCSprite spriteWithFile:@"pix.png"];
pix.position = ccp(size.width/2, size.height/2);
//pix.scale = 50000;
[self addChild:pix z:1];
//[pix runAction:[CCTintTo actionWithDuration:10 red:255 green:0 blue:0]];
//[pix runAction:[CCScaleTo actionWithDuration:15 scale:500]];
pix.color = ccc3(255, 255, 255);
[self scheduleUpdate];
[self initJoystick];
}
return self;
}
- (void)numCollectedChanged:(int)numCollected {
[label setString:[NSString stringWithFormat:@"%d", numCollected]];
// [label setString:[NSString stringWithFormat:@"%d", score]];
}
- (void) pause: (id) sender
{
[[CCDirector sharedDirector] pushScene:[pauseM scene]];
}
- (void) dealloc
{
self.background = nil;
self.background2 = nil;
self.health = nil;
self.meta =nil;
player = nil;
// don't forget to call "super dealloc"
[super dealloc];
}
@end
上は問題が発生したときに実行されている .m シーンで、下は GameLogic.m です。
#import "GameLogic.h"
#import "Player.h"
#import "Menu.h"
@implementation GameLogic
+(id) scene
{
CCScene *scene = [CCScene node];
GameLogic *layer = [GameLogic node];
[scene addChild: layer];
return scene;
}
+(id) gameLogicSaveDataManager {
static id gameLogicSaveDataManager = nil;
if (gameLogicSaveDataManager == nil) {
gameLogicSaveDataManager = [[self alloc] init];
}
return gameLogicSaveDataManager;
}
-(id) init
{
if( (self=[super init] )) {
CCSprite *bg = [CCSprite spriteWithFile:@"bg.jpg"];
bg.anchorPoint = ccp(0,0);
id fadeIn = [CCFadeIn actionWithDuration:3];
[self addChild:bg];
[bg runAction: fadeIn];
CCLayer *menuLayer = [[[CCLayer alloc] init] autorelease];
[self addChild:menuLayer];
CCMenuItemImage *home = [CCMenuItemImage
itemFromNormalImage:@"bg.jpg"
selectedImage:@"bg.jpg"
target:self
selector:@selector(home:)];
CCMenu *menu = [CCMenu menuWithItems: home, nil];
home.position = ccp(0,0);
[menuLayer addChild: menu];
}
return self;
}
- (void) home: (id) sender
{
[[CCDirector sharedDirector] replaceScene:[Menu scene]];
}
- (void) dealloc
{
[super dealloc];
}
@end