iOS Drag a CCSprite not working? - ios

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);
}
}

Related

Sprite Kit: How to make a node "jump" and also move it left or right, dependant on node position and length of touch?

This is my first post so go easy haha.
I'm new to 'iOS' 'coding', 'Xcode' and 'spritekit'. I'm looking to make an image node "jump" a distance on the positive y-axis if I touch anywhere on the screen, although if I touch somewhere to the left or right if the image and hold for a certain time, it moves in the respective left or right direction, a distance respective to the length of the touch.
Not sure if that's very clear, but any help would be appreciated! Thanks!
You could move a node like this
In touchesEnded: or touchesBegan: method:
{
node.position.y += 50;
}
In order for sprite to move somewhere you could also use actions, there is a family of actions like moveTo action.
I would suggest picking upa tutorial or a book about sprite kit. Good site with free tutorials is raywenderlich.com
Please Try this code :
a sprite move : left/right according to your touch direction anywhere on screen
// CGPoint initialPos; // in .h file
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint touchPt = [touch locationInView:touch.view];
initialPos = [[CCDirector sharedDirector] convertToGL:touchPt];
}
-(void) ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *myTouch=[touches anyObject];
CGPoint currentPos=[myTouch locationInView:[myTouch view]];
currentPos=[[CCDirector sharedDirector] convertToGL:currentPos];
float diffX = currentPos.x - initialPos.x;
float diffY = currentPos.y - initialPos.y;
CGPoint velocity = ccp(diffX, diffY);
initialPos = currentPos;
[Sprite setPosition:ccpAdd([SmileBall position], velocity)];
}
- (void) ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *myTouch=[touches anyObject];
CGPoint currentPos=[myTouch locationInView:[myTouch view]];
currentPos=[[CCDirector sharedDirector] convertToGL:currentPos];
float diffX = currentPos.x - initialPos.x;
float diffY = currentPos.y - initialPos.y;
CGPoint velocity = ccp(diffX, diffY);
initialPos = currentPos;
[Sprite setPosition:ccpAdd([SmileBall position], velocity)];
}
a sprite jump up: according to your touch on screen
-(void) ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
CCSprite *RunningChar;
RunningChar=(CCSprite *)[self getChildByTag:10];
UITouch *touch = [touches anyObject];
CGPoint touchPt = [touch locationInView:touch.view];
touchPt = [[CCDirector sharedDirector] convertToGL:touchPt];
float radian = ccpToAngle(ccpSub(touchPt, prevPoint));
float degrees = CC_RADIANS_TO_DEGREES(radian);
if (degrees >= 22.5 && degrees <= 112.5) // for upward direction :). otherwise you can write only code without ant condition
{
CCJumpTo *jump=[CCJumpTo actionWithDuration:0.7 position:CGPointMake(RunningChar.position.x, 87) height:110 jumps:1];
[RunningChar runAction:seq];
}
else
{
}
}
Try this :)

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
}

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;

previousLocationInView, clarification needed

As part of the following method, i can ask recorgnier object of type UISwipeGestureRecognizer*
- (void) handleSwipeFrom:(UISwipeGestureRecognizer*)recognizer
About its current location
CGPoint currentLocation = [recognizer locationInView:self];
According to documentation, i should also be able to get
CGPoint previousLocation = [recognizer previousLocationInView:self];
This method, however, is not available. What am i missing please?
You can obtain previous location by using
[recognizer locationOfTouch:<#(NSUInteger)#> inView:<#(UIView *)#>]
I think that previousLocation is deprecated for GR, or exactly for SwipeGR
I too Faced the same problem..
I used UITouch object to get the previousLocationInView
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
CGPoint pre_moveLocation ;
UITouch *theTouch =[touches anyObject];
pre_moveLocation =[theTouch previousLocationInView:imageView;
}

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

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

Resources