When I try to drag a shape it's stuck.

Official forum for the Chipmunk2D Physics Library.
Post Reply
Studder
Posts: 1
Joined: Sun Aug 14, 2011 3:58 pm
Contact:

When I try to drag a shape it's stuck.

Post by Studder »

Situation :

I got some obstacles falling from the sky my sprites collide with the obstacles. When the obstacles are done falling I unify the obstacles so it becomes one big rectangle. My sprites collide properly against it. But when a sprite comes near the obstacles and you try to drag the sprite away from it it sometimes gets stuck so you can't drag the sprite anymore.

Spawning obstacles like this :

Code: Select all

//*************************************************************************************************************
- (void) spawnObstacle:(id) sender :(int) redOrBlue
{	
	CCSprite *obstacle = [CCSprite spriteWithSpriteFrameName:[self getObstacleName]];
	
	CGPoint point;
	int i;
	
	if(redOrBlue)
	{
		for(i = 0 ; i < [redObstacles count] ; i++)
		{
			point = CGPointFromString([redObstacles objectAtIndex:i]);
			if(point.x != 0 && point.y != 0)
			{
				[redObstacles replaceObjectAtIndex:i withObject:NSStringFromCGPoint(ccp(0,0))];
				break;
			}
		}
	}
	else
	{
		for(i = 0 ; i < [blueObstacles count] ; i++)
		{
			point = CGPointFromString([blueObstacles objectAtIndex:i]);
			if(point.x != 0 && point.y != 0)
			{
				[blueObstacles replaceObjectAtIndex:i withObject:NSStringFromCGPoint(ccp(0,0))];
				break;
			}
		}
	}
	
	if(i >= [blueObstacles count])
	{
		return;	//no free spots left. Do not spawn
	}
	
	obstacle.position = point;
	obstacle.tag = i;
	CCScaleTo *scaleAction = [CCScaleTo actionWithDuration:1.5 scale:scaleObstacleDownTo];
	CCCallFuncN *callback = [CCCallFuncN actionWithTarget:self selector:@selector(addObstacle:)];
	CCSequence *seq = [CCSequence actions:scaleAction , callback, nil];
	[obstacle runAction:seq];
	[self addChild:obstacle z:-2];
}
//*************************************************************************************************************
- (NSString *) getObstacleName
{
	switch (SCENE)
	{
		case kMineScene:	return @"obstacleIceBlock.png";
		case kChinaScene:	return @"obstacleCrate.png";
		case kNinjaScene:	return @"obstacleIceBlock.png";
		case kMummyScene:	return @"obstacleCrate.png";
		default:
		case kEskimoScene:	return @"obstacleCrate.png";
	}
}
//*************************************************************************************************************
- (void) addObstacle:(CCSprite*) sender
{
    if(isPaused)
        return;
    
    //cpSpaceAddPostStepCallback(space, newObstacle, nil, sender);
    [obstacleBuffer addObject:sender];
    [soundEngine playEffect:@"obstacleDrop.mp3"];
}
//********************************************
- (void) compress
{
    cpSpaceAddPostStepCallback(space, unifyObstacles, nil, nil);
}

