Accelerometer in Box2D - iphone

I am new in Box2D....
I have ball image in CCSprite. I want to move ball in whole screen using accelerometer...
tell me
How to use accelerometer in box2d??
Thanks...in advance

The standard cocos2d-box2d template file moves boxes using the accelerometer by applying gravity relative to the accelerometer value.
- (void)accelerometer:(UIAccelerometer*)accelerometer didAccelerate:(UIAcceleration*)acceleration
{
static float prevX=0, prevY=0;
//#define kFilterFactor 0.05f
#define kFilterFactor 1.0f // don't use filter. the code is here just as an example
float accelX = (float) acceleration.x * kFilterFactor + (1- kFilterFactor)*prevX;
float accelY = (float) acceleration.y * kFilterFactor + (1- kFilterFactor)*prevY;
prevX = accelX;
prevY = accelY;
// accelerometer values are in "Portrait" mode. Change them to Landscape left
// multiply the gravity by 10
b2Vec2 gravity( -accelY * 10, accelX * 10);
world->SetGravity( gravity );
}
You need to be more specific on what you want the ball to do dependent on how you move the phone. Your question is difficult to answer in its current form.

Get the accelerometer measurements and say Force = coefficient*measurements. The apply this force to your b2Body

Let your Ball Sprite having tag is 1.
Replace this code with your Accelerometer delegate,
I test it on device, its working.
and your ball will move with accelerometer.
-(void)accelerometer:(UIAccelerometer*)accelerometer didAccelerate:(UIAcceleration*)acceleration
{
#define kFilterFactor 0.75
accelerometer.updateInterval = 1.0f/60.0f;
static UIAccelerationValue rollingX = 0, rollingY = 0;
for (b2Body *b = world->GetBodyList(); b; b = b->GetNext())
{
if (b->GetUserData() != NULL)
{
CCSprite *sprite = (CCSprite*)b->GetUserData();
if (sprite.tag == 1) {
rollingX = (acceleration.x * kFilterFactor) + (rollingX * 0.25);
rollingY = (acceleration.y * kFilterFactor) + (rollingY * 0.25);
float accelX = rollingX;
float accelY = rollingY;
CGPoint moveNewPosition = sprite.position;
if (accelX > 0.1) {
moveNewPosition.y += 2;
} if (accelX < 0.1) {
moveNewPosition.y -= 2;
}
if (accelY > 0.1) {
moveNewPosition.x -= 2;
} if (accelY < -0.1) {
moveNewPosition.x += 2;
}
b->SetLinearVelocity(b2Vec2(2,2));
sprite.position = ccp(moveNewPosition.x , moveNewPosition.y );
sprite.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle());
}
}
}
}
I hope it'll work.

Related

how use Accelerometer in Landscape in iphone/ipad

i am working on game in which i want to move CCSprite in direction of accelerometer tilt.i have referred this tutorial http://www.raywenderlich.com/457/intro-to-box2d-with-cocos2d-tutorial-bouncing-balls but i am not clear with it. Please can any one help me.
Thanks in Advance.
Refer this solution. I used same for moving sprite from left to right in landscape game.: See answer here
Only change for landscape mode is use accelerometer y in place of x.
-(void) accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
if(self.isGamePaused || self.isGameOver)
return;
float deceleration = 1.0f, sensitivity = 15.0f, maxVelocity = 450;
if(sGame.IsIpad)
{
sensitivity = 14.0f;
maxVelocity = 850;
deceleration = 1.5f;
}
// adjust velocity based on current accelerometer acceleration
// vel.x = vel.x * deceleration + acceleration.x * sensitivity;
AppController *app = (AppController*)[UIApplication sharedApplication].delegate;
float velocity_x = self.gameActor.velocity.x ;
self.gameActor.accelVal = ABS(acceleration.y);
if(app.orient == UIInterfaceOrientationLandscapeLeft)
{
velocity_x = velocity_x * deceleration + acceleration.y * sensitivity;
}
else
{
velocity_x = velocity_x * deceleration + (-acceleration.y) * sensitivity;
}
//limit the maximum velocity of the player sprite, in both directions (positive & negative values)
velocity_x = fmaxf(fminf(velocity_x, maxVelocity), -maxVelocity);
self.gameActor.velocity = ccp(velocity_x, self.gameActor.velocity.y);
}

