Box2D stopping a dynamic body from moving after collision - java

I am trying to re-create Pong using LibGDX and Box2D. I have 2 problems, if I fix one it creates another.
My paddles are currently set to Kinematic and are controlled using the up/down keys via a controller class. This works just fine and I can happily play back and forth.
Problem being, my walls are static bodies and my paddles just travel right through them.
Now I can fix this by simple changing the paddle body to a dynamic one, this stops the paddles from going through the walls but then when my ball strikes off a paddle, it goes flying off the X axis and off the screen.
I have tried adding an update method in my controller class as follows:
public void update(float delta){
paddleBodyPosY = paddleBody.getPosition().x;
paddleBodyPosY = paddleBody.getPosition().y;
System.out.println(paddleBodyPosY);
}
The console reports the paddle position being updated every frame, from top to bottom of screen.
So I went back to my GameScreen class and tried all sorts of code in the Render() method like so:
if(playerOnePaddle.paddleBodyPosY < 0){
playerOnePaddle.paddleBody.getPosition().y = 0;
System.out.println("resetting paddle");
}
I have tried LOADS of variations, I can easily break movement by calling paddleBody.setLinearVelocity(0,0) but then it gets stuck like this and it's not movable anymore. Obviously the problem must lie with the fact that I can't set a position using a getter lol.
Any ideas? If you need more snippets ask, I didn't want to overload the question with 100 lines of code you don't need to see :S.
The paddle creation method:
public void createPaddle(World world, float x, float y){
//Define a body for the paddle
BodyDef paddleBodyDef = new BodyDef();
paddleBodyDef.type = BodyType.KinematicBody;
paddleBodyDef.position.set(x, y);
//Define a shape for the paddle
PolygonShape paddleShape = new PolygonShape();
paddleShape.setAsBox(paddleWidth, paddleHeight);
//Define a fixture for the paddle
FixtureDef paddleFixtureDef = new FixtureDef();
paddleFixtureDef.shape = paddleShape;
paddleFixtureDef.density = 0;
//Ensures ball bounces off paddle
//Consistently without losing velocity
paddleFixtureDef.restitution = 1.005f;
//Create the paddles
paddleBody = world.createBody(paddleBodyDef);
paddleFixture = paddleBody.createFixture(paddleFixtureDef);
paddleShape.dispose();
}

Heh, so what I did was.
Set my paddles to dynamic, then set there mass to a stupidly high number so that the a ball would not move them on the x axis, well not enough for the human eye to see at least.
Seems like a cheap fix, if anyone has anything better...that would be great lol

Related

Collision detection in game of pong corner cases causing issues

I have made a game of pong and everything about it is working so far. I did the collisions against the paddles to the ball and it can correctly bounce them away unless it hits the corners.
This is a video of what happens when the ball hits the corner of one of the paddles.
https://drive.google.com/file/d/1nyRzsp5tn5Qvst7kVjtlr_rDNH98avbA/view?usp=sharing
Essentially what you can see happen in the video is the ball hits the the paddle on the left at the corner and it doesn't bounce back it just traverses the paddle downwards and then keeps going and they get a point. Here is my code for the collision testing
public void collision() {
this.width = (float) getBounds().width;
this.height = (float) getBounds().height;
for (int i = 0; i < handler.objects.size(); i++) {
if (handler.objects.get(i).getId() == ID.ball) {
GameObject current = handler.objects.get(i);
if (getBounds().intersects(current.getBounds())) {
current.setVx(current.getVx() * -1);
}
}
}
}
getBounds is an overridden method that just returns a rectangle for both the ball(which is a circle) and the paddle
I am happy to provide more of my code if necessary.
Any help on this would be great, thanks!
You are swapping the velocity direction each time you are hitting the paddle, even when you are still touching the paddle in the next frame. The solution is to swap the velocity direction only when the ball is heading towards the paddle, not when (already) going away. The pseudo code can look like this:
if (GeometryUtil.isDirectionGoingDown(direction)) {
if (GeometryUtil.isBallHittingHorizontalLine(
newPosition,
Ball.RADIUS,
paddleTopLeft,
paddleTopRight)) {
direction = calculateNewDirectionAfterHittingPaddle(
direction,
paddlePosition,
newPosition);
ball.setDirection(direction);
}
}
Here the GeometryUtil.isDirectionGoingDown() method is checking if the ball is actually going down. That way the new direction is only set when this condition returned true. When the direction has been swapped in one frame, the next frame will not swap the direction again because GeometryUtil.isDirectionGoingDown() will return false then.

