how can i get touch location in init function in cocos2d-iphone? - ios

I need touch coordinates in
-(id) init{ }
but just can get them in
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event{
CGPoint touchLocation = [touch locationInView: [touch view]];
touchLocation = [[CCDirector sharedDirector] convertToGL:touchLocation];
touchLocation = [self convertToNodeSpace:touchLocation];
return YES;
}
How can I do it?

ccTouchBegan is called "randomly". That is, your program doesn't know when the user is going to touch the screen. This is called an asynchronous event.
I can't think of a way to get the touches that are already on the screen when init is called unless you can find a way of doing using the CCTouchDispatcher

Related

What does userInteractionEnabled = NO mean and how does it work?

Cocos 2d-iphone 3.0. I am using this code to detect whether a single sprite is touched
-(void) touchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
CGPoint location = [touch locationInView: [touch view]];
CGPoint convertedlocation = [[CCDirector sharedDirector] convertToGL: location];
CGPoint convertedNodeSpacePoint = [self convertToNodeSpace:convertedlocation];
if (CGRectContainsPoint([_sprite boundingBox],convertedNodeSpacePoint))
{
// Remove sprite
}
}
I have some code inside that should remove some other sprites from parent. Logically, when _sprite
is touched second time, application will crash, because other sprites'v been already removed.
I was trying to make _sprite untouchable using _sprite.userInteractionEnabled = NO;, but this has no effect.
What does userInteractionEnabled mean exactly and how would one use this to facilitate touch detection on sprites.
What is the optimal way of handling touches on sprites in my scene?
There is no way to disable interactions on a ccsprite. What you should do is:
bool firstTimeClicked=false;
-(void) touchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
if(firstTimeClicked==true)
{
return NO;
}
CGPoint location = [touch locationInView: [touch view]];
CGPoint convertedlocation = [[CCDirector sharedDirector] convertToGL: location];
CGPoint convertedNodeSpacePoint = [self convertToNodeSpace:convertedlocation];
if (CGRectContainsPoint([_sprite boundingBox],convertedNodeSpacePoint)) {
firstTimeClicked=true;
}
}
What userInteractionEnabled does
When you set userInteractionEnabled=YES on a sprite that mean that user interaction callbacks are going to get called.
So for example in your scene if you would have userInteractionEnabled=NO your -(void) touchBegan:(UITouch *)touch withEvent:(UIEvent *)event would not get called.
What you we're doing
You were detecting the touches in your scene. And then you we're checking what was under that touch location, so if anything was under there it would be detected.
How to accomplish this properly - subclass your CCSprite
You want to handle these kind of behaviours in custom CCSprite classes, because if not your scenes touchBegan is going to turn into a huge buggy if else switch statement.
Believe me, I have been there.
Here is a code example of what this class could look like :
The .h file
#interface SubclassedSprite : CCSprite
#end
And the .m file
#implementation SubclassedSprite
- (void) onEnter
{
[super onEnter];
self.userInteractionEnabled = YES;
}
- (void) touchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
CCLOG(#"Touch began on sprite");
// Your code when the Sprite was touched [self removeFromParentAndCleanup:YES];
}
#end
This is the proper, scalable way to handle this.
Below code is without taking an extra BOOL variable and it should work for you:
-(void) touchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
CGPoint location = [touch locationInView: [touch view]];
CGPoint convertedlocation = [[CCDirector sharedDirector] convertToGL: location];
CGPoint convertedNodeSpacePoint = [self convertToNodeSpace:convertedlocation];
if (CGRectContainsPoint([_sprite boundingBox],convertedNodeSpacePoint)) {
if(_sprite.userInteractionEnabled)//Here you can remove the children of _sprite. e.g.
{
//Here run some action or do what you want to do. For e.g.
CCFadeTo *fadeOut = [CCFadeTo actionWithDuration:0.5f opacity:0];
CCCallfuncN *clean = [CCCallFuncN actionWithTarget:self SEL:#selector(cleanSpriteChildren:)];
for(id item in _sprite.children)
if(item)
[item runAction:[CCSequence runActions:fadeOut, clean]];
}
else{//Do your own task while _sprite is untouchable}
}
}
-(void)cleanSpriteChildren:(id)sender
{
[item removeFromParentAndCleanUp:YES]
if(([_sprite children] count) == 0)
_sprite.userInteractionEnabled = YES; //Here make the _sprite touchable again
}

Drag an image when touched on the object itself

I created a very simple app that contains a draggable UIImageView but I faced a problem that the image can be dragged without touching it. I'm sure that the hole issue is from anyObject but I have no idea how to replace it I tried self.view.image but it failed. So here's my code
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:touch.view];
lineView.center = location;
}
-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
[self touchesBegan:touches withEvent:event];
}
any ideas?
Consider using a pan gesture recogniser. Add it only to the image view (and enable user interaction on the view). Now you will only get action method callbacks from the gesture when the view has actually been touched, your code becomes simpler, and you can move the view with that position.
Also, in your current code, it's weird to call touchesBegan: from touchesMoved:. If you keep that code (because you don't want to use a gesture), you should refactor the code that moves the view out into a different method and have both touchesBegan: and touchesMoved: call that method.
Try the following
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:touch.view];
if ([lineView pointInside:location withEvent:event])
lineView.center = location;
}

