Не могу показать сцену второй раз в Cocos3D
У меня есть viewController с кокосовой сценой, которую я нажимаю в своем контроллере навигации. В этом представлении контроллера у меня есть следующие методы:
-(void) viewDidLoad
{
[super viewDidLoad];
[_cc3FrameView addSubview: [self createGLView]];
CC3Backgrounder.sharedBackgrounder.shouldRunTasksOnRequestingThread = YES;
}
- (void) viewWillAppear:(BOOL)animated
{
if (!sceneInitialized) {
sceneInitialized = YES;
[CCDirector.sharedDirector runWithScene: [[self makePanoramaScene] asCCScene]];
} else {
[CCDirector.sharedDirector resume];
}
[CCDirector.sharedDirector startAnimation];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[[self runningPanoramaScene] sceneWillShow];
});
}
-(AxPanoramaScene *)runningPanoramaScene
{
CCScene *scene = [CCDirector.sharedDirector runningScene];
AxPanoramaLayer *panoramaLayer = [scene.children lastObject];
AxPanoramaScene *panoramaScene = (AxPanoramaScene *)panoramaLayer.cc3Scene;
return panoramaScene;
}
-(void)viewWillDisappear:(BOOL)animated
{
[CCDirector.sharedDirector pause];
}
Пока я нажимаю на этот контроллер - все работает, но когда я нажимаю на этот контроллер и снова нажимаю на него - я получаю ярко-розовый экран и продолжаю сообщения в журнале:
2014-12-12 19:30:06.447 UniversalMapExample[2262:258353] cocos2d: animation started with frame interval: 60.00
2014-12-12 19:30:06.452 UniversalMapExample[2262:258353] cocos2d: surface size: 768x973
OpenGL error GL_INVALID_OPERATION detected at -[CCES2Renderer resizeFromLayer:] 161
2014-12-12 19:30:06.452 UniversalMapExample[2262:258353] Failed to make complete framebuffer object 0x8219
2014-12-12 19:30:06.453 UniversalMapExample[2262:258353] cocos2d: surface size: 768x973
OpenGL error GL_INVALID_OPERATION detected at -[CCES2Renderer resizeFromLayer:] 161
2014-12-12 19:30:06.453 UniversalMapExample[2262:258353] Failed to make complete framebuffer object 0x8219
OpenGL error GL_INVALID_OPERATION detected at -[CCRenderer(NoARCPrivate) setRenderState:] 232
OpenGL error GL_INVALID_OPERATION detected at -[CCRenderer(NoARCPrivate) setRenderState:] 232
OpenGL error GL_INVALID_OPERATION detected at -[CCRenderer(NoARCPrivate) setRenderState:] 232
OpenGL error GL_INVALID_OPERATION detected at -[CCRenderer(NoARCPrivate) setRenderState:] 232
[***GL ERROR***] GL_INVALID_VALUE: Numeric argument is out of range from glUseProgram(15).
[***GL ERROR***] GL_INVALID_OPERATION: Operation not allowed in current state from glUniform3fv(7, 4, (0.329, 0.944, 0.000)) setting u_cc3LightSpotDirectionModel.
[***GL ERROR***] GL_INVALID_OPERATION: Operation not allowed in current state from glUniformMatrix4fv(12, 1, GL_FALSE,
[0.021050, -0.007339, -0.000000, 0.210503
0.000000, -0.000000, 0.017596, -0.977556
0.005937, 0.017031, 0.000000, -0.660065
0.005926, 0.016997, 0.000000, 1.339256]) setting u_cc3MatrixModelViewProj.
Как правильно нажать контроллер с кокосовой сценой несколько раз? Я изменил пример с кода Cocos для этого кода. Что я здесь не так делаю? Пожалуйста, обратите внимание - мой контроллер не CCDirector
- он просто содержит вид со сцены Cocos - реализация как CC3DemoMultiScene
, Спасибо!
2 ответа
Помните, что CCDirector
это UIViewController
, но это тоже синглтон, что придает ему некоторые уникальные нюансы.
Например, вы, кажется, вызываете createGLView
метод каждый раз, когда вы хотите заменить свой контроллер. Если это следует CC3DemoMultiScene
дизайн, это попытается воссоздать другой CCGLView
прежде чем старый был выпущен из CCDirector
синглтон.
Обычно лучше всего лечить CCDirector
и CCGLView
что вы создаете для него как самостоятельную многоразовую единицу. Когда вы открываете содержащий контроллер, оставьте все как есть, и просто добавьте и удалите CCGLView
из представления иерархии каждый раз.
...Билл
Это копия / вставка из моего блога, где я освещал аналогичную проблему. Разница лишь в том, что я хотел полной интеграции UIKit. У меня была проблема, когда через 2 раза. Возможно, это поможет вам.
http://www.notthepainter.com/full-cocos2d-uikit-integration/
Я работал над игрой на основе cocos2d и не смог запустить мою игру дважды. Было ясно, что я не закрывал 1-ю игру правильно или строил 2-ю игру правильно, или оба!
В Интернете есть множество учебных пособий, в которых вы узнаете, как добавить кнопки UIKit в приложение Cocos2D или как запустить Cocos2D из приложения на основе UIKit. Но мне нужно было сделать оба. Я хотел UIViewController под моей игрой и виджеты UIKit поверх моей игры. Я потратил много времени на чтение, и это то, что я придумал.
Во-первых, создание проекта XCode было кошмаром. В конце концов я использовал шаблон cocos2d/box2d, а затем извлек файлы, которые мне не нужны, и добавил все мои исходные файлы обратно. Файл AppDelegate.m выглядит так, как должно выглядеть приложение, не относящееся к cocos2d. Это противоречит многим учебным пособиям, которые советуют вам построить вашу среду cocos2d в AppDelegate. Я боролся с этим, у меня не было удачи большую часть пятницы, а затем в понедельник я вставил Cocos2DSingleton, и он в значительной степени запустился в первый раз.
Вот метод viewDidLoad моего GameViewController:
- (void)viewDidLoad
{
[super viewDidLoad];
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:NO];
TTCocos2DSingleton *shared = [TTCocos2DSingleton sharedCocos2D];
CCGLView *glView = [shared currentGLView];
[self.view insertSubview:glView atIndex:1];
}
Есть мнение, что стоит отметить. GameViewController содержит игровые UIB-кнопки, счетчики UILabels и другие игровые виджеты пользовательского интерфейса. Это позволяет мне использовать многие элементы управления игрой в Интерфейсном Разработчике, не раскладывая их вручную. Заметьте, я скрываю строку состояния, так как игра в полноэкранном режиме.
Я получаю свой экземпляр cocos2d через синглтон, получаю его glView и вставляю его в представление GameViewController по индексу 1. Это помещает его ниже всех элементов управления игрой. Позже я покажу вам метод sharedCocos2D, давайте посмотрим на viewWillAppear.
- (void) viewWillAppear:(BOOL)animated
{
if(![[CCDirector sharedDirector] runningScene]){
CCScene *scene = [MyGameLayer scene];
myGame = [MyGameLayer node];
myGame.delegate = self;
[scene addChild: myGame];
[[CCDirector sharedDirector] runWithScene:scene];
} else {
// we have a scene already, replace the original to get a new game
[[CCDirector sharedDirector] startAnimation];
CCScene *scene = [MyGameLayer scene];
myGame = [MyGameLayer node];
myGame.delegate = self;
[scene addChild: myGame];
[[CCDirector sharedDirector] replaceScene:scene];
}
}
Обратите внимание, как мы относимся к первому прогону иначе, чем ко второму. Для второго и последующих прогонов мы заменяем сцену новой. Это позволяет избежать всех проблем с "перезапуском". Также обратите внимание, что я установил делегата. Я использую протокол делегата для связи между моим игровым уровнем и моим UIViewController.
Мой синглтон-паттерн происходит из блога Duck Rowing, и я должен признать, что это довольно классное название для блога. Я не собираюсь показывать весь синглтон-код здесь, этот блог о cocos2d, но вот как я строю свою среду cocos2d.
+ (TTCocos2DSingleton *) sharedCocos2D;
{
static dispatch_once_t onceQueue;
dispatch_once(&onceQueue, ^{
if (sharedInstance) {
return;
}
sharedInstance = [[TTCocos2DSingleton alloc]init];
// Create an CCGLView with a RGB565 color buffer, and a depth buffer of 0-bits
sharedInstance->glView = [CCGLView viewWithFrame:[[UIScreen mainScreen] bounds]
pixelFormat:kEAGLColorFormatRGB565 //kEAGLColorFormatRGBA8
depthFormat:0 //GL_DEPTH_COMPONENT24_OES
preserveBackbuffer:NO
sharegroup:nil
multiSampling:NO
numberOfSamples:0];
[sharedInstance->glView setMultipleTouchEnabled:YES];
[sharedInstance setupDirector];
});
return sharedInstance;
}
Синглтон настраивает CCGLView, включает мультитач, а затем настраивает режиссера. (Я поместил это в другой метод, так как ошибочно подумал, что мне нужно вызвать его в другом месте. Оказывается, мне это не нужно.)
- (void)setupDirector
{
CCDirectorIOS *director = (CCDirectorIOS*) [CCDirector sharedDirector];
[director setView:glView];
[director enableRetinaDisplay:YES];
director.wantsFullScreenLayout = YES;
[director setDisplayStats:NO];
[director setAnimationInterval:1.0/60];
}
И в setupDirector мы устанавливаем обычных подозреваемых, необходимых для приложения cocos2d. Теперь в игру можно играть несколько раз, у меня есть полноценный UIViewController/UINavController и у меня есть виджеты UIKit поверх моей игры. Nirvana.