Confilicting behavior between dynamic and static bodies in Box2d

I have created Chain shapes (static bodies) all around the perimeter of the game screen whose dimensions are:
(2f*camera.viewportWidth,2f*camera.viewportHeight).
Each chain shape has a density of 5f.
I've also created a Circle Shape (dynamic body) whose
density = 0.5f
friction = 0.25f
restitution =0.2f.
In addition, I've created a polygon shape set as a box shape (dynamic body) which has the same density, restitution and friction as the circle shape.
The world's gravity is (0,-5.8f).
All shapes render appropriately. However, the box shape just keeps falling right through the bottom chain shape which is located at the bottom of the screen. The circle shape doesn't go through, but the box shape does go through. I don't want this to happen. The size of the box shape is
(1.96f*camera.viewportWidth, 1.96f*camera.viewportHeight).
The position of this body(box shape) is set to
(0.02f*camera.viewportWidth, 0.02f*camera.viewportHeight).
I don't know why the box shape just keeps falling through and is not stopped by the bottom chain shape, just like the circle shape is stopped. Can anyone provide any insight?
Also, the reason I am trying to set up my box2d world like this is to eliminate some camera lagging movement when I use camera.translate to move around the world. My idea is to move the box shape by applying linear velocities to its body. Please any thoughts would be appreciated.
You probably did not set filtering on those fixtures. Take a look at the following example
FixtureDef f = new FixtureDef();
f.density = density;
f.friction = friction;
f.restitution = restitution;
now if you want Box2D to handle collisions for you, you should tell it which fiture will collide with which and you are doing it by assigning categoryBits and maskBits like this:
f.filter.categoryBits = categoryBits; //who am I?
f.filter.maskBits = maskBits; //with who I will collide?
Bits should be short type and power of two - you cannot have two bits defined as same value. You can set many maskBits by using logical sum ('|' operator).
public static final short BIT_F1 = 2;
public static final short BIT_F2 = 8;
public static final short BIT_F3 = 32;
FixtureDef f1, f2, f3;
//creating f1, f2, f3...
f1.filter.categoryBits = BIT_F1;
f2.filter.categoryBits = BIT_F2;
f3.filter.categoryBits = BIT_F3;
f1.filter.maskBits = BIT_F1; //now every body having f1 fixture will collide with another f1
f2.filter.maskBits = BIT_F1; //f2 will collide with f1
f3.filter.maskBits = (short)(BIT_F1 | BIT_F2 | BIT_F3); //f3 collides with everything
Please notice that if you want fixture to avoid any collision you can it to be a sensor like:
f.isSensor = sensor;
Here is link to official documentation although it is not very helpful to be honest.

Libgdx chainshape position

