please help touch specific sprite in array, which are dropping code - cocos2d-iphone

I try to detect specific sprite with position and while i am using 'if' statement, there was failed built.
here is my codes
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch* myTouch = [touches anyObject];
CGPoint location = [myTouch locationInView: [myTouch view]];
location = [[CCDirector sharedDirector]convertToGL:location];
int numGrades = [grades count];
for (int i = 0; i < numGrades; i++)
{
// Put each spider at its designated position outside the screen
CCSprite* grade = [grades objectAtIndex:i];
int numGrades = [grades count];
for (int i = 0; i < numGrades; i++)
{
CCSprite* grade = [grades objectAtIndex:i];
// the if statement seems doesn't work...
What i try to do is if i touch specific sprite.. it should stop moving, but it does not.
if ((grade.position.x==location.x) && (grade.position.y==location.y))
{
[grade stopAllAction];
}
}
}
}
please correct 'if' statement...

It appears that you are simply trying to detect a touch on a sprite. Your current intersection test requires that your touch coordinates match exactly that of your sprite's center point, which is practically impossible..
Instead, you should try to test the touch coordinates against the bounding box of the sprite.
if (CGRectContainsPoint(grade.boundingBox, location))
{
[grade stopAllActions];
}
Do note too that it is stopAllActions with an "s"..
Hope this helps.

Related

Camera following the touched body

