cocos2d:在菜单的背景中播放视频 [英] cocos2d: playing a video in the background of a menu

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

问题描述

我有一个CCLayer与我的应用程序的开始菜单,我想有一个短片在后台播放。
我已经成功地在glView中播放一个电影,但是当它播放的菜单没有描绘。
为了处理这个电影,我实例化了一个MPMoviePlayerController
,然后我把它的视图添加到glView中:

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

我看到这个问题很相似



如何进行菜单a movie is playing-iphone cocos2d



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



我已尝试以这种方式发送moviePlayer.view。

  [theView sendSubviewToBack:moviePlayer.view]; 

但菜单被电影隐藏。



(多小时后..)



好吧,你可以在第一个评论中看到,我意识到(可能)唯一的方法是利用自定义视图。我做到了,它运行在模拟器通过在moviePlayer.view后添加任何视图到glView。然而,当我运行它在我的目标IPod触摸与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秒,而电影实际上正在运行,添加我的标志视图作为movieplayer的子视图。它在模拟器上正确工作,但在Ipod(3.1.3),结果是一个不同的结果。第一次播放电影时,不显示标志(顶部的电影)。然而,因为一旦电影完成播放方法冷却,从第二次开始徽标与背景上的电影(我会的)。它对你有意义吗?



我真的需要了解如何解决这个问题,这是很可笑的我已经成功开发一个游戏在2个月,现在我从开始菜单的2周停留:)



无论如何,如果我决定粘贴图层的整个代码,我想修复,以便你可以更好地(或至少那是我的希望:))

  +(id)scene 
{
//'scene'是一个autorelease对象。
CCScene * scene = [CCScene node];

//'layer'是一个autorelease对象。
StartMenu * layer = [StartMenu node];

//将图层作为子级添加到场景
[scene addChild:layer];

//返回场景
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.mp4ofType:@]];
moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:url];
//注册以在电影播放完毕后收到通知。
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(moviePlayBackDidFinish :)
name:MPMoviePlayerPlaybackDidFinishNotification
object:moviePlayer];

if([moviePlayer respondingToSelector:@selector(view)]){
if([MPMoviePlayerController instancesRespondToSelector:@selector(view)]){
//使用新的3.2 style API
moviePlayer.controlStyle = MPMovieControlStyleNone;
moviePlayer.shouldAutoplay = FALSE;
//这样会在cocos2d中弹出来,所以我们手动调整大小
// [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); //宽度和高度在旋转后交换
[[[CCDirector sharedDirector] openGLView] addSubview:moviePlayer.view];
[moviePlayer播放];
}
} else {
//使用旧的2.0样式API
moviePlayer.movi​​eControlMode = MPMovieControlModeHidden;
[moviePlayer播放];
}
return self;
}


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


解决方案

我找到了答案。 (我想这样做,但后来,所以我也可以得到它现在!)



我使用的代码和技术在 this link by ascorbin,借助此链接。它不完整,除非你也添加以下行到EAGLView:

  glView.opaque = NO; 

电影视图位于EAGLView的一侧,并推到后面,对于。你可能还需要调整EAGLView的透明度,就像它在那篇文章中提到的。希望有帮助。






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



您需要向您的项目添加apple的 mediaPlayer.framework ,并在您的应用程序委托中包含以下行:.h:

  #import< MediaPlayer / MediaPlayer.h>在CCDirector的 setGLDefaultValues 方法中,将glClearColor的alpha值设置为为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从旧值更改为:

  // kEAGLColorFormatRGB565 
kEAGLColorFormatRGBA8

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

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

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

  [self startMovie]; 

和方法本身:

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

if([moviePlayer respondingToSelector:@selector(setFullscreen:animated :)]){
//使用新的3.2样式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
{
//使用旧的2.0样式API
moviePlayer.movi​​eControlMode = MPMovieControlModeHidden;
[moviePlayer播放];
}
}

注意,你不必添加观察者在链接的示例中列出,也不是重复电影的功能,这是使用'MPMovieRepeatModeOne'选项自动完成的。如果你不想让电影重复,你也可以在这里选择MPMovieRepeatModeNone选项。



我还应该注意,我无法让这个工作与旧的前3.2 API(所以在你的3.1.3的情况下,它不工作),视频没有通过EAGLView显示。我不知道那里发生了什么,但我没有看到关于如何做的具体选项。


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];

I have seen this question was quite similar

How to have a menu when a movie is playing-iphone 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).

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...

(many hours later..)

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.

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

but the movie still remains on top

please guys any help would very appreciated!

(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?

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!)

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;

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.

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>

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);

When creating your EAGLView in applicationDidFinishLaunching: change the following things:

Change the pixelFormat from the old value to be this:

// kEAGLColorFormatRGB565
kEAGLColorFormatRGBA8

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];

and the method itself:

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

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.

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:在菜单的背景中播放视频的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