//********************************************
void newObstacle(cpSpace *space, void *obj, void *data)
{
    CCSprite *sender = (CCSprite *) data;
    
    float width = sender.contentSizeInPixels.width * scaleObstacleDownTo;
	float height = sender.contentSizeInPixels.height * scaleObstacleDownTo;
	float x = sender.positionInPixels.x;
	float y = sender.positionInPixels.y;
		
	if(sender.tag < base_width * base_height)	//if it's an level 0 obstacle
	{
        //		CCLOG(@"new base obstacle : %@" , NSStringFromCGRect(CGRectMake(x-width/2,y+height/2,width,height)));
		CGRect aux;
		CGRect new = CGRectMake(x-width/2,y+height/2,width,height);
		CGRect united;
		for(int i = 0 ; i < [allBaseObstacles count] ; i++)
		{
			aux = CGRectFromString([allBaseObstacles objectAtIndex:i]);
			united = CGRectUnion(aux, new);
			if(abs(united.size.width * united.size.height - new.size.height*new.size.width - aux.size.height *aux.size.width) < 5 *factor)
			{
                //				CCLOG(@"join");
				[allBaseObstacles removeObjectAtIndex:i];
				new = CGRectUnion(aux, new);
			}
		}
		[allBaseObstacles addObject:NSStringFromCGRect(new)];		
	}
}
//********************************************
void unifyObstacles(cpSpace *space, void *obj, void *data)
{        
    CGPoint centerBlue = ccp(centerOfTheBlueObstacles.x * factor,centerOfTheBlueObstacles.y*factor);
    CGPoint centerRed = ccp(centerOfTheRedObstacles.x * factor,centerOfTheRedObstacles.y*factor);
    
    float Width = ObstacleWidth * scaleObstacleDownTo * factor;
    float Height = ObstacleHeight * scaleObstacleDownTo * factor;
    
    cpVect verts[] = 
	{
		cpv(centerBlue.x - (Width * base_width/2) , centerBlue.y + (Height * base_height/2)),
		cpv(centerBlue.x + (Width * base_width/2) , centerBlue.y + (Height * base_height/2)),
		cpv(centerBlue.x + (Width * base_width/2) , centerBlue.y - (Height * base_height/2)),
		cpv(centerBlue.x - (Width * base_width/2) , centerBlue.y - (Height * base_height/2)),
	};
    
    cpPolyShape *newShape = cpPolyShapeInit(cpPolyShapeAlloc(),staticBody, 4, verts, cpv(0,0));
	newShape->shape.collision_type = kCollisionType_Obstacle;
	cpSpaceAddStaticShape(space, &newShape->shape);
    
    cpVect verts2[] = 
	{
		cpv(centerRed.x - (Width * base_width/2) , centerRed.y + (Height * base_height/2)),
		cpv(centerRed.x + (Width * base_width/2) , centerRed.y + (Height * base_height/2)),
		cpv(centerRed.x + (Width * base_width/2) , centerRed.y - (Height * base_height/2)),
		cpv(centerRed.x - (Width * base_width/2) , centerRed.y - (Height * base_height/2)),
	};
    
    cpPolyShape *newShape2 = cpPolyShapeInit(cpPolyShapeAlloc(),staticBody, 4, verts2, cpv(0,0));
	newShape2->shape.collision_type = kCollisionType_Obstacle;
	cpSpaceAddStaticShape(space, &newShape2->shape);
    
//    cpSpaceRehashStatic(space);
}

Here's how I drag the sprites.

Code: Select all

- (BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
//    NSLog(@"touch began");
	if(isPaused || !canBeDragged || LOST)
		return NO;
	
	//take the coordinates of the touch and transform them into the OpenGL system. 
	CGPoint location = [touch locationInView: [touch view]];
	location = [[CCDirector sharedDirector] convertToGL: location];
	
	CGRect frame = CGRectMake(self.position.x - self.contentSize.width/2, self.position.y - self.contentSize.height/2, 
                              self.contentSize.width, self.contentSize.height);
	
	if(!CGRectContainsPoint(frame, location))
		return NO;
	
    if(self.scale != 1)
        [self setScale:1];
    
    CCScaleBy *scale = [CCScaleBy actionWithDuration:0.2 scale:1.25];
    [self runAction:scale];
    
	location.x *= factor;
	location.y *= factor;
	
	if(BombShape)
	{
		offsetX = BombBody->p.x - location.x;
		offsetY = BombBody->p.y - location.y;
		
        velVal = BombBody->v;
		BombBody->v = cpvzero;
		BombShape->collision_type++;	//make it 'Dragged'. For example RedNinja++ is DraggedRedNinja
	}
    return YES;
}
//****************************************************************************************
- (void) ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event
{
	if(isPaused || !canBeDragged)
		return;

	CGPoint location = [touch locationInView: [touch view]];
	location = [[CCDirector sharedDirector] convertToGL: location];
	
	CGPoint prevLocation = [touch previousLocationInView: [touch view]];
	prevLocation = [[CCDirector sharedDirector] convertToGL: prevLocation];
	
	location.x *= factor; 
	location.y *= factor;
	
	prevLocation.x *= factor;
	prevLocation.y *= factor;
		
	if(BombBody)
	{
		//during the dragging, the bomb must not have velocity. Otherwise, it will "run" beneath your finger.
		//so we are constantly calculating the velocity and ,when you end the draging, assign that value to the velocity of the bomb.
		velocity = cpv((location.x - prevLocation.x) * 30 , (location.y - prevLocation.y)*30);  

		CGPoint newPosition = cpv(location.x + offsetX, location.y + offsetY); 
		//test per X
		
		canMoveOnX = CheckOnX(BombBody->p , newPosition,radius);
		canMoveOnY = CheckOnY(BombBody->p , newPosition,radius);

		if(canMoveOnX)
			BombBody->p.x = newPosition.x;
		
		if(canMoveOnY)
			BombBody->p.y = newPosition.y;
	}
}
Thanks.
Post Reply

Who is online

Users browsing this forum: No registered users and 14 guests