Box2d in Andengine - attaching child bodies - is it possible - android

I have a problem with Andengine Box2d Extension.
I have 2 rectangles: base and fuelStation.
fuelStation is a child of base. When I'm rotating base with setTransform method, fuelStation sprite is rotating too, but body remains in the same position.
base = new Rectangle(CAMERA_WIDTH / 2, CAMERA_HEIGHT / 2 - 200, 200, 200, vbom);
fuelStation = new Rectangle(base.getWidth() / 2, 0, 500, 10, vbom);
this.attachChild(base);
base.attachChild(fuelStation);
final FixtureDef objectFixtureDef1 = PhysicsFactory.createFixtureDef(1, 0.0f, 0.5f);
final FixtureDef objectFixtureDef2 = PhysicsFactory.createFixtureDef(1, 0.0f, 0.5f);
baseBody = PhysicsFactory.createBoxBody(physicsWorld, base, BodyType.StaticBody, objectFixtureDef1);
baseBody.setUserData("base");
fuelStationBody = PhysicsFactory.createBoxBody(physicsWorld, fuelStation, BodyType.KinematicBody, objectFixtureDef2);
fuelStationBody.setUserData("station");
physicsWorld.registerPhysicsConnector(new PhysicsConnector(base, baseBody, true, true));
// physicsWorld.registerPhysicsConnector(new PhysicsConnector(fuelStation, fuelStationBody,
// true, true));
When I remove comment from the last line - sprite position changes but still not working properly (body stands still).
How to connect properly these 2 bodies?

You have to keep in mind that all the transformations that you do to the entities (sprites) will only affect the "visual" content, in other words, will never affect the physic bodies. If you want to affect the entities and the bodies you will only achieve that by applying forces to the physic bodies and, because they are connected with a PhysicsConnector, those transformations will affect both the physic body and the the sprite ("visual body").
So, having the fuelStating as a child of base will affect nothing. To affect two bodies you need a "connection" between them and you can achieve that by creating a joint that will connect the two bodies: http://www.iforce2d.net/b2dtut/joints-overview
Hope it helps.

Related

Libgdx: Framebuffer for "Fog of War"-Effect