I'm trying to make a game where the player ( the circle ) has to collect some stars. The stars will be at different positions and in order to get the stars the player must draw ramps in order to reach the stars. Picture below.
http://3w-bg.org/game/pic.PNG
The red line is where the user has drawn on the screen.
Ok so i capture the coordinates when the user touches and drags on the screen and then i use this coordinates to create a ChainShape for the line. The problem is that the line is drawn nowhere near the touched area. Picture below.
http://3w-bg.org/game/pic2.PNG
The world and the screen positions are not the same to my understanding. So how can i draw the chainshape line exactly where the user has touched. Tried camera.project/unproject but that didn't help.
Usually when using Box2D you should have some kind of pixel-to-meter ratio defined. This is done in order to keep the coordinates in your physics world smaller to keep numeric stability.
When using a Camera and a constant PIXEL_TO_METER to convert the values, you can convert your coordinates like this:
public static Vector2 screenToPhysics(Camera camera, Vector2 screenPos) {
Vector3 worldPos = camera.unproject(new Vector3(screenPos.x, screenPos.y, 0));
return new Vector2(worldPos.x, worldPos.y).scl(1f / PIXEL_TO_METER);
}
public static Vector2 physicsToScreen(Camera camera, Vector2 physicsPos) {
Vector3 worldPos = new Vector3(physicsPos.x, physicsPos.y, 0).scl(PIXEL_TO_METER);
Vector3 screenPos = camera.project(worldPos);
return new Vector2(screenPos.x, screenPos.y);
}

Why can't I remove and draw the same java object?

I try to do homework, and I write breakout game. Now,I write the basic function of this game finish.but I want to increase Bonus When ball crash the bonusbricks,I write method to check them and get the color form object that ball crash.
} else if(color == Color.BLACK){
double xBonus = ball.getX() +20;
double yBonus = ball.getY() +20;
remove(ball);
ball = new GOval(xBonus, yBonus, BALL_RADIUS+20, BALL_RADIUS+20);
ball.setFilled(true);
ball.setFillColor(Color.RED);
add(ball);
GObject collider = getCollidingObject();
I use collider to detect the object that ball crash
but when the ball crash the bonus brick. The ball has increase size but collider is detect new ball object to be the bricks and bounce ball though game edge.
Please help me .. Sorry,for my wrong grammatically.
I believe you want to use * 20 on your ball.getX and ball.getY assignments.
It sounds like the new ball object is not in the same instance as the original game panel. You should make sure you are accepting the new ball object in the same instance on the panel that the game is played.
If you show some more of your code I may be able to be more specific.

MouseJointDef libgdx - draw a trajectory line like Angry Birds

in libgdx game
I want to touchDown and then drag somewhere and then on the release (touchUp) apply a directional force based on the distance and direction from the target body. When you touchdown the target body stays still and then on touchup the force is applied along the desired trajectory.
(very similar to Angry birds - where you get to see the trajectory in dotted lines for the target body when you hold hack the slingshot - I want to do the same)
So I guess that this might not be the hardest thing to do but given a few options Im leaning towards using a MouseJointDef but its an immediate force applied (i.e. the target moves immediately - I want it to stay still and then once the touchup event happens then apply the force)
Whats the easiest way to draw the trajectory also? Im using Box2D also.
Create a class that inherits InputAdapter class, then create an instance of it and register it to listen the touch inputs.
Gdx.input.setInputProcessor(inputAdapter);
There are 3 methods to handle the touch events touch_down, touch_dragged and touch_up that you have to override.
In touch_down, check the touching position to whether is in the birds area or not. If it is, make a boolean flag true.
In touch_dragged, check the flag above and if it was true, calculate the distance of the touch position relative to the bird shooting center and the shooting angle.
In touch_up, you can order to shoot with the calculated amounts by calling
body2shoot.applyLinearImpulse(impulse, body2shoot.getWorldCenter());
There is no need to MouseJointDef to move the body2shoot. Just set the transform of body2shoot in touching position to be dragged in each cycle of render.
For calculating the trajectory I wrote a class like this:
public class ProjectileEquation
{
public float gravity;
public Vector2 startVelocity = new Vector2();
public Vector2 startPoint = new Vector2();
public ProjectileEquation()
{ }
public float getX(float t)
{
return startVelocity.x*t + startPoint.x;
}
public float getY(float t)
{
return 0.5f*gravity*t*t + startVelocity.y*t + startPoint.y;
}
}
and for drawing it just I set the startPoint and startVelocity and then in a loop I give a t (time) incrementally and call getX(t) and getY(t).

Categories