How to add UIView behind CCGLView (Cocos2d-objc) - ios

I'm trying to play a video using MPMoviePlayerController and wanted to show it behind the cocos2d assets. I was able to play the video but it appears on top of the cocos2d assets. Cocos2D-ObjC version is 3.5.0.
Here's my code snippet:
MPMoviePlayerController *moviePlayer = self.moviePlayerController.moviePlayer;
CCDirectorIOS *director = (CCDirectorIOS*)[CCDirector sharedDirector];
CC_VIEW *directorView = [director view];
[directorView addSubview:moviePlayer.view];
[directorView sendSubviewToBack:[moviePlayer view]];
directorView.opaque = NO;
Any help is highly appreciated.

Just for info: there is no way to add it beetween, because cocos2d view controller(with all your images) is a layer added on the directorView.
So cocos2d director is a view controller drawing into a single view, a CCGLView. You can't add a view to a layer, because layers are not views. Layers are just objects used by cocos2d.
As with other views, you can add a view below the cocos2d CCGLView (as a parent or earlier sibling of the GLView) or above the cocos2d CCGLView (as a child or later sibling of the GLView), but not anywhere in-between. Because of this, your UIView can only be logically above or below all Cocos2d drawing.
And for sending back just use:
[viewController.view addSubview:moviePlayer.view];
[viewController.view sendSubviewToBack:moviePlayer.view];

Related

How to create popup using sprite kit on iphone?