Rotate sprite image according to user touch location?

I m start learning game development. As a beginner i create one demo game in which one cannon hit bullets to the enemies (coming toward cannon from different direction).
Now i stuck on cannon sprite image rotation anywhere user touch on the screen or enemies. How i do that, My initial code as following,
void HelloWorld:: ccTouchesBegan(CCSet *touches, CCEvent * event)
{
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
CCTouch* touch = (CCTouch*)( touches->anyObject() );
CCPoint location = touch->locationInView(touch->view());
location = CCDirector::sharedDirector()->convertToGL(location);
//Rotate cannon direction toward touch point
CCPoint diffPoint = ccpSub(_cannonImage->getPosition(), location);
float angleRadians = atanf((float)diffPoint.y/(float)diffPoint.x);
float angleOffset = CC_DEGREES_TO_RADIANS(180);
if(diffPoint.x < 0){
angleRadians += angleOffset;
}else{
angleRadians -= angleOffset;
}
CCLog("angle to be rotate = %f", angleRadians);
_cannonImage->runAction(CCRotateBy::actionWithDuration(0.1, angleRadians));
}
The code is written in cocos2d-x . I also accepting answer by someone who written in plain cocos2d.
Thanks
iHungry
The perfect answer as follows,
float HelloWorld::changingAngleAccordingToCoordinateSystem(CCPoint imageCenter, CCPoint touchLocation, float calculatedAngle){
//Consideration :- all Angles is in Degree
if((calculatedAngle >= 0 && calculatedAngle <= 90) || (calculatedAngle >= 90 && calculatedAngle <= 180)){
//Ist quardant
calculatedAngle = calculatedAngle;
}
else if(calculatedAngle < 0 && calculatedAngle >= -90){
//IInd quardant
calculatedAngle = 270 + (90 + calculatedAngle);
}
else if(calculatedAngle < -90 && calculatedAngle >= -180){
calculatedAngle = 180 + (180 + calculatedAngle);
}
return calculatedAngle;
}
//Rotate cannon direction toward touch point
float diff_X = touchLocation.x - myImage->getPosition().x;
float diff_Y = touchLocation.y - myImage->getPosition().y;
CCPoint diffPoint = CCPoint(diff_X, diff_Y);
float angleRadians = atan2f(diffPoint.y,diffPoint.x);
angleRadians = CC_RADIANS_TO_DEGREES(angleRadians);
angleRadians = HelloWorld::changingAngleAccordingToCoordinateSystem(myImage->getPosition(), touchLocation, angleRadians);
myImage->setRotation(-angleRadians);
i used this code to rotate my sprite. i Was moving the sprite according to my accelerometer reading.
float angleRadians =-accelX;
float angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians);
objGlider->sprite_Glider.rotation = cocosAngle;
Check it. The reason of slow may be that you may be using CClog or NSLog in the code.
Here goes the complete code.
if(!boolPlayerDied)
{
static float prevX=0, prevY=0;
#define kFilterFactor 1.0f// don't use filter. the code is here just as an example
float accelX = (float) acceleration.x * kFilterFactor + (1- kFilterFactor)*prevX;
float accelY = (float) acceleration.y * kFilterFactor + (1- kFilterFactor)*prevY;
prevX = accelX;
prevY = accelY;
accelX = accelX-0.5;// Angle check fot tgfor the player to play
float angleRadians =-accelX;
float angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians);
if(accelX>0)
{
cocosAngle = 1.1 * angleDegrees;
}
else
{
if(accelX<-0.5)
accelX=-0.5;
cocosAngle = 1.1 * angleDegrees;
}
objGlider->sprite_Glider.rotation = cocosAngle;
}
objGlider is the object of the class which creates glider sprite and sprite_Glider is the sprite used in glider class.
you can use rotation property with your sprite to be rotated. In cocos2Dx it might be setRotation.
First of all, replace
float angleRadians = atanf((float)diffPoint.y/(float)diffPoint.x);
float angleOffset = CC_DEGREES_TO_RADIANS(180);
if(diffPoint.x < 0){
angleRadians += angleOffset;
}else{
angleRadians -= angleOffset;
}
by
float angleRadians = atan2f(diffPoint.y, diffPoint.x);
Then it would be better to set rotation immediately (without actions) to process multiple frequent touches.
_cannonImage->setRotation(angleRadians);
Maybe you will need to adjust rotation like setRotation(-angleRadians) or setRotation(angleRadians+90) - it depends on your coordinate system.