Dragable UIImageView is Teleporting when tapping somewhere else

The code below is based on the idea of how to make a UIImageView be able to be dragged around the ViewController. When I use this code however, I click on a different location instead of pressing on the Image and it teleports to that location instead of requiring me to always drag the image. I want the code below to only work when pressing on that specific image. Please Help-
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:touch.view];
image.center = location;
[self ifCollided];
}
-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
[self touchesBegan:touches withEvent:event];
}
It's teleporting simply because you don't have any check for whether the user has in fact touched the image, so any touch causes the image to jump to that location. What you need to do is check if the user has touched the image, then move it only if they have. Try the following code in the ViewController, assuming 'image' is the draggable view:
You'll need to create a variable/property on your ViewController to track if the view is being dragged. If you need just one image, you can use a BOOL (the code below assumes you've done this, called isDragging).
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:image];
if([image pointInside:location withEvent:event]) {
isDragging = YES;
}
}
-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesMoved:touches withEvent:event];
if(isDragging)
{
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:self.view];
image.center = location;
[self ifCollided];
}
}
-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesEnded:touches withEvent:event];
isDragging = NO;
}
This code basically does a check in touchesBegan and sets the property to true if you touch inside the image, moves it in touchesMoved if your initial touch was on the image, and finally unsets the check in touchesEnded.

Moving a sprite by touching anywhere on the screen

In my game only one sprite responds to touches. How can I make a mousejoint move this sprite/body regardless of where I touch on the screen?
- (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView: [touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
mySprite.position = location;
}
Make sure in your initmethod that self.isTouchEnabled = YES;

iOS Drag a CCSprite not working?

So I'm using cocos2d and trying to drag a sprite across the screen, it was working prior to this.. but I can't seem to figure out what I did to make it not work. I'm seeing the ccTouchBegan and ccTouchEnd methods being called but not the ccTouchMoved.
I tried converting over to ccTouchesBegan, ccTouchesMoved, and ccTouchesEnded but am still only seeing the Began and Ended methods being called. Obviously I've commented out or changed a setting somewhere. I also commented out [[CCTouchDispatch sharedDisptacher] ...]; because it error'd with the ccTouches methods because it's native touches I believe.
Anyone have any idea what's going on?
Did you add yourself as a delegate?
[[CCTouchDispatcher sharedDispatcher]addTargetedDelegate:self priority:0 swallowsTouches:NO];
And then try this:
- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint location = [touch locationInView: [touch view]];
mySprite.position = location;
}
You can do the moving of the sprite using the ccTouchMoved Easily.
Please try the below code. I made a short demo for my understanding of the same concept of yours. It works for me.
- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event
{
NSSet *touches = [event allTouches];
for (int i = 0; i < touches.count; i++) {
UITouch *touch = [[touches allObjects] objectAtIndex:i];
CGPoint touchLocation = [touch locationInView: [touch view]];
CGPoint location = [[CCDirector sharedDirector]
convertToGL:touchLocation];
if(CGRectContainsPoint([sprite boundingBox], location))
sprite.position = ccp(location.x,location.y);
}
}

Resources