I am a beginner developing an iOS game using sprite kit. I would like to have 'pop-up' menu's that display objects (skspritenodes) such as daily rewards or settings/pause menu. The settings pop-up for example should be able to be accessed on the main home screen or during the game. Currently I have one view controller and the home scene and play scene are two different SKScenes. For reusability (and a clean project, as well as learning) I would like to have these pop-ups be their own class, including handling touches. Currently, I have a class for the settings pop-up that returns an SKNode, and this sknode contains several skspritenodes (the buttons/images that correspond to a settings pop up including enabling/disabling sound etc). However, I have to duplicate the touches code in both my home scene and my play scene to interact with this. (I currently have, in each skscene's touchesbegan method, "if nodeSettings !=nil", check the name of the skspritenode that corresponds to the touch-location, then call a method in the setting-pop-up class passing the name of the skspritenode clicked to handle interactions with the pop-up).
For my own knowledge and also to solve this problem, I would like to use a class that can handle the touch logic on its own (so in my play or home skscene, the only thing I do is create the pop-up. Any interaction, including dismissal, I would like to have handled in the class. No using the skscene's touches methods). I have found one 'solution' to this:
LTPopUpReward *test = [[LTPopUpReward alloc] init];
UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:test];
CGFloat fltHeight = [UIScreen mainScreen].bounds.size.height;
CGFloat fltWidth = [UIScreen mainScreen].bounds.size.width;
popover.popoverContentSize = CGSizeMake(fltWidth/2, fltHeight/2); //your custom size.
CGRect rectPopUpReward = CGRectMake(500, 500, fltWidth/2, fltHeight/2);
[popover presentPopoverFromRect:rectPopUpReward inView:self.view permittedArrowDirections: UIPopoverArrowDirectionAny animated:YES];
and I like that you can dismiss the UIPopoverController by clicking outside of it, but this UIPopoverController only works on the iPad and doesn't work on the iPhone. I've seen this UIPopoverController for iphone not working? but was wondering if there is another way to solve my problem that Apple won't possibly disapprove of? For example, could I create a UIViewController, resize it and position it (i don't know how to do this) to simulate the pop-up?
Summarizing: my goal is to have a pop-up appear, but have all of its code (including touch) self contained within one class, and the objects on the pop-up are skspritenodes.
answering my own question: The solution I used to solve this problem is to use different SKViews. One SKView presents the main scene and another SKView presents the pop-up scene. You can adjust the size of the second SKView and even make its background transparent. Interacting with objects in this view will correctly call the touches methods in the class of the scene presented - That is this pop-up is dealt with when being created, and there is no other code dealing with it on the view-controller or main-scene's logic (all code, including creating objects and handling touch) are in the second skscene's code. The method below is called when I do "something" to call the 'pop-up'.
-(void)test4
{
skViewPopUp=nil;
scenePopUpReward=nil;
NSLog(#"test4 successfully fired");
CGFloat fltHeight = [UIScreen mainScreen].bounds.size.height;
CGFloat fltWidth = [UIScreen mainScreen].bounds.size.width;
CGRect rectPopUpReward = CGRectMake(0, 0, fltWidth/2, fltHeight/2);
skViewPopUp = [[SKView alloc] initWithFrame:rectPopUpReward];
[self.view addSubview:skViewPopUp];
skViewPopUp.allowsTransparency = YES;
scenePopUpReward = [[LTSceneStoreMain alloc] initWithSize:CGSizeMake(fltWidth/2, fltHeight/2)];
scenePopUpReward.backgroundColor = [UIColor clearColor];
[skViewPopUp presentScene:scenePopUpReward];
}

How to make my sprite kit scene appear above a UIView?

I've done some searching but haven't found anything directly addressing my issue: I have an SKScene with several SKNodes each with SKSpriteNode objects for my game, and I am using a background UIImageView (there are some things I need to do with background that cannot be reasonable done with sprite kit - to my knowledge at least); the problem I'm having is that the UIImageView appears above everything and I can't see my game objects.
In my view controller (.m file) I have the following code to call my scene
#implementation GameViewController
- (void)viewDidLoad
{
[super viewDidLoad];
SKView * skView = (SKView *)self.view;
SKScene * scene = [GameScene sceneWithSize:skView.bounds.size];
scene.scaleMode = SKSceneScaleModeAspectFill;
[skView presentScene:scene];
}
In the GameScene above, I have several SKNodes where all my game objects are children of (for example nodeHDU, nodePlay, nodePauseMenu...), and I am using a UIImageView as my background (I am switching between background scenes over time and am using some nice transitions such as UIViewAnimationOptionTransitionCrossDissolve; couldn't accomplish this with a SKSpriteNode as background without using multiple SKSpriteNodes and an intricate array of SKActions so I"m using UIImageView)
UIView *backgrounds = [[UIView alloc] init];
[self.view insertSubview:backgrounds belowSubview:self.view];
UIImageView *imageBackground = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,self.view.frame.size.width,self.view.frame.size.height)];
[backgrounds addSubview:imageBackground];
[backgrounds sendSubviewToBack:imageBackground];
[imageBackground setImage:[UIImage imageNamed:#"1-A.png"]];
imageBackground.alpha=1.0;
However, the ImageBackground above is the only thing I see when running the app in Xcode. The other objects from my game (children of other nodes) exist, and various NSLog statements are getting called, but they seem to appear behind the ImageBackground I have. The code above "belowSubview" and "sendSubviewToBack" don't help.
So How can I send the imageBackground to actually be the background?
Your problem is here that you are directly setting SKView as a controller view. To overcome from this issue don't make self.view a type of SKView. Do the following step in your storyboard or Xib :
Add an UIImageView on the controller's view first. Set the image as well.
Then add a SKView over the UIImageViewand set UIClearColor to the background colour.
So the complete hierarchy is like UIViewController->UIView->UIImageView->SKView

UIKit + SpriteKit - Cannot properly layer buttons, nodes, and image views

I'm quite new to iOS development, and I'm working on an app that uses UIKit for buttons and Sprite Kit for a virtual joystick. My goal is to have the buttons and joystick visible on top of a UIImageView (more specifically, a MotionJpegImageView). I used a storyboard to create the buttons, and programatically created a UIImageView and added it as a subview to my main view in my view controller. The joystick was created in a separate file that subclasses SKScene. However, there's a problem. My UIImageView shows up below the buttons (as desired) but covers the joystick. I need the joystick to be visible on top of the image. I've already tried the sendSubviewToBack method but that isn't doing the trick. I've also tried using zPositions, but that is not working either. Does anyone know how I can achieve my goal? Relevant code is below. Thanks for looking!
ViewController.m
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
NSURL *url = [NSURL URLWithString:#"http://shibuya.ipcam.jp:60001/nphMotionJpeg?Resolution=320x240&Quality=Standard"];
_imageView = [[MotionJpegImageView alloc] initWithFrame:CGRectMake(self.view.frame.origin.y, self.view.frame.origin.x,
[[UIScreen mainScreen] bounds].size.height,[[UIScreen mainScreen] bounds].size.width)];
_imageView.url = url;
[self.view addSubview:_imageView];
[self.view sendSubviewToBack:_imageView];
[_imageView play];
SKView *spriteView = (SKView *) self.view;
JoystickScene* joystick = [[JoystickScene alloc] initWithSize:CGSizeMake(768,1024)];
[spriteView presentScene: joystick];
[self.view bringSubviewToFront:spriteView];
}
JoystickScene.m
- (void)didMoveToView: (SKView *) view
{
SKSpriteNode *jsThumb = [SKSpriteNode spriteNodeWithImageNamed:#"joystick.png"];
SKSpriteNode *jsBackdrop = [SKSpriteNode spriteNodeWithImageNamed:#"dpad.png"];
joystick = [Joystick joystickWithThumb:jsThumb andBackdrop:jsBackdrop];
joystick.position = CGPointMake(jsBackdrop.size.width, jsBackdrop.size.width);
velocityTick = [CADisplayLink displayLinkWithTarget:self selector:#selector(joystickMovement)];
[velocityTick addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
joystick.zPosition = 1;
[self addChild:joystick];
}
The spritekit SKView is the view of your viewcontroller. Every subview will be rendered on top of it. Is there a special reason you want to use Spritekit for the joystick? Otherwise I would suggest to make it with standard UIKit elements and just add it after the imageView.
Using an SKView on top of other views will not give you the desired results, since it cannot have a transparent background.
Another issue with your code: you shouldn't create and add views in viewWillLayoutSubviews, since this method could be called multiple times (every device Rotation for instance). Use viewDidLoad instead.

CocosBuilder Animations not running

I'm creating a simple animation with CocosBuilder that just moves a CCLayerColor from top right to bottom left and for some reason the animations will not perform. I have the timeline set to auto play and over a duration of 2 seconds. I have a class that splits up all layers and then adds those layers to a CCScrollLayer. I'm just wondering if the problem is when i remove the layers from the scene and add then to the CCScrollLayer that the animations are removed and in turn not performed.
CCScene* scene = [CCBReader sceneWithNodeGraphFromFile:#"Untitled.ccbi"];
self.scrollLayer = [[CCScrollLayer alloc] init];
CCLayer* child = [[scene children] objectAtIndex:0];
for (CCNode* layer in [child children]) {
[layer removeFromParent];
[self.scrollLayer addChild:layer];
[layer resumeSchedulerAndActions];
}
[self.scrollLayer updatePages];
self.scrollLayer.delegate = self;
[self addChild:self.scrollLayer];
I can see the CCLayerColor object added to the screen but its just not animating.
i've added some custom code to the CCScrollLayer to deal with the situation but i'm just confused as to why the animations are not performing. any help would be great!
EDIT: Maybe a better question would be in CocosBuilder are the actions on the timeline directly linked to the object performing the action or somehow linked through the scene to that object?
Perhaps you forgot to add the scrollLayer as child?
[self addChild:self.scrollLayer];
In the sample code the node created from a ccbi is not referenced either. Maybe you aren't actually using it?

Cocos2D z-index issue with openGLView

I have a UITableView that shows scores and names. I also have animated objects that move around the screen.. However they go under the tableview and not visible no matter what z-index value that have.. How can I make the animated objects go on top of my UITableView?
Thanks..
Before you continue (samfisher's solution works to place all UIKit below cocos2d views) keep this in mind:
It is technically impossible to have a UIKit view in cocos2d where cocos2d draws nodes both in front of and behind the UIKit view at the same time.
In other words: a UIKit view can either be completely in front of all cocos2d nodes, or completely behind all of cocos2d nodes.
The reason is that cocos2d is a view from UIKit's perspective.
you must have added UITableView as subview of CCDirector's openGLView.
All the COCOS2D animations with the objects are going on the openGLView which is obviously below the TableView so z index wont work in this case.
All you have to do is insert the UITableView directly on UIWindow and move it below the openGLView. You can also use:
[<UIWindow> insertSubview:<TableView> belowSubview:<openGLView>];
all you need to do is to make your openGLView transparent and make sure that you have no background image added on CCLayer (or else it will cover the )
so the question is hoe to make your openGLView - transparent
-(void) initGLDefaultValues
{
// This method SHOULD be called only after openGLView_ was initialized
NSAssert( openGLView_, #"openGLView_ must be initialized");
[self setAlphaBlending: YES];
[self setDepthTest: YES];
[self setProjection: CCDirectorProjectionDefault];
// ***** NEW CODE: make open gl view transparent
openGLView_.opaque = NO;
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
// disable regular, opaque clear color
//glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// ***** NEW CODE end
}

Resources