2010-12-15 44 views
17

J'ai un CCLayer avec le menu Démarrer de mon application et j'aimerais faire jouer un court métrage en arrière-plan. J'ai réussi à lire un film dans le glView mais quand il joue le menu n'est pas représenté. Pour gérer le film que j'instancier un MPMoviePlayerController puis ajouter son point de vue à la GLView de cette façon:cocos2d: lecture d'une vidéo en arrière-plan d'un menu

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

J'ai vu cette question était tout à fait similaire

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

mais je voudrais savoir s'il y a une meilleure solution, peut-être une qui me permettrait d'exploiter encore les entités du framework cocos2d (et non mes propres vues).

J'ai essayé d'envoyer le moviePlayer.view à dos de cette façon

[theView sendSubviewToBack:moviePlayer.view]; 

mais le menu est Stil caché par le film ...

(plusieurs heures plus tard ..)

Ok, comme vous pouvez le lire dans le premier commentaire, j'ai réalisé que (probablement) le seul moyen est d'exploiter les vues personnalisées. Je l'ai fait et il s'exécute dans le simulateur en ajoutant des vues au glView après le moviePlayer.view. Cependant, quand je le lance sur mon IPod Touch cible avec un FW 3.1.3, la vue du film est toujours au top. J'ai donc réalisé que MPMoviePlayerController crée sa propre fenêtre et sa propre vue. Certains messages (comme celui-ci Overlay on top of Streaming MPMoviePlayerController) suggèrent d'intercepter l'événement la nouvelle fenêtre est chargée et seulement ensuite ajouter les sous-vues.

c'est ce que j'ai essayé de faire mais cet événement n'est en fait jamais détecté sur le simulateur ni sur l'Ipod cible. J'ai donc ajouté un sélecteur prévu - (void) mise à jour qui est mis en œuvre ainsi:

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

mais le film reste sur le dessus

plaît les gars tout d'aide serait très apprécié!

(quelques jours plus tard ...) J'ai également attendu pendant 2 secondes, alors que le film est en cours d'exécution, pour ajouter mon logo sous forme de sous-vue du ciné-lecteur. Cela fonctionne correctement sur le simulateur mais sur l'Ipod (3.1.3) il en résulte un résultat différent. La première fois que le film est joué, le logo n'est pas représenté (film en haut). Cependant, dès que le film se termine, la méthode de jeu est collée, à partir de la deuxième fois le logo est représenté avec le film sur le fond (Est-ce que je le ferais). Cela a-t-il un sens pour vous?

je vraiment besoin de comprendre comment résoudre ce problème, il est tout à fait ridicule que j'ai reussi développer un jeu en 2 mois et maintenant je suis coincé de 2 semaines pour le menu de démarrage :)

Quoi qu'il en soit, si je a décidé de coller tout le code de la couche que je suis en train de corriger afin que vous puissiez mieux comprendre ce que le problème est (ou du moins est mon espoir :))

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

J'ai trouvé ceci: http://www.cocos2d-iphone.org/forum/topic/61 un de ses commentaires dit: "cela ne fonctionne pas parce que l'imageView est ajouté à l'openGLView. ne dessine pas sur l'objet UI La seule façon de le faire est d'utiliser la méthode UI standard, mais ce n'est pas pratique comme cocos2d quand l'animation est impliquée ". C'est possible? cela pourrait être moche ... – Sindico

Répondre

19

Après avoir passé quelque temps avec ce que je trouvé la réponse. (Je veux faire ça aussi, mais plus tard, je ferais mieux de le faire maintenant!

J'ai utilisé le code et les techniques dans this link par ascorbin, avec l'aide de this link. Il n'est pas complète si vous ajoutez également la ligne suivante à la EAGLView:

glView.opaque = NO; 

La vue film est le long du côté de la EAGLView, et poussé à l'arrière pour obtenir ce que vous recherchez. Vous devrez peut-être également modifier la transparence de l'EAGLView comme indiqué dans ce message. J'espère que cela pourra aider.


Les choses que j'ai besoin de modifier sont listées ici.

Vous devez ajouter de mediaPlayer.framework pomme à votre projet et inclure la ligne suivante dans votre délégué app .h:

#import <MediaPlayer/MediaPlayer.h> 

Dans la méthode de CCDirector setGLDefaultValues, définissez alpha être de glClearColor 0.0f pas 1.0f:

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

Lorsque vous créez votre EAGLView dans applicationDidFinishLaunching: changer les choses suivantes:

changer le pixelFor tapis de l'ancienne valeur pour être ceci:

// kEAGLColorFormatRGB565 
kEAGLColorFormatRGBA8 

Assurez-vous d'ajouter le EAGLView comme une sous-vue (et de le rendre non-opaque) plutôt que comme la vue principale:

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

Enfin , avant d'exécuter votre scène, vous pouvez ajouter votre code pour lire le film en boucle. J'ai ajouté une méthode au délégué de l'application pour cela. Vous pouvez également ajouter une méthode pour empêcher votre film de jouer ici dans le délégué de l'application et pour quand (si?) Vous devez supprimer votre film.

[self startMovie]; 

et la méthode elle-même:

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

Notez que vous ne devez pas ajouter l'observateur comme figure dans l'exemple lié, ni la fonction de répéter le film, cela se fait automatiquement l'option 'MPMovieRepeatModeOne'. Si vous ne voulez pas que le film se répète, vous pouvez également choisir l'option 'MPMovieRepeatModeNone' ici.

Je devrais également noter que je ne pouvais pas obtenir ceci pour fonctionner avec l'ancienne API pré-3.2 (ainsi dans votre cas 3.1.3 cela ne fonctionnait pas), la vidéo n'a pas montré à travers le EAGLView. Je ne suis pas sûr de ce qui se passe là-bas, mais je n'ai pas vu d'options spécifiques sur ce qu'il faut faire à ce sujet.

+0

+1 pour une excellente réponse. –