How does one move the background image in a timer using cocos2d.
-(void) update:(ccTime)delta
What would be set in this method to move the background only on its y axis? I would like to scroll the map/background downwards as if the player is moving upwards.
I would like to then call this update method somehow every second or so.
-(void)update:(ccTime)delta
{
backgrd.position = ccp(backgrd.position.x,backgrd.position.y-10);
}
In your init:
-(id)init
{
self = [super init];
if(self)
{
//init your backgrd and stuff..
[self schedule:#selector(update:) interval: 1.0];
}
return self;
}
Related
I finally have iAds working, how would I make is so the ads dont show up on my game scene?
This is my iAds code
- (id)init
{
{
if ([ADBannerView instancesRespondToSelector:#selector(initWithAdType:)]) {
_adView = [[ADBannerView alloc] initWithAdType:ADAdTypeBanner];
} else {
_adView = [[ADBannerView alloc] init];
}
_adView.requiredContentSizeIdentifiers = [NSSet setWithObject:ADBannerContentSizeIdentifierPortrait];
_adView.currentContentSizeIdentifier = ADBannerContentSizeIdentifierPortrait;
[[[CCDirector sharedDirector]view]addSubview:_adView];
[_adView setBackgroundColor:[UIColor clearColor]];
[[[CCDirector sharedDirector]view]addSubview:_adView];
_adView.delegate = self;
}
return self;
}
To stop the iAd from staying even though a scene has been changed add
[_adView removeFromSuperview]
To where the Scene is being changes so it look like this
- (void)onscoreButtonClicked:(id)sender
{
// start spinning scene with transition
[[CCDirector sharedDirector] replaceScene:[HighScoreScene scene]
withTransition:[CCTransition transitionPushWithDirection:CCTransitionDirectionUp duration:1.0f]];
[_adView removeFromSuperview];
}
Thank you to LearnCocos2d
I enabled ARC for my cocos2d project.
Now i try doing the following:
BuildTowerMenu *menu = [BuildTowerMenu menuAtLocation:tileScreenPos];
[self addChild:menu];
And in the BuildTowerMenu class:
+(id)menuAtLocation:(CGPoint)location {
return [[self alloc] initMenuAt:location];
}
-(id) initMenuAt:(CGPoint)location {
if (self = [super init]) {
self.position = location;
CCSprite *item1 = [CCSprite spriteWithFile:#"Icon.png"];
item1.position = location;
[self addChild:item1];
}
return self;
}
But for some reason, the Sprite never shows up. After a bit of debugging i see that when i return from menuAtLocation, the CCSprite is still in the Array of children of BuildTowerMenu, but empty (only got an id).
If i actually add the sprite from outside it works and the Sprite is displayed:
BuildTowerMenu *menu = [BuildTowerMenu menuAtLocation:tileScreenPos];
CCSprite *item1 = [CCSprite spriteWithFile:#"Icon.png"];
item1.position = location;
[menu addChild:item1];
[self addChild:menu];
Any hints on what i did wrong here?
P.S.: i added a breakpoint in the dealloc of CCSprite, which never gets called (i guess it should be called if ARC is releasing it)...
I think that the problem is that you set equal positions to your menu and sprite.
I mean that this part of code
CGPoint location = ccp(200.f, 200.f);
[menu setPosition: location];
[sprite setPosition: location];
[menu addChild: sprite];
will add your sprite with position position (400.f, 400.f), relatieve to the menu's parent. You are doing almost the same thing in your BuildTowerMenu's initMenuAt: method/
As already commented on the initial question_:
Ok, it had nothing to do with ARC; the Sprite which seemed to be released was there, it was just a debugger - bug which didnt display it correctly. The problem was actually the line self.position = location; After moving the setposition after the addChild, everything worked.
I have an image that loads on a MainMenu scene and appears as wrong sized when the game launches but then after finishing a level returns you to the MainMenu again the image appears right sized.
The first time the image appears to be three quarters or 4/5 of the size of the screen from left to right. The image has a white background around it so I can see a black tall rectangle in the right side of the screen on the main menu's first launch. But after a game it is sized properly and the white background image is sized properly.
Anybody ever have this happen?
Here is the init code for the MainMenuLayer:
-(id)init {
if( (self=[super initWithColor:ccc4(255,255,255,255)]) ) {
[[GameManager sharedGameManager] playBackgroundTrack:BACKGROUND_TRACK_MAIN_MENU];
CGSize screenSize = [CCDirector sharedDirector].winSize;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
CCSprite *background = [CCSprite spriteWithFile:#"MainMenu-iPad.png"];
[background setPosition:ccp(screenSize.width/2,screenSize.height/2)];
[self addChild:background];
[self displayMainMenu];
} else {
CCSprite *background = [CCSprite spriteWithFile:#"MainMenu.png"];
[background setPosition:ccp(screenSize.width/2,screenSize.height/2)];
[self addChild:background];
[self displayMainMenu];
}
-
It works fine on the simulator though...
Print screen position, if position is wrong then put you code in onEnter instead of init.
See this thread in Stack overflow.
-(id)init {
if( (self=[super initWithColor:ccc4(255,255,255,255)]) ) {
}
return self;
}
-(void)onEnter {
[super onEnter];
[[GameManager sharedGameManager] playBackgroundTrack:BACKGROUND_TRACK_MAIN_MENU];
CGSize screenSize = [CCDirector sharedDirector].winSize;
CCSprite *background = [CCSprite spriteWithFile:#"MainMenu.png"];
[background setPosition:ccp(screenSize.width/2,screenSize.height/2)];
[self addChild:background];
[self displayMainMenu];
}
The image was apparently being cached even after clean and build! I ended up replacing the image by removing the original and adding the same one but with some markers just to make sure it got replaced.
I am developing a simple game app.
I am required to have two screens one on left & other on right, just like on scroll view with pagination having 2 screens to toggle between. I am detecting swipes with the help of RootViewController class and successfully swiping left and right screens.
But the problem is I have to have infinitely running rotateBy action on both screens each running this action on single sprite placed on center of screen.
I am using a main scene called SelectWorld & two are it's sub scenes.
First screen is called factory & other is called stack.
Following is my code:
Select World Screen:
#implementation SelectWorld
+(CCScene*)scene
{
CCScene* scene = [CCScene node];
SelectWorld* layer = [SelectWorld node];
[scene addChild:layer];
return scene;
}
-(id)init
{
if((self = [super init]))
{
[RootViewController singleton].swipeCallBackHandler = self;
[[RootViewController singleton] enableSwipeDetection];
factory = [[ColorfulFactory scene] retain];
stack = [[CoinsStack scene] retain];
[self addChild:factory];
isOnFactory = YES;
}
return self;
}
-(void)swipedLeft
{
if(isOnFactory)
{
[self removeAllChildrenWithCleanup:YES];
isOnFactory = NO;
CCTransitionScene* transitionalScene = [CCTransitionSlideInR transitionWithDuration:0.3 scene:stack];
[[CCDirector sharedDirector] replaceScene:transitionalScene];
}
}
-(void)swipedRight
{
if(!isOnFactory)
{
[self removeAllChildrenWithCleanup:YES];
isOnFactory = YES;
CCTransitionScene* transitionalScene = [CCTransitionSlideInL transitionWithDuration:0.3 scene:factory];
[[CCDirector sharedDirector] replaceScene:transitionalScene];
}
}
Here's the code for factory only, same goes for stack-
#implementation ColorfulFactory
+(CCScene*)scene
{
CCScene* scene = [CCScene node];
ColorfulFactory* layer = [ColorfulFactory node];
[scene addChild:layer];
return scene;
}
-(id)init
{
if((self = [super init]))
{
CGSize size = [CCDirector sharedDirector].winSize;
CCLabelTTF* info = [CCLabelTTF labelWithString:#"Colorful Factory" fontName:#"Helvetica" fontSize:35.0];
info.position = ccp(size.width/2, size.height-50);
[self addChild:info];
CCSprite* sprite = [CCSprite spriteWithFile:#"Icon.png"];
sprite.position = ccp(size.width/2, size.height/2);
[self addChild:sprite];
sprite.tag = 123;
CCRotateBy* rotateBy = [CCRotateBy actionWithDuration:60 angle:360.0];
CCRepeatForever* repeatForever = [CCRepeatForever actionWithAction:rotateBy];
[sprite runAction:repeatForever];
repeatForever.tag = 456;
}
return self;
}
Now the problem is, in first two swipes actions are running fine, but as soon as I try to swipe more than two or three times, actions got stopped. I haven't written a single line to stop this in both the classes. I require it there running forever.
Your mistake is that you're re-using the same scene object for every scene change. You can't do that in cocos2d, you have to create a new instance of the scene object.
You should never retain a scene object, since there ought to be only one active scene at any one time (with the exception of the duration of a scene transitioning to another scene - but that's handled by cocos2d internally).
For example:
CCScene* factory = [ColorfulFactory scene];
CCTransitionScene* transitionalScene = [CCTransitionSlideInR transitionWithDuration:0.3 scene:factory];
[[CCDirector sharedDirector] replaceScene:transitionalScene];
If you need both objects in memory, make them layers (or nodes), not scenes. Don't use replaceScene but instead animate the layers with regular moveTo actions in and out of the screen.
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.