I am writing a RTS Game for Android and I want the "Fog of War" effect on the player's units. This effect means that only a "circle" around each unit shows the background map while on places where no player unit is located, the screen should be black. I don't want to use shaders.
I have a first version of it working. What I am doing is to render the map to the default framebuffer, then I have a second Framebuffer (similar to light technics) which is completely black. Where the units of the players are, I then batch-draw a texture which is completely transparent and has a white circle with blurred edges in its middle.
Finally I draw the second (light) FrameBuffer's colorTexture over the first one using Gdx.gl.glBlendFunc(GL20.GL_DST_COLOR, GL20.GL_ZERO);
The visual effect now is that indeed the whole map is black and a circle around my units is visible - but a lot of white color is added.
The reason is pretty clear as I drew the light textures for the units like this:
lightBuffer.begin();
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE);
Gdx.gl.glEnable(GL20.GL_BLEND);
Gdx.gl.glClearColor(0.1f, 0.1f, 0.1f, 1f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.setColor(1f, 1f, 1f, 1f);
for (RTSTroopAction i : unitList) {
batch.draw(lightSprite, i.getX() + (i.getWidth() / 2) - 230, i.getY() + (i.getHeight() / 2) - 230, 460, 460); //, 0, 0, lightSprite.getWidth(), lightSprite.getHeight(), false, true);
}
batch.end();
lightBuffer.end();
However, I don't want the "white stuff" on the original texture, I just want the original background shine through. How can I achieve that ?
I think it's playing around with the blendFuncs, but I was not able to figure out which values to use yet.
Thanks to Tenfour04 pointing into the right direction, I was able to find the solution. First of all, the problem is not directly within batch.end();. The problem is, that indeed a sprite batch maintains its own blendFunc Settings. These get applied when flush(); is called. (end() calls it also ).
However the batch is also calling flush when it draws a TextureRegion that is bound to a different texture than the one used in the previous draw() call.
So in my original code: whatever blendFunc I had set was always overridden when I called batch.draw(lightBuffer,...). The solution is to use the spritebatch's blendFunc and not the Gdx.gl.blendFunc.
The total working code finally looks like this:
lightBuffer.begin();
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
Gdx.gl.glEnable(GL20.GL_BLEND);
// start rendering to the lightBuffer
// set the ambient color values, this is the "global" light of your scene
Gdx.gl.glClearColor(0.1f, 0.1f, 0.1f, 1f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
// start rendering the lights
batch.setProjectionMatrix(camera.combined);
batch.begin();
// set the color of your light (red,green,blue,alpha values)
batch.setColor(1f, 1f, 1f, 1f);
for (RTSTroopAction i : unitList) {
if (i.getOwnerId() == game.getCallback().getPlayerId()) {
batch.draw(lightSprite, i.getX() + (i.getWidth() / 2) - 230, i.getY() + (i.getHeight() / 2) - 230, 460, 460); //, 0, 0, lightSprite.getWidth(), lightSprite.getHeight(), false, true);
}
}
batch.end();
lightBuffer.end();
// now we render the lightBuffer to the default "frame buffer"
// with the right blending !
Gdx.gl.glEnable(GL20.GL_BLEND);
Gdx.gl.glBlendFunc(GL20.GL_ZERO, GL20.GL_SRC_COLOR);
batch.setProjectionMatrix(getStage().getCamera().combined);
batch.enableBlending();
batch.setBlendFunction(GL20.GL_ZERO, GL20.GL_SRC_COLOR);
batch.begin();
Gdx.gl.glEnable(GL20.GL_BLEND);
Gdx.gl.glBlendFunc(GL20.GL_ZERO, GL20.GL_SRC_COLOR);
batch.draw(lightBufferRegion,0, 0, getStage().getWidth(), getStage().getHeight());
batch.end();
batch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);

Why does android.graphics.DashPathEffect double interval distances?

The following code draws from the start of my path to halfway through my path when animatedProgressPercentage = 0f and as it reaches 1f, it will nearly reach the end.
dashPathEffect = new DashPathEffect( new float[]{
new PathMeasure(path, false).getLength()/4f, // length of intervals 'on'
aVeryLargeNumber}, // length of intervals 'off'
0f - (pathLength/2f)*animatedProgressPercentage); // offset length to start (aka phase)
paint.setPathEffect(dashPathEffect);
When I switch the /4f to /8f half becomes a quarter. My question is, why isn't /4f drawing a quarter of the path? Why do I need to divide pathLength by two in the phase? And why does it only nearly reach the end instead of the whole thing?
I'm also doing this
viewRect.set(0, 0, w, h);
m.setRectToRect(boundsRect, viewRect, Matrix.ScaleToFit.CENTER);
path.transform(m);
but using scale = viewRect.width() / boundsRect.width(); as a multiplier didn't seem to help at all. Maybe I've completely misunderstood the intended usage of DashPathEffect or maybe I need to show more code here to be understood myself? Please let me know!

Libgdx Creating On Screen Controls

I am using the libgdx framework to create a game. I'm trying create onscreen buttons/controls.
Currently, I have a
class LevelOne that implements Screen.
This class has a private variable world (From Box2d)
I want to add a
Table with Textbuttons or a Libgdx Touchpad to the Box2d world.
However, I'm not sure how to do this.
Next, I know I can add a table or a touchpad to a Libgdx Stage. Is there anyway to get the Libgdx stage and Box2d world to work together so, I can add a Touchpad or Table to the Box2d world.
For onscreen controls, you can do it like this:
Make a new cam which will be fixed for the controls:
OrthographicCamera guicam = new OrthographicCamera(480, 320);
guicam.position.set(480/2F, 320/2F, 0);
Make a (libgdx) Rectangle for each control:
Rectangle wleftBounds = new Rectangle(0, 0, 80, 80);
Rectangle wrightBounds = new Rectangle(80, 0, 80, 80);
Create a new Vector3 to hold your unprojected touch coordinates:
Vector3 touchPoint = new Vector3();
Then you can poll the Input to see if the user is touching these rectangles:
//in render method
for (int i=0; i<5; i++){
if (!Gdx.input.isTouched(i)) continue;
guicam.unproject(touchPoint.set(Gdx.input.getX(i), Gdx.input.getY(i), 0));
if (wleftBounds.contains(touchPoint.x, touchPoint.y)){
//Move your player to the left!
}else if (wrightBounds.contains(touchPoint.x, touchPoint.y)){
//Move your player to the right!
}
}
Notice I'm checking the first 5 touch indexes, thats because you will surely want to have controls that are being used at the same time (i.e. Jumping while Moving Right).
Last but not least, you will want to draw some nice graphics over the controls:
batch.draw(leftRegion, wleftBounds.x, wleftBounds.y, wleftBounds.width, wleftBounds.height);
batch.draw(rightRegion, wrightBounds.x, wrightBounds.y, wrightBounds.width, wrightBounds.height);
If you want to include a HUD stage
Create HUD matrix (import com.badlogic.gdx.math.Matrix4):
HUDMatrix = camera.combined.cpy();
HUDMatrix.setToOrtho2D(0, 0, wwidth, wheight);
Then draw it HUD
batch.setProjectionMatrix(HUDMatrix);
batch.begin();
stage.draw(batch)
batch.end();

Box2d body setLinearImpulse() function stability

I'm developing a game by Andengine for Android.
Game: There is a body(let's say small box). And I want: the player collision with it, player will jump. It is jumping but not jumping the same height(in my code 100px) in every collision! My codes are here:
if (footFake.collidesWith(this))
{
player.getBody().applyLinearImpulse(new Vector2(0, 100/PhysicsConstants.PIXEL_TO_METER_RATIO_DEFAULT), player.getBody().getWorldCenter());
}
And the box body features:
final FixtureDef fixtureDef = PhysicsFactory.createFixtureDef(0, 0, 0);
this.body = PhysicsFactory.createBoxBody(this.mPhysicsWorld, this, BodyType.StaticBody, fixtureDef);
this.body.setUserData("jumpBox");
this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(this, this.body, true, true));
And player:
final FixtureDef fixtureDef = PhysicsFactory.createFixtureDef(0, 0, 0.1f);
this.body = PhysicsFactory.createBoxBody(this.mPhysicsWorld, this, BodyType.DynamicBody, fixtureDef);
Applying an impulse will not always give the same height jump, because the existing velocity of the body may be different. You could use SetLinearVelocity to set the vertical velocity of the body to make sure that the starting velocity is constant every time.
Of course like Singhak has said, you should also make sure that there are no other influences (like collisions) on the body that will mess up the velocity that you want.
Instead of applying impulse you can transform body gradually upto height you want.
And in you case body is not jumping at same height because when body collide many force applied on it. some time value of forces is same and some time it is different.

Adding a Vertex to a libgdx Mesh

the title basically.
You can reserve more than you need when creating a mesh
mesh = new Mesh(false, 100, 0, new VertexAttribute(Usage.Position, 3, "a_position"));
But there is no method for adding a vertex. You can get the FloatBuffer and add to that, but I get strange results. I also tried the mesh.setVertices with offset but that does not work either.
I debugged with drawing points. Works until I try adding a vertex by any means (even if I tweak offsets to account for 3 floats in one vertex)
Copied code segment:
mesh.setVertices(new float[] {
-0.5f, -0.5f, 0,
0.5f, -0.5f, 0/*,
-0.5f,0.5f,0.f*/});//works if I uncoment this
mesh.setVertices(new float[]{-0.5f,0.5f,0.f}, 6, 3);//but comment this out
I also tried
squareMesh.setVertices(new float[]{-0.5f,0.5f,0.f}, 2, 3);
Thanks :)
Adding is a bad idea because the underlying buffers must be recreated and that takes up a lot of time. Instead, one should allocate meshes in bulk and only render what is currently used.
For example mesh.render(GL10.GL_TRIANGLES,0,num_triangles);
As for updating the buffer:
FloatBuffer fbuftmp = mesh.getVerticesBuffer();
BufferUtils.copy(buf,fbuftmp,fbuftmp.capacity(),0);
Where buf is an float array.
Use BufferUtils.copy for reason explained here

Categories

Resources