Handling CCSprites with Multiple Touch - cocos2d-iphone

I have one or more than one sprites stored in a array. What i want is to drag these sprites with multiple fingers around the screen. i.e (Multiple Touch)
Can anyone tell me how to do that?
Any help will be appreciated..
Here is my code:
-(void)touchBegan:(CCTouch *)touch withEvent:(CCTouchEvent *)event
{
CGPoint location = [touch locationInNode:self];
selectedSprite.paused = YES;
[self selectSpriteFromTouch:location];
//this is where i get sprite selected from i.e selectedSprite from array
}
-(void)touchMoved:(CCTouch *)touch withEvent:(CCTouchEvent *)event
{
selectedSprite.position = [touch locationInNode:self];
}
-(void)touchEnded:(CCTouch *)touch withEvent:(CCTouchEvent *)event
{
selectedSprite.paused = NO;
selectedSprite.position = [touch locationInNode:self];
selectedSprite = nil;
}
-(void)touchCancelled:(CCTouch *)touch withEvent:(CCTouchEvent *)event
{
selectedSprite.paused = NO;
selectedSprite = nil;
}

If I understand correctly you want say two fingers on the screen, each to move 1 sprite? I guess you have the images in an array so get the location of each touch and if each touch is on a sprite, then you know which touch is on which sprite.
CGPoint fingerOne = [event.allTouches.allValues[0] locationInWorld];
CGPoint fingerTwo = [event.allTouches.allValues[1] locationInWorld];
If sprite at index 0 is touched by fingerOne, then you can move that by the same amount as fingerOne moves and similarly for fingerTwo and sprite at index 1.

Related

MultiTouch control of a sprites movement - cocos2d

