Chase player with camera in AndEngine and limit world's bounds - android

Using AndEngine for Android, I would like to have my scene look like this:
The red box is the world which must be limited to a given size, say 2000px*450px.
The blue box is the Camera, which is limited as well (as usual), for example to 750px*450px.
For the whole scene, I have a background image that is exactly 450px high. So my Camera can be scaled to whatever size is appropriate, but the background must exactly fit to the height. The width of the Camera may be variable.
The player (circle) must always be in the center (horizontally) but may not leave the world's boundaries.
To achieve this, I've tried adding two types of sizes:
camera size (CAMERA_WIDTH, CAMERA_HEIGHT)
world size (WORLD_WIDTH, WORLD_HEIGHT)
And this function was to add boundaries to the world so that the physics engine prevents the player from leaving those boundaries:
private void createWorldBoundaries() {
Body body;
final Rectangle wall_top = new Rectangle(0, WORLD_HEIGHT-5, WORLD_WIDTH, 10, mVertexManager);
final Rectangle wall_bottom = new Rectangle(0, 5, WORLD_WIDTH, 10, mVertexManager);
final Rectangle wall_left = new Rectangle(5, 0, 10, WORLD_HEIGHT, mVertexManager);
final Rectangle wall_right = new Rectangle(WORLD_WIDTH-5, 0, 10, WORLD_HEIGHT, mVertexManager);
body = PhysicsFactory.createBoxBody(mPhysicsWorld, wall_top, BodyType.StaticBody, new PhysicsFactory.createFixtureDef(0.0f, 0.5f, 0.5f));
wall_top.setUserData(body);
body = PhysicsFactory.createBoxBody(mPhysicsWorld, wall_bottom, BodyType.StaticBody, new PhysicsFactory.createFixtureDef(0.0f, 0.5f, 0.5f));
wall_bottom.setUserData(body);
body = PhysicsFactory.createBoxBody(mPhysicsWorld, wall_left, BodyType.StaticBody, new PhysicsFactory.createFixtureDef(0.0f, 0.5f, 0.5f));
wall_left.setUserData(body);
body = PhysicsFactory.createBoxBody(mPhysicsWorld, wall_right, BodyType.StaticBody, new PhysicsFactory.createFixtureDef(0.0f, 0.5f, 0.5f));
wall_right.setUserData(body);
attachChild(wall_top);
attachChild(wall_bottom);
attachChild(wall_left);
attachChild(wall_right);
}
But this is not working, unfortunately. (see edit)
Setting the camera to chase the player has the wrong result for me: The player does really stay in the center of the screen all time, but I want the player only to stay in the center horizontally, not vertically.
What am I doing wrong and what can I change? And the basic question is: How can I make the world wider than the camera view, while the height is equal to the camera view. The result should be that you can horizontally walk through your world (moving camera) and you can always see the full height.
Edit:
As you define the coordinates of the Rectangle's center and not its top-left corner, you have to do it like this, it seems:
final Rectangle wall_top = new Rectangle(WORLD_WIDTH/2, WORLD_HEIGHT-1, WORLD_WIDTH, 2, mVertexManager);
final Rectangle wall_bottom = new Rectangle(WORLD_WIDTH/2, FIELD_BASELINE_Y+1, WORLD_WIDTH, 2, mVertexManager);
final Rectangle wall_left = new Rectangle(1, WORLD_HEIGHT/2, 2, WORLD_HEIGHT, mVertexManager);
final Rectangle wall_right = new Rectangle(WORLD_WIDTH-1, WORLD_HEIGHT/2, 2, WORLD_HEIGHT, mVertexManager);
However, I had found the other solution in several tutorials. Are these authors not testing their code before writing the tutorials or did the behaviour change from GLES1 to GLES2 or with any recent version?

