Box2d body OnUpdate Function - android

I have two bodies(A,B). I want B follows A. I can change B position with setTransfrom() function to A position. But I have to change B's position in every frame rate. So I have to use something like contact listener. When I use normal object in Andengine, it has this function below instead of contactlistener.
this.foot = new Rectangle(this.getX(), this.getY(), 8, 10, ResourcesManager.getInstance().vbom){
#Override
protected void onManagedUpdate(float pSecondsElapsed)
{
// super.onManagedUpdate(pSecondsElapsed);
this.setPosition(body.getPosition().x*PhysicsConstants.PIXEL_TO_METER_RATIO_DEFAULT+1,
body.getPosition().y*PhysicsConstants.PIXEL_TO_METER_RATIO_DEFAULT-15);
}
};
I mean I can set this kind of listener when I am creating it.Is there any option for box2d body? I mean something like that:
this.footBody=PhysicsFactory.createBoxBody(this.mPhysicsWorld, this.foot, BodyType.DynamicBody, footFixtureDef){
#Override
protected void onManagedUpdate(float pSecondsElapsed)
{
// super.onManagedUpdate(pSecondsElapsed);
this.setPosition(body.getPosition().x*PhysicsConstants.PIXEL_TO_METER_RATIO_DEFAULT+1,
body.getPosition().y*PhysicsConstants.PIXEL_TO_METER_RATIO_DEFAULT-15);
}
};

