【问题标题】:cocos2d: playing a video in the background of a menucocos2d:在菜单背景下播放视频
【发布时间】:2011-05-26 04:21:14
【问题描述】:

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

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

我看到这个问题很相似

How to have a menu when a movie is playing-iphone cocos2d

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

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

[theView sendSubviewToBack:moviePlayer.view];

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

(几个小时后..)

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

【问题讨论】:

  • 我发现了这个:cocos2d-iphone.org/forum/topic/61 它的 cmets 之一说:“它不起作用,因为 imageView 已添加到 openGLView。似乎 cocos2d 无法在 UI 对象上绘制。唯一的这样做的方法是使用标准的 UI 方法,但在涉及动画时,它不像 cocos2d 那样方便”。可能吗?那可能很丑……

标签: iphone objective-c cocos2d-iphone


【解决方案1】:

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

this link 的帮助下,我使用了 ascorbin 在 this link 中的代码和技术。除非您还将以下行添加到 EAGLView,否则它是不完整的:

glView.opaque = NO;

电影视图位于 EAGLView 的一侧,并被推到后面以获取您要查找的内容。您可能还需要调整 EAGLView 的透明度,就像它在那篇文章中提到的那样。希望对您有所帮助。


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

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

#import <MediaPlayer/MediaPlayer.h>

在 CCDirector 的setGLDefaultValues 方法中,设置 glClearColor 的 alpha 为 0.0f 而不是 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 添加为子视图(并使其不透明)而不是主视图:

//  [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”选项。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多