Andengine Box2D physics body is not rotating when increase weight - android

Andengine Box2D physics body is not rotating when increase weight otherwise its perfectly rotating.I am making a game in which the player can throw the bomb, when the player throws the bomb with bombsBody's natural weight its rotating perfectly but when i increase the weight of bomb the bomb does not rotate.i m stuck here..plz help.
Thank you.
if (bomb)
{
mScene.detachChild(target);
target = null;
bombFire = new Sprite(mBall2.getX()+mBall2.getWidth()/2,mBall2.getY(),bombFireRegion);
mScene.attachChild(bombFire);
bombBody = PhysicsFactory.createCircleBody(mPhysicsWorld, bombFire,BodyType.DynamicBody, bombFixDef);
bombBody.setMassData(bombMass);
mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(bombFire, bombBody, true, true));
Vector2 v = new Vector2((xpt-mBall2.getX()),(ypt-mBall2.getY()));
bombBody.applyLinearImpulse(v,bombBody.getWorldCenter());
}

Changing the mass of an existing body is best done by scaling the existing massData of that body. This keeps the center of mass in the right place and also ensures that the mass and rotational inertia match correctly.
b2MassData massData;
body->GetMassData(&massData);
float scaleFactor = desiredMass / massData.mass;
massData.mass *= scaleFactor;
massData.I *= scaleFactor;
body->SetMassData(&massData);
One thing to be aware of is that this does not affect the density of the fixtures on the body. If you add or remove any fixtures from the body after this, the mass data will be recalculated from the fixtures, not from your mass data. So you would have to do this again after changing fixtures to restore your desired mass.

Related

Corona SDK move object without it being effected by gravity

So I am trying to make a Flappy Birdesque game to learn how to make games using Corona SDK. I have a top column that I want to be able to move linearly. So I am using topColumn.setLinearVelocity(), but I also have gravity set in the game so the bird can flap properly :). But my issue is that when the game starts, the pipes fall to the ground due to gravity. Is there a way to move the topColumn and bottomColumn without them being affected by gravity? They are dynamic bodies right now, but I don't know how to move them using static.
Any help?
local physics = require "physics"
physics.start()
physics.setGravity( 0, 100 )
...
function addColumns()
height = math.random(display.contentCenterY - 200, display.contentCenterY + 200)
topColumn = display.newImageRect('topColumn.png',100,714)
topColumn.anchorX = 0.5
topColumn.anchorY = 1
topColumn.x = display.contentWidth
physics.addBody(topColumn, "dynamic", {density=0, bounce=0, friction=0})
topColumn.y = height - 160
topColumn:setLinearVelocity( -20,0 )
bottomColumn = display.newImageRect('bottomColumn.png',100,714)
bottomColumn.anchorX = 0.5
bottomColumn.anchorY = 0
bottomColumn.x = display.contentWidth
bottomColumn.y = height + 160
physics.addBody(bottomColumn, "dynamic", {density=0, bounce=0, friction=0})
bottomColumn:setLinearVelocity( -20,0 )
end
...
It sounds like you need kinematic bodies.
From Corona documentation
"dynamic" — dynamic bodies are fully simulated. They can be moved
manually in code, but normally they move according to forces like
gravity or reactionary collision forces. This is the default body type
for physical objects in Box2D. Dynamic bodies can collide with all
body types.
"static" — static bodies does not move under simulation and they
behave as if they have infinite mass. Static bodies can be moved
manually by the user, but they do not accept the application of
velocity. Static bodies collide only with dynamic bodies, not with
other static bodies or kinematic bodies.
"kinematic" — kinematic bodies move under simulation only according to
their velocity. Kinematic bodies will not respond to forces like
gravity. They can be moved manually by the user, but normally they are
moved by setting their velocities. Kinematic bodies collide only with
dynamic bodies, not with other kinematic bodies or static bodies.

How to make TMXTiledMap responsive?

