I know Cocos2d 2.0 is in alpha and will obviously have certain issues with it. I am trying to convert several projects to use OpenGL 2.0 for multiple reasons, but am having one very strange issue.
When I start up a scene, my textures load as desired and everything works great. I then display some Apple UI elements that allow me to quit the scene. The scene and its view controller are deallocated, the director is told to end, and I return to another view. Then I press a UIButton that launches the scene again. The scene begins again and runs, but no textures are visible. Fonts load and display, audio loads and plays, but no textures are visible. When dumping info from the CCTextureCache, I can see that the desired textures are available in the cache ( [[CCTextureCache sharedTextureCache] dumpCachedTextureInfo] ). I have also tried clearing the cache before the scene is relaunched. No matter what, I can not see any textures or add nodes to the scene.
There could be something wrong with how I reset the scene, or how the EAGLView is setup. Here is the code for starting said scene from a View Controller:
(void)startGame {
CCDirector *director = [CCDirector sharedDirector];
EAGLView *glView = [EAGLView viewWithFrame:[self.view bounds]];
[director setOpenGLView:glView];
[self setView:glView];
[[CCTextureCache sharedTextureCache] removeUnusedTextures];
//[CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_RGBA8888];
[[CCDirector sharedDirector] runWithScene:[Cocos2DChipmunkScene scene]];
}
Then, the scene is quit, and the following is called:
CCDirector *director = [CCDirector sharedDirector];
[[director openGLView] removeFromSuperview];
[director end];
The above startGame method is called again when I try to start the game again. This is the point where no textures are displayed.
Let me know if I need to provide more details on this issue.
My recommendation is to not shut down the director and keep the openGLView in the hierarchy, just set it as hidden: openGLView.hidden = YES;
You can start and stop cocos2d via [[CCDirector sharedDirector] startAnimation] respectively stopAnimation.
Related
I created a regular simple iOS app (a single view application) with one button and I want to launch a cocos2D game from the iOS app. In other words, I want to launch the cocos2D game when I press on the button from my myapp.xib. I don't want to use URL schemes to launch the game because that will require the user to download my app as well as download the game. I want the user to be able to launch the game from my app internally. This is the game I want to launch from my app:
http://www.raywenderlich.com/14439/how-to-make-a-game-like-fruit-ninja-with-box2d-and-cocos2d-part-3
I was able to successfully add this game as a dependency in my xcode project. However, I'm not sure how to go about launching the game from app.
Here's some ideas that I had, but they didn't really work for me.
Is there any way I can:
Call the app delegate of the game (not the app delegate of my app) from the IBAction in my app to launch the game?
Call the didFinishLaunchingWithOptions method of the game (not the didFinishLaunchingWithOptions of my app) from the IBAction in my app to launch the game?
Call the main.m file of the game (not the main.m of my app) from the IBAction in my app to launch the game?
From what I understand, these are three different ways of launching an iOS app. Keep in mind that I am developing an app (not a game) that will allow a user to launch the game above internally through the app. Ideally, it would nice (and also easy) if I can simply do a pushviewcontroller from my app to the game, but I'm not sure if there is an easy way to approach this.
Is there anyway I can launch this game internally through my app? Any advice, suggestions, sample source code would be greatly appreciated.
Short answer: YES
You would need to have just one AppDelegate (the one of your iOS app), and move there all the cocos2D init stuff. Then, you can launch the game from your IBAction with something like this.-
CCDirector *director = [CCDirector sharedDirector];
[director pushScene:[YourFirstGameScene node]];
[director resume];
[self presentModalViewController:director animated:YES];
Please, take next snippet as an example to init/end cocos2d from your appDelegate
- (void) initCocos {
// Create an CCGLView with a RGB565 color buffer, and a depth buffer of 0-bits
CCGLView *glView = [CCGLView viewWithFrame:[self.window bounds]
pixelFormat:kEAGLColorFormatRGBA8 //kEAGLColorFormatRGBA8
depthFormat:0 //GL_DEPTH_COMPONENT24_OES
preserveBackbuffer:NO
sharegroup:nil
multiSampling:NO
numberOfSamples:0];
self.director = (CCDirectorIOS*) [CCDirector sharedDirector];
self.director.wantsFullScreenLayout = YES;
// Display FSP and SPF
[self.director setDisplayStats:NO];
// set FPS at 60
[self.director setAnimationInterval:1.0/60];
// attach the openglView to the director
[self.director setView:glView];
// for rotation and other messages
[self.director setDelegate:self];
// 2D projection
[self.director setProjection:kCCDirectorProjection2D];
// [director setProjection:kCCDirectorProjection3D];
// Enables High Res mode (Retina Display) on iPhone 4 and maintains low res on all other devices
if( ! [self.director enableRetinaDisplay:NO] )
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];
// When in iPhone RetinaDisplay, iPad, iPad RetinaDisplay mode, CCFileUtils will append the "-hd", "-ipad", "-ipadhd" to all loaded files
// If the -hd, -ipad, -ipadhd files are not found, it will load the non-suffixed version
//[CCFileUtils setiPhoneRetinaDisplaySuffix:#"-hd"]; // Default on iPhone RetinaDisplay is "-hd"
[CCFileUtils setiPadSuffix:#""]; // Default on iPad is "" (empty string)
//[CCFileUtils setiPadRetinaDisplaySuffix:#"-ipadhd"]; // Default on iPad RetinaDisplay is "-ipadhd"
// Assume that PVR images have premultiplied alpha
[CCTexture2D PVRImagesHavePremultipliedAlpha:YES];
}
- (void) endCocos {
CC_DIRECTOR_END();
self.director = nil;
}
Actually, what I do is a call to initCocos just before pushing my director, and endCocos just after closing the game, like
AppDelegate *appDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate];
[[CCDirector sharedDirector] dismissModalViewControllerAnimated:YES];
[appDelegate endCocos];
Hope it helps.
In Kobold2d certain functions that in Cocos2d is in the appDelegate is in a config.lua file. And this brings me to the problem cause to initialize a Cocos Builder as the first scene in cocos2d you replace this line (in the app delegate)
[director runWithScene: [IntroLayer scene]];
with
[director runWithScene: [CCBReader sceneWithNodeGraphFromFile:#"MainMenuScene.ccbi"]];
but this is all hidden away in Kobold2d - replaced by FirstSceneClassName = "HelloWorldLayer" in the config.lua file.
Anyone knows a bugfree way around this?
You can still use runWithScene, just put it in AppDelegate's initializationComplete method. This will take precedence over loading the scene specified in config.lua.
I want to add a UiView on the CCDirector and a scene on that UIView.
Actually i have some custom Cocoa touch control and that i want to use in my game and above that i need a scene.
Currently i am doing like this.
[[[CCDirector sharedDirector] openGLView] addSubview:gridViewController.view];
and after that line i do
[[CCDirector sharedDirector] runWithScene:[MYScene scene]];
[MYScene scene] returns a CCScene instance.
But what happens that on my custom cocoa touch control is visible but my scene is not visible at all.
Can any one guide me for that how i can accomplish my task.
You should try the opposite approach and have the UIView handled as a CCNode, then add the node to the scene.
There is even a class that makes this easily possible: CCUIViewWrapper.
If you use it, you can do the following:
CCUIViewWrapper* wrapper = [CCUIViewWrapper wrapperForUIView:view];
wrapper.contentSize = view.frame.size;
[self addChild:wrapper z:1 tag:LayerTagUILayer];
and you will get both the UIView and the scene added to CCDirector.glView. The UIView can be any, you can even define it in IB.
I have a timer set up, in place, and working fully. My problem is that I do not know if it is possible to completely flip everything on screen and keep it in the same position after a certain amount of time has elapsed.
E.G.
I have a tree. After 30 seconds has passed flip the orientation from "landscapeleft" to "landscapeRight" and flip all sprites/timers on screen.
Is it possible?
Should I just change the orientation, check to see if the orientation has changed and if it has, change the sprites rotation?
Also, I would really like to Thank EVERYONE on this site for all of there help and putting up with my "easily answered" questions.
Thank You!
you could use a scheduling method like nash suggested along with a CCDirector orientation method [[CCDirector sharedDirector] setDeviceOrientation:kCCDeviceOrientationPortrait]; or whichever orientation you need.
-(void) flipOrientation:(ccTime)delta {
CCDirector *director = [CCDirector sharedDirector];
if ([director deviceOrientation] == kCCDeviceOrientationLandscapeLeft )
[director setDeviceOrientation:kCCDeviceOrientationLandscapeRight];
else
[director setDeviceOrientation:kCCDeviceOrientationLandscapeLeft];
}
then when you schedule your method
[self schedule:#selector(flipOrientation:) interval:30.0];
this should do what you are asking for however i strongly suggest, as nash said, that you rotate instead of setting the orientation. You can rotate your main layer, or gameScene.. it will be more responsive and you can have control over how it animates. You can do it the same way as above by scheduling but instead of setting device Orientation just rotate your layer.... hope this helps
I've got a CCLayer subclass i'm using to display some sprites and to show some animations. Also it has a CCMenu with some items. When user selects some of the menu item i want to run an animation and then to show another scene. But i want user not to be able to touch anything on the screen while animation is running.
Of course, i can just disable handling touches in my callbacks, but maybe there is more simple way - just to disable all touch handling for a while ?
Disable touch dispatcher before animation running and enable touch dispatcher after animation stopped. Here is the code snippet:
[[CCDirector sharedDirector] touchDispatcher].dispatchEvents = NO;
CCAnimation* animation = [CCAnimation animationWithFrame:#"numberexplode" frameCount:5 delay:0.2];
CCAnimate* animate = [CCAnimate actionWithAnimation:animation];
CCCallBlock* completion = [CCCallBlock actionWithBlock:^{
[[CCDirector sharedDirector] touchDispatcher].dispatchEvents = YES;
}];
CCSequence* sequence = [CCSequence actions:animate, completion, nil];
[self runAction:sequence];
You want to look at the CCTouchDispatcher singleton class. If you add a targeted touch handler that swallows touches (and does nothing) then you won't get any touches handled. As far as I can tell there's no way to totally disable touches.
Alternatively you can make a new CCLayer that's on top of everything else (I think z order really high will do this), and make it clear, and have it do nothing with touches.
hope that helps.