Creating a array of Box2D body

i have a ball which is a box2d body and moves around the screen... i want to create multiple balls of similar type and they should also collide among them self..
the code i am using now is
ballcount = [[levelData objectForKey:#"ballcount"]intValue] ;
ballarray = [[NSMutableArray arrayWithCapacity:ballcount]init] ;
for (int j=0; j<ballcount; j++) {
ball = [CCSprite spriteWithFile:#"ball.png"];
[ballarray insertObject:ball atIndex:j];
[self createBallBoundingBox:(CCSprite *)[ballarray objectAtIndex:j]];
[[ballarray objectAtIndex:j]setPosition:ccp(arc4random() % 480 , arc4random() % 320)];
[self addChild:[ballarray objectAtIndex:j]];
}
There is only one sprite appearing on the screen when i run it ? any suggestions what am i doing wrong ... it works perfectly when only one ball is there
Thanks
ok i have got the above code to work but now i am having a problem with the movement in the tick method .. the box2d shapes are moving but the CCSprite shapes are not getting attached to the box2d bodies here is my code
world->Step(dt, 10, 10);
for(b2Body *b = world->GetBodyList(); b; b=b->GetNext()) {
if (b->GetUserData() != NULL) {
CCSprite *sprite = (CCSprite *)b->GetUserData();
if ([sprite isKindOfClass:[Ball class]])
{
b2Vec2 Vel = b->GetLinearVelocity();
float32 angle = atan2(Vel.y, Vel.x);
angle += -M_PI/2;
b->SetTransform(b->GetPosition(),angle);
sprite.position = ccp(b->GetPosition().x * PTM_RATIO,
b->GetPosition().y * PTM_RATIO);
sprite.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle());
}
Ok guys here is my createBoundingBox definition
-(void)createBallBoundingBox:(Ball *)ballSprite{
b2BodyDef BallBodyDef;
ballBodyDef.type = b2_dynamicBody;
ballBodyDef.position.Set(ballSprite.position.x/PTM_RATIO, ballSprite.position.y/PTM_RATIO);
ballBodyDef.userData = ballSprite;
ballBody = world->CreateBody(&ballBodyDef);
/// test circle shape on ballbody
b2CircleShape BallCircleShape;
BallCircleShape.m_radius = 10/PTM_RATIO;
// Create shape
/*
b2PolygonShape ballShape;
int num = 7;
b2Vec2 verts[] = {
b2Vec2(0.0f / PTM_RATIO, 19.2f / PTM_RATIO),
b2Vec2(-10.7f / PTM_RATIO, 15.2f / PTM_RATIO),
b2Vec2(-6.7f / PTM_RATIO, -3.2f / PTM_RATIO),
b2Vec2(-1.7f / PTM_RATIO, -18.0f / PTM_RATIO),
b2Vec2(7.7f / PTM_RATIO, 0.5f / PTM_RATIO),
b2Vec2(10.5f / PTM_RATIO, 14.7f / PTM_RATIO),
b2Vec2(0.2f / PTM_RATIO, 19.0f / PTM_RATIO)
};
ballShape.Set(verts,num);
*/
// Create shape definition and add to body
b2FixtureDef ballFixtureDef;
ballFixtureDef.shape = &ballCircleShape;
ballFixtureDef.density = 1.0f;
ballFixtureDef.friction = 0.0f;
ballFixtureDef.restitution = 1.0f;
ballFixture = ballBody->CreateFixture(&ballFixtureDef);
b2Vec2 direction(5,2);
direction.Normalize();
float force = 1.0f;
b2Vec2 position = ballBody->GetPosition();
//Apply linear velocity
ballBody->ApplyLinearImpulse(force*direction,ballBody->GetPosition());
b2Vec2 Vel = ballBody->GetLinearVelocity();
float32 angle = atan2(Vel.y, Vel.x);
angle += -M_PI/2;
ballBody->SetTransform(ballBody->GetPosition(),angle);
}
any ideas ? Let me know
Thanks a lot guys
inside your method
[self createBallBoundingBox:(CCSprite *)[ballarray objectAtIndex:j]];
//OR NOW
[self createMiceBoundingBox:tempmice];
did you forgot to attach the Ball as UserData to your b2Body
- (void) createMiceBoundingBox: (Ball*) ball
{
//...
b2Body body = ...
body.SetUserData(ball);
//..
}
if not show us the code of the method
EDIT: if you use Mice instead of Ball make sure you update tick method to
if ([sprite isKindOfClass:[Mice class]])

Trouble tying a CCSprite deceleration to the ccTime dt

I've got a subclass of CCSprite that knows how to move itself based on two float properties, velX and velY. I call the subclass's - (void)update:(ccTime)dt method from the method of the same name in my game layer.
I use dt to scale how much I move the player and it works great. I'd like to use dt to scale a deceleration factor to make how the player slows down consistent regardless of how often it's updated.
But it just makes my CCSprite not even show up.
Here's the CCSprite class...
#import "Player.h"
#define kDeceleration 0.95
#implementation Player
#synthesize velX, velY;
# pragma mark
+ (id)player
{
Player *player = nil;
if ((player = [[[super alloc] initWithFile:#"rocket.png"] autorelease])) {
player.velX = 0.0;
player.velY = 0.0;
}
return player;
}
- (void)update:(ccTime)dt
{
CGSize winSize = [[CCDirector sharedDirector] winSize];
// move
self.position = ccp(self.position.x + self.velX * dt, self.position.y + self.velY * dt);
if (self.position.x < -self.contentSize.width/2) self.position = ccp(winSize.width + self.contentSize.width/2, self.position.y);
if (self.position.x > winSize.width + self.contentSize.width/2) self.position = ccp(-self.contentSize.width/2, self.position.y);
if (self.position.y < -self.contentSize.width/2) self.position = ccp(self.position.x, winSize.height + self.contentSize.width/2);
if (self.position.y > winSize.height + self.contentSize.width/2) self.position = ccp(self.position.x, -self.contentSize.width/2);
// decelerate
self.velX *= kDeceleration * 0.0165 / dt; // works if the line is: self.velX *= kDeceleration;
if (fabs(self.velX) < 1.0) self.velX = 0.0;
self.velY *= kDeceleration * 0.0165 / dt; // works if the line is: self.velY *= kDeceleration;
if (fabs(self.velY) < 1.0) self.velY = 0.0;
}
- (void)draw
{
[super draw];
glLineWidth(1);
ccDrawCircle(ccp(self.contentSize.width/2, self.contentSize.height/2), 3*self.contentSize.width/4, CC_DEGREES_TO_RADIANS(360), 60, NO);
}
#end
The problem is in the // decelerate section. If I leave out the * 0.0165 / dt part of the two lines that decelerate the player, it works, but it's way faster on the phone than the simulator due to framerate differences. This should scale it, but it just screws it up.
I've tried all kinds of NSLogging and if I use dt at all, I get nan for the value of my velX and velY properties.
Could it have something to do with using the method name -update?
Try using this formula instead:
float decelerator = pow(kDeceleration, 60 * dt);
self.velX *= decelerator;
self.velY *= decelerator;
The logic behind the math:
Suppose the framerate on simulator is at 30fps compared to the normal 60fps on device. Thus, for every frame on simulator, the device already shows 2 frames. Thus every call on the update on simulator should give the same result for 2 calls on device. After two calls on device, self.velX has been multiplied by kDeceleration two times, meaning the new value is equal to self.velX * kDeceleration * kDeceleration. By same logic, if the framerate on simulator is 1/3 of that on device, the new value is self.velX * kDeceleration * kDeceleration * kDeceleration. Thus, we can generalize it as self.velX * pow(kDeceleration, n) where n is the number of times the update method to be called to catch up with framerate of 60fps, which is 60 * dt.

cocos2d fruit ninja parabola math

i am making a game similar to fruit ninja. birds flying down the water and then up (just like fruits up side down)
but some of the birds fly too far and the others too near.
can someone check my code? vy should quite close to each other.(vx is not a problem)
static float tuna = 10.0f;
-(void) reset
{
float vy = 0.0f;
float vx = 0.0f;
int sign = 1;
if (CCRANDOM_0_1() >= 0.5) {
sign = -1;
}
float hurry = 0.0f;
if (CCRANDOM_0_1() <= 0.1) {
hurry = 1.0f;
}
switch (birdType) {
case BirdType1:
vx = 1.0f * sign + (CCRANDOM_0_1() - 0.5f) * 0.08f;
vy = -6.5f;
break;
case BirdType2:
vx = 1.5f * sign + (CCRANDOM_0_1() - 0.5f) * 0.08f;
vy = -6.2f + (CCRANDOM_0_1() - 0.5f) * 0.1f;
break;
case BirdType3:
vx = 1.0f * sign + (CCRANDOM_0_1() - 0.5f) * 0.1f;
vy = -5.8f - hurry;
break;
default:
[NSException exceptionWithName:#"BirdMoveComponent exception" reason:#"unhandled bird type" userInfo:nil];
break;
}
velocity = CGPointMake(vx * 5, vy * 5);
if ((int)([[GameManager sharedManager] score] / 100) >= prevLevel) {
if (tuna <= 12.0f) {
tuna += 0.01f;
}
prevLevel = (int)[[GameManager sharedManager] score] / 100;
}
}
-(void) update:(ccTime) delta
{
if (self.parent.visible) {
NSAssert([self.parent isKindOfClass:[BirdEntity class]], #"node is not an entity");
BirdEntity* bird = (BirdEntity*) self.parent;
bird.position = ccpAdd(bird.position, ccpMult(velocity, delta * tuna));
velocity = ccpAdd(velocity, ccpMult(acceleration, delta * tuna));
acceleration = ccp(0, 0.3f);
float birdHeight = CGRectGetHeight([bird boundingBox]);
//20 is the bottom trap
if (bird.position.y <= (birdHeight / 2) + 20) {
[bird dieAccidently];
}
if (CGRectIntersectsRect([GameScene screenRect], [bird boundingBox]) == NO)
{
bird.visible = NO;
[bird stopAllActions];
[bird unscheduleAllSelectors];
[bird unscheduleUpdate];
[self reset];
}
}
}
thoght your question not programmatical but physical (mechanical).
position of object can be calculated from the system of equation:
x = Vx * t + x0
y = (-g*t*t)/2 + Vy * t + y0
, where g - Gravitational acceleration, V - initial speed, Vx and Vy - its projections on axes X and Y, respectively.
Question is what's the highest point, i.e. we need to found MAX(y(t)).
derivative: y'(t) = -g*t + Vy.
y'(t) should equals zero, -g*t + Vy = 0; t = Vy/g; MAX(y) = y(Vy/g) = Vy*Vy/2g.
MAX(y) = Vy*Vy/2g + y0 // ballistic trajectory
MIN(y) = y0 - Vy*Vy/2g // your case
End you should calculate velocity accroding to this, if you want your bird Y to be in certain range.
Addition:
btw is there a sample cocos2d code for
parabola?
Here is my working code.
- (void) update: (ccTime)dt
{
t += dt*20;
...
[self getVertices];
}
- (void) getVertices
{
//for every index: {
...
//getting initial position (x0, y0)
...
vertices[index] = ccpAdd(vertices[index], ccpMult(velocity[index/3], t * screenFactor)); //+velocity*t
vertices[index] = ccpAdd(vertices[index], ccpMult(gravity, (t*t/2) * screenFactor)); //+acceleration*t^2 /2
//}
}
1) As you can see, there's no need to calculate Velocity every time: use initial speed.
2) Vertices is CGPoint array of current Sprite positions.
3) t (current time), vertices, gravity, velocity are instance variables of common class.