My game is a 2D car-based one, with a straight infinite map where I've finally been able to add some random obstacles. There are only 3 positions the car can be at, and everything is working fine.
The point is that I've recently noticed that it is not responsive, and tried to make it responsive by adding a line like these one to the AppDelegate.cpp:
glview->setDesignResolutionSize(1024.0, 600.0, kResolutionFixedWidth);
I've tried to use kResolutionFixedWidth, kResolutionFixedHeight and all others 5 variables you can put there, but I only got black lines along the screen and every single screen breakdown you can imagine -.-'
I can figure out I need to resize my TMXTiledMap manually because of the nature of tiles (I did it with Tiled), but I don't know how to face this problem.
Note that I'm currently developing for a 1024x600 Android device but I would want to support at least the most common resolutions for both tablets and smartphones.
There are probably 2 resolution policies you want to use.
If you use No Border then you shouldn't see any black bars, but the engine will crop your design resolution so you won't want to put UI in the corners, or you'll want to use Visible Origin and Visible Size to calculate positions.
If you use Exact Fit you should set the design resolution to the devices exact size, and then you're responsible for positioning and scaling everything correctly to avoid distortion.
You will need to scale your art depending on your policy and design resolution choices if you are seeing black bars.
Have you read through this wiki page?
http://www.cocos2d-x.org/wiki/Multi_resolution_support
Here's what we do for one of our games:
auto director = Director::getInstance();
auto glview = director->getOpenGLView();
float contentScaleFactor = 1.f;
// Set the design resolution
Size frameSize = glview->getFrameSize();
Size designSize = glview->getDesignResolutionSize();
CCLOG("defaults:");
CCLOG("framesize = {%f,%f}", frameSize.width, frameSize.height);
CCLOG("visibleSize = {%f,%f}", glview->getVisibleSize().width, glview->getVisibleSize().height);
CCLOG("designSize = {%f,%f}", designSize.width, designSize.height);
CCLOG("contentscalefactor = %f", director->getContentScaleFactor());
Vec2 origin = director->getVisibleOrigin();
CCLOG("visibleSize = %s", CStrFromSize(director->getVisibleSize()));
CCLOG("origin = {%f,%f}", origin.x, origin.y);
// Retina?
contentScaleFactor = director->getContentScaleFactor();
float designWidth = frameSize.width / contentScaleFactor;
float designHeight = frameSize.height / contentScaleFactor;
CCLOG("contentScale = %f, designWidth/Height = {%f,%f}", contentScaleFactor, designWidth, designHeight);
glview->setDesignResolutionSize(designWidth, designHeight, ResolutionPolicy::EXACT_FIT);
// we designed the game for 480x320 (hence the divisors)
// used to scale full screen backgrounds
float fullWidthScaleFactor = designWidth/480.f;
// used to scale up most UI
float largeScaleFactor = floorf(designHeight/320.f);
// round to closest HALF step (1.0,1.5,2.0,2.5,3.0,etc)
// used for scaling UI where pixel art is affected by .1 scales
float largeScaleFactorExact = floorf(designHeight * 2.f / 320.f) * 0.5f;
// used to scale up UI that must be touchable (larger on high desnsity)
float largeScaleFactorUI = STROUND(designHeight / 320.f);
// this forces minimum of 1x scale (we should just not support these devices)
float scaleFitAll = designWidth > designHeight ? designHeight/320.f : designWidth/480.f;
if(largeScaleFactor < 1.f)
largeScaleFactor = scaleFitAll;
if(largeScaleFactorExact < 1.f)
largeScaleFactorExact = scaleFitAll;
if(largeScaleFactorUI < 1.f)
largeScaleFactorUI = scaleFitAll;

Calculate object position direction after collision

