cocos2d: воспроизведение видео на фоне меню

У меня есть CCLayer с меню "Пуск" моего приложения, и я хотел бы, чтобы на заднем плане воспроизводился короткий фильм. Мне удалось воспроизвести фильм в glView, но когда он воспроизводится, меню не отображается. Для обработки фильма я создаю экземпляр MPMoviePlayerController, а затем добавляю его представление в glView следующим образом:

[[[CCDirector sharedDirector] openGLView] addSubview:moviePlayer.view];

Я видел, что этот вопрос был очень похож

Как иметь меню при воспроизведении фильма-iphone cocos2d

но я хотел бы знать, есть ли лучшее решение для этого, возможно, такое, которое позволило бы мне все еще использовать объекты каркаса cocos2d (а не мои собственные взгляды).

Я попытался отправить moviePlayer.view обратно таким образом

[theView sendSubviewToBack:moviePlayer.view];

но меню все еще скрыто фильмом...

(много часов спустя..)

Хорошо, как вы можете прочитать в первом комментарии, я понял, что (возможно) единственный способ - использовать пользовательские представления. Я сделал это, и он запускается в симуляторе, добавляя любые виды в glView после moviePlayer.view. Однако, когда я запускаю его на своем IPod touch с 3.1.3 FW, просмотр фильма всегда на высоте. Поэтому я понял, что MPMoviePlayerController фактически создает свое собственное окно и свое собственное представление. В некоторых публикациях (например, это наложение поверх потокового MPMoviePlayerController) предлагается перехватить событие, когда загружается новое окно, и только затем добавлять подпредставления.

это то, что я пытался сделать, но это событие фактически никогда не ловится ни на симуляторе, ни на целевом Ipod. Поэтому я добавил запланированное обновление селектора -(void), которое реализовано следующим образом:

-(void) update{
    NSArray *windows = [[UIApplication sharedApplication] windows];
    if ([windows count] > 1)
    {
    UIImageView *logo = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"logo.png"]];
    UIView *theView = [[CCDirector sharedDirector] openGLView];
    [logo setCenter:ccp(240,80)];
    [moviePlayer.view addSubview:logo];
        [self unscheduleAllSelectors];
    }
}

но фильм все еще остается на вершине

пожалуйста, ребята, любая помощь будет очень признателен!

(несколько дней спустя...) Я также ждал 2 секунды, пока фильм на самом деле запущен, чтобы добавить мой вид логотипа в качестве подпредставления игрока. На симуляторе работает корректно, а на Ipod (3.1.3) получается другой результат. При первом воспроизведении фильма логотип не отображается (фильм сверху). Однако, как только фильм заканчивается, воспроизводится метод воспроизведения, начиная со второго раза, когда логотип отображается с фильмом на заднем плане (если это так). Это имеет какой-то смысл для вас?

Мне действительно нужно понять, как решить эту проблему, это довольно нелепо, я преуспел в разработке игры за 2 месяца, а теперь я застрял на 2 недели для меню "Пуск":)

В любом случае, если я решил вставить весь код слоя, который я пытаюсь исправить, чтобы вы могли лучше понять, в чем проблема (или, по крайней мере, это моя надежда:))

+(id) scene
{
    // 'scene' is an autorelease object.
    CCScene *scene = [CCScene node];

    // 'layer' is an autorelease object.
    StartMenu *layer = [StartMenu node];

    // add layer as a child to scene
    [scene addChild: layer];

    // return the scene
    return scene;
}