i think your question about the world boundaries is self answered, isn't it?
PhysicsWorld Boundaries
for further research you can download nicolas' AndEngine Examples App from the Play Store and look up the different examples here (GLES_2, didn't look for AnchorCenter yet): https://github.com/nicolasgramlich/AndEngineExamples/tree/GLES2/src/org/andengine/examples
Taken from the PhysicsExample, the code for the rectangles should look like this, if the bounds are set to the camera bounds. in your case, you can extend width like you want (3 times CAMERA_WIDTH?)
final Rectangle ground = new Rectangle(0, CAMERA_HEIGHT - 2, WORLD_WIDTH, 2, vertexBufferObjectManager);
final Rectangle roof = new Rectangle(0, 0, WORLD_WIDTH, 2, vertexBufferObjectManager);
final Rectangle left = new Rectangle(0, 0, 2, CAMERA_HEIGHT, vertexBufferObjectManager);
final Rectangle right = new Rectangle(WORLD_WIDTH - 2, 0, 2, CAMERA_HEIGHT, vertexBufferObjectManager);
Camera following player
for the Camera to follow your player, you can lookup the code of the BoundCameraExample https://github.com/nicolasgramlich/AndEngineExamples/blob/GLES2/src/org/andengine/examples/BoundCameraExample.java
the interesting part for you should be the addFace method at the bottom
private void addFace(final float pX, final float pY) {
final FixtureDef objectFixtureDef = PhysicsFactory.createFixtureDef(1, 0.5f, 0.5f);
final AnimatedSprite face = new AnimatedSprite(pX, pY, this.mBoxFaceTextureRegion, this.getVertexBufferObjectManager()).animate(100);
final Body body = PhysicsFactory.createBoxBody(this.mPhysicsWorld, face, BodyType.DynamicBody, objectFixtureDef);
this.mScene.attachChild(face);
this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(face, body, true, true));
this.mBoundChaseCamera.setChaseEntity(face);
}
this method creates a physics body + sprite for "your player" (in this case, a boxed face) and sets the sprite as a chaseEntity for the camera to follow. Since the camera has bounds, that it can't exceed and your camera will have the height of your PhysicWorld boundaries, you can use this to let your camera follow the player in x, but not in y direction.
if you (i don't know why) don't want to use these boundaries, you can overwrite the onUpdate method of your Sprite and re-locate your camera only in x-direction, instead of xy coords
face.registerUpdateHandler(new IUpdateHandler() {
#Override
public void onUpdate(final float pSecondsElapsed) {
float[] coord = face.getSceneCenterCoordinates();
this.mBoundChaseCamera.setCenter(sceneCenterCoordinates[0], CAMERA_Y_POSITION);
}
}
where the CAMERA_Y_POSITION is a static final field with the y-position.
I hope this answers your question(s). :-)
edit: oops, i forgot to mention, how to achieve the camera to be bound and i will edit the world width above:
this.mBoundChaseCamera.setBounds(0, 0,
WORLD_WIDTH, CAMERA_HEIGHT);
all settings are like your image given (except the exact position of the face, that has to be given to the addFace(px, py))
Edit: Difference between scene boundaries in Andengine GLES2 vs GLES2-AnchorCenter
As far as i understood the question, i thought you would use GLES2, i thought of the (older) default GLES2 branch of AndEngine and posted the boundaries. As you found out yourself before and stated in the comments, you use another approach to set the rectangles - where you need to set the rectangles center as pX and pY. The reason for this is in fact, that with the AnchorCenter branch, you won't set the upper left position of an entity anymore and instead use it's center position.

Related

Libgdx - box2d polygonshape doesn't fit its sprite

I have a body with a polygonshape created using .setasbox but when I run my game the box is a bit bigger than my sprite.
I know setasbox uses half height and half width, I used my scaling constant to convert meters to pixels and I know the sprite has the origin of the axis on the bottom left as well. Despite of that I still have a box with a width a bit larger than the sprite and this gap is the same however I change the size of the box...
This is the code I use to create my box (160 is the constant to scale meters to pixels):
public Block(World w, float halfWidth, float halfHeight, Vector2 position, Texture tex){
world = w;
bodyd = new BodyDef();
bodyd.type = BodyDef.BodyType.KinematicBody;
bodyd.gravityScale = 0;
shape = new PolygonShape();
shape.setAsBox(halfWidth, halfHeight);
fixtured = new FixtureDef();
fixtured.shape = shape;
fixtured.density = DENS;
fixtured.friction = FRIC;
fixtured.restitution = REST;
bodyd.position.set(new Vector2(position.x, position.y));
body = world.createBody(bodyd);
fixture = body.createFixture(fixtured);
body.setUserData(this);
texture = tex;
sprite = new Sprite(texture);
sprite.setSize(halfWidth * 2 * 160, halfHeight*2*160);
sprite.setPosition((body.getPosition().x - halfWidth) * 160, (body.getPosition().y - halfHeight) * 160);
}
can you try using Box2DSprite? its very easy..
https://bitbucket.org/dermetfan/libgdx-utils/wiki/net.dermetfan.gdx.graphics.g2d.Box2DSprite
http://www.java-gaming.org/index.php?topic=29843.0
I don't see anything wrong with your code
did you consider that the size that you put for your sprite is the size of the full sprite not the size of the block inside your sprite
I think this is why your brick sprite is smaller than your brick physic :
unless the your brick has the full size of the sprite then may be the problem is related to something else
hope that was helpful !

Imprecise Box2d coordinates using LibGDX

I am using LibGDX and Box2d to build my first Android game. Yay!
But I am having some serious problems with Box2d.
I have a simple stage with a rectangular Box2d body at the bottom representing the ground, and two other rectangular Box2d bodies both at the left and right representing the walls.
A Screenshot
Another Screenshot
I also have a box. This box can be touched and it moves using applyLinearImpulse, like if it was kicked. It is a DynamicBody.
What happens is that in my draw() code of the Box object, the Box2d body of the Box object is giving me a wrong value for the X axis. The value for the Y axis is fine.
Those blue "dots" on the screenshots are small textures that I printed on the box edges that body.getPosition() give me. Note how in one screenshot the dots are aligned with the actual DebugRenderer rectangle and in the other they are not.
This is what is happening: when the box moves, the alignment is lost in the movement.
The collision between the box, the ground and the walls occur precisely considering the area that the DebugRenderer renders. But body.getPosition() and fixture.testPoint() considers that area inside those blue dots.
So, somehow, Box2d is "maintaining" these two areas for the same body.
I thought that this could be some kind of "loss of precision" between my conversions of pixels and meters (I am scaling by 100 times) but the Y axis uses the same technique and it's fine.
So, I thought that I might be missing something.
Edit 1
I am converting from Box coordinates to World coordinates. If you see the blue debug sprites in the screenshots, they form the box almost perfectly.
public static final float WORLD_TO_BOX = 0.01f;
public static final float BOX_TO_WORLD = 100f;
The box render code:
public void draw(Batch batch, float alpha) {
x = (body.getPosition().x - width/2) * TheBox.BOX_TO_WORLD;
y = (body.getPosition().y - height/2) * TheBox.BOX_TO_WORLD;
float xend = (body.getPosition().x + width/2) * TheBox.BOX_TO_WORLD;
float yend = (body.getPosition().y + height/2) * TheBox.BOX_TO_WORLD;
batch.draw(texture, x, y);
batch.draw(texture, x, yend);
batch.draw(texture, xend, yend);
batch.draw(texture, xend, y);
}
Edit 2
I am starting to suspect the camera. I got the DebugRenderer and a scene2d Stage. Here is the code:
My screen resolution (Nexus 5, and it's portrait):
public static final int SCREEN_WIDTH = 1080;
public static final int SCREEN_HEIGHT = 1920;
At the startup:
// ...
stage = new Stage(SCREEN_WIDTH, SCREEN_HEIGHT, true);
camera = new OrthographicCamera();
camera.setToOrtho(false, SCREEN_WIDTH, SCREEN_HEIGHT);
debugMatrix = camera.combined.cpy();
debugMatrix.scale(BOX_TO_WORLD, BOX_TO_WORLD, 1.0f);
debugRenderer = new Box2DDebugRenderer();
// ...
Now, the render() code:
public void render() {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
camera.update();
world.step(1/45f, 6, 6);
world.clearForces();
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
debugRenderer.render(world, debugMatrix);
}
Looks like the answer to that one was fairly simple:
stage.setCamera(camera);
I was not setting the OrthographicCamera to the stage, so the stage was using some kind of default camera that wasn't aligned with my stuff.
It had nothing to do with Box2d in the end. Box2d was returning healthy values, but theses values were corresponding to wrong places in my screen because of the wrong stage resolution.

Why physics body automatically moves upwards in andengine gles2 anchor center live wallpaper

I am trying to develop a live wallpaper using andengine gles2 anchor center , with some physics.But when i add a physics object it was moving upwards.instead of moving downward due to gravity
what are the mistakes i am making
please help me to sort out the issue
Here is my code
FixtureDef FIXTURE_DEF = PhysicsFactory.createFixtureDef(1, 0.5f,
0.5f);
mPhysicsWorld = new PhysicsWorld(new Vector2(0,
SensorManager.GRAVITY_EARTH), false);
final AnimatedSprite animatedSprite;
animatedSprite = new AnimatedSprite(500, 250,
this.mBoxFaceTextureRegion, this.getVertexBufferObjectManager());
body = PhysicsFactory.createBoxBody(this.mPhysicsWorld, animatedSprite,
BodyType.DynamicBody, FIXTURE_DEF);
scene.attachChild(animatedSprite);
animatedSprite.animate(200);
mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(
animatedSprite, body, true, true));
Just multiply SensorManager.GRAVITY_EARTH by -1.
Setting negative gravity did not respond properly to sensor data. By adding acceleration to the sensor data in the overridden method **onAccelerationChanged()**, could make the bject falling down with sensor flat.
public void onAccelerationChanged(final AccelerationData pAccelerationData) {
/* Add constant value for vertical gravity*/
final Vector2 gravity = Vector2Pool.obtain(pAccelerationData.getX(), pAccelerationData.getY() + 4.0);
this.mPhysicsWorld.setGravity(gravity);
Vector2Pool.recycle(gravity);
}
This will make your phy world in real gravity experience and you will get objects influenced by sensor data properly

Sprite collisions in android andengine

I'm developing a simple game by andengine.
I have 10 balls which are moving randomly on screen.i'm importing the balls as picture in sprites.if they move at the same coordinate , they pass though their own insides.but i want: if they move at the same coodirnates ,they should change their directions.so they cannot pass through their insides.how can i do that?
private Runnable mStartCircle = new Runnable() {
public void run() {
int i = circleNumber++;
Scene scene = Level1Activity.this.mEngine.getScene();
float startY = -64.0f;
float startX = randomNumber.nextFloat()*(CAMERA_WIDTH-70.0f);
float a= randomNumber.nextFloat()*(CAMERA_WIDTH-70.0f);
circles[i] = new Sprite(startX, startY, textRegCircle[i]);
circles[i].registerEntityModifier(
(IEntityModifier) new SequenceEntityModifier (
new MoveModifier(10.0f, circles[i].getX(), a,
circles[i].getY(),CAMERA_HEIGHT+64.0f)));
}
scene.getLastChild().attachChild(circles[i]);
if (circleNumber < 10){
mHandler.postDelayed(mStartCircle,1000);
}
}
};
Each object(ball) requires a bounding box, or in your case a bounding circle, which is equal to the size of your sprite.
When the game updates and any balls position changes, you have to test for collisions.
Circle to circle collision testing is the simplest type to do.
if distance between (ball1.pos + ball2.pos) is less than (ball1.radius + ball2.radius) = collision.
You then handle the collision by reversing the velocities or calculating new momentums or something. (You also need to move the objects apart so they are no longer colliding)
Just apply a physical connector between balls:
so it will collide and bounce back.
final FixtureDef boxFixtureDef = PhysicsFactory.createFixtureDef(0.1f, 0.5f, 0.5f);
final Body ballBody = PhysicsFactory.createBoxBody(this.mPhysicsWorld, circles[i],BodyType.DynamicBody, boxFixtureDef);
this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(circles[i], ballBody, true, true));
this.mScene.attachChild(circles[i]);

