I need make active background which consists of 2 CCSprites which moves successive. But at the same time between CCSprites appear a little interval. How fix it?
Some init code:
sprite1 = [sprites objectAtIndex:0];
[sprite2 setPosition:ccp(240.0,self.position.y)];
sprite2 = [sprites objectAtIndex:1];
[sprite2 setPosition:ccp(720.0,self.position.y)];
[self addChild:sprite1 z:0];
[self addChild:sprite2 z:1];
[self schedule:#selector(update) interval:1/60.0];
This is the code, which move sprites:
-(void)update{
if (sprite1.position.x<=-239.0) {
[sprite1 setPosition:ccp(720.0,self.position.y)];
flag = false;
}else{
if (sprite2.position.x<=-239.0) {
[sprite2 setPosition:ccp(720.0,self.position.y)];
flag = true;
}
}
if (sprite1.position.x<=720.0) {
if (flag) {
[sprite1 setPosition:ccp(sprite1.position.x-speed, self.position.y)];
[sprite2 setPosition:ccp(sprite1.position.x+480, self.position.y)];
}else {
[sprite2 setPosition:ccp(sprite2.position.x-speed, self.position.y)];
[sprite1 setPosition:ccp(sprite2.position.x+480, self.position.y)];
}
}
}
Interval : image
If the gap is just one pixel, it's likely this is just the way OpenGL/Cocos2D behaves.
Instead of making your images 480x320, make them 482x320, and make them overlap with those extra pixels. Then the gap will be gone.
Related
Thank you for taking the time to look at my question, As I am very new to programming any help or pointers in the right direction is much appreciated.
Overview...
I have a simple game I am trying to create and it includes a class for 'Ball' sprite that is fired from the left of the screen to the right. The speed at which this "Ball" sprite is created is random and each time the "Ball" moves past the right of the screen a point is added to the score.
Problem....
The problem I have is when 2 "Balls" fire at almost the same time (which happens some times as its random) they pass the right hand of the screen less then a second apart and when this happens it only seems to add 1 when it should be adding 2 to the score (as 2 balls has passed the right side).
Below is the code for my Ball launcher class (use this class to call the ball randomly).
If you have used or gone through 'Ray Wenderlichs' Learn Cocos2D then allot of this will look familiar as after going through his book I have tried to edit his code to do what I want (to me after reading the book its the best way to learn, by messing with the code etc).
#implementation BL
#synthesize delegate;
#synthesize lauchingAnim;
#synthesize afterlauchingAnim;
-(void) dealloc {
delegate = nil;
[lauchingAnim release];
[afterlauchingAnim release];
[super dealloc];
}
//--The below shootPhaser method takes the current direction the launcher is facing and asks the delegate (gameplaylayer) to create the ball moving in that direction.
//--The below createPhaserWithDirection method was declared (created) in the GamePlayLayerDelegate protocol.
-(void)shootPhaser {
CGPoint phaserFiringPosition;
PhaserDirection phaserDir;
CGPoint position = [self position];
float xPosition = position.x + position.x * 0.51f;
float yPosition = position.y + position.y * 0.045f;
{
phaserDir = kDirectionRight;
}
phaserFiringPosition = ccp(xPosition, yPosition);
[delegate createPhaserWithDirection:phaserDir andPosition:phaserFiringPosition];
}
-(void)changeState:(CharacterStates)newState {
[self stopAllActions];
id action = nil;
characterState = newState;
switch (newState) {
case kStatespawning:
// CCLOG(#“launcher->Changing State to Spwaning");
[self setDisplayFrame:
[[CCSpriteFrameCache sharedSpriteFrameCache]
spriteFrameByName:#“lancher_1.png"]];
break;
case kStateIdle:
// CCLOG(#“laucher->Changing state to idle");
[self setDisplayFrame:
[[CCSpriteFrameCache sharedSpriteFrameCache]
spriteFrameByName:#"lancher_1.png"]];
break;
case kStateFiring:
// CCLOG(#“launcher->Changing State to firing");
action = [CCSequence actions:
[CCAnimate actionWithAnimation:lauchingAnim],
[CCCallFunc actionWithTarget:self
selector:#selector(shootPhaser)],
[CCAnimate actionWithAnimation:afterlauchingAnim],
[CCDelayTime actionWithDuration:2.0f],
nil];
lauchingAnim.restoreOriginalFrame = NO;
afterlauchingAnim.restoreOriginalFrame = NO;
[self changeState:kStateIdle];
break;
case kStateDead:
CCLOG(#“launcher->changing state to dead");
break;
default:
CCLOG(#"unhandled state %d in launcher", newState);
break;
}
if (action !=nil) {
[self runAction:action];
}
}
-(void)updateStateWithDeltaTime: (ccTime)deltaTime andListOfGameObjects:(CCArray*)listOfGameObjects {
if (characterState == kStateFiring) {
// 5
if (characterState != kStateFiring) {
// If RadarDish is NOT already taking Damage
[self changeState:kStateFiring];
return;
}
}
if ((([self numberOfRunningActions] == 0) && (characterState != kStateDead)) ) {
// CCLOG(#"launcher Going to Idle!!!");
[self changeState:kStateIdle];
return;
}
}
-(void)initAnimations {
[self setLauchingAnim:[self loadPlistForAnimationWithName:#"lauchingAnim" andClassName:NSStringFromClass([self class])]];
[self setAfterlauchingAnim:[self loadPlistForAnimationWithName:#"afterlauchingAnim" andClassName:NSStringFromClass([self class])]];
}
-(id) initWithSpriteFrameName:(NSString*)frameName{
if ((self=[super init])) {
if ((self = [super initWithSpriteFrameName:frameName])) {
CCLOG(#"### Laauncher initialized");
[self initAnimations];
characterHealth = 3.0f;
gameObjectType = kBallLaucher;
// 3
[self changeState:kStateIdle];
}
}
return self;
}
#end
Below is the code for my "Ball" class...
#import “Ball.h"
#implementation Ball
#synthesize delegate;
#synthesize myDirection;
#synthesize travelingAnim;
#synthesize ScoreAnim;
-(void) dealloc {
delegate = nil;
[travelingAnim release];
[ScoreAnim release];
[super dealloc];
}
-(void)changeState:(CharacterStates)newState {
[self stopAllActions];
[self setCharacterState:newState];
CGSize screenSize1 = [CCDirector sharedDirector].winSize;
CGPoint position = [self position];
CGPoint endPosition = ccp(screenSize1.width*1.5f, screenSize1.height*0.20f);
id action = nil;
//id action1 = nil;
switch (newState) {
case kStatespawning:
CCLOG(#“Spawning Ball");
[self setDisplayFrame:[[CCSpriteFrameCache
sharedSpriteFrameCache]
spriteFrameByName:#"Ball_1.png"]];
break;
case kStateTravelling: {
movementAction = [CCMoveTo actionWithDuration:5.0f
position:endPosition];
}
break;
case kStateScore:
PLAYSOUNDEFFECT(SCORE);
CCLOG(#“Ball Past Left Of Screen => Add 1 to Score");
action = [CCSequence actions:
[CCCallFunc actionWithTarget:self selector:#selector(removeSelf)],
nil];
break;
default:
CCLOG(#“Ball -> Unknown CharState %d",
characterState);
break;
}
if (action !=nil)
[self runAction:action];
}
-(void)removeSelf{
CCLOG(#"Removing Ball Object Has Scored.");
[self setVisible:NO];
[self removeFromParentAndCleanup:YES];
return;
}
-(void)updateStateWithDeltaTime:(ccTime)deltaTime andListOfGameObjects:(CCArray *)listOfGameObjects {
CGPoint currentSpitePosition = [self position];
CGSize screenSize = [CCDirector sharedDirector].winSize;
if (currentSpitePosition.x > screenSize.width*1.1f) {{
[self changeState:kStateScore];
}
}
return;
}
if ([self numberOfRunningActions] == 0) {
if (characterState == kStatespawning) {
[self changeState:kStateTravelling];
return;
}
}
}
-(void)initAnimations {
[self setTravelingAnim:[self loadPlistForAnimationWithName:#"travelingAnim" andClassName:NSStringFromClass([self class])]];
[self setScoreAnim:[self loadPlistForAnimationWithName:#"ScoreAnim" andClassName:NSStringFromClass([self class])]];
}
-(id) initWithSpriteFrameName:(NSString*)frameName{
if ((self=[super init])) {
if ((self = [super initWithSpriteFrameName:frameName])) {
CCLOG(#"### Ball Initialised");
[self initAnimations];
characterHealth = 3.0f;
gameObjectType = kEnemyTypeBall;
[self changeState:kStatespawning];
}
}
return self;
}
#end
Below is the code for my "GameplayLayer" class...
#import "GamePlayLayer.h"
#import “Ball.h"
#import “BL.h"
#implementation GamePlayLayer
#synthesize delegate;
-(void) dealloc {
delegate = nil;
[super dealloc];
}
-(void) update:(ccTime)deltaTime {
CCArray *listOfGameObjects =
[sceneSpriteBatchNode children];
for (GameCharacter *tempChar in listOfGameObjects) {
[tempChar updateStateWithDeltaTime:deltaTime andListOfGameObjects:listOfGameObjects];
}
GameCharacter *tempChar = (GameCharacter*)[sceneSpriteBatchNode
getChildByTag:kEnemyTypeBall];
if ([tempChar characterState] == kStateScore) <==HERE I AM SEEING IF THE BALL HAS SCORED - THIS IS ALSO WHERE I THINK I MAY BE GOING WRONG SOMEHOW.
{
CCLOG(#"Add 1 Points To Score");
[self addPoint];
return;
}
}
-(void)addPoint
{
score = score + 1;
[scoreLabel setString:[NSString stringWithFormat:#"$%i", score]]; <===ADDING THE POINT TO THE SCORE
return;
}
-(void) createObjectOfType: (GameObjectType)objectType
withHealth:(int)initialHealth atLocation:(CGPoint)spawnLocation withZValue:(int)ZValue {
if (kBallLaucher == objectType) {
CCLOG(#"Creating launcher Object");
BL *ballLauncher = [[[BL alloc] init] initWithSpriteFrameName:#“launcher_1.png"];
[ballLauncher setCharacterHealth:initialHealth];
[ballLauncher setPosition:spawnLocation];
[sceneSpriteBatchNode addChild:tBT z:ZValue tag:kBallLaucher ];
[ballLauncher setDelegate:self];
[ballLauncher release];
}
}
**BELOW IS HOW I CONTROL WHEN THE BALL IS FIRED**
-(void)ChangeStateLaucher:(int)brandnewState withState:(CharacterStates)newState andObject:(GameObjectType)objectType; {
BL *bL = (BL*)
[sceneSpriteBatchNode getChildByTag:kBallLaucher];
int x = (arc4random() % 2);
if (x==0) {
CCLOG(#"Start Laucher Firing");
[bL changeState:kStateFiring];
count = 0;
}
if (x==1) {
CCLOG(#"No Laucher Firing");
count = count + 1;
if (count == 2) {
CCLOG(#"No Laucher Firing x2 - Start Laucher Firing");
[bL changeState:kStateFiring];
} else if (count > 3) {
CCLOG(#"No Laucher Firing x3 - Start Laucher Firing");
[bL changeState:kStateFiring];
}
}
[delegate ChangeStateLaucher:x withState:kStateFiring andObject:objectType];
}
-(void)createPhaserWithDirection:(PhaserDirection)phaserDirection andPosition:(CGPoint)spawnPosition {
CCLOG(#"Creating Ball from Gameplay Layer");
Ball *ballSprite = [[Ball alloc]initWithSpriteFrame:[[CCSpriteFrameCache
sharedSpriteFrameCache]
spriteFrameByName:#"Ball_1.png"]];
[ballSprite setPosition:spawnPosition];
[ballSprite setMyDirection:phaserDirection];
[ballSprite setCharacterState:kStatespawning];
[ballSprite setCharacterHealth:3.0f];
[sceneSpriteBatchNode addChild:ballSprite z:20 tag:kEnemyTypeBall];
[ballSprite release];
}
-(id)init {
self = [super init];
if (self !=nil) {
CGSize screenSize = [CCDirector sharedDirector]. winSize;
self.TouchEnabled = YES;
srandom(arc4random()); // Seeds the random number generator
[[CCSpriteFrameCache sharedSpriteFrameCache]
addSpriteFramesWithFile:#"scene1atlas.plist"]; // 1
sceneSpriteBatchNode =
[CCSpriteBatchNode batchNodeWithFile:#"scene1atlas.png"]; // 2
[self createObjectOfType:kBallLaucher withHealth:3 atLocation:ccp(screenSize.width * 0.05f, screenSize.height * 0.822f) withZValue:10];
[gameBeginLabel setPosition:ccp(screenSize.width/2,screenSize.height/2)]; // 2
[self addChild:gameBeginLabel]; // 3
id labelAction = [CCSpawn actions:
[CCFadeOut actionWithDuration:2.5f],
nil]; // 4
[gameBeginLabel runAction:labelAction];
lives = 3;
scoreLabel = [CCLabelBMFont labelWithString:#"$0"
fntFile:#“BallTest.fnt"];
scoreLabel.position = ccp(screenSize.width * 0.5f, screenSize.height * 0.9f);
[self addChild:scoreLabel
z:-1 tag:kNewScoreTagValue];
[self scheduleUpdate];
}
return self;
}
#end
Once again I would like to thank anyone that has taken the time to look at this question regardless if you have posted a pointer or answer or not.
Thanks.
I think that when there are more than one Ball objects on the screen, the GamePlayLayer update method is unable to pick up on the state change on one of the balls at times because that ball is removed as soon as it enters kStateScore.
If you add a certain delay before removing the ball , the update method should pick up the changes in all the balls and your problem should be resolved.
In your Ball.m -(void)changeState:(CharacterStates)newState function , modify the action on state kStateScore like
action = [CCSequence actions:[CCDelayTime actionWithDuration:0.2],
[CCCallFunc actionWithTarget:self selector:#selector(removeSelf)],
nil];
Try this out and let me know if this worked for you!
EDIT
The above solution would end up adding more than one point as the ball would remain in kStateScore state for a long time due to delay. In order to counter that problem , we can introduce a new state call kStateDead and change the ball state to kStateDead after adding the point. This will ensure a point is added only once and also we can put the responsibility of removing the ball in kStateDead state. The new code would like as follows :
Ball.m
case kStateScore:
PLAYSOUNDEFFECT(SCORE);
CCLOG(#“Ball Past Left Of Screen => Add 1 to Score");
break;
case kStateDead:
action = [CCSequence actions:
[CCCallFunc actionWithTarget:self selector:#selector(removeSelf)],
nil];
default:
CCLOG(#“Ball -> Unknown CharState %d",
characterState);
break;
and in your Gameplayer.m
if ([tempChar characterState] == kStateScore) <==HERE I AM SEEING IF THE BALL HAS SCORED - THIS IS ALSO WHERE I THINK I MAY BE GOING WRONG SOMEHOW.
{
CCLOG(#"Add 1 Points To Score");
[self addPoint];
[tempChar changeState:kStateDead]; //change the state to dead after the point is added
return;
}
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.
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;
}