I am using box2d to simulate projectile motion from a cannon. I am calculating the angle and distance between the cannon barrel and the crosshair. The greater the distance between the crosshair and the barrel the larger the force. I am running this program on Xcode 8.2.1 and cocos2d. When I run my program on the iPad air I see inconsistent behavior. For example, as I increase the distance I expect the force to increase, and as a result I expect the distance the projectile travels to be longer, but I am not seeing this behavior. I decrease the distance between the barrel and the crosshair and the projectile flies farther. Below is the code I am using. I know that box2d is not deterministic and I have tried applyForce, applyLinerarImpulse, and setLinearVelocity, but I cannot get the behavior correct. I want the force to be less when the distance is less, and the force to be greater when the distance is greater. Below is my code. Any help is appreciated.
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if( self.boulderFired || gamePaused)
{
bulletStartingVelocity = b2Vec2(0,0);
bulletStartingPosition = b2Vec2(0,0);
return;
}
NSLog(@"began");
UITouch *myTouch = [touches anyObject];
CGPoint location = [myTouch locationInView:[myTouch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
float angleDegree, angleRadian;
int direction =1;
if(self.hud.isSoundOn)
[self.musicInterface playAudioStartTouch];
float distanceX = ( (location.x/PTM_RATIO) - (barrel.position.x/PTM_RATIO) );
float distanceY = ( (location.y/PTM_RATIO) - (barrel.position.y/PTM_RATIO) );
if (fabsf(distanceX)>18*(screenSize.height/designSizeHeight)*(screenSize.width/designSizeWidth) ||
fabsf(distanceY)>18*(screenSize.height/designSizeHeight)*(screenSize.width/designSizeWidth))
{
bulletStartingVelocity = b2Vec2(0,0);
bulletStartingPosition = b2Vec2(0,0);
return;
}
if(barrel.position.x<location.x)
{
angleRadian = atanf(distanceY/distanceX);
angleDegree = CC_RADIANS_TO_DEGREES(angleRadian);
}
else
{
angleRadian = atanf(distanceY/distanceX);
angleDegree =180 + CC_RADIANS_TO_DEGREES(angleRadian);
direction=-1;
}
slingPosition = ccp(barrel.position.x, (barrel.position.y+15/scaleFactorSpriteResolution));
barrel.rotation = (angleDegree*-1);
if (distanceX*distanceX+distanceY*distanceY>(17*(screenSize.height/designSizeHeight)*(screenSize.width/designSizeWidth)))
{
CGFloat angleTemp = atan2f(distanceY,distanceX);
CGPoint tempStandPos = [self scalePoint:ccp(35,135)];
CGPoint tempBarrelPos = [self scalePoint:ccp(65,165)];
location.x=tempBarrelPos.x+tempStandPos.y*cosf(angleTemp);
location.y=tempBarrelPos.y+tempStandPos.y*sinf(angleTemp);
}
crossHair.position = ccp(location.x, location.y);
distanceX = ( (crossHair.position.x/PTM_RATIO) - (slingPosition.x/PTM_RATIO) );
distanceY = ( (crossHair.position.y/PTM_RATIO) - (slingPosition.y/PTM_RATIO) );
float distance = sqrtf(distanceX*distanceX+distanceY*distanceY)*direction;
bulletStartingPosition = b2Vec2(slingPosition.x, slingPosition.y);
//bulletStartingVelocity = b2Vec2(cosf(angleRadian)*(distance/scaleFactorSpriteResolution),sinf(angleRadian)*(distance/scaleFactorSpriteResolution));
bulletStartingVelocity = b2Vec2(cosf(angleRadian)*(distance*10),sinf(angleRadian)*(distance*10));
if(sniperOn)
[self drawProjectilePath:b2Vec2(barrel.position.x, barrel.position.y) withVelocity:b2Vec2(cosf(angleRadian)*(distance*23.895),sinf(angleRadian)*(distance*23.895))];
// [self drawProjectilePath:bulletStartingPosition :b2Vec2(cosf(angleRadian)*distance*56.595,sinf(angleRadian)*distance*56.595)];
//[self drawProjectilePath:bulletStartingPosition :bulletStartingVelocity];
}
-(void) ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(@"move start");
if( self.boulderFired || gamePaused)
{
bulletStartingVelocity = b2Vec2(0,0);
bulletStartingPosition = b2Vec2(0,0);
return;
}
UITouch *myTouch = [[touches allObjects] objectAtIndex:0];
CGPoint location = [myTouch locationInView:[myTouch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
float angleDegree, angleRadian;
int direction=1;
float distanceX = ( (location.x/PTM_RATIO) - (barrel.position.x/PTM_RATIO) );
float distanceY = ( (location.y/PTM_RATIO) - (barrel.position.y/PTM_RATIO) );
if (fabsf(distanceX)>18*(screenSize.height/designSizeHeight)*(screenSize.width/designSizeWidth) ||
fabsf(distanceY)>18*(screenSize.height/designSizeHeight)*(screenSize.width/designSizeWidth))
{
bulletStartingVelocity = b2Vec2(0,0);
bulletStartingPosition = b2Vec2(0,0);
return;
}
if(barrel.position.x<location.x)
{
angleRadian = atanf(distanceY/distanceX);
angleDegree = CC_RADIANS_TO_DEGREES(angleRadian);
}
else
{
angleRadian = atanf(distanceY/distanceX);
angleDegree =180 + CC_RADIANS_TO_DEGREES(angleRadian);
direction=-1;
}
barrel.rotation = (angleDegree*-1);
if (distanceX*distanceX+distanceY*distanceY>(17*(screenSize.height/designSizeHeight)*(screenSize.width/designSizeWidth)))
{
CGFloat angleTemp = atan2f(distanceY,distanceX);
CGPoint tempStandPos = [self scalePoint:ccp(35,135)];
CGPoint tempBarrelPos = [self scalePoint:ccp(65,165)];
location.x=tempBarrelPos.x+tempStandPos.y*cosf(angleTemp);
location.y=tempBarrelPos.y+tempStandPos.y*sinf(angleTemp);
}
crossHair.position = ccp(location.x, location.y);
distanceX = ( (crossHair.position.x/PTM_RATIO) - (slingPosition.x/PTM_RATIO) );
distanceY = ( (crossHair.position.y/PTM_RATIO) - (slingPosition.y/PTM_RATIO) );
float distance = sqrtf(distanceX*distanceX+distanceY*distanceY)*direction;
bulletStartingPosition = b2Vec2(slingPosition.x, slingPosition.y);
//bulletStartingVelocity = b2Vec2(cosf(angleRadian)*(distance/scaleFactorSpriteResolution),sinf(angleRadian)*(distance/scaleFactorSpriteResolution));
bulletStartingVelocity = b2Vec2(cosf(angleRadian)*(distance*10),sinf(angleRadian)*(distance*10));
if(sniperOn)
[self drawProjectilePath:b2Vec2(barrel.position.x, barrel.position.y) withVelocity:b2Vec2(cosf(angleRadian)*(distance*23.895),sinf(angleRadian)*(distance*23.895))];
// [self drawProjectilePath:bulletStartingPosition :b2Vec2(cosf(angleRadian)*distance*56.595,sinf(angleRadian)*distance*56.595)];
//[self drawProjectilePath:bulletStartingPosition :bulletStartingVelocity];
}
- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
if(gamePaused )
{
bulletStartingVelocity = b2Vec2(0,0);
bulletStartingPosition = b2Vec2(0,0);
return;
}
NSLog(@"ended");
if(!self.boulderFired)
{
[self createBullets:slingPosition];
bullet->SetActive(true);
NSLog(@"ending starting position %f and %f", bulletStartingPosition.x, bulletStartingPosition.y);
NSLog(@"ending began starting velocity %f and %f", bulletStartingVelocity.x, bulletStartingVelocity.y);
//bullet->ApplyForce(bulletStartingVelocity, bulletStartingPosition);
bullet->SetLinearVelocity(bulletStartingVelocity);
self.boulderFired = true;
[self enableGestureSwipes:true];
bulletStartingVelocity = b2Vec2(0,0);
bulletStartingPosition = b2Vec2(0,0);
}
}