I've been dealing with this problem for quite some time.
What I am trying to do is have a CCSprite's right/left movement controlled by touches on either the left side of the screen or the right.
Doing this is no problem if you lift your finger after each touch. But what I want is best described by an example:
The player touches the left side of the screen and the sprite moves to the left. Now the player (while still touching the left side) touches the right side...the sprite should now move right. Now the player has one finger on the left and one on the right side, if he now lifts the touch off the right side the sprite should again move to the left.
This is what I have now:
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSSet *allTouches = [event allTouches];
UITouch * touch = [[allTouches allObjects] objectAtIndex:0];
CGPoint location = [touch locationInView: [touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
if (location.x < 240) {
[player walk:kkMoveLeft];
} else if (location.x > 240) {
[player walk:kkMoveRight];
}
//Swipe Detection Part 1
firstTouch = location;
}
-(void) ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
NSSet *allTouches = [event allTouches];
UITouch * touch = [[allTouches allObjects] objectAtIndex:0];
CGPoint location = [touch locationInView: [touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
//Swipe Detection Part 2
lastTouch = location;
float swipeLength = ccpDistance(firstTouch, lastTouch);
if (firstTouch.y < lastTouch.y && swipeLength > 60) {
[player jump:kkJumpUp];
} else if (firstTouch.y > lastTouch.y && swipeLength > 60){
[player jump:kkJumpDown];
}
[player endWalk];
}
I'd appreciate it if someone could tell me how to go about this. Thank you .
UPDATE MY SOLUTION:
//1. Enable multitouch in the appDelegate
[glView setMultipleTouchEnabled:YES];
//2. Create an Array to keep track of active touches
touchArray = [[NSMutableArray alloc] init];
//3. Touch Methods
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
for (UITouch *touch in touches) {
if (![touchArray containsObject:touch]) {
[touchArray addObject:touch];
CGPoint location = [touch locationInView:[touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
CCLOG(#"start: %f", location.x);
if (location.x < 240) {
[player walk:kkMoveLeft];
} else if (location.x > 240) {
[player walk:kkMoveRight];
}
}
}
}
-(void) ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
for (UITouch *touch in touches) {
[touchArray removeObject:touch];
CGPoint location = [touch locationInView:[touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
CCLOG(#"end: %f", location.x);
}
for (UITouch *touch in touchArray) {
CGPoint location = [touch locationInView:[touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
CCLOG(#"still: %f", location.x);
if (location.x < 240) {
[player walk:kkMoveLeft];
} else if (location.x > 240) {
[player walk:kkMoveRight];
}
}
if ([touchArray count] == 0) {
[player endWalk];
}
}
If I understand correctly your problem, what you should do is:
in ccTouchesEnded, instead of simply calling endWalk, check to see is any touch is still present (to do so, you could iterate over allTouches);
in the appropriate case (i.e., a touch is still activating the player), call startWalk.
if no touch is present, call endWalk.
The code would be similar to what you have in ccTouchesBegan, only you iterate (I am not sure what allTouches contains at index 0 in touchesEnded).
OLD ANSWER:
You are not saying anything about how you are handling touches right now. In any case, the way to go is defining ccTouches* methods (vs. ccTouch*), where * can be: Began, Moved, Ended.
-(void)tccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:[touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
...
}
-(void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
...
}
-(void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
...
}
Keep in mind that touchesBegan is fired at each new touch that is detected. So, if you want to know the status of all touches currently active, you have to use allTouches.
Have also a look at this post from iphonesdk which I found insightful as to the semantics of touches in those methods.

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
}

how to detect touch in a circle

I really assistance. Im a little confused.
i have a circle sprite, and this code
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
CGSize winSize =[[CCDirector sharedDirector] winSize];
UITouch* myTouch = [touches anyObject];
CGPoint location = [myTouch locationInView: [myTouch view]];
location = [[CCDirector sharedDirector]convertToGL:location];
CCSprite *circleSprite = (CCSprite*)[self getChildByTag:30];
CGRect correctColorSprite1 = [circleSprite boundingBox];
if (CGRectContainsPoint(correctColorSprite1, location)) {
NSLog(#"inside");
}
as i know there is a bounding box, when i touch slightly outside of the top circle it will still detect the touch.
i have read in some forums that i need to detect distance of the centre of the sprite and the touch point. But i really don't know how to write that code. My circle size is around 50 points.
I hope someone can help me out give me some snippets of a improved code to detect the touch only in the circle. Not with the bounding box. Your help is very great full.
Try this:
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
CGSize winSize =[[CCDirector sharedDirector] winSize];
UITouch* myTouch = [touches anyObject];
CGPoint location = [myTouch locationInView: [myTouch view]];
location = [[CCDirector sharedDirector]convertToGL:location];
CCSprite *circleSprite = (CCSprite*)[self getChildByTag:30];
//CGRect correctColorSprite1 = [circleSprite boundingBox];
CGRect correctColorSprite1 = CGRectMake(
circleSprite.position.x - (circleSprite.contentSize.width/2),
circleSprite.position.y - (circleSprite.contentSize.height/2),
circleSprite.contentSize.width,
circleSprite.contentSize.height);
//find the center of the bounding box
CGPoint center=ccp(correctColorSprite1.size.width/2,correctColorSprite1.size.height/2);
//now test against the distance of the touchpoint from the center
if (ccpDistance(center, location)<50)
{
NSLog(#"inside");
}
}

Cocos2D: SneakyJoystick + Touch Events, problem

im having some trouble using SneakyJoystick and ccTouchEnded stuff.
What is my goal, use the joystick to walk around and the touches to interact with the surrounding area.
I have two layers,ControlLayer (z:2) and GamePlayLayer (z:1)
Im Using TiledMap for my ground and map.
The Joystick by it self works fine, it is attached to the ControlLayer. I can walk, colide and stuff.
When i add the Touch events to the GamePlayLayer, the touch works, i can click on something on the "ground" and interact with it. BUT my joystick dosent work then, if i run using the touch the joystick just sit there not responsive.
Here is some of my code, if u guys need more, just ask.
Touch methods in the GameplayLayer
-(void) registerWithTouchDispatcher
{
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self
priority:0 swallowsTouches:YES];
}
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
return YES;
}
-(void) ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint touchLocation = [touch locationInView: [touch view]];
touchLocation = [[CCDirector sharedDirector] convertToGL: touchLocation];
touchLocation = [self convertToNodeSpace:touchLocation];
CGPoint tileCoord = [self tileCoordForPosition:touchLocation];
int tileGid = [meta tileGIDAt:tileCoord];
if (tileGid) {
NSDictionary *properties = [tileMap propertiesForGID:tileGid];
if (properties) {
NSString *collectable = [properties valueForKey:#"Collectable"];
if (collectable && [collectable compare:#"True"] == NSOrderedSame) {
[meta removeTileAt:tileCoord];
[foreground removeTileAt:tileCoord];
}
}
}
}
And how my scene is arranged:
#implementation SandBoxScene
-(id)init {
self = [super init];
if (self!=nil) {
//Control Layer
controlLayer = [GameControlLayer node];
[self addChild:controlLayer z:2 tag:2];
//GamePlayLayer
GameplayLayer *gameplayLayer = [GameplayLayer node];
[gameplayLayer connectControlsWithJoystick:[controlLayer leftJoyStick]
andJumpButton:[controlLayer jumpButton]
andAttackButton:[controlLayer attackButton]];
[self addChild:gameplayLayer z:1 tag:1];
}
return self;
}
#end
Thanks for the help!
The problem is that your code does not account for multiple touches. Using -(BOOL) ccTouchBegan:(UITouch *)touch.. or -(void) ccTouchEnded:(UITouch *)touch.. will only take one touch... instead you need to use ccTouchesEnded:.. your method should look something like this:
-(void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
//get your touch from the set of UITouches
UITouch *myTouch = [touches anyObject];
//the rest below is the same from your method
CGPoint touchLocation = [myTouch locationInView: [myTouch view]];
touchLocation = [[CCDirector sharedDirector] convertToGL: touchLocation];
touchLocation = [self convertToNodeSpace:touchLocation];
CGPoint tileCoord = [self tileCoordForPosition:touchLocation];
int tileGid = [meta tileGIDAt:tileCoord];
if (tileGid) {
NSDictionary *properties = [tileMap propertiesForGID:tileGid];
if (properties) {
NSString *collectable = [properties valueForKey:#"Collectable"];
if (collectable && [collectable compare:#"True"] == NSOrderedSame) {
[meta removeTileAt:tileCoord];
[foreground removeTileAt:tileCoord];
}
}
}
}
You also need to add [glView setMultipleTouchEnabled:YES]; to your appDelegate. I am not entirely sure that the method above works. This question deals with implementing multitouch with cocos2d. Hope this helps
Sorry thats was not the solution, i do want to handle just one touch, the problem was in the priority, i was giving priority 0 to my gameplayLayer, and swalloing every time, so i didnt give chance to the controlayer that had priority 1 to get the touch and act upon my joystick.
The solution that i found was changing the priority from 0 to 2 then, the (controlLayer) joystick would act and pass the touch to the priority 2, that was my gameplayLayer
but thanks anyway :)

Leaves falling animation and dragging along with finger

I am new to Cocos2D, could any one please tell me how we can do leaves falling from top and settled down at bottom of the iPad, when ever user tilt the iPad or touches the leaves, the leaves should respond accordingly.It should be similar to alice wonderland lite application page number 13 animation.
I am posting my code but However it doesn't behave exactly how I want. Whenever I touch near a sprite all the sprites move with incredible force.... they literally move out of the way of where I'm touching. Surely I'm not the only one who's implemented this before? Can anyone lead me in the right direction?
static float hw = 639.0/2.0, hh = 479.0/2.0;
static cpVect mouseToSpace(cpVect pos, CGSize size)
{
cpVect v = cpvsub(cpvmult(cpv(pos.y/size.height, pos.x/size.width), 2.0f), cpv(1.0f, 1.0f));
v = cpv(v.x*hw, v.y*hh);
// printf("%s\n", cpvstr(v));
return v;
}
#define GRABABLE_MASK_BIT (1<<31)
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *myTouch = [touches anyObject];
CGPoint location = [myTouch locationInView:[myTouch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
cpVect point = mouseToSpace([myTouch locationInView:[myTouch view]], [myTouch view].bounds.size);
mousePoint = point;
cpShape *shape = cpSpacePointQueryFirst(space, point, GRABABLE_MASK_BIT, 0);
if(shape) {
cpBody *body = shape->body;
mouseJoint = cpPivotJointNew2(mouseBody, body, cpvzero, cpBodyWorld2Local(body, point));
mouseJoint->maxForce = 50000.0f;
mouseJoint->biasCoef = 0.15f;
cpSpaceAddConstraint(space, mouseJoint);
}
}
- (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *myTouch = [touches anyObject];
CGPoint location = [myTouch locationInView:[myTouch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
mousePoint = mouseToSpace([myTouch locationInView:[myTouch view]], [myTouch view].bounds.size);
}
- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[self touchesCancelled:touches withEvent:event];
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
cpSpaceRemoveConstraint(space, mouseJoint);
cpConstraintFree(mouseJoint);
mouseJoint = nil;
}
Any one please guide me or post the code, i need it urgently.
Waiting for your valuable suggestions and any code.
Thanks in advance.
Shiva.
Cocos2d comes with projects to get you started. One of these is "Cocos2d with Box2D". This project starts you off with a scene that spawns a load of boxes at the top which fall to the bottom of the screen using the Box2D physics. If I remember correctly, it also shifts them around when you tilt.
Look at that project and adapt it to suit your needs.
This blog was my invaluable go-to resource when starting off with iPhone games development. I suggest you read it.