Spritebuilder touch - cocos2d-iphone

I have a problem in using touches in my scene.
I’ ve created a sprite (player.ccb) working in Sprite Builder that has a name =player in CCnode section.
Here it is the main code written in GameScene :
So after opening the simulator nothing doesn’t happen and in the Debug area there is nothing written.
Thank you in advance for your help!
//
// GameScene.m
// MIOGIOCO18
//
// Created by Fabio Tavanti on 12/12/15.
// Copyright (c) 2015 Apportable. All rights reserved.
//
#import "GameScene.h"
#implementation GameScene
{
__weak CCNode* _levelNode;
__weak CCPhysicsNode* _physicsNode;
__weak CCNode* _playerNode;
__weak CCNode* _backgroundNode;
}
-(void) didLoadFromCCB
{
// enable receiving input events
self.userInteractionEnabled = YES;
// load the current level
[self loadLevelNamed:nil];
}
-(void) loadLevelNamed:(NSString*)levelCCB
{
// get the current level's player in the scene by searching for it recursively
_playerNode = [self getChildByName:#"player" recursively:YES];
NSAssert1(_playerNode, #"player node not found in level: %#", levelCCB);
}
//-(void) touchBegan:(CCTouch *)touch withEvent:(UIEvent *)event
-(void) touchBegan:(CCTouch *)touch withEvent:(CCTouchEvent *)event
{
NSLog(#"okaay pressed");
_playerNode.position = [touch locationInNode:self];
}
#end

I don't know how you structured your ccb file and if you made proper relation to your actual GameScene, so best thing for you would be to put
self.userInteractionEnabled = YES;
in the GameScene's onEnter method...

Related

Cocos2d: ARC releasing CCSprite too soon?

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.

cocos2d-Menu's label shown on layer but doesn't react to touch

I don't know whats wrong, maybe because i'm using more layers?
I think that my other layer (sliding menu grid subclass is stealing the touches...)
//
// BGLayer.m
// MainProject
//
// Created by NSSL1 on 8/30/12.
// Copyright (c) 2012 MyCompanyName. All rights reserved.
//
#import "BGLayer.h"
#import "GameManager.h"
#import "MainMenuLayer.h"
#interface BGLayer()
-(void)displayBGMenu;
#end
#implementation BGLayer
-(void)backtomenu:(CCMenuItem*)itemPassedIn{
CCLOG(#"why I can't reach here?");
[[GameManager sharedGameManager] runSceneWithID:kMainMenuScene];}
-(id)init {
self = [super init];
if (self != nil) {
self.isTouchEnabled=YES;
[self displayBGMenu];
}
return self;
}
-(void)displayBGMenu{
NSString* backLabelstring = [NSString stringWithFormat:#"Back to Menu"];
CGSize screenSize = [CCDirector sharedDirector].winSize;
//Shadow
CCLabelTTF *backLabel = [CCLabelTTF labelWithString:backLabelstring fontName:#"Marker Felt" fontSize:32];
backLabel.position=CGPointMake(screenSize.height*0.5f, screenSize.width*0.1f);
backLabel.color = ccBLUE;
CCMenuItem* backbtnitem=[CCMenuItemLabel itemWithLabel:backLabel target: self
selector:#selector(backtomenu:)];
[backbtnitem setTag:21];
menu = [CCMenu menuWithItems:backbtnitem ,nil];
menu.position = CGPointMake((screenSize.width / 2), screenSize.height*0.1f);
menu.tag = 200;
[self addChild:menu z:20 tag:200];
}
#end
I had an issue with layers swallowing touches in the same type of class, and to avoid this someone suggested me to add this in the grid button item class init method:
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:-1 swallowsTouches:YES];
The effect is that the class calling this method would not be greedy towards the parent's layer touch detector by detecting only the touches in its area, and would allow the user to scroll the menu in a smooth way as well as pressing other items in the parent layer (such as your menu).

Resume game loop in cocos2d

I have a game with animation. In game scene, I use the method below to pause my game (it works perfectly, because the game is paused when the users taps on any point of the iOS device):
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch=[touches anyObject];
CGPoint locationOfTouch=[self convertTouchToNodeSpace: touch];
CGRect rectOfScreen=CGRectMake(0, 0, screenSize.width, screenSize.height);
if (CGRectContainsPoint(rectOfScreen, locationOfTouch))
{
[[CCDirector sharedDirector] replaceScene:[PauseScene scene]];
[self unschedule:#selector(spawnEnemies:)];
[self unschedule:#selector(checkCollisionOfEnemyWithBullet:)];
[self unschedule:#selector(update:)];
[self unschedule:#selector(isJoystickActivated:)];
[self unschedule:#selector(checkHasGameEnded:)];
[[CCDirector sharedDirector] pause];
}
}
To implement resume action, I'v created PauseLayer:CCLayer, where I've implemented the following method to resume the game:
-(void) continueGame:(id)sender
{
[[CCDirector sharedDirector] resume];
[[CCDirector sharedDirector] replaceScene:[GameSceneLayer scene]];
//[self resumeSchedulerAndActions];
}
Here is the code, how I envoke the method above:
CCMenuItemFont* continue_game=[CCMenuItemFont itemWithString:#"continue game" target:self selector:#selector(continueGame:)];
But, when I select continue game, the game start from the blank point: every game state, every game character will be new. How can I resume my game from the intial point where it was paused by user? Thank you!
You can use these two cocos2D function to pause and resume:
[self pauseSchedulerAndActions]; //pause
[self resumeSchedulerAndActions];//resume
Also maintain one bool variable, and check that whenever u need.
bool mISGamePaused;

Cannot remove sprite from new CCNode class

I am creating a small game where objective is to tap and destroy mouse. I created a separate mouse class for it.
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#import "HelloWorldLayer.h"
#interface Mouse : CCNode <CCTargetedTouchDelegate> {
CCSprite *sprite;
HelloWorldLayer *HelloLayer;
}
-(id) initWithGame:(HelloWorldLayer *)aGame;
-(void) runFloatAction;
#property(nonatomic, retain) CCSprite *sprite;
#property(nonatomic, retain) HelloWorldLayer *HelloLayer;
#end
I am initializing like this in .m file:
-(id) initWithGame:(HelloWorldLayer *)aGame{
if ((self = [super init])) {
self.sprite = [CCSprite spriteWithFile:#"mouse.png"];
self.sprite.scale = 0.3f + CCRANDOM_0_1() * 0.5f;
self.sprite.position = ccp(CCRANDOM_0_1() * 480, CCRANDOM_0_1() * 320);
self.HelloLayer = aGame;
[aGame addChild:sprite];
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self
priority:1
swallowsTouches:YES];
//[self runFloatAction];
}
return (self);
}
I want to remove sprite on tap. For which I am using this code in .m file: -
- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
if ([self containsTouchLocation:touch]) {
[self.sprite removeFromParentAndCleanup:YES];
return YES;
}else{
return NO;
}
}
Unfortunately I am not able to remove sprite. Logically, we have to remove sprite from parent. But, its not working in actual.
The way I structure my classes is to have the Mouse class as a subclass of CCSprite. If you handle the touch events in the main game class than you just remove the mouse. You also need to enable touch events if you haven't done that.
I recommend you do the above and put this in your game class.
[self setIsTouchEnabled:YES];
Mouse *myMouse = [Mouse spriteWithImage:#"Mouse.png"];
[myMouse setPosition:CGPointMake(160, 240)];
[self addChild:myMouse];
Then just handle the touch events in your game class.

How do I detect multi-touch in cocos2d?

Edited Post
Ok I tried what rptwsthi said in another project just to test it......
-(id) init
{
if( (self=[super init])) {
self.isTouchEnabled = YES;
}
return self;
}
- (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
NSArray *touchArray=[touches allObjects];
if ([touchArray count] == 2) {
NSLog(#"touch 2");
}
else if([touchArray count]==1) {
NSLog(#"touch 1");
}
}
But only the "touch 1" NSLog pops ups when I press the screen with two fingers. Do I need to put what LearnCocos2D said in there somewhere too.
Old Post
I have a test app I'm making and in it I have 3 buttons in the hud, 2 are for moving left and right and the other is for shooting. This is what I currently have.....
-(void) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint loc = [touch locationInView:[touch view]];
loc = [[CCDirector sharedDirector] convertToGL:loc];
//Move Left
CGRect left = CGRectMake(leftButton.position.x-50/2, leftButton.position.y-50/2, 50, 50);
if (CGRectContainsPoint(left, loc)) {
[self schedule:#selector(moveLeft)];
}
//Move Right
CGRect right = CGRectMake(rightButton.position.x-50/2, rightButton.position.y-50/2, 50, 50);
if (CGRectContainsPoint(right, loc)) {
[self schedule:#selector(moveRight)];
}
//Shoot
CGRect shoot = CGRectMake(shootButton.position.x-50/2, shootButton.position.y-50/2, 50, 50);
if (CGRectContainsPoint(shoot, loc)) {
bullet = [CCSprite spriteWithFile:#"bullet.png"];
bullet.position = ccp(plane.position.x, plane.position.y+20);
[self addChild:bullet];
}
}
-(void) ccTouchesEnded:(UITouch *)touch withEvent:(UIEvent *)event {
[self unschedule:#selector(moveLeft)];
[self unschedule:#selector(moveRight)];
}
But I can only press one button at a time. I want to be able to hold the right or left button and also shoot with the shoot button. Can anyone fix my code or show me a basic example of multi-touch?
Also I'm new to iOS development and any help will be much appreciated. Thanks.
Have you enabled multiple touches on the cocos2d view?
[[CCDirector sharedDirector].openGLView setMultipleTouchEnabled:YES];
You Just use allObject instead of anyObject, and check it like:
- (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
NSArray *touchArray=[touches allObjects];
if ([touchArray count] == 2)
//DO ONE THING
else if([touchArray count]==1)
//DO ANOTHER THING
}