#iphone #cocos2d-iphone
#iPhone #cocos2d-iphone
Вопрос:
У меня есть игровая сцена Cocos2d, которая загружается с помощью EAGLView, загруженного UIViewController, но когда я выхожу из игровой сцены обратно в меню UIKit, моя игровая сцена освобождается странным образом. Я думаю, что если бы я создал игру исключительно в Cocos2d, не комбинируя ее с UIKit, этого бы не произошло. Если я вызову pause в CCDirector при появлении UIViewController, я обнаружил, что если я захочу повторно войти в игровую сцену, UIViewController загрузится снова, и простое возобновление CCDirector покажет пустой экран с ошибкой OpenGL. При попытке [[CCDirector sharedDirector] runWithScene]
он говорит, что я не могу этого сделать, если сцена уже запущена, но если я попробую replaceScene , он говорит, что сообщение об освобождении (для CCSprite, не знаю, какой именно) отправляется в освобожденный экземпляр. Вот часть моего кода:
- (void)viewDidLoad {
[super viewDidLoad];
glView = [EAGLView viewWithFrame:self.view.bounds
pixelFormat:kEAGLColorFormatRGB565 // kEAGLColorFormatRGBA8
depthFormat:0 // GL_DEPTH_COMPONENT16_OES
];
glView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.view insertSubview:glView atIndex:0];
[[CCDirector sharedDirector] setOpenGLView:glView];
if (![[CCDirector sharedDirector] runningScene]) {
CCScene *scene = [GameLayer scene];
[[CCDirector sharedDirector] runWithScene:scene];
}
else {
[self.view insertSubview:[[CCDirector sharedDirector] openGLView] atIndex:0];
[[CCDirector sharedDirector] resume]; // Pause is in viewWillDisappear
// If I replace resume with below, I get message sent to deallocated instance
[[CCDirector sharedDirector] replaceScene:scene];
}
}
Если я запускаю ее таким образом, я получаю EXC_BAD_ACCESS внутри CCTextureAtlas в строке с glDrawElements(GL_TRIANGLES, (GLsizei) n*6, GL_UNSIGNED_SHORT, (GLvoid*)(start*6*sizeof(indices_[0])));
Если я запускаю ее без повторной инициализации glview, инициализируя только в первый раз, например if (![[CCDirector sharedDirector]openGLView]) initialize
, я получаю пустой экран и ошибку OpenGL 0x0506 в -[EAGLView SwapBuffers].
Как бы я мог либо сохранить свою сцену, не делая чего-то слишком искаженного, либо чисто освободить свою сцену, чтобы я мог перезагрузить ее с [[CCDirected sharedDirector] runWithScene]
?
Ответ №1:
Как вы «выходите из сцены»? Это был бы более интересный код для просмотра.
Вот что мне показалось странным в опубликованном вами коде:
- (void)viewDidLoad {
…
if (![[CCDirector sharedDirector] runningScene]) {
...
}
else {
// Where does this scene variable come from?
[[CCDirector sharedDirector] replaceScene:scene];
}
}
Обычно при запуске replaceScene вы предоставляете новую сцену. Возможно, вы пытаетесь заменить сцену той же сценой, которая также является текущей сценой. Это, безусловно, приведет к сбою cocos2d. Если вы хотите, чтобы та же сцена снова появилась, либо не вызывайте replaceScene, либо создайте сцену заново.
Вы также захотите проверить, что текущая запущенная сцена не освобождается. Установите точку останова в методе освобождения сцены. Если это освобождает, вы, вероятно, попали в заблуждение, что вам нужно стереть сцену cocos2d из памяти. Вы не должны этого делать, я считаю, что cocos2d всегда ожидает, что после вызова runWithScene будет хотя бы одна запущенная сцена.
Как бы то ни было, вы захотите использовать startAnimation и stopAnimation вместо паузы и возобновления. Это полностью остановит Cocos2D без освобождения сцены, поэтому она работает так же, как пауза / возобновление. Я предполагаю, что внутренне он полностью отключает игровой цикл, тогда как pause / resume поддерживает его работу с очень низкой скоростью, то есть 4 кадра в секунду, если я правильно помню.
У меня были случаи, когда пауза / возобновление вызывали «ошибку OpenGL 0x0506 в [буферах обмена EAGLView]», и startAnimation / stopAnimation исправили бы это.
Комментарии:
1. О, я звонил
[GameLayer scene]
, думая, что это создаст новый экземпляр. На самом деле, ничего не освобождалось, и замена сцены на ту же сцену, вероятно, вызвала мою странную проблему с освобождением, как вы сказали. Изменение паузы и возобновления на stopAnimation и startAnimation также исправило мою ошибку OpenGL! спасибо за ответы. Кстати, код, который я использую для «выхода из сцены», взят из фрагмента кода, который я нашел здесь , который позволяет мне создать интерфейс одноэлементного класса для RootViewController.
Ответ №2:
Как вообще вы оставляете вызов sene
[[CCDirector SharedDirector]end];
Это вызовет ряд методов в директоре и позволит вам повторно войти в сцену без проблем.