I need to have the Cocos2d camera follow a sprite (attached to a Box2D body) that the user is touching on the screen. As the user is dragging the player around, I need it to be able to go to other parts of the world. This has to be through touch, and not automatic scrolling.
I tried several approaches based on tutorials but nothing seem to address this issue. For example the solution offered here Move CCCamera with the ccTouchesMoved method? (cocos2d,iphone) by #Michael Fredrickson has the entire layer move, but when it moves, the sprites / bodies on the screen have unmatched coordinations and when I test to see if they're touched, the if(fixture->TestPoint(locationWorld)) fails.
I also looked at the tutorials here http://www.learn-cocos2d.com/2012/12/ways-scrolling-cocos2d-explained/ but this also isn't what I'm looking for.
Any help would be greatly appreciated.
EDIT:
I'm accepting Liolik's answer below because it put me on the right track. The last piece of the puzzle, though, is to make the value received from the getPoint method an instance variable, and deduce it from locationWorld which I'm doing the TestPoint against. Like this:
UITouch *myTouch = [touches anyObject];
CGPoint location = [myTouch locationInView:[myTouch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
b2Vec2 locationWorld = b2Vec2(location.x/PTM_RATIO, location.y/PTM_RATIO);
b2Vec2 diff = b2Vec2(difference.x, difference.y);
for (b2Body* b = _world->GetBodyList(); b; b = b->GetNext()) {
b2Fixture* f = b->GetFixtureList();
while(f != NULL) {
if(f->TestPoint(locationWorld-diff)) {
b2MouseJointDef def;
def.bodyA = _groundBody;
def.bodyB = b;
def.target = locationWorld-diff;
def.maxForce = 9999999.0f * b->GetMass();
_mouseJoint = (b2MouseJoint*)_world->CreateJoint(&def);
b->SetAwake(true);
}
f = f->GetNext();
}
}
in update function :
CGPoint direction = [self getPoint:myBody->GetPosition()];
[self setPosition:direction];
- (CGPoint)getPoint:(b2Vec2)vec
{
CGSize screen = [[CCDirector sharedDirector] winSize];
float x = vec.x * PTM_RATIO;
float y = vec.y * PTM_RATIO;
x = MAX(x, screen.width/2);
y = MAX(y, screen.height/2);
float _x = area.width - (screen.width/2);
float _y = area.height - (screen.height/2);
x = MIN(x, _x);
y = MIN(y, _y);
CGPoint goodPoint = ccp(x,y);
CGPoint centerOfScreen = ccp(screen.width/2, screen.height/2);
CGPoint difference = ccpSub(centerOfScreen, goodPoint);
return difference;
}
So if i understand correctly, when the sprite is inside of the middle of the screen, the background is stationary and the sprite follows your finger, but when you scroll toward the edge, the camera starts to pan?
I had something roughly similar in my game Star Digger where there's a ship in the middle of the screen on its own layer that has to fly around the world, and had the same problem when the ship fired bullets into the main world layer.
heres what I did:
float thresholdMinX = winSize*1/3;
float thresholdMaxX = winSize*2/3;
if(touch.x > thresholdMaxX) //scrolling right
{
self.x += touch.x - thresholdMaxX;
}
else if(touchX < thresholdMinX)
{
self.x += thresholdMinX - touchX;
}
else
{
sprite.position = touch;
}
CGPoint spritePointInWorld = ccp(sprite.x - self.x, sprite.y - self.y);
then every time you calculate collisions, you need to recompute the sprites "actual" position in the world, which is its screen position minus the worlds offset, instead of the sprites screen position.

Animations are not working properly(Cocos2d)

My problem is that animation are not working properly during movements of sprite.
Below is the code which i'm using
- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
[selSprite resumeSchedulerAndActions];
CGPoint touchLocation = [self convertTouchToNodeSpace:touch];
[self selectSpriteForTouch:touchLocation];
return TRUE;
}
- (void)selectSpriteForTouch:(CGPoint)touchLocation
{
CCSprite * newSprite = nil;
for (CCSprite *sprite in movableSprite) {
if (CGRectContainsPoint(sprite.boundingBox, touchLocation)) {
newSprite = sprite;
break;
}
}
if (newSprite != selSprite) {
[selSprite stopAllActions];
selSprite = newSprite;
_MoveableSpritetouch = TRUE;
}
if(_MoveableSpritetouch==TRUE)
{
movement=0;
CGRect selRect=CGRectMake((SpriteX)-20.0,(SpriteY)-20.0,40.0,40.0);
if(CGRectContainsPoint(selRect, touchLocation))
{
[selSprite stopAllActions];
}
if((selSprite==MarshallCar)&& (!(CGRectContainsPoint(selRect, touchLocation))))
{
movement=1;
[self reorderChild:selSprite z:5];
NSMutableArray *MarshallCarWalkAnimFrames = [NSMutableArray array];
for(int i = MarshallCarTouchStartFrameIndex; i <= MarshallCarTouchEndFrameIndex; ++i) {
[MarshallCarWalkAnimFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:#"mcar_move_%d.png", i]]];
}
MarshallCarWalkAnim = [CCAnimation animationWithFrames:MarshallCarWalkAnimFrames delay:MarshallCarTouchFrameDelay];
walkMarshallCar = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:MarshallCarWalkAnim restoreOriginalFrame:NO]];
[selSprite runAction:walkMarshallCar];
}
}
}
- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event {
if(gameState == TRUE){
CGPoint point = [touch locationInView:[touch view]];
point = [[CCDirector sharedDirector] convertToGL:point];
if (moveDifference.x>0)
{
selSprite.flipX = YES;
}
else {
selSprite.flipX = NO;
}
[selSprite setPosition:point];
}
}
-(void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event
{
movement=0;
if(selSprite==MarshallCar)
{
[selSprite setDisplayFrame:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:#"mcar_idle.png"]];
}
[selSprite pauseSchedulerAndActions];
}
The animation frames for movement are not playing every time during movements sometimes it plays or sometimes not. It plays properly when you touch and move your sprite for the first time but if touch another sprite and then again move the previous sprite the animations for movement won't play.
Is anyone having any idea why this is happening?
Please tell me the proper code for removing this bug.
Thanks!!!
I believe your problem is the if/else if construct:
if (_MoveableSpritetouch==TRUE)
{
CGRect selRect = CGRectMake(SpriteX - 20, SpriteY - 20, 40, 40);
if(CGRectContainsPoint(selRect, touchLocation))
{
[selSprite stopAllActions];
}
else if(...)
{
...
[selSprite runAction:walkMarshallCar];
}
}
If you don't see it right away: if the touch location is inside the selRect, you call stopAllActions on the selected (new) sprite and do nothing else. Only if the touch location is not within that rectangle you'll run the animation action.
I think the "in rectangle" check is superfluous since you've already called stopAllActions anyway a few lines above.
Allow me a few general remarks about your code:
The method "selectSpriteForTouch" tells me that you're selecting a new sprite. The function does that. But it does not advertise playing an animation. You might want to refactor this out to a seperate "playAnimationOnSelectedSprite" method.
You wrote 20.0 and 40.0 several times. This means you're actually passing a double (8 bytes floating point data type) to a CGPoint which takes floats (4 bytes floating point). Strictly speaking use either 20.0f with the suffixed "f" to denote it as a floating point data type, or use integers since you don't use the floating point part.
Why you put (SpriteX) in brackets is not clear to me, if you want to enhance readability you'll achieve more by adding spaces after commas and operands.
In Objective-C, use YES and NO macros instead of TRUE and FALSE.
The bool variable _MoveableSpritetouch seems superfluous, unless needed someplace else. In any case you should move the following if(_MoveableSpritetouch==TRUE) block to where you set the _MoveableSpritetouch variable to TRUE because it just makes your code harder to read by setting a variable, leaving the code block you were in ( if(selSprite != newSprite) ) just to jump into another block of code ( if(_MoveableSpritetouch==TRUE) ) that you already know you're going to run anyway.
if((selSprite==MarshallCar)&& (!(CGRectContainsPoint(selRect, touchLocation))))
{
movement=1;
[self reorderChild:selSprite z:5];
NSMutableArray *MarshallCarWalkAnimFrames = [NSMutableArray array];
for(int i = MarshallCarTouchStartFrameIndex; i <= MarshallCarTouchEndFrameIndex; ++i) {
[MarshallCarWalkAnimFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:#"mcar_move_%d.png", i]]];
}
MarshallCarWalkAnim = [CCAnimation animationWithFrames:MarshallCarWalkAnimFrames delay:MarshallCarTouchFrameDelay];
walkMarshallCar = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:MarshallCarWalkAnim restoreOriginalFrame:NO]];
[selSprite runAction:walkMarshallCar];
}
I have added [selSprite stopAllActions];
and it started working correctly because in the touch ended method i was pausing the actions
but not resuming them so when i touch the sprite for the second time it was not playing animation because the action was paused.

Jumping and moving at the same time...Help!

As the title says, I'm stuck with jumping and moving at the same time,
this is how I'm moving along the 'x' axis
-(void)collisionCheckingAndMovementRight:(ccTime)dt{
CGPoint tileCoord = [self tileCoordForPosition:player.position];
int tileGid = [csLayer tileGIDAt:tileCoord]; //csLayer is the layer which was created in tiled for the collision
if (tileGid) {
NSDictionary *properties = [levelOne propertiesForGID:tileGid];
if (properties) {
NSString *collision = [properties valueForKey:#"Collidable"];
if (collision && [collision compare:#"True"] == NSOrderedSame){
//[[SimpleAudioEngine sharedEngine] playEffect:#"hit.caf"];
return;
}
}
}
player.position = ccp(player.position.x +100*dt, player.position.y);
i want to try and do a jump that goes with the movement i have at the moment for the x axis.... help is greatly appreciated
You want to look at the actions examples in cocos2d. the CCBezierTo action comes to mind for a good way of animating a jump.

dragging sprite

I have a problem dragging a sprite i've got the sprite moving left and right while keeping the y position the same, but i can't get the sprite to move up or down when the x position stays the same.
Also in the cctouchended the sprite moves so that it is in a fixed position, when all touches have ended
I am trying to make a game like slidieo/skozzle. Could do with some help
c1 is the column that is being moved, r1 is the row that is being moved,
[pos objectAtIndex:0] is the sprite's:red1 position and checks if the sprite is in c1 as every time you go into the game the sprite has a new random position and t1 is the cgrect of the sprite so that you must be clicking on the spirte because if you don't when you click above the sprite and try moving the sprite jumps to the touchlocation.
here is my code:
CGPoint touchLocation = [touch locationInView:[touch view]];
CGPoint prevLocation = [touch previousLocationInView:[touch view]];
touchLocation = [[CCDirector sharedDirector] convertToGL:touchLocation];
prevLocation = [[CCDirector sharedDirector] convertToGL:prevLocation];
if (CGRectContainsPoint(c1,touchLocation)) {
if (CGRectContainsPoint(c1,[[pos objectAtIndex:0]CGPointValue])) {
if (CGRectContainsPoint(t1,touchLocation)) {
if (touchLocation.y>0||touchLocation.y<0) {
touchLocation.x = red1.position.x;
[red1 setPosition:ccp(touchLocation.x,touchLocation.y)];
}
}
}
}
if (touchLocation.x>0||touchLocation.x<0) {
touchLocation.y=red1.position.y;
[red1 setPosition:ccp(touchLocation.x,touchLocation.y)];
}
}
thanks
i've solved the problem :) just had to remove a few if statements and edit a few, now i've got it moving up and down and when the sprite stops it can move left and right

Dragging a particularly large sprite up and down like scroll effect in COCOS2D

I am really stuck on this. My application is in landscape view and on one screen i wanted my instructions image to be scrollable. I have added this image as a sprite. First i tried to get scroll effect available from other sites, but soon i saw that scrolling was being done for the complete screen and not the sprite image. Then i resorted to implement the scrolling effect by dragging the sprite only in y axis (up and down). Unfortunately i am messing things somewhere, due to which only a portion of the sprite (shown on the screen only with the height 320pixels) is being dragged and the rest of the sprite is not being shown. The code is as follows
in the init layer function i have
//Add the instructions image
instructionsImage = [Sprite spriteWithFile:#"bkg_InstructionScroll.png"];
instructionsImage.anchorPoint = CGPointZero;
[self addChild:instructionsImage z:5];
instructionsImage.position = ccp(40,-580);
oldPoint = CGPointMake(0,0);
self.isTouchEnabled = YES;
//The touch functions are as follows
- (BOOL)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
// Move me!
if(touch && instructionsImage != nil) {
CGPoint location = [touch locationInView: [touch view]];
CGPoint convertedPoint = [[Director sharedDirector] convertCoordinate:location];
CGPoint newPoint = CGPointMake(40, (instructionsImage.anchorPoint.y+ (convertedPoint.y - oldPoint.y)));
instructionsImage.position = newPoint;
return kEventHandled;
}
return kEventIgnored;
}
//The other function
- (BOOL)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
// Move me!
if(touch && instructionsImage != nil) {
CGPoint location = [touch locationInView: [touch view]];
CGPoint convertedPoint = [[Director sharedDirector] convertCoordinate:location];
oldPoint = convertedPoint;
return kEventHandled;
}
return kEventIgnored;
}
Your approach is generally correct.
The code did not format properly, and you were not clear on exactly what the symptom is of the problem...
But it appears as if your math in the ccTouchesMoved is wrong. The anchor point is not what you care about there, as that's just a ratio within the image where the position and rotation anchor occurs. Set that, like you do, to whatever makes sense in the constructor but after that you don't need to reference it.
Try just adding your movement to the sprite:
deltaY = convertedPoint.y - oldPoint.y;
Now you know how many pixels your finger has moved up and down.
Reset your oldPoint data for next time:
oldPoint.y = convertedPoint.y;
Now apply this delta to your sprite:
instrucitonsImage.position = ccp(instructionsImage.position.y,instructionsImage.position.y + delta);
Should do it.