Aligning CCMenu at top the screen - cocos2d-iphone

I would have expected a 'Menu' button over a 'Switch Player' button at the upper left corner of the screen, but the upper part of the 'Menu' button is above the screen. Howcome? Is this a bug?
Left alignment is ok.
Thanks!
-(void) superSceneEnded
{
_sceneEnded = true;
CCMenu *menu = [CCMenu menuWithItems:nil];
menu.anchorPoint = ccp(0, 1); // Upper left corner
menu.position = ccp(2, _winSize.height - 2); // Almost at upp left corner of screen
[self addChild:menu];
[self addButton:menu :#"Menu" :#selector(goToMenu)];
if ([MatchMgr instance].currentMatch.isOnDevice)
{
[self addButton:menu :#"Switch player" :#selector(switchPlayer)];
}
[menu alignItemsVerticallyWithPadding:10];
}
-(void) addButton: (CCMenu*) menu: (NSString*) text: (SEL) selector
{
CCMenuItem *menuItem = [CCMenuItemImage itemFromNormalImage:#"button.png" selectedImage:#"button-pressed.png" target:self selector:selector];
menuItem.anchorPoint = ccp(0, 1); // Upper left corner
//menuItem.scale = 0.5;
[menu addChild:menuItem];
// The code below is not relevant for the question, but I keep it for your understanding.
CCLabelBMFont *bmText = [CCLabelBMFont labelWithString:text fntFile:#"MainFont.fnt"];
bmText.color = ccBLACK;
bmText.scale = 0.75;
bmText.alignment = NSTextAlignmentCenter;
bmText.position = ccp(75, 15);
[menuItem addChild: bmText];
}

It seems like this really is broken:
http://www.cocos2d-iphone.org/forum/topic/8261
I do my own placement of the buttons instead.
Here's my, not so fancy, code:
-(void) superSceneEnded
{
_sceneEnded = true;
CGFloat yPos = _winSize.height - 10;
CCMenu *menu = [CCMenu menuWithItems:nil];
menu.position = ccp(0, 0);
[self addChild:menu];
[self addButton:menu :#"Menu" :#selector(goToMenu): &yPos];
if ([MatchMgr instance].currentMatch.isOnDevice)
{
[self addButton:menu :#"Switch player" :#selector(switchPlayer): &yPos];
}
}
-(void) addButton: (CCMenu*) menu: (NSString*) text: (SEL) selector: (CGFloat*) yPos
{
CCMenuItem *menuItem = [CCMenuItemImage itemFromNormalImage:#"button.png" selectedImage:#"button-pressed.png" target:self selector:selector];
menuItem.scale = 0.5;
menuItem.position = ccp(42, *yPos);
*yPos -= 20;
[menu addChild:menuItem];
CCLabelBMFont *bmText = [CCLabelBMFont labelWithString:text fntFile:#"MainFont.fnt"];
bmText.color = ccBLACK;
bmText.scale = 0.75;
bmText.alignment = NSTextAlignmentCenter;
bmText.position = ccp(75, 15);
[menuItem addChild: bmText];
}

Related

trying to touch an item in an array not working

I have An Array inside my touches began method (I would like to be able to touch the sprite
and for it to NSlog the touch) is there something im forgetting to do or am doing something wrong?
I can log the touch on the screen but when I touch the bubbles nothing happens.
any help would be great.
-(id) init
{
if((self=[super initWithColor:ccc4(10, 10, 10,10)]) ) //sand 101, 116, 88
{
size = [[CCDirector sharedDirector] winSize];
self.touchEnabled = YES;
//other stuff here
Bubble01 = [[Bubble alloc]initWithBubbleWithLabel:#"_Bubble.png" opacity:255 gloss:#"_Bubble_overlay.png" posX:0 posY:0 data:[NSString stringWithFormat:#"%#", [Sortingarray objectAtIndex:BubbleAnswerBubble_1_IndexValue]]];
Bubble02 = [[Bubble alloc]initWithBubbleWithLabel:#"_Bubble.png" opacity:255 gloss:#"_Bubble_overlay.png" posX:0 posY:0 data:[NSString stringWithFormat:#"%#", [Sortingarray objectAtIndex:BubbleAnswerBubble_2_IndexValue]]];
Bubble03 = [[Bubble alloc]initWithBubbleWithLabel:#"_Bubble.png" opacity:255 gloss:#"_Bubble_overlay.png" posX:0 posY:0 data:[NSString stringWithFormat:#"%#", [Sortingarray objectAtIndex:BubbleAnswerBubble_3_IndexValue]]];
Bubble04 = [[Bubble alloc]initWithBubbleWithLabel:#"_Bubble.png" opacity:255 gloss:#"_Bubble_overlay.png" posX:0 posY:0 data:[NSString stringWithFormat:#"%#", [Sortingarray objectAtIndex:BubbleAnswerBubble_4_IndexValue]]];
Bubble05 = [[Bubble alloc]initWithBubbleWithLabel:#"_Bubble.png" opacity:255 gloss:#"_Bubble_overlay.png" posX:0 posY:0 data:[NSString stringWithFormat:#"%#", [Sortingarray objectAtIndex:BubbleAnswerBubble_5_IndexValue]]];
Bubble06 = [[Bubble alloc]initWithBubbleWithLabel:#"_Bubble.png" opacity:255 gloss:#"_Bubble_overlay.png" posX:0 posY:0 data:[NSString stringWithFormat:#"%#", [Sortingarray objectAtIndex:AnswerBubble_6_IndexValue]]];
//other stuff here
}
return self;
}
touchesbegan
-(void) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
//set up touches
NSSet *allTouch = [event allTouches];
UITouch *touch = [[allTouch allObjects]objectAtIndex:0];
CGPoint location = [touch locationInView:[touch view]];
location = [[CCDirector sharedDirector]convertToGL:location];
//log if touches are working if I touch the screen area
NSLog(#"touches screen");
//create an array from bubble class (CCSprites with labels,
//I need to be able to determine which sprite was touched and run an action on it)
BubbleArray = [[NSMutableArray alloc]initWithObjects:Bubble01,
Bubble02,
Bubble03,
Bubble04,
Bubble05,
Bubble06,
nil];
for(int i = 0; i < [BubbleArray count]; i++)
{
Bubble *sprite = (Bubble *)[BubbleArray objectAtIndex:i];
//create a rect to find the position and size of the sprite
//BackBubble is a sprite that i'm using to detect the content size
CGRect targetRect = CGRectMake(
sprite.BackBubble.position.x - (sprite.BackBubble.contentSize.width/2),
sprite.BackBubble.position.y - (sprite.BackBubble.contentSize.height/2),
sprite.BackBubble.contentSize.width,
sprite.BackBubble.contentSize.height);
//use the rect and touch location to determine hit
if(CGRectContainsPoint(targetRect, location))
//this doesn't work possibly because Bubble class is a CClayer?
//if(CGRectContainsPoint([sprite boundingBox], location))
{
selectedSprite = sprite;
NSLog(#"touches bubble sprite");
}
}
}
Any insight would be great to help me understand what i'm doing wrong.
cheers :)
new array code (getting the height and width of the sprite through the custom class
for(int i = 0; i < [DragItems count]; i++)
{
Bubble *sprite = (Bubble *)[BubbleArray objectAtIndex:i];
location = [sprite convertToNodeSpace:location];
if(CGRectContainsPoint([sprite.BackBubble boundingBox], location))
{
selectedSprite = sprite;
NSLog(#"touches bubble");
}
}
Bubble.m
#import "Bubble.h"
#import "Common.h"
#define ButtonFlashTime .4
#define KBubbleColourTurqoiseBlueFlash 2323
#define ScrollSpeed 5.2f
#define DecoyTextY 5
#define DecoyTextX -2
#implementation Bubble
#synthesize BackBubble,FrontShine,BubbleLabel,startX,startY,currentY,currentX,isNotTouchActivated,myInt,bubblespeed,tagNumber; //isTouched
-(id)init
{
self=[super init];
{
//touches
[[[CCDirector sharedDirector] touchDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];
isNotTouchActivated = false;
isTouched = NO;
bubblespeed = 0;
//start scrolling
[self MoveWithoutProblem];
[self setAnchorPoint:ccp(0.5,0.5)];
BackBubble = [CCSprite spriteWithSpriteFrameName:Bubblepng];
BackBubble.position = ccp(X,Y);
[BackBubble setAnchorPoint:ccp(0,0)];
[self addChild: BackBubble z:5];
NSLog(#"BackBubble, %f %f",BackBubble.position.x,BackBubble.position.y);
//other code here
[self setContentSize:[BackBubble boundingBox].size];
}
return self;
}
-(BOOL) isTouchOnSprite:(CGPoint)touch{
CGPoint local = [self convertToNodeSpace:touch];
CGRect r = self.boundingBox;
r.origin = CGPointZero;
Boolean b = CGRectContainsPoint( r, local );
//CCLOG(#"touch %f : %f : %d",touch.x,touch.y,b);
if (b) {
return YES;
}else {
return NO;
}
}
- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event{
CGPoint touchPoint = [touch locationInView:[touch view]];
touchPoint = [[CCDirector sharedDirector] convertToGL:touchPoint];
if([self isTouchOnSprite:touchPoint]){
//CGPoint move = [self convertTouchToNodeSpace:touch];
isNotTouchActivated = TRUE;
//isTouched = YES;
//NSLog(#"isTouched = %#", self.isTouched ? #"YES" : #"NO");
currentX = touchPoint.x;
currentY = touchPoint.y;
self.position = touchPoint;
return YES;
}
// NSLog(#"isTouched = %#", self.isTouched ? #"YES" : #"NO");
return NO;
}
- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event{
CGPoint touchPoint = [touch locationInView:[touch view]];
touchPoint = [[CCDirector sharedDirector] convertToGL:touchPoint];
if (isNotTouchActivated) {
currentX = touchPoint.x;
currentY = touchPoint.y;
self.position = touchPoint;
}
}
- (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event{
isNotTouchActivated = FALSE;
//isTouched = NO;
}
-(void)MoveWithoutProblem{
CGSize size = [[CCDirector sharedDirector] winSize];
int MaxHeightofBubbles = 350;
int minHeightofBubbles = 150;
int RandomNumber = [self generateRandomNumberBetweenMin:minHeightofBubbles Max:MaxHeightofBubbles];
float ConvertedRandom = [[NSNumber numberWithInt: RandomNumber] floatValue];
int MaxWidthofBubbles = 0;
int minWidthofBubbles = 900;
int RandomNumber02 = [self generateRandomNumberBetweenMin:MaxWidthofBubbles Max:minWidthofBubbles];
float ConvertedRandom02 = [[NSNumber numberWithInt: RandomNumber02] floatValue];
startX = ConvertedRandom02;
startY = ConvertedRandom;
currentX = startX+myInt;
currentY = startY;
self.position = ccp(startX,startY);
[self schedule:#selector(startMoving)];
}
-(void)startMoving{
if (!isNotTouchActivated) {
currentX+=bubblespeed;
[self setPosition:ccp(currentX,currentY)];
}
if (self.position.x >= 1024+50) {
//NSLog(#"off screen");
isrestartscrolling = YES;
}
if (isrestartscrolling == YES) {
//[self RandomYPOs];
[self scheduleOnce:#selector(newRandomX) delay:0.2];
isrestartscrolling = NO;
}
}
#end
Your code is a little hard to read but your immediate problem to why the touch doesn't work is because you are assuming your layer (Bubble) has a content width and height. If you did not set this, it wouldn't have it which is why your commented out line for [sprite boundingBox] does not work. Try [sprite.BackBubble boundingBox]. Adding items to a layer does not adjust that layer's content size automatically.
Another thing you can try is to add:
location = [sprite convertToNodeSpace:location];
If your bubble layer or that back bubble is moved at any point then simply adding the back bubble's position to a CGRect is not likely to work. Try the first idea first then try this if it doesn't work.
Hope this helped you Natalie.

Individual buttons in cocos2d

Most talk about buttons for cocos2d seems to be directed to CCMenu, where CCMenu AFAIK is meant for having a row or column in center of screen.
I need to place buttons randomly on screen and have yet to find a simple out of the box solution for this. I did try CCControlButton but didn't get it to work (CCScale9Sprite spriteWithSpriteFrameName loads incorrectly from sprite atlas).
For now I try to use this. It uses only one button in each CCMenu. So my screen will have lots of CCMenu instances, one for each button.
+(CCMenu*)button:(NSString*)spriteframename at:(const CGPoint)POINT block:(void(^)(id sender))block {
CCSprite* sprite1 = [CCSprite spriteWithSpriteFrameName:spriteframename];
CCSprite* sprite2 = [CCSprite spriteWithSpriteFrameName:spriteframename];
CCMenuItem* menuitem = [CCMenuItemImage itemWithNormalSprite:sprite1 selectedSprite:sprite2 block:block];
CCMenu* menu = [CCMenu menuWithItems:menuitem, nil];
menu.contentSize = sprite1.contentSize;
menu.position = POINT;
return menu;
}
This is a better way which I changed to.
Put this in like init:
CCMenuItem* menuitemRetry = [[self class] buttonWithSpriteframenameOff:#"retry_off.png" on:#"retry_on.png" at:ccp(198, 184) block:^(id sender) {
// Do something
}];
CCMenuItem* menuitemMenu = [[self class] buttonWithSpriteframenameOff:#"menu_off.png" on:#"menu_on.png" at:ccp(362, 184) block:^(id sender) {
// Do something else
}];
CCMenu* menuLow = [CCMenu menuWithItems:menuitemMenu, menuitemRetry, nil];
menuLow.position = CGPointZero;
[self addChild:menuLow];
This also needed
+(CCMenuItem*)buttonWithSpriteframenameOff:(NSString*)spriteframenameOff on:(NSString*)spriteframeOn at:(const CGPoint)POINT block:(void(^)(id sender))block {
CCMenuItem* menuitem = [CCMenuItemImage itemWithNormalSprite:[CCSprite spriteWithSpriteFrameName:spriteframenameOff] selectedSprite:[CCSprite spriteWithSpriteFrameName:spriteframeOn] block:block];
menuitem.position = POINT;
return menuitem;
}

touch create body touch destroy body

I am looking at ways to create a body in Box2D with the first touch
and destroy it with a second touch.
To create the body I am using this method:
(void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView: [touch view]];
location = [[CCDirector sharedDirector] convertToGL: location];
if (touch.tapCount > 1) {
CGSize winSize = [CCDirector sharedDirector].winSize;
CCSprite *sprite = [CCSprite spriteWithFile:#"sprite.png" rect:CGRectMake(0, 0, 90, 90)];
sprite.position = ccp(location.x/PTM_RATIO, location.y/PTM_RATIO);
sprite.tag = 7;
[self addChild: sprite];
b2BodyDef ballBodyDef2;
ballBodyDef2.type = b2_dynamicBody;
ballBodyDef2.position.Set(location.x/PTM_RATIO, location.y/PTM_RATIO);
ballBodyDef2.userData = sprite;
b2Body *body2 = _world->CreateBody(&ballBodyDef2);
b2CircleShape circle;
circle.m_radius = 22.0/PTM_RATIO;//(arc4random()*26.0)/PTM_RATIO;
b2FixtureDef ballShapeDef2;
ballShapeDef2.shape = &circle;
ballShapeDef2.density = 1.0f;
ballShapeDef2.friction = 0.5f;
ballShapeDef2.restitution = 0.2f;
body2->CreateFixture(&ballShapeDef2);
} else {
b2Vec2 locationWorld = b2Vec2(location.x/PTM_RATIO, location.y/PTM_RATIO);
for (b2Body* b = _world->GetBodyList(); b; b = b->GetNext()) {
b2Fixture *bf1 = b->GetFixtureList();
if (bf1->TestPoint(locationWorld)) {
CCSprite *tempSprite = (CCSprite *) b->GetUserData();
if (tempSprite .tag==7) {
[self removeChild:tempSprite cleanup:YES];
_world->DestroyBody(b);
}
}
}
}
}
With this method, to create the body, I have to touch the screen 2 times, and then once more to destroy it. What I would need to do so that you tap once to create the body, then tap again to destroy?
In this way you create body when tap once then tap again to destroy
if (isBodyCreated ==NO)
{
isBodyCreated=YES;
CGSize winSize = [CCDirector sharedDirector].winSize;
CCSprite *sprite = [CCSprite spriteWithFile:#"Icon.png"];
sprite.position = ccp(location.x/PTM_RATIO, location.y/PTM_RATIO);
sprite.tag = 7;
[self addChild: sprite];
b2BodyDef ballBodyDef2;
ballBodyDef2.type = b2_dynamicBody;
ballBodyDef2.position.Set(location.x/PTM_RATIO, location.y/PTM_RATIO);
ballBodyDef2.userData = sprite;
b2Body *body2 = world->CreateBody(&ballBodyDef2);
b2CircleShape circle;
circle.m_radius = 22.0/PTM_RATIO;//(arc4random()*26.0)/PTM_RATIO;
b2FixtureDef ballShapeDef2;
ballShapeDef2.shape = &circle;
ballShapeDef2.density = 1.0f;
ballShapeDef2.friction = 0.5f;
ballShapeDef2.restitution = 0.2f;
body2->CreateFixture(&ballShapeDef2);
}
else
{
b2Vec2 locationWorld = b2Vec2(location.x/PTM_RATIO, location.y/PTM_RATIO);
for (b2Body* b = world->GetBodyList(); b; b = b->GetNext())
{
b2Fixture *bf1 = b->GetFixtureList();
if (bf1->TestPoint(locationWorld))
{
CCSprite *tempSprite = (CCSprite *) b->GetUserData();
if (tempSprite .tag==7)
{
[self removeChild:tempSprite cleanup:YES];
world->DestroyBody(b);
isBodyCreated=NO;
}
}
}
}
I hope this will help you.

how to do a function for a sprite or menu in cocos2d?

I created two CCLayers, one is gamelayer, another is howlayer. The code of gamelayer.m is
-(id)init{
if (self = [super init]) {
CCSprite *gamebg = [CCSprite spriteWithFile:#"bg.png"];
gamebg.anchorPoint = CGPointZero;
[self addChild:gamebg z:0 tag:1];
HowLayer *howLayer = [HowLayer node];
[self addChild:howLayer];
[self schedule:#selector(showthegamecontent:) interval:0.4];
}
return self;
}
the code of howlayer is
-(id)init{
if (self=[super init]) {
CCSprite *howbg = [CCSprite spriteWithFile:#"translucentbg.png"];
howbg.anchorPoint = CGPointZero;
[self addChild:howbg z:5 tag:1];
CCMenuItem *howmenu = [CCMenuItemImage itemFromNormalImage:#"how.png"
selectedImage:#"how.png"
target:self
selector:#selector(startgame:)];
CCMenu *ccMenuhowmenu = [CCMenu menuWithItems:howmenu, nil];
ccMenuhowmenu.position=ccp(517,384);
[self addChild:ccMenuhowmenu z:5 tag:2];
}
return self;
}
-(void)startgame:(id)sender{
[self removeAllChildrenWithCleanup:YES];
}
I want to do function like this:
When I click the menu on howlayer, the Howlayer will be removed (I have done), and then the game starts, calls the selector 'showthegamecontent', so how should I do?
Simple hack in your howlayer:
-(void)startgame:(id)sender{
gameLayer* parent = (gameLayer*) self.parent;
[parent showthegamecontent];
}
but it may leave you with a warning.. But it works..
The implementation without warning is that you have to store a reference to the parent with you init. Which i feel its unnecessary as you only need to reference it once.

Change color of a line on a button click event in cocos2d

I am a newbie at Cocos2D and i'm just getting started. I have set up a scene, and I have to change the color of a line in Cocos2D. Please can anyone help me out with this? Any help will be appreciated.
This should work:
-(id) init{
if((self = [super init])){
//CGSize winSize = [[CCDirector sharedDirector] winSize];
naughtytoucharray = [[NSMutableArray alloc] init];
self.isTouchEnabled = YES;
CCMenuItem *starMenuItem = [CCMenuItemImage itemFromNormalImage:#"ButtonStar.png" selectedImage:#"ButtonStarSel.png"
target:self selector:#selector(starButtonTapped:)];
CCMenuItem *starMenuItem1 = [CCMenuItemImage itemFromNormalImage:#"ButtonPlus.png" selectedImage:#"ButtonPlusSel.png"
target:self selector:#selector(starButtonTapped1:)];
CCMenuItem *menuItem1 = [CCMenuItemImage itemFromNormalImage:#"Button1.png" selectedImage:#"Button1Sel.png" target:self selector:#selector(button1Tapped:)];
CCMenuItem *menuItem2 = [CCMenuItemImage itemFromNormalImage:#"Button2.png" selectedImage:#"Button2Sel.png" target:self selector:#selector(button2Tapped:)];
CCMenuItem *menuItem3 = [CCMenuItemImage itemFromNormalImage:#"Button3.png" selectedImage:#"Button3Sel.png" target:self selector:#selector(button3Tapped:)];
_scoreLabel = [CCLabelTTF labelWithString:#" MyScore" dimensions:CGSizeMake(150, 30) alignment:UITextAlignmentLeft fontName:#"Arial" fontSize:15];
_scoreLabel.color = ccc3(255, 0, 0);
[_scoreLabel setPosition:ccp(80, 300)];
CCMenu *starMenu = [CCMenu menuWithItems:starMenuItem, nil];
CCMenu *starMenu1 = [CCMenu menuWithItems:starMenuItem1, nil];
CCRadioMenu *radioMenu = [CCRadioMenu menuWithItems:menuItem1, menuItem2, menuItem3, nil];
starMenuItem.position = ccp(60, 60);
starMenuItem1.position = ccp(60, 120);
radioMenu.position = ccp(120, 120);
[radioMenu alignItemsVertically];
radioMenu.selectedItem_ = menuItem1;
[menuItem1 selected];
starMenu.position = CGPointZero;
starMenu1.position = CGPointZero;
[self addChild:starMenu];
[self addChild:starMenu1];
[self addChild:radioMenu];
[self addChild:_scoreLabel];
}
[_scoreLabel setString:[NSString stringWithFormat:#"MyScore: %d", score]];
return self;
}
-(void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint new_location = [touch locationInView:[touch view]];
new_location = [[CCDirector sharedDirector] convertToGL:new_location];
CGPoint oldTouchLocation = [touch previousLocationInView:touch.view];
oldTouchLocation = [[CCDirector sharedDirector] convertToGL:oldTouchLocation];
oldTouchLocation = [self convertToNodeSpace:oldTouchLocation];
[naughtytoucharray addObject:NSStringFromCGPoint(new_location)];
[naughtytoucharray addObject:NSStringFromCGPoint(oldTouchLocation)];
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0)
{
exit(0);
NSLog(#"exit");
}
else if(buttonIndex == 1)
{
//CCScene *scene = [CCScene node];
[[CCDirector sharedDirector] replaceScene:[GameScene scene1]];
NSLog(#"Play again");
}
}
-(void)draw
{
glEnable(GL_LINE_SMOOTH);
for (int i = 0; i < [naughtytoucharray count]; i+=2)
{
CGPoint start = CGPointFromString([naughtytoucharray objectAtIndex:i]);
CGPoint end = CGPointFromString([naughtytoucharray objectAtIndex:i+1]);
ccDrawLine(start, end);
glColor4ub(200, 120, 120, 255);