I have a cocos2d powered game that uses UIKit menues, so I only use the framework for one viewcontroller, which is the game itself. Also, it only has one scene. Since cocos2d 2.0 the director itself is a UIViewController subclass, so I just push it in my MenuViewController when the user taps a start button:
-(void)startGameButtonPressed {
CCDirectorIOS* director = (CCDirectorIOS *) [CCDirector sharedDirector];
// Create an CCGLView with a RGB565 color buffer, and a depth buffer of 0-bits
self.glView = [CCGLView viewWithFrame:CGRectMake(0, 0, 480, 320)
pixelFormat:kEAGLColorFormatRGB565 //kEAGLColorFormatRGBA8
depthFormat:0 //GL_DEPTH_COMPONENT24_OES
preserveBackbuffer:NO
sharegroup:nil
multiSampling:NO
numberOfSamples:0];
// attach the openglView to the director
[director setView:glView];
[director runWithScene:[GameLayer scene]];
[director setDelegate:(id <CCDirectorDelegate>) [[UIApplication sharedApplication] delegate]];
[self.navigationController pushViewController:director animated:YES];
}
This works fine for the first time the method is called, when the user starts the first game. When the game is over, I call [[CCDirector sharedDirector] end].
Most of the director setup is done in the appDelegate (it's taken unchanged from the default Cocos2d template). I only put the CCGLView as a retained property into my MenuViewController, because otherwise the app crashes when [[CCDirector sharedDirector] end] is called and the CCGLView is not retained. I think that might be a cocos2d bug. In [[CCDirector sharedDirector] end] the framework calls [self setView:nil], but it still tries to access the view later on (probably on another thread).
The problem now is that on the second call of my method above (when the user wants to start another game from the menu), startGameButtonPressed, the director gets pushed but the screen remains black. The game is running and responding, I just don't see anything. Can someone please help me out with that?
OK, I had the same problem and I was able to "fix it".
When you set the CCGLView and [director setView:], even if you pop the controller the scene still exists. the only thing that happens is that the scene gets stopped.
So in order to have the "restart" working, you have to check if there is already a running scene (even if it's stopped, and instead of runWithScene: you use replaceScene:.
Here is my code so you can see:
- (void)setupCocos2D {
CCGLView *glView = [CCGLView viewWithFrame:CGRectMake(0, 0, 320, 480)
pixelFormat:kEAGLColorFormatRGB565 //kEAGLColorFormatRGBA8
depthFormat:0 //GL_DEPTH_COMPONENT24_OES
preserveBackbuffer:NO
sharegroup:nil
multiSampling:NO
numberOfSamples:0];
// HERE YOU CHECK TO SEE IF THERE IS A SCENE RUNNING IN THE DIRECTOR ALREADY
if(![director_ runningScene]){
[director_ setView:glView]; // SET THE DIRECTOR VIEW
if( ! [director_ enableRetinaDisplay:YES] ) // ENABLE RETINA
CCLOG(#"Retina Display Not supported");
[director_ runWithScene:[HelloWorldLayer scene]]; // RUN THE SCENE
} else {
// THERE IS A SCENE, START SINCE IT WAS STOPPED AND REPLACE TO RESTART
[director_ startAnimation];
[director_ replaceScene:[HelloWorldLayer scene]];
}
[director_ setDelegate:(id <CCDirectorDelegate>) [[UIApplication sharedApplication] delegate]];
// I DO NOT PUSH BECAUSE I ALREADY PUSHED TO THIS CONTROLLER, SO I ADD THE COCOS2D VIEW AS A SUBVIEW
[self.view addSubview:[director_ view]];
}
Hope this code will help you, because I spent a whole day trying to figure this out.
It may not be the correct way or even the prettiest way, but it's working :)
EDIT:
Also, please not that if you POP the COCOS2D scene, you don't have to [[CCDirector sharedDirector] end] as the animation will be stopped when the view is dealloc/removed.
I have spent several days looking for information relating to this, and will share with you my own experience. I am also trying to create a game that loads into a UITableViewController, from which the CCDirector is loaded when a cell is touched. This is a Game Center turn-based game, hence the design (think Words With Friends). The best approach I have found so far for this is as follows (note I'm working in 2.0 - where CCDirector is a UIViewController subclass):
In AppDelegate.h, create a new ivar to hold the CCGLView that is created from the template code. Then assign the CCGLView created in didFinishLaunching to your new ivar. This allows the director to reuse the originally created view instead of trying to recreate it every time you reload the CCDirector, which seems to cause all sorts of weird issues in my experience.
You also want to create a new method in AppDelegate called -setupDirector or something of the like where you will, well, setup the director. This should be called each time you are recreating the CCDirector. I have posted my version below. Note my ivar for the CCGLView is called "GLView".
- (void)setupDirector {
if (![CCDirector sharedDirector]) {
CCLOG(#"Calling setupDirector");
director_ = (CCDirectorIOS*) [CCDirector sharedDirector];
director_.wantsFullScreenLayout = YES;
// Display FSP and SPF
[director_ setDisplayStats:NO];
// set FPS at 60
[director_ setAnimationInterval:1.0/60];
// attach the openglView to the director
[director_ setView:GLView];
// for rotation and other messages
[director_ setDelegate:self];
// 2D projection
[director_ setProjection:kCCDirectorProjection2D];
// [director setProjection:kCCDirectorProjection3D];
// Enables High Res mode (Retina Display) on iPhone 4 and maintains low res on all other devices
if( ! [director_ enableRetinaDisplay:YES] )
CCLOG(#"Retina Display Not supported");
// Default texture format for PNG/BMP/TIFF/JPEG/GIF images
// It can be RGBA8888, RGBA4444, RGB5_A1, RGB565
// You can change anytime.
[CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_RGBA8888];
// If the 1st suffix is not found and if fallback is enabled then fallback suffixes are going to searched. If none is found, it will try with the name without suffix.
// On iPad HD : "-ipadhd", "-ipad", "-hd"
// On iPad : "-ipad", "-hd"
// On iPhone HD: "-hd"
CCFileUtils *sharedFileUtils = [CCFileUtils sharedFileUtils];
[sharedFileUtils setEnableFallbackSuffixes:NO]; // Default: NO. No fallback suffixes are going to be used
[sharedFileUtils setiPhoneRetinaDisplaySuffix:#"-hd"]; // Default on iPhone RetinaDisplay is "-hd"
[sharedFileUtils setiPadSuffix:#"-ipad"]; // Default on iPad is "ipad"
[sharedFileUtils setiPadRetinaDisplaySuffix:#"-ipadhd"]; // Default on iPad RetinaDisplay is "-ipadhd"
// Assume that PVR images have premultiplied alpha
[CCTexture2D PVRImagesHavePremultipliedAlpha:YES];
}
In addition, you will want to make a couple changes to the way the template loads up the view controllers. Normally, cocos2D sets up the navigation controller with director_ as the root view controller. Here, you want to alloc and init your menu view controller and add THAT instead of director_:
// Create a Navigation Controller with the Director
gamesTVC_ = [[GamesTableViewController alloc] initWithStyle:UITableViewStyleGrouped];
navController_ = [[UINavigationController alloc] initWithRootViewController:gamesTVC_];
navController_.navigationBarHidden = NO;
Everything else in didFinishLaunching can remain the same. Now, in your menuViewController in your startGameButtonPressed method, you will call the newly created setupDirector method on your app instance, which is referenced by calling:
AppController *app = (AppController *)[[UIApplication sharedApplication] delegate];
if ([CCDirector sharedDirector].runningScene) {
[[CCDirectorIOS sharedDirector] end];
}
[app setupDirector];
[app.navController pushViewController:app.director animated:YES];
I include a check to make sure the CCDirector isn't still running, and if it is, end it. In your game layer, when the time comes that you want to pop the view controller, you will simply call it like so:
AppController *app = (AppController *)[[UIApplication sharedApplication] delegate];
[app.navController popViewControllerAnimated:YES];
[[CCDirector sharedDirector] end];
This flow should allow you to freely use a navigation controller to push your game scene with CCDirector, and pop that view controller when you want to go back to your UIKit-based main menu. I hope this helps, as I have spent a lot of frustrating time trying to get this right for my own game.
What works well is to just call startAnimation and stopAnimation in the director but keep the cocos2d view around and just re-use it.
Any attempts to shut down cocos2d and its OpenGL view and re-initializing it later on will cause more or less issues, because it really hasn't been tested well enough. Other than that cocos2d works just fine with UIKit, it just has the same issues any other OpenGL ES app has when mixing it with UIKit views.
In my experience, Cocos doesn't really support ending and resuming, it acts like it's done and pretty much shuts itself down.
There are two things you can try, the first one (and it just came to my mind) is to call CC_DIRECTOR_INIT (may not be the exact name) after the director ended, and before you want to start it again.
The second one is to edit the director source code, and modify the end method so that it leaves cocos in a usable state (stop it from releasing the view and purging the cache, etc). Alternatively to this, you can modify the start method so that it makes sure Cocos is in a usable state before starting.
Sadly, Cocos doesn't make it easy for us to use UIKit+Cocos, but with luck with it.
Related
The app crash on startup and I have this error in the console :
Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-[Chartboost showInterstitial]:
unrecognized selector sent to instance 0x7f844c9b74e0'
my code is :
#import "cocos2d.h"
#import "AppDelegate.h"
#import "IntroLayer.h"
#import "AppSpecificValues.h"
#import <RevMobAds/RevMobAds.h>
#import <Chartboost/Chartboost.h>
#implementation AppController
#synthesize gameCenterManager=gameCenterManager_, currentLeaderBoard=currentLeaderBoard_;
#synthesize window=window_, navController=navController_, director=director_;
#synthesize cb;
#synthesize nScore;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Create the main window
window_ = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Create an CCGLView with a RGB565 color buffer, and a depth buffer of 0-bits
CCGLView *glView = [CCGLView viewWithFrame:[window_ bounds]
pixelFormat:kEAGLColorFormatRGB565 //kEAGLColorFormatRGBA8
depthFormat:0 //GL_DEPTH_COMPONENT24_OES
preserveBackbuffer:NO
sharegroup:nil
multiSampling:NO
numberOfSamples:0];
director_ = (CCDirectorIOS*) [CCDirector sharedDirector];
director_.wantsFullScreenLayout = YES;
// Display FSP and SPF
// [director_ setDisplayStats:YES];
// set FPS at 60
[director_ setAnimationInterval:1.0/60];
// attach the openglView to the director
[director_ setView:glView];
// for rotation and other messages
[director_ setDelegate:self];
// 2D projection
[director_ setProjection:kCCDirectorProjection2D];
// [director setProjection:kCCDirectorProjection3D];
// Enables High Res mode (Retina Display) on iPhone 4 and maintains low res on all other devices
if( ! [director_ enableRetinaDisplay:YES] )
CCLOG(#"Retina Display Not supported");
// Default texture format for PNG/BMP/TIFF/JPEG/GIF images
// It can be RGBA8888, RGBA4444, RGB5_A1, RGB565
// You can change anytime.
[CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_RGBA8888];
// If the 1st suffix is not found and if fallback is enabled then fallback suffixes are going to searched. If none is found, it will try with the name without suffix.
// On iPad HD : "-ipadhd", "-ipad", "-hd"
// On iPad : "-ipad", "-hd"
// On iPhone HD: "-hd"
CCFileUtils *sharedFileUtils = [CCFileUtils sharedFileUtils];
[sharedFileUtils setEnableFallbackSuffixes:NO]; // Default: NO. No fallback suffixes are going to be used
[sharedFileUtils setiPhoneRetinaDisplaySuffix:#"-hd"]; // Default on iPhone RetinaDisplay is "-hd"
[sharedFileUtils setiPadSuffix:#"-ipad"]; // Default on iPad is "ipad"
[sharedFileUtils setiPadRetinaDisplaySuffix:#"-ipad-hd"]; // Default on iPad RetinaDisplay is "-ipadhd"
// Assume that PVR images have premultiplied alpha
[CCTexture2D PVRImagesHavePremultipliedAlpha:YES];
self.nScore = 0;
//Revmobs
[RevMobAds startSessionWithAppID:[[NSBundle mainBundle] objectForInfoDictionaryKey:#"RevMobAPI"]];
// and add the scene to the stack. The director will run it when it automatically when the view is displayed.
[director_ pushScene: [IntroLayer scene]];
[self initGameCenter];
// Create a Navigation Controller with the Director
navController_ = [[UINavigationController alloc] initWithRootViewController:director_];
navController_.navigationBarHidden = YES;
// set the Navigation Controller as the root view controller
// [window_ addSubview:navController_.view]; // Generates flicker.
[window_ setRootViewController:navController_];
// make main window visible
[window_ makeKeyAndVisible];
return YES;
}
-(void) lunchRevmobADLink
{
[[RevMobAds session] openAdLinkWithDelegate:self];
}
- (void) setUpRevMob {
[[RevMobAds session] showFullscreen];
}
-(void) launchChartboost
{
// Initialize the Chartboost library
[Chartboost startWithAppId:#"53be6ed01873dc9741aafa"
appSignature:#"fcd1715a73c97b22c5ad557323a59d7348476"
delegate:self];
// Begin a user session. This should be done once per boot
[cb startSession];
[cb cacheInterstitial];
[cb cacheMoreApps];
}
-(void) showChartboostInterestitial
{
// Show an interstitial
[[Chartboost sharedChartboost] showInterstitial];
}
-(void) showChartboostMoreApps
{
[[Chartboost sharedChartboost] showMoreApps];
}
// Supported orientations: Landscape. Customize it for your own needs
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return UIInterfaceOrientationIsPortrait(interfaceOrientation);
}
// getting a call, pause the game
-(void) applicationWillResignActive:(UIApplication *)application
{
if( [navController_ visibleViewController] == director_ )
[director_ pause];
}
// call got rejected
-(void) applicationDidBecomeActive:(UIApplication *)application
{
if( [navController_ visibleViewController] == director_ )
[director_ resume];
[self launchChartboost];
#ifdef FREE_VERSION
[self showChartboostInterestitial];
[self setUpRevMob];
[self hideAdBanner:YES];
#endif
}
and other code.
I tried lot of things! So I ask you now, How I can resolve this???
Thank's in advance!
According to Chartboost documentation you are not trying to show interstitial the right way :
To show a static or interstitial video ad:
// Show interstitial at location HomeScreen. See Chartboost.h for available location options.
[Chartboost showInterstitial:CBLocationHomeScreen];
The way you are doing it has been removed in their SDK 5.x
All references to [Chartboost sharedChartboost] are now changed to
Chartboost:
[[Chartboost sharedChartboost] showInterstitial:CBLocationHomeScreen]; is now [Chartboost
showInterstitial:CBLocationHomeScreen];
you are calling showInterstitial on an instance although it is a class method. it should be something like [Chartboost showInterstitial...
I have integrated the SKD of UnityAds into my game to show full screen interstitial video ads.
When the video is finished, a link to the AppStore is provided by the ad framework. When I select this link, the AppStore is opened. My app crashes in this moment, throwing EXC_BAD_ACCESS in CCGraphicsBufferGLUnsynchronized.
When starting my app, the UnityAds SDK is initialized like this:
[[UnityAds sharedInstance] startWithGameId:UNITYADS_MYAPP_ID
andViewController:[CCDirector sharedDirector]
];
As you can see, I am passing [CCDirector sharedDirector] as the view controller. I am mentioning this, as this might by a part of the problem?
Later I am calling the UnityAds SDK from within a Cocos2D scene like this:
-(void)showFullscreenAd {
// Stop Cocos2D rendering
[[CCDirector sharedDirector] pause];
[[CCDirector sharedDirector] stopAnimation];
// Is an ad available?
if ([[UnityAds sharedInstance] canShowAds]) {
// Display the ad
[[UnityAds sharedInstance] setZone:#"rewardedVideoZone"];
[[UnityAds sharedInstance] show];
}
}
As you can see I am stopping Cocos2D rendering before displaying the add.
When I select the AppStore link in the add, my app crashes.
This is the code Xcode points me to after the crash (in class CCGraphicsBufferGLUnsynchronized)
-(void)prepare
{
_count = 0;
GLenum target = (GLenum)_type;
glBindBuffer(_type, _buffer);
==> _ptr = _mapBufferRange(target, 0, (GLsizei)(_capacity*_elementSize), BUFFER_ACCESS_WRITE);
glBindBuffer(target, 0);
CC_CHECK_GL_ERROR_DEBUG();
}
Can someone point me into the right direction for debugging?
I am running my app on an iPad and iPhone under iOS 8.1.3
OK, I found a solution myself. Seems like the crash occurs because the app is in the background and rendering continues. So all I had to do was to make sure that rendering is not resumed after the app was moved to the background.
I do it like this now:
// Added a flag to control resuming of rendering
#property (readwrite) bool resumeRendering;
[...]
-(void)showFullscreenAd {
// Stop Cocos2D rendering
[[CCDirector sharedDirector] pause];
[[CCDirector sharedDirector] stopAnimation];
// Set to resume redering by default
_resumeRendering = YES;
// Is an ad available?
if ([[UnityAds sharedInstance] canShowAds]) {
// Display the ad
[[UnityAds sharedInstance] setZone:#"rewardedVideoZone"];
[[UnityAds sharedInstance] show];
}
}
[...]
#pragma mark - UnityAdsDelegate
// This method is called when the interstitial ad is discarded
// check if rendering should be resumed
-(void)unityAdsDidHide {
if ( _resumeRendering ) {
[[CCDirector sharedDirector] resume];
[[CCDirector sharedDirector] startAnimation];
}
// do anything else here
// In my case I transfer to the next scene
[...]
}
-(void)unityAdsWillLeaveApplication {
// Will leave application. Make sure rendering is not resumed anymore
_resumeRendering = NO;
}
When the user clicks the AppStore link in the ad now, the method unityAdsWillLeaveApplication will be called and I can mark resumeRendering as false.
Hope this helps other with the same problem.
I have an app with a tab bar controller at the root. The "home view" is a 3D rendered screen in OpenGL. There are certain 3D objects that you can click on that need to display a video. The video should be fullscreen and fade in and out.
To do this, I made the HomeViewController create a MPMoviePlayerViewController, assigned it a URL and then presented it from the tab bar controller. (I would have presented it from the HomeViewController but for some reason it didn't change its orientation properly--I'm sure it's related to all of the custom 3D stuff, and I didn't program it, so I just did a workaround by displaying it from a senior view.)
(Note that I am presenting the MPMoviePlayerViewController modally (not using the built-in presentModalMovieViewController or whatever) because Apple forces the transition to be the wacky screen-shift, and I wanted the dissolve.)
Now, that works fine. The modal window dissolves in, the video plays. You can play and pause it, fast forward, hit "Done" and the modal window goes away. Voila.
Now, here comes the totally weird bug: if you don't tap the video player and let the controls fade out (as they do after a second or two) the user cannot bring them back by tapping. It seems like the video controller stops responding to user input after that fade. Again, it works fine before they fade away. But after that point, I have to wait for the video to play all the way (at which point the modal window does, in fact, go away).
For reference, here is the relevant code to the modal video player:
-(void) startVideoWithURL:(NSURL *)videoURL {
if (!self.outsideMoviePlayerViewController) {
self.outsideMoviePlayerViewController = [[MPMoviePlayerViewController alloc] initWithContentURL:nil];
}
if (videoURL) {
[self stopAnimation];
self.outsideMoviePlayerViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
self.outsideMoviePlayerViewController.moviePlayer.contentURL = videoURL;
[[[AppController instance] getCustomTabBarViewController] presentModalViewController:self.outsideMoviePlayerViewController animated:YES];
// Move observation of the dismiss from the MoviePlayerViewController to self.
[[NSNotificationCenter defaultCenter] removeObserver:self.outsideMoviePlayerViewController
name:MPMoviePlayerPlaybackDidFinishNotification
object:self.outsideMoviePlayerViewController.moviePlayer];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(movieFinishedCallback:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:self.outsideMoviePlayerViewController.moviePlayer];
}
}
-(void) movieFinishedCallback:(NSNotification *)aNotification {
// Summary: Restart 3D animation, unregister from notifications, kill the modal video.
[self startAnimation];
MPMoviePlayerController *moviePlayer = [aNotification object];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:moviePlayer];
[[[AppController instance] getCustomTabBarViewController] dismissModalViewControllerAnimated:YES];
}
The only other reference I could find to an issue like this was some archived post on the Apple Support Communities, here:
https://discussions.apple.com/thread/2141156?start=0&tstart=0
In this thread, the issue poster figures it out himself, and states that the issue was resolved. Here's his explanation:
The problem occurs when CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE). After i changed to CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.002, TRUE), the playback control can appears/disappear by tapping the screen.
Unfortunately, I'm not programming a game and nobody on my dev team calls CFRunLoopRunInMode anywhere in the code. The closest thing I found to this was in the animation code (in the same ViewController):
- (void)startAnimation
{
if (!animating)
{
NSLog(#"startAnimation called");
CADisplayLink *aDisplayLink = [[UIScreen mainScreen] displayLinkWithTarget:self selector:#selector(drawFrame)];
[aDisplayLink setFrameInterval:animationFrameInterval];
[aDisplayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
self.displayLink = aDisplayLink;
animating = TRUE;
}
}
If anyone has any insights on what could be causing this, I would appreciate it. I figured that, at the very least, even if I figure it out myself tonight, this problem could go up on Stack Overflow and be archived for the sake of posterity.
Cheers.
I figured out what was causing this problem.
I noticed that the first video did play, while successive ones did not. I moved this code:
if (!self.outsideMoviePlayerViewController) {
self.outsideMoviePlayerViewController = [[MPMoviePlayerViewController alloc] initWithContentURL:nil];
}
This way the creation of the outsideMoviePlayerViewController was inside the next block, like so:
if (videoURL) {
self.outsideMoviePlayerViewController = [[MPMoviePlayerViewController alloc] initWithContentURL:nil];
[self stopAnimation];
self.outsideMoviePlayerViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
self.outsideMoviePlayerViewController.moviePlayer.contentURL = videoURL;
Now a new controller is created instead of recycling the controller each time I played a video. The bug went away. I'm not 100% sure why this happened, because there are a variety of things that occur when you display a modal view controller.
The bottom line is probably that I should have done this in the first place as part of the lazy loading paradigm instead of trying to keep the controller in memory.
I'm a beginner at cocos2d, and I'm trying to perform a segue from inside cocos2d.
Currently I set up the following function:
-(void) return_mm {
NSLog(#"returned to main menu");
UIViewController * con = self.controller;
[con performSegueWithIdentifier:#"Game2MenuSegue" sender:con];
}
to ran whenever a CCMenuItem is pressed. This actually does indeed work once. However, when I segue back into the game scene, the menu button stops working.
To be more specific, the segue is called, and the preparetosegue function is ran, but no transition happens. The other view's viewWillAppear function never runs.
I'm probably doing something stupid, so if anyone has suggestions on doing this, it would be greatly appreciated.
This is what I currently have in the game view controller's willDidAppear function.
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
if ([[CCDirector sharedDirector] isPaused]) {
[[CCDirector sharedDirector] resume];
[mainView addSubview:[[CCDirector sharedDirector] openGLView]];
return;
}
EAGLView *glview = [EAGLView viewWithFrame:self.view.bounds
pixelFormat:kEAGLColorFormatRGB565 // kEAGLColorFormatRGBA8
depthFormat:0 // GL_DEPTH_COMPONENT16_OES
];
CCDirector *director = [CCDirector sharedDirector];
//[director setDisplayStats:kCCDirectorStatsFPS];
// Enables High Res mode (Retina Display) on iPhone 4 and maintains low res on all other devices
if( ! [director enableRetinaDisplay:YES] )
CCLOG(#"Retina Display Not supported");
[window makeKeyAndVisible];
[mainView addSubview:glview];
[director setOpenGLView:glview];
CCScene *scene = [CCScene node];
GameScene * gs =[GameScene sceneWithController:self];
[gs returnFromMenu];
[scene addChild:gs];
if (director.runningScene) {
[director replaceScene:scene];
} else {
[director runWithScene:scene];
}
}
I found the problem. I saved the controller on creation, but didn't update it when it segues back into the game view. The controller was outdated so the segue didn't do anything.
I just had to add
gs.controller = self
below the call to super
Currently I have this code in my UIViewController:
//Cocos2D methods
-(id) init {
if((self=[super init]))
{
CCScene *scene = [CCScene node];
CCLayer *layer = [CCLayer node];
[scene addChild:layer];
[[CCDirector sharedDirector] runWithScene:scene];
[[CCDirector sharedDirector] setDisplayFPS:NO];
[self performSelector:#selector(cocosgameLoop:) withObject:nil afterDelay:1/60.0f];
}
return self;
}
- (void)cocosgameLoop:(ccTime)dT {
//Check for collisions here and add gravity, etc....
}
- (void)viewDidUnload {
[super viewDidUnload];
[[CCDirector sharedDirector] end];
}
//
My view controller is somewhat Objective-C code, but I want to add Cocos2D to the UIView. I think the code above is initializing it, but I am not sure. Also should the CCScene have its own class dedicated to everything that goes on in the scene? if so how would I do that?
I know these are a lot of questions, but my game is very similar to Doodle Jump and I need to know where to go from the current state I am in.
Does anyone have any ideas/tips?
Thanks!
performSelector will call the cocosgameLoop only once. You will want to call CCDirector startAnimation, and then schedule updates in your cocos2d nodes.
My Learn Cocos2D book (2nd Edition) explains how to add and setup Cocos2D in a UIKit view (regular iPhone) app.