I am writing my own game engine (a very base one), I want to learn how physics work in game development and not using an already built game engine. I am writing my code in Java for Android devices (using SurfaceView).
The problem is that I don't know how to calculate the position for my object after a collision. I have created my own collision detection and it is working perfectly.
As you can see, the red rectangle is the area where my ball should move. The arrows is showing where the ball should move after a collision happens. The ball have different position, marked with 1 - 11 (note, while rendering the "world" you see only one ball!).
The balls are actually rectangles! But you can not see the edges.
I have created my own Game Object class, where I'm keeping data about the object position, velocity, origin, etc.:
public abstract class GameObject
{
public Vector2 dimension;
public Vector2 position;
public Vector2 velocity;
public Vector2 origin;
public Rectangle rectangle;
public GameObject(Resources resources)
{
this.dimension = new Vector2();
this.position = new Vector2();
this.velocity = new Vector2();
this.origin = new Vector2();
this.rectangle = new Rectangle();
}
public void update(float deltaTime)
{
position.x += velocity.x;
position.y += velocity.y;
rectangle.set(position.x, position.y, dimension.x, dimension.y);
origin.x = position.x + dimension.x / 2;
origin.y = position.y + dimension.y / 2;
}
}
This method is called if a ball collide with one of the red rectangle margins:
protected void onBallCollideWithLevelEdge(Ball ball)
{
// Calculate next position:
??????????
}
My ball have a velocity and a position. Should I save the previous position of the ball?
1) Why do you represents balls as rectangles? Circle is far more easy to handle, expecially if you want to extend collision to ball-ball.
2) If you are trying to make a physics engine you must have coordinates of all objects and the respective first and second derivatives, aka speed and acceleration. Moreover you need a mass for each object and maybe some other parameters, for example material (for friction) and elasticity, but this is not needed at the beginning.
3) When a collision with walls happens you have current ball position and velocity. Given this data you have to calculate normal force. Normal force is such that ball cannot pass through the wall, so I'd calculate it's magnitude using something like this:
Nx = DELTAx*k;
Ny = DELTAy*k;
where k is some elasticity constant that you can trim and x is the measure of how much the ball has penetrated in the wall. Note that this is good only for "slow" objects. If you deal with bullets you'd better using something like rays or.
Another way could be to calculate kinetic energy at the time of collision and transfer it to elastic energy. Once you have elastic energy you can release it in a direction normal to the wall, transforming it to a force.
Once you have the force, it becomes an acceleration by dividing it for the mass.
4) at each simulation iteration you add speed to position, and acceleration to speed, remembering of multiplying it for the integration time (dt). This time can be set arbitrarly and it's a constant. If you want a 100Hz simulation you set dt to 10ms. You also have to recalculate acceleration as the sum of forces divided by the mass.
5) As you note I never talked about direction because you don't need it if you are reasoning decomposing coordinates in each axis (x,y in a 2D engine). If the normal force is "right", as in your example, the Ny component will be set to zero, while Nx will be tranformed into acceleration and will change the horizontal speed. This also will change the ball's direction.
These are only advices, actually you should start by studying kinematics and later something of rational mechanics.
I had an function that looked something like this:
Position calculateValidPosition(Position start, Position end)
Position middlePoint = (start + end) /2
if (middlePoint == start || middlePoint == end)
return start
if( isColliding(middlePont) )
return calculateValidPosition(start, middlePoint)
else
return calculate(middlePoint, end)
I just made this code on the fly, so there would be a lot of room for improvements... starting by not making it recursive.
This function would be called when a collision is detected, passing as a parameter the last valid position of the object, and the current invalid position. On each iteration, the first parameter is always valid (no collition), and the second one is invalid (there is collition).
But I think this can give you an idea of a possible solution, so you can adapt it to your needs.

Unit of measurement in a game physics engine