-(void) update{
    timer ++;
    if (timer==120){

    UIImageView *logo = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"stupidLogo.png"]];
    UIView *theView = [[CCDirector sharedDirector] openGLView];
    [logo setCenter:ccp(240,80)];
    //logo.transform = CGAffineTransformMakeRotation(3.14/2);
    [moviePlayer.view addSubview:logo];
        [self unscheduleAllSelectors];
    }
}
-(id) init{
    self = [super init];

    [self schedule: @selector(update)];
    NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"test_005_conv_06.mp4" ofType:@""]];        
    moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:url];
    // Register to receive a notification when the movie has finished playing.
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(moviePlayBackDidFinish:)
                                                 name:MPMoviePlayerPlaybackDidFinishNotification
                                               object:moviePlayer];

    if ([moviePlayer respondsToSelector:@selector(view)]) {
        if([MPMoviePlayerController instancesRespondToSelector:@selector(view)]){
        // Use the new 3.2 style API
        moviePlayer.controlStyle = MPMovieControlStyleNone;
        moviePlayer.shouldAutoplay = FALSE;
        // This does blows up in cocos2d, so we'll resize manually
        // [moviePlayer setFullscreen:YES animated:YES];
        [moviePlayer.view setTransform:CGAffineTransformMakeRotation((float)M_PI_2)];
        CGSize winSize = [[CCDirector sharedDirector] winSize];

        moviePlayer.view.frame = CGRectMake(0, 0, winSize.height, winSize.width);   // width and height are swapped after rotation
        [[[CCDirector sharedDirector] openGLView] addSubview:moviePlayer.view];
        [moviePlayer play];
        }
    } else {
        // Use the old 2.0 style API
        moviePlayer.movieControlMode = MPMovieControlModeHidden;
        [moviePlayer play];
    }
    return self;
}


- (void)moviePlayBackDidFinish:(NSNotification*)notification {
    MPMoviePlayerController *moviePlayer = [notification object];
    [moviePlayer play];
}

1 ответ

Решение

Потратив некоторое время с этим, я нашел ответ. (Я тоже хочу сделать это, но позже, так что я могу с этим начать!)

Я использовал код и методы в этой ссылке от ascorbin, с помощью этой ссылки. Это не завершено, если вы также не добавите следующую строку в EAGLView:

glView.opaque = NO;

Вид фильма расположен вдоль стороны EAGLView и отодвинут назад, чтобы получить то, что вы ищете. Возможно, вам также придется настроить прозрачность EAGLView, как это упоминается в этом посте. Надеюсь, это поможет.


Вещи, которые мне нужно было изменить, перечислены здесь.

Вам нужно добавить яблоко mediaPlayer.framework к вашему проекту и включите следующую строку в ваш делегат приложения.h:

#import <MediaPlayer/MediaPlayer.h>

В CCDirector's setGLDefaultValues метод, установите альфа glClearColor равным 0.0f, а не 1.0f:

//  glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

При создании вашего EAGLView в applicationDidFinishLaunching: изменить следующие вещи:

Измените pixelFormat со старого значения на следующее:

// kEAGLColorFormatRGB565
kEAGLColorFormatRGBA8

Убедитесь, что вы добавили EAGLView как вспомогательное представление (и сделайте его непрозрачным), а не как основное представление:

//  [viewController setView:glView];
    [viewController.view addSubview:glView];
    glView.opaque = NO;

Наконец, перед запуском сцены вы можете добавить свой код для воспроизведения зацикленного фильма. Я добавил метод к делегату приложения для этого. Вы также можете добавить метод, позволяющий остановить воспроизведение фильма, здесь, в приложении-делегате, а также для случаев, когда (если?) Вам нужно удалить фильм.

[self startMovie];

и сам метод:

- (void) startMovie
{
    NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"test" ofType:@"m4v"]];
    moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:url];

    if ([moviePlayer respondsToSelector:@selector(setFullscreen:animated:)]) {
        // Use the new 3.2 style API
        moviePlayer.controlStyle = MPMovieControlStyleNone;
        moviePlayer.shouldAutoplay = YES;
        moviePlayer.repeatMode = MPMovieRepeatModeOne;
        CGRect win = [[UIScreen mainScreen] bounds];

        moviePlayer.view.frame = CGRectMake(0, 0, win.size.height, win.size.width);
        [viewController.view  addSubview:moviePlayer.view];
        [viewController.view  sendSubviewToBack:moviePlayer.view];
    } 
    else
    {
        // Use the old 2.0 style API
        moviePlayer.movieControlMode = MPMovieControlModeHidden;
        [moviePlayer play];
    }
}

Обратите внимание, что вам не нужно добавлять наблюдателя, как указано в связанном примере, ни функцию повторения фильма, это делается автоматически с опцией 'MPMovieRepeatModeOne'. Если вы не хотите, чтобы фильм повторялся, вы также можете здесь выбрать опцию "MPMovieRepeatModeNone".

Я также должен отметить, что мне не удалось заставить это работать со старым API до 3.2 (так что в вашем случае 3.1.3 он не работал), видео не показывалось через EAGLView. Я не уверен, что там происходит, но я не видел конкретных вариантов того, что с этим делать.

Другие вопросы по тегам