How to change the center of mass?

I am try
MassData md = mBody.getMassData();
md.center.set(2f, 0); mBody.setMassData(md);
But this is not working properly. Help me do this correctly.
I want add a bit more weight to the bottom half of my body.
Instead of trying to change mass directly, what you want to do is to add an extra fixture to the bottom of your body. You can do it e.g. like this (this is a snippet, not complete code; create your textures, scene etc).
Sprite sprite = new Sprite(CAMERA_WIDTH / 2, CAMERA_HEIGHT / 2, 32, 32, mDTextureRegion, vbom);
Body body = PhysicsFactory.createCircleBody(mPhysicsWorld, sprite, BodyType.DynamicBody, PhysicsFactory.createFixtureDef(0.5f, 0.5f, 0.5f)); // create a simple circle body from the sprite
scene.attachChild(sprite);
Debug.i("ORIG MASS Y: " + body.getMassData().center.y); // this is just generated info
FixtureDef fd = PhysicsFactory.createFixtureDef(10f, 1f, 1f, true); // high density fixture; it is a sensor, i.e. it won't affect collisions
CircleShape cs = new CircleShape();
cs.setRadius(0.1f); // make it very small
fd.shape = cs;
cs.setPosition(new Vector2(0, -0.5f)); // attach below the current centre
body.createFixture(fd); // attach to body
Debug.i("NEW MASS Y: " + mDBody.getMassData().center.y); // the generated info changed
mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(sprite, body, true, true));
This example body will behave like a spintop, it will try to reposition itself so the bottom of the sprite will touch the ground. When you rotate it, it will try to get to that position again.

Categories

Resources