cocos2d:在菜单背景下播放视频

cocos2d: playing a video in the background of a menu(cocos2d:在菜单背景下播放视频)

本文介绍了cocos2d:在菜单背景下播放视频的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有我的应用程序开始菜单的 CCLayer,我想在后台播放一部短片.我已成功在 glView 中播放电影,但播放时未显示菜单.为了处理电影,我实例化了一个 MPMoviePlayerController然后我以这种方式将其视图添加到 glView:

I have a a CCLayer with the start menu of my app and I would like to have a short movie playing in the background. I have succeded in playing a movie in the glView but when it plays the menu is not depicted. To handle the movie I instantiate a MPMoviePlayerController and then I add its view to the glView this way:

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

我看到这个问题很相似

如何拥有菜单电影播放时-iphone cocos2d

但我想知道是否有更好的解决方案,可能会让我仍然利用 cocos2d 框架实体(而不是我自己的观点).

but I would like to know if there is a better solution to it, possibly one that would let me still exploit the cocos2d framework entities (and not my own views).

我已尝试以这种方式将moviePlayer.view 发送回去

I have tried to send the moviePlayer.view to back this way

[theView sendSubviewToBack:moviePlayer.view];

但菜单仍然被电影隐藏...

but the menu is stil hidden by the movie...

(几个小时后..)

好的,正如您在第一条评论中看到的那样,我已经意识到(可能)唯一的方法是利用自定义视图.我这样做了,它通过在moviePlayer.view 之后将任何视图添加到glView 来在模拟器中运行.但是,当我使用 3.1.3 FW 在我的目标 iPod touch 上运行它时,电影视图始终位于顶部.因此,我意识到 MPMoviePlayerController 实际上创建了自己的窗口和自己的视图.一些帖子(例如 Overlay on top of Streaming MPMoviePlayerController)建议拦截事件加载新窗口,然后才添加子视图.

Ok as you can read in the first comment i have realized that (probably) the only way is exploiting custom views. I did that and it runs in the simulator by adding any views to the glView after the moviePlayer.view. However when i run it on my target IPod touch with a 3.1.3 FW the movie view is always on top. I have therefore realized the MPMoviePlayerController actually creates its own window and its own view. Some post (like this Overlay on top of Streaming MPMoviePlayerController) suggest to intercept the event the new window is loaded and only then adding the subviews.

这就是我试图做的,但该事件实际上从未在模拟器或目标 Ipod 上捕获.因此,我添加了一个预定的选择器 -(void) 更新,它是通过这种方式实现的:

that is what I tried to do but that event is actually never catched neither on the simulator nor on the target Ipod. I have therefore added a scheduled selector -(void) update which is implemented this way:

-(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) 上却产生了不同的结果.第一次播放电影时,未显示徽标(电影在顶部).但是,由于电影一结束,播放方法就会被关闭,从第二次开始,徽标会以电影为背景(我愿意).这对你有意义吗?

(some days later...) I have also waited for 2 seconds, while the movie is actually running, to add my logo view as a subview of the movieplayer. It works correctly on the simulator but on the Ipod (3.1.3) it turns out a different result. The first time the movie is played the logo is not depicted (movie on top). However, since as soon as the movie finishes the play method is colled, starting from the second time the logo is depicted with the movie on the background (Is i would). Does it make any sense to you?

我真的需要了解如何解决这个问题,这太荒谬了,我在 2 个月内成功开发了一款游戏,而现在我在开始菜单的 2 周内被卡住了 :)

I really need to understand how to fix this issue it is quite ridiculous I have succeded in developing a game in 2 months and now i am stuck from 2 weeks for the start menu :)

无论如何,如果我决定粘贴我正在尝试修复的图层的整个代码,以便您可以更好地找出问题所在(或者至少这是我的希望:))

Anyway if I have decided to paste the whole code of the layer I am trying to fix so that you can better figure out what the problem is (or at least that is my hope :) )

+(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];
}

推荐答案

在花了一些时间之后,我找到了答案.(我也想这么做,不过等会儿,不如现在就开始吧!)

After spending some time with this I found the answer. (I want to do this too, but later, so I may as well get it going now!)

我在 this link 中使用了 ascorbin 中的代码和技术,并得到了 这个链接.除非您还将以下行添加到 EAGLView,否则它是不完整的:

I used the code and techniques in this link by ascorbin, with help from this link. It is not complete unless you also add the following line to the EAGLView:

glView.opaque = NO;

电影视图位于 EAGLView 的一侧,并被推到后面以获取您要查找的内容.您可能还必须像该帖子中提到的那样调整 EAGLView 的透明度.希望对您有所帮助.

The movie view is along side of the EAGLView, and pushed to the back to get what you are looking for. You may also have to tweak the transparency of the EAGLView like it mentions in that post. Hope that helps.

这里列出了我需要修改的内容.

The things I needed to modify are listed here.

您需要将苹果的 mediaPlayer.framework 添加到您的项目中,并在您的应用委托.h 中包含以下行:

You need to add apple's mediaPlayer.framework to your project and include the following line in your app delegate .h:

#import <MediaPlayer/MediaPlayer.h>

在 CCDirector 的 setGLDefaultValues 方法中,将 glClearColor 的 alpha 设置为 0.0f 而不是 1.0f:

In CCDirector's setGLDefaultValues method, set glClearColor's alpha to be 0.0f not 1.0f:

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

applicationDidFinishLaunching 中创建 EAGLView 时: 更改以下内容:

将 pixelFormat 从旧值更改为:

Change the pixelFormat from the old value to be this:

// kEAGLColorFormatRGB565
kEAGLColorFormatRGBA8

确保将 EAGLView 添加为子视图(并使其不透明)而不是主视图:

Make sure to add the EAGLView as a sub-view (and make it non-opaque) rather than as the main view:

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

最后,在运行场景之前,您可以添加代码来播放循环电影.为此,我向应用程序委托添加了一个方法.您还可以在应用程序委托中添加一个方法来阻止您的电影在此处播放,以及何时(如果?)您需要删除您的电影.

Finally, before running your scene you can add your code to play the looping movie. I added a method to the app delegate for this. You could also add a method to stop your movie from playing here in the app delegate as well for when (if?) you need to remove your movie.

[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"选项.

Note that you do not have to add the observer like is listed in the linked example, nor the function to repeat the movie, this is done automatically with the 'MPMovieRepeatModeOne' option. If you don't want the movie to repeat you can choose the 'MPMovieRepeatModeNone' option here as well.

我还应该注意,我无法让它与旧的 pre-3.2 API 一起工作(所以在你的 3.1.3 情况下它不起作用),视频没有通过 EAGLView 显示.我不确定那里发生了什么,但我没有看到关于如何处理的具体选项.

I should also note that I was unable to get this to work with the old pre-3.2 API (so in your 3.1.3 case it was not working), the video didn't show through the EAGLView. I am not sure what is happening there, but I have seen no specific options on what to do about that.

这篇关于cocos2d:在菜单背景下播放视频的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:cocos2d:在菜单背景下播放视频