The poisition updates of physics bodies is managed by the Box2D library. But you can register an additional update handler to your scene and tell the box2D world what you want done during that update.
this.scene.registerUpdateHandler(new IUpdateHandler() {
#Override
public void onUpdate(float pSecondsElapsed) {
// TODO Auto-generated method stub
//Your code to run here!
}
So if you maintain a list of references to the bodies in your world, you should be able to apply forces or set their positions on each tick of the game.
If you want to make sure you update the world before or after the box2D world step, you could event call
mBox2dWorld.onUpdate(pSecondsElapsed);
from within your own update handler, instead of registering the world as an updateHandler itself.
Here are a couple of less practical suggestions as well:
Or to do that the box2D way you could use a joint. I depends on the following behavior you want.
OR... you don't even have object B as part of the Box2D world, perhaps, and just manage the following behavior outside of box2D. Does it need to collide with stuff?

Related

why i can't update anything? (onModifierFinished, runOnUpdateThread, registerUpdateHandler...) AndEngine

i'm doing my first andengine project, so i'm building a framework to work with it. I have a typical ResourceManager and a SceneManager (both Singleton).
Until here, all ok. Then i start to make MyScenes (SceneManager -> MyScene), i create all ok, but when i register handlers or listener to update something (like attach, dettach objects or setVisible or even setScreen), nothing works. Like if there are not any GameLoop.
I use GLES2-Anchor center.
In my GameBaseActivity i setup the ResourceManager:
rm.setup(Game.this, this.getEngine(), this.getApplicationContext(), CAMERA_WIDTH, CAMERA_HEIGHT, 1f, 1f);
In ResourceManager, mEngine is static.
In MyScene, first createScene() method at then end call to populatesScene() method, where i set animations to entities but it doesn't update:
this.registerUpdateHandler(new IUpdateHandler() {
#Override
public void onUpdate(float pSecondsElapsed) {
Log.d("2","this show in log");
ResourceManager.g_menu_manual.getSprite().setVisible(true);
}
#Override public void reset() {}
});
also, i have this Modifier:
SequenceEntityModifier sem = new SequenceEntityModifier(moveLeft){
#Override
public void onModifierFinished(final IModifier<IEntity> pModifier,final IEntity pItem) {
Log.d("2","this show in log");
ResourceManager.mEngine.runOnUpdateThread(new Runnable() {
#Override
public void run() {
ResourceManager.g_menu_manual.getSprite().setVisible(true);
}
});
Log always shows the messages, but bots updates never works.
If i setVisibility when createScene() or populatesScene() all is alright.
What i'm doing wrong with updates?
Register the update handler to the scene, not the engine.
Also entity modifiers should be registered to entities with the registerEntityModifier method.

Destroy body on collision JBox2D android

I need to destroy one of the body's after collision in JBox2D android game. I found that JBox2D world become locked when body's become in contact. I wanted to destroy one of the body after collision. Can i get any call back after world released lock ?. I found an option that adding the body's into an array for destroying it. But when to destroy the body ?. I am not using andengine/libgdx in this game. Find my collision listener class below,
private class CollisionListener implements ContactListener {
#Override
public void beginContact(Contact contact) {
Object fixtureA = contact.getFixtureA().getUserData();
Object fixtureB = contact.getFixtureB().getUserData();
Body mBodyA = contact.getFixtureA().getBody();
Body mBodyB = contact.getFixtureB().getBody();
if (fixtureA instanceof Bullet) {
destroyBalloonBody(mBodyB);
}
if (fixtureB instanceof Bullet) {
destroyBalloonBody(mBodyA);
}
}
#Override
public void endContact(Contact contact) {
}
#Override
public void postSolve(Contact contact, ContactImpulse contactImpulse) {
}
#Override
public void preSolve(Contact contact, Manifold manifold) {
}
}
public void destroyBalloonBody(Body balloon){
//Can i start a new thread which is having a loop until the world become release for destroying the body
//Or
//Do i need to add the body to a deletionArrayList to destroy it.
}
I believe the problem is that you are trying to remove the body during a collision callback.
From the Box2D Manual:
It is tempting to implement game logic that alters the physics world
inside a contact callback. For example, you may have a collision that
applies damage and try to destroy the associated actor and its rigid
body. However, Box2D does not allow you to alter the physics world
inside a callback because you might destroy objects that Box2D is
currently processing, leading to orphaned pointers.
That is to say, you should not destroy bodies inside of a collision callback.
You should store off the references to the bodies you wish to destroy and destroy them using the World reference after the update cycle.
Was this what you needed?

Physics with Box2d and Andengine tutorial

Hello everyone I'm trying to develop a game like Jetpack so i want to set a gravity that normally push down and when the user tap the screen the gravity change it push up. I searched for a week a tutorial that explain how to do that but I didn't find what I search. Someone can explain me how to do that or post a link to a tutorial ?
Thank you !!
main = new Sprite(sX, sY, mainTextureRegion);
main.setScale(1);
main.setFlippedHorizontal(true);
scene.attachChild(main);
mPhysicsWorld = new PhysicsWorld(new Vector2(0, SensorManager.GRAVITY_EARTH), false);
final FixtureDef objectFixtureDef = PhysicsFactory.createFixtureDef(1, 0.5f, 0.5f);
final Body body = PhysicsFactory.createBoxBody(mPhysicsWorld, main, BodyType.DynamicBody, objectFixtureDef);
mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(main, body, true, true));
final Vector2 gravity = new Vector2(0, 5f);
mPhysicsWorld.setGravity(gravity);
scene.registerUpdateHandler(new IUpdateHandler() {
#Override
public void onUpdate(float pSecondsElapsed) {
}
#Override
public void reset() {
// TODO Auto-generated method stub
}});
When the user touches the screen, you shouldn't change the gravity because it is not suppose to be done like that.
When he touches the screen, just apply a LinearImpulse (check if it not already at maximum speed) or something like that to make it go upper. The gravity shouldn't change as it should always attract all of your physics objects down. If your change the gravity you change the behavior of all your objects, not only the player one.
EDIT
To have the physics engine to work you have to call the step() method of the PhysicsWorld class at each render. The problem with Andengine is that you don't directly access the render() method as Andengine handle it at all.
So what you have to do is to register a IUpdateHandler on the Engine object that you return in your onLoadEngine() method.
This way the onUpdate() method of the interface will be called at each render and here you can call the step() method to get the physics part to work. The float value tells you about how many seconds elapsed since last render but you don't have to take care of that. The method is called multiple times per second.
Hope it helps.
EDIT 2
I think this should work :
//on the Scene object or on the Engine one
scene.registerUpdateHandler(new IUpdateHandler() {
#Override
public void onUpdate(float pSecondsElapsed) {
mPhysicsWorld.onUpdate(pSecondsElapsed);
}
#Override
public void reset() {}
});

Draw on a canvas with delay - "make onDraw() slow down"

I use functions for canvas like drawCircle and drawPoint in android.
This works fine.
But the problem now is to draw these different items with a delay, so it looks like an animation.
What kind of mechanism should I use? Have tried with async but I dont like that way of doing it.
Should I use some kind of timer that just draw with an interval or is there other clever ways to do this?
I use this strategy, first I declare a Handler and a Runnable that way:
private final Observable mObservable = new Observable();
private final static int TIME_STEP_MS = 5;
private final Handler mHandler = new Handler();
private final Runnable mTimeManager = new Runnable()
{
public void run()
{
mObservable.notifyObservers(TIME_STEP_MS);
mHandler.postDelayed(mTimeManager, TIME_STEP_MS);
}
};
Then when I want to start my time manager I just call the mTimeManager.run() and it will start to notify my Observer s (previously added) periodically.
If you need for some reason stop the timer or something you just do that:
mHandler.removeCallbacks(mTimeManager);
[ EDIT - More complete code ]
Ok than let's make it clearer, first I made a custom Observable object like that [that's optional]:
private final Observable mObservable = new Observable()
{
public void notifyObservers()
{
setChanged();
super.notifyObservers();
};
#Override
public void notifyObservers(Object data)
{
setChanged();
super.notifyObservers(data);
};
};
the reason for that is just because I can't call setChanged() outside Observable class - it's protected, if it's not changed it doesn't notify any observer.
The other declarations keep the same as shown before, now I need to start this TimeManager somewhere, my app is a LiveWallpaper and I make all rendering stuff into a class that extends a Thread but you don't need that necessarily, I made a method called resumeDrawing(), this one is called right after super.start(); at my #Override of public synchronized void start() from Thread class, the method looks like that:
public void resumeDrawing()
{
if (!mTimeManagerRunning) // just a boolean field in my class
{
System.err.println("Resuming renderer."); // just for debug
mTimeManager.run();
mTimeManagerRunning = true;
}
else
{
System.err.println("Renderer already running."); // just for debug
}
}
and it's dual:
public void pauseDrawing()
{
if (mTimeManagerRunning)
{
System.err.println("Pausing renderer.");
mHandler.removeCallbacks(mTimeManager);
mTimeManagerRunning = false;
}
else
{
System.err.println("Renderer already paused.");
}
}
Ok, now we can start and stop the time manager, but who's listening? Nobody! so let's add'em: On the constructor of my Renderer I add some Observer s to my mObservable object, one of those is the Renderer itself, so my renderer extends Thread and implements Observer:
#Override // from Observer interface
public void update(Observable arg0, Object arg1)
{
mElapsedMsRedraw += (Integer) arg1;
if (mElapsedMsRedraw >= mDrawingMsPerFrame)
{
mElapsedMsRedraw = 0;
drawEm(); // refresh the canvas and stuff
}
}
to add observers you simply do mObservable.addObserver(THE_OBJECT - Implements Observer)
you can see that I don't re-render my stuff each time I'm notified, that's because I use this TimeManager for other thinks than just refresh the Canvas like updating the position of the objects I want to draw just internally.
So, what you need to slow down the drawing is to change the way your objects change internally while the time passes, I mean your circles and points etc, or you can chance your time step, I recommend the first one.
Was it clearer? I hope it helps.
I would use a timer, or create Animations. You can create Animations that will do all sorts of things including changing transparency over time.
Here's the Android Documentation for Animation Resources
I believe there may be sophisticated ways of doing this, but for my needs I used a simple method that has a lot of advantages:
I first create records of coordinates (and any other data needed) for every point of the drawing -- instead of drawing the points on the spot -- and then reproduce them using a timer (Android handler, preferably). This also offers a lot of possibilities while actual drawing: pause, go faster/slower, go backwards, ...
I don't know if this method can be used for complicated drawings, but it is fine for drawing shapes, curves, surfaces, etc.

Problem Simulating WeldJoint

I'd have already post this question in the Andengine forum but there are already some questions regarding this topic, some have replies but the ones i want to know don't have any replies yet.
I'm trying to simulate a player jump like in Super Mario Bros. First, I used a simple contact listener to have a boolean value false when contact occurs but the contact occurs with walls grounds, everything. So, I'm now trying to attach another small body to the bottom of player as foot sensor using WeldJoint. But I couldn't achieve that. The WeldJoint wouldn't stick at all. I tried to create the WeldJoint on an update thread, nothing. I tried with the setposition method to update the sensor position with the player's, but it just positions the sensor below ground.
Any suggestions would be appreciated. Here is how i tried to create WeldJoint.
Player and sensor
mPlayer = new AnimatedSprite(100, 150, PlayerTextureRegion);
PlayerBody = PhysicsFactory.createBoxBody(this.mPhysicsWorld,mPlayer,BodyType.DynamicBody, PLAYER_FIXTURE_DEF);
this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(mPlayer, PlayerBody, true, true));
mScene.getLastChild().attachChild(mPlayer);
final Shape mSensor= new Rectangle(mPlayer.getX()+4,mPlayer.getY()+mPlayer.getHeight(),10,4);
final Body SensorBody = PhysicsFactory.createBoxBody(this.mPhysicsWorld,mSensor,BodyType.DynamicBody, SENSOR_FIXTURE_DEF);
this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(mSensor, SensorBody, true, true));
mScene.getLastChild().attachChild(mSensor);
mScene.registerUpdateHandler(new IUpdateHandler() {
#Override
public void reset() { }
#Override
public void onUpdate(final float pSecondsElapsed) {
this.createJoint(PlayerBody,SensorBody);
.......
Joint Method
private void createJoint(Body Anchor, Body Sensor){
final WeldJointDef join = new WeldJointDef();
join.initialize(Anchor,Sensor,Anchor.getWorldCenter());
this.mPhysicsWorld.createJoint(join);
}
Ok, instead of WeldJoint I used RevoluteJoint, without the motor configuration and it works fine now. Just initialize two bodies using revoluteJointDef and they are stuck like weldjoint. For time being I'm going with revoluteJoint to make two bodies as one.

Categories

Resources