I am working on a Pause screen menu for a game. After displaying the pause screen, I have the user touch the screen to hide the pause screen and resume the game. This works perfect on the simulator but doesn't work when I test on an actual device. It seems that the device doesn't respond to touches specifically for the pause menu. Every other part of the game works fine on both the simulator and device. It's weird how it does work on the simulator but not on the device. This is the code I have for the pause screen:
- (id)init {
if ((self = [super init])) {
CGSize windowSize = [[CCDirector sharedDirector] winSize];
//windowSize.height = 768.0;
//windowSize.width = 1024.0;
CCSprite *whiteScreen = [CCSprite spriteWithFile:#"OutOfTime.png"];
whiteScreen.position = ccp(windowSize.width / 2, windowSize.height / 2);
[self addChild:whiteScreen];
CCLabelTTF *touchToDismiss = [CCLabelTTF labelWithString:#"Touch screen to continue" fontName:#"Marker Felt" fontSize:30];
touchToDismiss.color = ccBLACK;
touchToDismiss.position = ccp(windowSize.width / 2, 20);
[self addChild:touchToDismiss];
}
return self;
}
- (void)onEnter {
[super onEnter];
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:NO];
}
- (void)gameOverWithScore:(NSInteger)score {
CGSize windowSize = [[CCDirector sharedDirector] winSize];
//windowSize.height = 768.0;
//windowSize.width = 1024.0;
CCLabelTTF *touchToDismiss = [CCLabelTTF labelWithString:#"Game Over" fontName:#"Marker Felt" fontSize:75];
touchToDismiss.color = ccBLACK;
touchToDismiss.position = ccp(windowSize.width / 2, windowSize.height / 2 + 40);
[self addChild:touchToDismiss];
NSString *scoreString = [NSString stringWithFormat:#"Final Score: %d", score];
CCLabelTTF *scoreLabel = [CCLabelTTF labelWithString:scoreString fontName:#"Marker Felt" fontSize:60];
scoreLabel.color = ccBLACK;
scoreLabel.position = ccp(windowSize.width / 2, (windowSize.height / 2) - 40);
[self addChild:scoreLabel];
}
- (void)setMessage:(NSString *)message {
}
- (void)dealloc {
[super dealloc];
}
- (BOOL)ccTouchBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(#"haha");
return YES;
}
You probably should add the following line on your init
self.isTouchEnabled = YES;
You have to do this for every CCLayer you have that has touch events.
EDIT: just noticed that your ccTouchBegan only prints a Log.
This log is easily viewed in the debug window of XCode, but in the device it is hidden from the user.
Try doing something else.
Related
Does iAd banner reduces FPS?
Indeed, since I added iAd my FSP is shit. I was 59 all game and now it's variable from 35-50 FPS.
Any ideas please because my game is almost not playable with this banner.
Thank for help.
You should implement the iAd logic in your UINavigationController subclass that was set in the appDelegate. At mine code it look like:
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Create the main window
window_ = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
CCGLView *glView = [CCGLView viewWithFrame:[window_ bounds]
pixelFormat:kEAGLColorFormatRGB565
depthFormat:0
preserveBackbuffer:NO
sharegroup:nil
multiSampling:NO
numberOfSamples:0];
// Enable multiple touches
[glView setMultipleTouchEnabled:YES];
director_ = (CCDirectorIOS*) [CCDirector sharedDirector];
director_.wantsFullScreenLayout = YES;
// Display FSP and SPF
[director_ setDisplayStats:YES];
// set FPS at 60
[director_ setAnimationInterval:1.0/60];
//FEW LINES LATER
// Create a Navigation Controller with the Director
navController_ = [[MyNavigationController alloc] initWithRootViewController:director_];
navController_.navigationBarHidden = YES;
[self checkDeviceType];
// setup iAds bannerView
[self setupIADs];
// for rotation and other messages
[director_ setDelegate:navController_];
// set the Navigation Controller as the root view controller
[window_ setRootViewController:navController_];
// make main window visible
[window_ makeKeyAndVisible];
return YES;
}
- (void)setupIADs {
CGSize size = [[CCDirector sharedDirector] winSize];
float bannerHeight = _isiPadRunning ? 66.0f : 50.0f;
ADAdType bannerType = _isiPadRunning ? ADAdTypeMediumRectangle : ADAdTypeBanner;
_bannerView = [[ADBannerView alloc] initWithAdType:bannerType];
_bannerView.frame = CGRectMake(0, navController_.view.frame.size.height, size.width, bannerHeight);
CGSize newBannerSize = [_bannerView sizeThatFits:CGSizeMake(size.width, bannerHeight)];
_bannerView.frame = CGRectMake(0, navController_.view.frame.size.height,
newBannerSize.width, newBannerSize.height);
_bannerView.delegate = self;
//get view
UIView *mainView = [navController_ view];
[mainView addSubview:_bannerView];
[mainView setNeedsLayout];
}
As you can see I use navController_ to place an iAd banner view. No FPS drops! :)
Please, try it out. For me it helped and I have no FPS drops or delay. Everything works great.
I'm using a CCParallaxNode for a scrolling background in my GameLayer and I'm getting a bunch of errors and I can't figure out why.
"Initializer element is not a compile-time constant" and also "Unk
#implementation Background
// Load the sprites for each parallax layer, from background to foreground.
CCSprite* para1 = [CCSprite spriteWithFile:#"color.png"];
CCSprite* para2= [CCSprite spriteWithFile:#"ship-hd.png"];
CCSprite* para3 = [CCSprite spriteWithFile:#"twit.png"];
CCSprite* para4 = [CCSprite spriteWithFile:#"Start.png"];
// Set the correct offsets depending on the screen and image sizes.
para1.anchorPoint = CGPointMake(0, 1);
para2.anchorPoint = CGPointMake(0, 1);
para3.anchorPoint = CGPointMake(0, 0.6f);
para4.anchorPoint = CGPointMake(0, 0);
CGPoint topOffset = CGPointMake(0, screenSize.height);
CGPoint midOffset = CGPointMake(0, screenSize.height / 2);
CGPoint downOffset = CGPointZero;
// Create a parallax node and add the sprites to it.
CCParallaxNode* paraNode = [CCParallaxNode node];
[paraNode addChild:para1 z:1 parallaxRatio:CGPointMake(0.5f, 0) ositionOffset:topOffset];
[paraNode addChild:para2 z:2 parallaxRatio:CGPointMake(1, 0) positionOffset:topOffset];
[paraNode addChild:para3 z:4 parallaxRatio:CGPointMake(2, 0) positionOffset:midOffset];
[paraNode addChild:para4 z:3 parallaxRatio:CGPointMake(3, 0) positionOffset:downOffset];
[self addChild:paraNode z:0 tag:ParallaxSceneTagParallaxNode];
// Move the parallax node to show the parallaxing effect.
CCMoveBy* move1 = [CCMoveBy actionWithDuration:5 position:CGPointMake(−160, 0)];
CCMoveBy* move2 = [CCMoveBy actionWithDuration:15 position:CGPointMake(160, 0)];
CCSequence* sequence = [CCSequence actions:move1, move2, nil];
CCRepeatForever* repeat = [CCRepeatForever actionWithAction:sequence];
[paraNode runAction:repeat];
#end
You need to enclose your code in an -(id)init method, like this:
#implementation Background
- (id)init
{
if (self = [super init]) {
// Load the sprites for each parallax layer, from background to foreground.
CCSprite* para1 = [CCSprite spriteWithFile:#"color.png"];
// ... the rest of your code ... //
}
return self;
}
#end
I keep getting the same crash report "'Signature not found for selector - does it have the following form? -(void) name: (ccTime) dt'".
This is getting pretty annoying now, i only wanted to make the Backgound scrolling infinitely.
Here is my code:
-(id) init {
// always call "super" init
// Apple recommends to re-assign "self" with the "super" return value
if( (self=[super init])) {
self.isTouchEnabled = YES;
self.isAccelerometerEnabled = YES;
CGSize screenSize = [CCDirector sharedDirector].winSize;
/*CCSprite *Player = [CCSprite spriteWithFile:#"Icon.png"];
Player.position = ccp(screenSize.width/2 -110, screenSize.height/2);
Player.scale = 0.7;
[self addChild:Player];
[self scheduleUpdate];*/
CCLOG(#"Screen width %0.2f screen height %0.2f",screenSize.width,screenSize.height);
b2Vec2 gravity;
gravity.Set(0.0f, -10.0f);
bool doSleep = true;
world = new b2World(gravity, doSleep);
world->SetContinuousPhysics(true);
// Debug Draw functions
/*m_debugDraw = new GLESDebugDraw( PTM_RATIO );
world->SetDebugDraw(m_debugDraw);
uint32 flags = 0;
flags += b2DebugDraw::e_shapeBit;
//flags += b2DebugDraw::e_jointBit;
//flags += b2DebugDraw::e_aabbBit;
//flags += b2DebugDraw::e_pairBit;
//flags += b2DebugDraw::e_centerOfMassBit;
m_debugDraw->SetFlags(flags);*/
// Define the ground body.
b2BodyDef groundBodyDef;
groundBodyDef.position.Set(0, 0); // bottom-left corner
// Call the body factory which allocates memory for the ground body
// from a pool and creates the ground box shape (also from a pool).
// The body is also added to the world.
b2Body* groundBody = world->CreateBody(&groundBodyDef);
// Define the ground box shape.
b2PolygonShape groundBox;
// bottom
groundBox.SetAsEdge(b2Vec2(0,0), b2Vec2(screenSize.width/PTM_RATIO,0));
groundBody->CreateFixture(&groundBox,0);
// top
groundBox.SetAsEdge(b2Vec2(0,screenSize.height/PTM_RATIO), b2Vec2(screenSize.width/PTM_RATIO,screenSize.height/PTM_RATIO));
groundBody->CreateFixture(&groundBox,0);
//Set up sprite
BG1 = [CCSprite spriteWithFile:#"SkyAndClouds.png"];
BG1.anchorPoint = ccp(0,0);
BG1.position = ccp(0, 0);
BG1.scale = 0.5;
[self addChild:BG1];
BG2 = [CCSprite spriteWithFile:#"SkyAndClouds.png"];
BG2.anchorPoint = ccp(0,0);
BG2.position = ccp([BG1 boundingBox].size.width-1,0);
[self addChild:BG2];
[self schedule: #selector(AnimatedBG:) interval:0];
CCSpriteBatchNode *batch = [CCSpriteBatchNode batchNodeWithFile:#"Stick.png" capacity:150];
[self addChild:batch z:0 tag:kTagBatchNode];
[self addNewSpriteWithCoords:ccp(screenSize.width/2-110, screenSize.height/2)];
[self addZombieWithCoords:ccp(screenSize.width/2+240, screenSize.height/2)];
CCLabelTTF *label = [CCLabelTTF labelWithString:#"Stick, you Better Run!" fontName:#"Helvetica" fontSize:16];
[self addChild:label z:0];
[label setColor:ccc3(0,0,255)];
label.position = ccp( screenSize.width/2, screenSize.height-17);
[self schedule: #selector(tick:)];
}
return self;
}
-(void)AnimatedBG {
BG1.position = ccp(BG1.position.x-1,BG1.position.y);
}
Your AnimatedBG method should be defined as:
-(void) AnimatedBG:(ccTime)dt {
}
You should also make sure you have a definition for your scheduled tick: method:
-(void) tick:(ccTime)dt {
}
I am coding a modal layer in cocos2d and I would like to use the OpenGL glScissor API call to crop the inside of a CCScrollLayer that I am using,
Basically,
Present some kind of Modal sprite
Put CCScrollLayer with assets on the modal sprite
I want to crop the CCScrollLayer so that it does not overflow the sprite.
Seems pretty simple.
The problem I'm having is that the visit function never seems to be get hit and thus glScissor never gets implemented.
I'm not sure what I'm doing wrong.
The way I do modals is I use blocks to handle a Yes and No condition/state.
// This appears in my "Pick City scene"
-(id) init
{
if ((self = [super init]))
{
NSLog(#"City list");
for (City *cityObj in listOfCities)
{
citySpriteOff = [CCSprite spriteWithSpriteFrameName:#"city.png"];
citySpriteOn = [CCSprite spriteWithSpriteFrameName:#"city_on.png"];
int x = [cityObj.x intValue];
int y = [cityObj.y intValue];
CCMenuItemSprite *mapMenuItem = [CCMenuItemSprite itemFromNormalSprite:citySpriteOff selectedSprite:citySpriteOn target:self selector:#selector(btnCity:)];
[mapMenuItem setTag:i];
[mapMenuItem setIsRelativeAnchorPoint:YES];
[mapMenuItem setAnchorPoint:CGPointMake(0, 0)];
[mapMenuItem setPosition:CGPointMake(x, y)];
[mapMenuItem setIsEnabled:YES];
[mapMenu addChild:mapMenuItem];
i++;
} // next
[self addChild:mapMenu z:2];
}
}
-(void) btnCity:(id)sender
{
NSLog(#"clicked a city button");
int tag = [sender tag];
City *cityObj = [listOfCities objectAtIndex:tag];
NSLog(#"You clicked on city: %#", cityObj.name);
[self lockLayers];
CCLayer *layer = [CCLayer node];
[self addChild:layer z:100];
[MapModalLayer ConfirmCity:cityObj onLayer:layer yesBlock:^{[self btnConfirmedCity:cityObj];} noBlock:^{[self unlockLayers];}];
}
-(void) btnConfirmedCity:(City *)cityObj
{
NSLog(#"confirmed city: %#", cityObj.name);
}
#pragma mark - Lock/Unlock layers
-(void) lockLayers
{
[self MenuStatus:NO Node:self];
}
-(void) unlockLayers
{
[self MenuStatus:YES Node:self];
}
// Disabled/Enable layers
-(void) MenuStatus:(BOOL)_enable Node:(id)_node
{
for (id result in ((CCNode *)_node).children) {
if ([result isKindOfClass:[CCMenu class]]) {
for (id result1 in ((CCMenu *)result).children) {
if ([result1 isKindOfClass:[CCMenuItem class]]) {
((CCMenuItem *)result1).isEnabled = _enable;
}
}
}
else
[self MenuStatus:_enable Node:result];
} // next
}
The actual modal code appears here,
#implementation MapModalLayer
- (id)init {
self = [super init];
if (self) {
// This method never seems to be called
NSLog(#"MapModalLayer init");
}
return self;
}
// This method never seems to be called
- (void) visit {
NSLog(#"Visit");
if (!self.visible)
return;
glPushMatrix();
glEnable(GL_SCISSOR_TEST);
glScissor(50, 50, 100 , 150);
[super visit];
glDisable(GL_SCISSOR_TEST);
glPopMatrix();
}
+ (void) CloseAlert: (CCSprite*) alertDialog onCoverLayer: (CCLayer*) coverLayer executingBlock: (void(^)())block {
// shrink dialog box
[alertDialog runAction:[CCScaleTo actionWithDuration:kAnimationTime scale:0]];
// in parallel, fadeout and remove cover layer and execute block
// (note: you can't use CCFadeOut since we don't start at opacity 1!)
[coverLayer runAction:[CCSequence actions:
[CCFadeTo actionWithDuration:0.2f opacity:0],
[CCCallBlock actionWithBlock:^{
[coverLayer removeFromParentAndCleanup:YES];
if (block) block();
}],
nil]];
}
+(void) ConfirmCity:(City *)cityObj onLayer:(CCLayer *)layer yesBlock :(void (^)())yesBlock noBlock:(void (^)())noBlock
{
CCLayerColor *coverLayer = [CoverLayer new];
[layer addChild:coverLayer z:INT_MAX]; // put to the very top to block application touches
[coverLayer runAction:[CCFadeTo actionWithDuration:kAnimationTime opacity:80]]; // smooth fade-in to dim with semi-transparency
CGSize winSize = [[CCDirector sharedDirector] winSize];
CCSprite *dialog = [CCSprite spriteWithSpriteFrameName:#"modal.png"];
[dialog setPosition:CGPointMake(winSize.width/2,winSize.height/2)];
[dialog setTag:kDialogTag];
//
// We put our CCScrollLayer *scroller content here... it doesn't matter what it is right now
//
//
// Finally we put our accept/reject buttons
//
// Tick/Cross buttons
CCSprite *closeButtonOn = [CCSprite spriteWithSpriteFrameName:#"btn_close.png"];
CCSprite *tickButtonOn = [CCSprite spriteWithSpriteFrameName:#"btn_accept.png"];
// add one or two buttons, as needed
CCMenuItemSprite *opt1Button = [CCMenuItemSprite itemFromNormalSprite:closeButtonOn
selectedSprite:nil
block:^(id sender){
// close alert and call opt1block when first button is pressed
[self CloseAlert:dialog onCoverLayer: coverLayer executingBlock:noBlock];
} ];
[opt1Button setPosition:CGPointMake(-200, -120)];
// create second button, if requested
CCMenuItemSprite *opt2Button = [CCMenuItemSprite itemFromNormalSprite:tickButtonOn
selectedSprite:nil
block:^(id sender){
// close alert and call opt2block when second button is pressed
[self CloseAlert:dialog onCoverLayer: coverLayer executingBlock:yesBlock];
} ];
[opt2Button setPosition:CGPointMake(40, -120)];
CCMenu *menu = [CCMenu menuWithItems:opt1Button, opt2Button, nil];
[menu setContentSize:dialog.contentSize];
[dialog addChild:menu z:2];
[coverLayer addChild:dialog];
}
#end
I think its because I only ever use MapModalLayer's private methods only.
But I am not sure.
Is there a way to allow me to use the glScissor in a modal like explained above?
I've tried moving the glScissor code to the display of the modal, but it never seems to do anything.
To confirm it is working, I moved the glScissor code to the parent and it seems to work fine.
Thus, how do I make the modal layer use/work with glScissor?
I have since resolved this problem.
I used the Viewport from http://pastebin.com/tWsEbxvJ
The way I did it was:
CoverLayer *coverLayer = [CoverLayer new];
[layer addChild:coverLayer z:INT_MAX]; // put to the very top to block application touches
[coverLayer runAction:[CCFadeTo actionWithDuration:kAnimationTime opacity:80]]; // smooth fade-in to dim with semi-transparency
// ------------------------------
CGSize winSize = [[CCDirector sharedDirector] winSize];
CCSprite *dialog = [CCSprite spriteWithSpriteFrameName:#"modal.png"];
[dialog setPosition:CGPointMake(winSize.width/2,winSize.height/2)];
[dialog setTag:kDialogTag];
.. // Build your pagesArray here for ScrollLayer...
// Now create the scroller and pass-in the pages (set widthOffset to 0 for fullscreen pages)
CCScrollLayer *scroller = [[CCScrollLayer alloc] initWithLayers:pagesArray widthOffset: 350];
[scroller setShowPagesIndicator:NO];
// finally add the scroller to your scene
//[dialog addChild:scroller];
Viewport *cn = [[Viewport alloc] initWithRect:CGRectMake(3, 0, dialog.contentSize.width-12, dialog.contentSize.height-5)];
[cn addChild:scroller];
[scroller release];
[coverLayer addChild:dialog z:1];
This allows me to put a modal on a layer, put a CCScrollLayer and make sure that the contents do not spill over the internals of the modal sprite I have made (this is why the width configuration looks a bit odd).
Thanks.
I try to show an intro and replaceScene when the intro has finished. But, when the movie finish, app is crashing on [[CCDirector sharedDirector] replaceScene:[CCFadeTransition transitionWithDuration:0.5f scene:[MenuScene scene]]];.
code is;
- (void) moviePlayBackDidFinish {
[self.moviePlayer stop];
[[CCDirector sharedDirector] replaceScene:[CCFadeTransition transitionWithDuration:0.5f scene:[MenuScene scene]]];
}
-(id) init
{
// always call "super" init
// Apple recommends to re-assign "self" with the "super" return value
if( (self=[super init] )) {
//pencere boyutu elde ediliyor
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"intro" ofType:#"mp4"]];
self.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:self.moviePlayer];
if ([self.moviePlayer respondsToSelector:#selector(setFullscreen:animated:)]) {
// Use the new 3.2 style API
self.moviePlayer.controlStyle = MPMovieControlStyleNone;
self.moviePlayer.shouldAutoplay = YES;
// This does blows up in cocos2d, so we'll resize manually
// [moviePlayer setFullscreen:YES animated:YES];
[self.moviePlayer.view setTransform:CGAffineTransformMakeRotation((float)M_PI_2)];
CGSize winSize = [[CCDirector sharedDirector] winSize];
self.moviePlayer.view.frame = CGRectMake(0, 0, winSize.height, winSize.width);// width and height are swapped after rotation
[[[CCDirector sharedDirector] openGLView] addSubview:self.moviePlayer.view];
} else {
// Use the old 2.0 style API
self.moviePlayer.movieControlMode = MPMovieControlModeHidden;
[self.moviePlayer play];
}
}
return self;
}
This line:
selector:#selector(moviePlayBackDidFinish:)
should be:
selector:#selector(moviePlayBackDidFinish)
CCScene* scene = [AboutLayer scene];
CCTransitionFade* transitionScene = [CCTransitionFade transitionWithDuration:0.1 scene:scene withColor:ccWHITE];
[[CCDirector sharedDirector] pushScene:transitionScene];