Andengine and box2d collision detection - java

I'm using AndEngine and Box2d in android application.
What to I have to do so that when player and coin collide, the player goes through coin without hitting against it as if it is a wall?
public class GameScene extends Scene {
GameScene() {
Body playerBody = PhysicsFactory.createBoxBody(world, playerSprite, BodyType.DynamicBody, fixtureDef);
PhysicsConnector playerConnector = new PhysicsConnector(playerSprite, playerBody, true, false);
world.registerPhysicsConnector(playerConnector);
Body coinBody = PhysicsFactory.createBoxBody(world, coinSprite, BodyType.StaticBody, fixtureDef);
PhysicsConnector coinConnector = new PhysicsConnector(coinSprite, coinBody, true, false);
world.registerPhysicsConnector(coinConnector);
}
private ContactListener createContactListener(){
//if player and coin collide --> destroy coin
}
}

Read about sensor fixtures in Box2D. You want your coin to be a sensor. From the Box2D manual:
Sometimes game logic needs to know when two fixtures overlap yet there
should be no collision response. This is done by using sensors. A
sensor is a fixture that detects collision but does not produce a
response.

Related

Collision detection does not seem to work

I am currently working on a school project where I am creating a side scrolling game. I am at the stage where I require collision detection. I would like my character sprite's visibility to be set to false when it intersects the evil character sprite.
Rectangle d = character.getCharRec();
for (EvilCharacter eChar1 : eChar) {
EvilCharacter m = (EvilCharacter) eChar1;
Rectangle wolfRec = m.getEvilCharRec();
if (d.intersects(wolfRec)) {
System.out.println("WASTED");
character.setAlive(false);
gameOver = true;
}
}
The above code unfortunately does not work (when the character sprite intersects the evil character sprite nothing happens) but strangely enough the code below does (when the rock sprite intersects the evil character sprite both sprites visibility's are set to false). If anyone is able to provide assistance it would be much appreciated.
ArrayList rocks = character.getRocks();
for (Object rock : rocks) {
Rock t = (Rock) rock;
Rectangle t1 = t.getRockRec();
for (EvilCharacter eChar1 : eChar) {
EvilCharacter m = (EvilCharacter) eChar1;
Rectangle wolfRec = m.getEvilCharRec();
if (t1.intersects(wolfRec) && m.Living()) {
t.setVisible(false);
m.setDead(false);
score = score + 10;
}
}
}
(Apologies for the simplistic coding, we don't go over complex or efficient coding in school all that much...)

Libgdx ,can i attach animation in a Body?

im kinda new here, anywho... i am interested in the android gaming app development and i am learning on my own how to do so, using Libgdx as my game-engine and already made a small game not something exciting.
i have recently started to learn how to use the World variable and creating bodies in it, i want to create a class that extends Actor, give it animations (i know how to give animations) and to try and display it on the body, so where ever the body goes, the animation is played on it (basically below the animation is the body that is not displayed ofc)
so my question is : is there a way to give this costume actor into the body so it will play it over the body? (attaching them)
Will appreciate the help!
** NOTE : be aware that my knowledge is still limited, i am a college student for Program Engineering and i am not fully into much depth in java yet (my college not teaching game-engines) **
UPDATE
i have created a costume class, made animations to each action (like herowalk, herosit ... etc...)
i wrote a render method in it :
public void render(SpriteBatch batch) {
float posX = bbody.getPosition().x * PPM;
float posY = bbody.getPosition().y * PPM;
float rotation = (float) Math.toDegrees(bbody.getAngle());
sprite.setPosition(posX,posY);
sprite.setRotation(rotation);
sprite.draw(batch);
}
and created a body, placed it in the middle of my screen and attached the sprite to it using SetUserData() :
BodyDef bdef = new BodyDef();
bdef.position.set(160 / PPM, 200 / PPM);
bdef.type = BodyDef.BodyType.DynamicBody;
PolygonShape shape = new PolygonShape();
shape.setAsBox(5 / PPM, 5 / PPM);
bbody = world.createBody(bdef);
Bodyarray.add(bbody);
FixtureDef fdef = new FixtureDef();
fdef.shape = shape;
fdef.filter.categoryBits = BIT_BOX;
fdef.filter.maskBits = BIT_PLATFORM | BIT_BALL;
bbody.createFixture(fdef);
bbody.setUserData(sprite);
and in my main class where i draw with batch i wrote :
player.sprite.setRegion(player.getAnimationup().getKeyFrame(dt, true));
dt += elapsedTime;
player.render(batch);
to constantly change the animations depends on if the player turns to the right, left, up , down.
the only problem i have is that the sprite it self (the animation works perfectly) is being drawn on the bottom left side of the screen (not on 0,0, it looks like it got the x,y of the body but still away from it) and can see that its attached to it when moving the body (i put controls to control the body movement) and i see the sprite moving with it.
for example im trying to check the coordination of X,Y for both the body and the sprite with Gdx.app.log as usual and both have the SAME exact X and Y. (ofc the sprite has his multiplied by PPM (placed it as 100) since the sprite is not a physical body)
what is causing the wrong location of the sprite?
Welcome to Stack Overflow!
The answer to your question is "Not exactly." Box2D gives you a method called Body#setUserData() which lets you create a reference from the Body to any object (in this case an Animation object, but it is up to you to keep their positions in sync. See the pseudo-code below adapted from the libGDX wiki:
// Create an array to be filled with the bodies
// (better don't create a new one every time though)
Array<Body> bodies = new Array<Body>();
// Now fill the array with all bodies
world.getBodies(bodies);
for (Body b : bodies) {
// Get the body's user data - in this example, our user
// data is an instance of the Entity class
Animation anim = (Animation) b.getUserData();
if (anim != null) {
// Update the entities/sprites position and angle
TextureRegion frame = anim.getKeyFrame( ... );
// Now draw the frame using b.getPosition() and b.getAngle()
}
}
By the way, the libGDX wiki is an excellent resource and reference as you start learning libGDX.

Libgdx - Having one Entity partially exempt from Phsyics

I'm using LibGDX to make a mobile game, now I'm facing a certain issue.
I have a certain Entity which can collide with the wall, when this happens the wall receives a certain force which then causes it to go off the screen and not be positioned properly anymore.
I have tried using LibGDX's isSensor variable but after doing that my Entity crosses straight through the wall.
How can I make it so the wall does stop the Entity from moving through but isn't affected itself by the force of the Entity?
I'm using the physics body editor for my colission shapes as they are not in normal geometrical formats.
Thank you,
Rene
You just need to make the wall static.
I'm not sure how you do it using the physics body editor as I've never used it, but here's some code I wrote a while back that does something similar...
private void buildRoom()
{
Vector2[] roomCorners = new Vector2[]{new Vector2(0f, 0f),
new Vector2(0f, ROOM_HEIGHT),
new Vector2(ROOM_WIDTH, ROOM_HEIGHT),
new Vector2(ROOM_WIDTH, 0f)};
ChainShape roomShape = new ChainShape();
try
{
roomShape.createLoop(roomCorners);
BodyDef roomDef = new BodyDef();
roomDef.type = BodyDef.BodyType.StaticBody;
Body room = world.createBody(roomDef);
room.createFixture(roomShape, 0);
} finally
{
roomShape.dispose();
}
}

How to create a body with Polygon and Rectangle attached together in Libgdx

I am a newbie in Libgdx. I am working on detecting collisions for two bodies. Have created two bodies using "polygonshape" but unfortunately there isn't any method to detect collision among "PolygonShapes" but for "rectangles" .So I came up with an idea of attaching the rectangle at the front of each of the polygons and then detect collision for rectangles but when I run the code, I don't see any rectangles but only polygons.
Here is my code,
public class Player implements Screen, InputProcessor {
private Body polybody;
private Player player;
private World world;
Array<Rectangle> raindrops;
private Body enemybody;
private Sprite polysprite;
public final float width,height;
private Vector2 movement=new Vector2();
private float speed=580;
public Player(World world,float x,float y,float width)
{
this.width=width; //IMP
height=width*2;
BodyDef polygon=new BodyDef();
polygon.type=BodyType.DynamicBody;
polygon.position.set(x,y); //
PolygonShape poly =new PolygonShape();
poly.setAsBox(width/2,height/2); //
FixtureDef polyfixture=new FixtureDef();
polyfixture.shape=poly;
polyfixture.friction=0.8f; //
polyfixture.restitution=0.1f; //
polyfixture.density=3; //
//creating actual body
polybody=world.createBody(polygon);
polybody.createFixture(polyfixture);
//disposing the body
BodyDef rectangle=new BodyDef();
rectangle.type=BodyType.DynamicBody;
Rectangle rect=new Rectangle();
rect.setWidth(50);
rect.setHeight(50);
rect.setPosition(x, y);
enemybody=world.createBody(rectangle);
polysprite=new Sprite(new Texture("img/car.jpg"));
polysprite.setSize(0.5f, 1);
polysprite.setOrigin(polysprite.getWidth()/2, polysprite.getHeight()/2);
polybody.setUserData(polysprite);
poly.dispose();
}
public void update()
{
polybody.applyForceToCenter(movement, true);
enemybody.applyForceToCenter(movement,true);
}
public Body getBody(){
{
return polybody;
}
}
}
Collision Code:
public Player(World world,float x,float y,float width)
{
this.width=width; //IMP
height=width*2;
BodyDef polygon=new BodyDef();
polygon.type=BodyType.DynamicBody;
polygon.position.set(x,y); //
// polygon.fixedRotation=true;
//polygon shape
//Rectangle poly=new Rectangle();
PolygonShape poly =new PolygonShape();
poly.setAsBox(width/2,height/2); //
//fixture defn
polygon.position.set(5,4);
FixtureDef polyfixture=new FixtureDef();
polyfixture.shape=poly;
polyfixture.friction=0.8f; //
polyfixture.restitution=0.1f; //
polyfixture.density=3; //
//creating actual body
polybody=world.createBody(polygon);
polybody.createFixture(polyfixture);
// polybody.applyAngularImpulse(52, true);
//disposing the body
polysprite=new Sprite(new Texture("img/car.jpg"));
polysprite.setSize(2, 3); //size of mario
polysprite.setOrigin(polysprite.getWidth()/2, polysprite.getHeight()/2);
polybody.setUserData(polysprite);
//2nd body
BodyDef polygons=new BodyDef();
polygons.type=BodyType.DynamicBody;
PolygonShape polys=new PolygonShape();
polys.setAsBox(2,2);
FixtureDef polyxfixture=new FixtureDef();
polyxfixture.shape=polys;
polyxfixture.friction=0.8f;
polyxfixture.restitution=0.1f;
polyxfixture.density=3;
polybodys=world.createBody(polygons);
polybodys.createFixture(polyxfixture);
poly.dispose();
}
#Override
public void beginContact(Contact contact) {
// TODO Auto-generated method stub
Fixture fixtureA=contact.getFixtureA();
Fixture fixtureB=contact.getFixtureB();
System.out.println("collides");
}
This is my code. I have created 2 bodies using "polygonshape" and "rectangle" but rectangle isn't created. I can't find what is the mistake. Please help!! Thanks in advance
It seems like you are a bit confused and you are mixing two absolutely independend things:
Box2D, a physics engine, which does all physic calculations
(including collission detection) for you.
The Rectangle, Polygon and the Intersector class of libgdx.
I try to explain what both of them do and why you can't use them together.
The Polygonshape is part of the Box2D engine. It is used to give a Fixture it's shape, which is then used by the collission detection of Box2D.
You can read something about Box2D here.
The Rectangle class is some kind of "Helperclass" in Libgdx, which let you define a Rectangle, with a given position, width and height. It can be used together with the Intersectorclass, which provides some usefull methods for collission detection and other things.
There is also a class caled Polygon. It is, again, a Libgdx class and can't be mixed with the Box2D PolygonShape. The Libgdx Polygon instead can be used with the Intersector class, which provides a method to check for an overlap between 2 Polygons. Polygons are defined by a float[], giving the position of all it's corner points.
That means, that if you want to use the physics engine Box2D, you need to work with the PolygonShape and other shapes, provided by Box2D.
If you instead don't want to use the physics engine and do the collission detection on your own, you can use Rectangle, Polygon and other shapes from Libgdx and you also can use the Intersector for overlap-testing.
EDIT:
If you take a look at this link, there is a section "Contact Listener". There you can see, that the ContactListener provides the methods beginContact (called when two objects start to collide/overlap) and endContact (called when the contact between the two objects ends).
You need to implement those methods and set it as the worlds ContactListener.
Node, that Box2D automatically handles collisions, by seperating the colliding objects (bounce back). If thats not what you want, you shouldset the isSensor-Flag of your FixtureDef. That way, Box2D will notify you, that there is a collision (beginContact gets called) but won't handle it for you.
EDIT 2:
The Contact object you get in your ContactListener-Methods holds 2 Fixtures: FixtrueA and FixtureB.
Thats because in every contact or collision 2 objects have to be involved, so FixtureA is one of them and FixtureB is the ther one.
The reason, why a Contact contains 2 Fixtures instead of 2 Bodys is the following:
Let's say we have a Player, defined by a Body. This Body contains 2 Fixtures: headFixture, a circle repressenting it's head and bodyFixture, a rectangle, repressenting the hitbox of the Players body and feet.
Now, if a Bullet (a Body with one Fixture) hits our Player, it may make a difference, if it hits its body or its head.
So basicly a Body repressents our whole object, the Player, while the Fixtures repressent some parts of it, which are used for the physics-calculation.
If you only want to handle collissions per Body, you can get the Body by calling fixtureA().getBody().

Binding sprite movement to the camera or scene (AndEngine)

I am using DigitalOnScreenControl to Move Player Sprite.But the Problem is that My Player Sprite goes out of Emulator Screen.I want player sprite be restricted to move in particular bounds and also camera to focus on player sprite as and when my sprite moves on.
i am trying this code:
public Scene onLoadScene() {
// Auto-generated method stub
this.mEngine.registerUpdateHandler(new FPSLogger());
final Scene mScene=new Scene();
mScene.setBackground(new ColorBackground(0.09804f, 0.6274f, 0.8784f));
final int centerX=(CAMERA_WIDTH-this.mPlayerTextureRegion.getWidth())/2;
final int centerY=(CAMERA_HEIGHT-this.mPlayerTextureRegion.getHeight())/2;
final Sprite player=new Sprite(centerX, centerY, this.mPlayerTextureRegion);
this.mCamera.setChaseEntity(player);
final PhysicsHandler physicsHandler=new PhysicsHandler(player);
player.registerUpdateHandler(physicsHandler);
mScene.attachChild(player);
this.mDigitalOnScreenControl=new DigitalOnScreenControl(0,CAMERA_HEIGHT-mOnScreenControlBaseTextureRegion.getHeight(),this.mCamera,this.mOnScreenControlBaseTextureRegion,this.mOnScreenControlKnobTextureRegion,0.1f,new IOnScreenControlListener() {
#Override
public void onControlChange(BaseOnScreenControl pBaseOnScreenControl,
float pValueX, float pValueY) {
// TODO Auto-generated method stub
physicsHandler.setVelocity(pValueX*100, pValueY*100);
}
});
this.mDigitalOnScreenControl.getControlBase().setBlendFunction(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
this.mDigitalOnScreenControl.getControlBase().setAlpha(0.5f);
this.mDigitalOnScreenControl.getControlBase().setScaleCenter(0, 128);
this.mDigitalOnScreenControl.getControlBase().setScale(1.25f);
this.mDigitalOnScreenControl.getControlKnob().setScale(1.25f);
this.mDigitalOnScreenControl.refreshControlKnobPosition();
mScene.setChildScene(this.mDigitalOnScreenControl);
return mScene;
}
Honestly I am Very new in andEngine Development
please Help me With Heart
Thank in advance.
Binding the Player to the Camera
What you're asking for is a form of collision handling. Essentially, when you've moved the player outside of the scene, you want to move the player back into the scene, and you want to do that in the same update as you've moved the player, immediately after moving the player, so the out-of-scene location never gets rendered.
Lets take apart what I just said. You move the player here:
physicsHandler.setVelocity(pValueX*100, pValueY*100);
Moving the player with a physicsHandler is perfectly reasonable and takes into account variable frame-rate so, so far, good job. Now you want to move them back into the scene if they're outside it. So we're going to need a new method. Lets throw in a method call right after moving the player (we'll call it "adjustToSceneBinding()" so you have this:
physicsHandler.setVelocity(pValueX*100, pValueY*100);
adjustToSceneBinding(player);
Sidenote, I'd rather have this method be on the player (i.e., player.adjustToSceneBinding()), but your player object is just a sprite. I'd suggest you change that to a custom object that extends sprite so you can throw in your own code there. In any event, lets make the adjustToSceneBinding() method.
public boolean adjustToSceneBinding(Sprite player) {
// Correct the X Boundaries.
if (player.getX() < 0) {
player.setX(0);
} else if (player.getX() + player.getWidth() > CAMERA_WIDTH) {
player.setX(CAMERA_WIDTH - player.getWidth());
}
}
See what I did? If the player's X coordinate is less than zero, move them back to zero. If the player's X PLUS the player's width is more than the camera width, move them back to the camera width minus the player width. Don't forget the player X coordinate represents the left side of the sprite. That's why I'm taking into account the width in addition to the position for calculating the right side.
The above code only addresses left/right movement, but I'm going to let you extrapolate how to do the same for up down.
Binding the Player to the Map Size Instead
Now, what we did so far was really intended for the situation where the map "size" is no larger than the screen. But often what you'll want is a larger map than the screen size and a camera that chases the player around. To do that, just replace the code above, where I referred to the CAMERA_WIDTH with a number that represents the width of your "map". In other words, the map can be much larger than the camera. If you use larger numbers there (than, say, the width of the camera), and you set the camera to chase the player entity (as you have), then you'll have a map where the player can move around until they hit the bounds of the map.
Hope this helps! :)

Categories

Resources