in my game I get the acceleration from the accelerometer.
Computing my calculation, I have to apply a coefficient to turn unit of measurementin pixel unit.
I apply the coefficient founded for an Android app (in a sample):
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
mXDpi = metrics.xdpi;
mYDpi = metrics.ydpi;
mMetersToPixelsX = mXDpi / 0.0254f;
mMetersToPixelsY = mYDpi / 0.0254f;
to my acceleration, getting pixels/s^2. in this way i can use pixel everywhere in my code instead of thinking all in meters.
It is right?
It's going to depend on what sort of physics you want to impose. (This assumes you want Newtonian mechanics.) If you want to track the motion of the device, then you need to integrate the acceleration to get velocity and then integrate the velocity to get position. Or I suppose, you could skip the intermediate step and translate from 'acceleration' to change in position by using 0.5*acceleration^2 (and then multiply that result by an appropriate scaling factor that you will probably need to determine by experiment). (That second method may not properly handle constant motion.) For each independent dimension, velocity and position would be a cumulative sum with these recurrence relations:
velocity[t] = acceleration[t] *(t -(t-1) ) + velocity[t-1]
position[t] = position[t-1] + velocity[t]*(t -(t-1) )

Calibrating 3d Accelerometer for 2d Game

I am making a 2d game. The phone is held horizontally and a character moves up/down & left/right to avoid obstacles. The character is controlled by the accelerometer on the phone. Everything works fine if the player doesn't mind (0,0) (the point where the character stands still) being when the phone is held perfectly flat. In this scenario it's possible to just read the Y and X values directly and use them to control the character. The accelerometer values are between -10 and 10 (they get multiplied by an acceleration constant to decide the movement speed of the character), libgdx is the framework used.
The problem is that having (0,0) isn't very comfortable, so the idea is to calibrate it so that 0,0 will be set to the phones position at a specific point in time.
Which brings me to my question, how would I do this? I tried just reading the current X and Y values then subtracting it. The problem with that is that when the phone is held at a 90 degree angle then the X offset value is 10 (which is the max value) so it ends up becoming impossible to move because the value will never go over 10 (10-10 = 0). The Z axis has to come into play here somehow, I'm just not sure how.
Thanks for the help, I tried explaining as best as I can, I did try searching for the solution, but I don't even know what the proper term is for what I'm looking for.
An old question, but I am providing the answer here as I couldn't find a good answer for Android or LibGDX anywhere. The code below is based on a solution someone posted for iOS (sorry, I have lost the reference).
You can do this in three parts:
Capture a vector representing the neutral direction:
Vector3 tiltCalibration = new Vector3(
Gdx.input.getAccelerometerX(),
Gdx.input.getAccelerometerY(),
Gdx.input.getAccelerometerZ() );
Transform this vector into a rotation matrix:
public void initTiltControls( Vector3 tiltCalibration ) {
Vector3.tmp.set( 0, 0, 1 );
Vector3.tmp2.set( tiltCalibration ).nor();
Quaternion rotateQuaternion = new Quaternion().setFromCross( Vector3.tmp, Vector3.tmp2 );
Matrix4 m = new Matrix4( Vector3.Zero, rotateQuaternion, new Vector3( 1f, 1f, 1f ) );
this.calibrationMatrix = m.inv();
}
Whenever you need inputs from the accelerometer, first run them through the rotation matrix:
public void handleAccelerometerInputs( float x, float y, float z ) {
Vector3.tmp.set( x, y, z );
Vector3.tmp.mul( this.calibrationMatrix );
x = Vector3.tmp.x;
y = Vector3.tmp.y;
z = Vector3.tmp.z;
[use x, y and z here]
...
}
For a simple solution you can look at the methods:
Gdx.input.getAzimuth(), Gdx.input.getPitch(), Gdx.input.getRoll()
The downside is that those somehow use the internal compass to give your devices rotation compared to North/South/East/West. I did only test that very shortly so I'm not 100% sure about it though. Might be worth a look.
The more complex method involves some trigonometry, basically you have to calculate the angle the phone is held at from Gdx.input.getAccelerometerX/Y/Z(). Must be something like (for rotation along the longer side of the phone):
Math.atan(Gdx.input.getAccelerometerX() / Gdx.input.getAccelerometerZ());
For both approaches you then store the initial angle and subtract it later on again. You have to watch out for the ranges though, I think Math.atan(...) is within -Pi and Pi.
Hopefully that'll get you started somehow. You might search for "Accelerometer to pitch/roll/rotation" and similar, too.

Categories

Resources