My Game screen with libgdx zoom out on android - java

I'm learning libgdx (java) game programming and I just finished my first game : a simple Brick Destroyer.
I made a desktop and android project. After some hours of "hard" work, my game finally works fine on desktop. I'm not using scene2D or box2D or anything else for this game (I just implemented the interface "screen" on my classes : GameScreen, MainMenuScreen etc...).
Here is the problem : When I export my game as an .APK file and then install it on my android phone (Sony Xperia Z1 compact), the screen is absolutely different. The ball still reacts well with all other elements (bricks and sides of the screen) but it seems not to be the same zoom. I've tried so much things, I don't know what to do anymore, please help me :).
I'm using a FitViewport and an Orthographic Camera.
See below the screenshots :
1 - The constructor of GameScreen class.
2 - Desktop programm.
3 - Android app.
Thank you all for your answers and sorry for my english if I made mistakes(I'm not an english native speaker).
final Bricks game;
Texture ball_img, plate_img, brique_img_rouge, brique_img_orange, brique_img_vert;
Vector2 posb, posp;
Vector2 vitb, vitp;
OrthographicCamera camera;
Rectangle ball, plate;
Array<Brique> briques;
FitViewport viewport;
final int plate_width = 60, plate_height = 10;
final int brique_width = 35, brique_height = 15;
final int ball_width = 15, ball_height = 14;
boolean left_p, right_p, up_p;
public GameScreen(final Bricks gam) {
this.game = gam;
ball_img = new Texture("ball_bl.PNG");
plate_img = new Texture("plate_bl.PNG");
brique_img_rouge = new Texture("brique_bl_rouge.PNG");
brique_img_orange = new Texture("brique_bl_orange.PNG");
brique_img_vert = new Texture("brique_bl_vert.PNG");
camera = new OrthographicCamera();
viewport = new FitViewport(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), camera);
viewport.apply();
ball = new Rectangle();
plate = new Rectangle();
briques = new Array<Brique>();
briques.add(new Brique(2));
briques.first().x = 50;
briques.first().y = Gdx.graphics.getHeight()-60;
briques.first().width = brique_width;
briques.first().height = brique_height;
posb = new Vector2(Gdx.graphics.getWidth()/2, Gdx.graphics.getHeight()/4);
vitb = new Vector2(0, 400*Gdx.graphics.getDeltaTime());
posp = new Vector2(Gdx.graphics.getWidth()/2 - plate_width/2, 20);
vitp = new Vector2(400*Gdx.graphics.getDeltaTime(), 0);
for (int i = 1; i < 65; i++) {
if( i % 13 == 0) {
briques.add(new Brique(1));
briques.get(i).x = briques.first().x;
briques.get(i).y = briques.get(i-1).y - 35;
briques.get(i).width = brique_width;
briques.get(i).height = brique_height;
} else {
briques.add(new Brique(1));
briques.get(i).x = briques.get(i-1).x + briques.get(i-1).width + 20;
briques.get(i).y = briques.get(i-1).y;
briques.get(i).width = brique_width;
briques.get(i).height = brique_height;
}
if(i > 51 || i == 19 || i == 32) {
briques.get(i).setType(3);
}
if((i < 13 || i %13 == 0 || i == 25 || i >= 38) && i < 52) {
briques.get(i).setType(2);
}
}
ball.x = posb.x;
ball.y = posb.y;
ball.width = ball_width;
ball.height = ball_height;
plate.x = posp.x;
plate.y = posp.y;
plate.width = plate_width;
plate.height = plate_height;
I think the problem comes from here, but it works on desktop.
camera = new OrthographicCamera();
viewport = new FitViewport(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), camera);
viewport.apply();
Desktop : Desktop programm
Android : android app from .APK file

This happens, since you use a FitViweport with a virtual screen size of the actual screen size. Since your desktop app and android phone have a different resolution, you get different viewports.
So for your desktop app the camera code might actually "look" like this:
camera = new OrthographicCamera();
viewport = new FitViewport(800, 600, camera);
viewport.apply();
And for you android it might actually "look" like this:
camera = new OrthographicCamera();
viewport = new FitViewport(400, 700, camera);
viewport.apply();
To solve that define an inner virtual world size, so that for both the world size is for example VIRTUAL_WIDTH x VIRTUAL_HEIGHT. This size must not be in pixels:
// Global static field in your game class
public static int VIRTUAL_WIDTH = XXX;
public static int VIRTUAL_HEIGHT = XXX;
// ...
camera = new OrthographicCamera();
viewport = new FitViewport(VIRTUAL_WIDTH, VIRTUAL_HEIGHT, camera);
viewport.apply();
This means that instead of using Gdx.graphics.getWidth() or Gdx.graphics.getHeight() you use these values, respectively, since you now work in your virtual screen size.
For example here in your code:
posb = new Vector2(VIRTUAL_WIDTH / 2f, VIRTUAL_HEIGHT / 4f);
For your out of screen problem:
Check how you draw your blocks, do you use Gdx.graphics.getXXX() or values that exceed your new size limit?

Related

Kinect for Processing error when using multiple cameras

I'm trying to run two Kinect V1 cameras simultaneously in Processing 3. I have gotten to a solution that is not sustainable, and am I trying to make something more stable/reliable.
At the moment, whenever I try to run both cameras simultaneously on a single sketch, I am hit with the error
"Could not claim interface on camera: -3
Failed to open camera subdevice or it is not disabled.Failed to open motor subddevice or it is not disabled.Failed to open audio subdevice or it is not disabled.There are no kinects, returning null"
One camera opens, the other does not. It is not always consistent which camera opens, which leads me to believe there's something tripping over permissions after the objects are created, or when the second object is initialized.
My code is as such
import SimpleOpenNI.*;
import org.openkinect.freenect.*;
import org.openkinect.freenect2.*;
import org.openkinect.processing.*;
import org.openkinect.tests.*;
//Imported libraries
//Some might be unnecessary but I don't have time to check
//Better safe than sorry, maybe I'll delete later
Kinect kinect;
Kinect kinect2;
PImage depthImage;
PImage depthImage2;
//Set depth threshold
float minDepth = 996;
float maxDepth = 2493;
float iWidth1 = 0;
float iHeight1 = 0;
float iWidth2 = 0;
float iHeight2 = 0;
//Double check for the number of devices, mostly for troubleshooting
int numDevices = 0;
//control which device is being controlled (in case I want device control)
int deviceIndex = 0;
void setup() {
//set Arbitrary size
size(640, 360);
//Set up window to resize, need to figure out how to keep things centered
surface.setResizable(true);
//not necessary, but good for window management. Window label
surface.setTitle("KINECT 1");
//get number of devices, print to console
numDevices = Kinect.countDevices();
println("number of V1 Kinects = "+numDevices);
//set up depth for the first kinect tracking
kinect = new Kinect(this);
kinect.initDepth();
//Blank Image
depthImage = new PImage(kinect.width, kinect.height);
//set up second window
String [] args = {"2 Frame Test"};
SecondApplet sa = new SecondApplet();
PApplet.runSketch(args, sa);
}
//Draw first window's Kinect Threshold
void draw () {
if ((width/1.7778) < height) {
iWidth1 = width;
iHeight1 = width/1.7778;
} else {
iWidth1 = height*1.7778;
iHeight1 = height;
}
//Raw Image
image(kinect.getDepthImage(), 0, 0, iWidth1, iHeight1);
//Threshold Equation
int[] rawDepth = kinect.getRawDepth();
for (int i=0; i < rawDepth.length; i++) {
if (rawDepth[i] >= minDepth && rawDepth[i] <= maxDepth) {
depthImage.pixels[i] = color(255);
} else {
depthImage.pixels[i] = color(1);
}
}
}
public class SecondApplet extends PApplet {
public void settings() {
//arbitrary size
size(640, 360);
kinect2 = new Kinect(this);
kinect2.initDepth();
//Blank Image
depthImage2 = new PImage(kinect2.width, kinect2.height);
}
void draw () {
if ((width/1.7778) < height) {
iWidth2 = width;
iHeight2 = width/1.7778;
} else {
iWidth2 = height*1.7778;
iHeight2 = height;
}
image(kinect2.getDepthImage(), 0, 0, iWidth2, iHeight2);
surface.setResizable(true);
surface.setTitle("KINECT 2");
int[] rawDepth2 = kinect2.getRawDepth();
for (int i=0; i < rawDepth2.length; i++) {
if (rawDepth2[i] >= minDepth && rawDepth2[i] <= maxDepth) {
depthImage2.pixels[i] = color(255);
} else {
depthImage2.pixels[i] = color(1);
}
}
}
}
Curiously, the code returns a confirmation that there are two kinect devices connected in the console. For some reason, it cannot access both at the same time.
I'm not a very experienced code, so this code might look amateur. Open to feedback on other parts, but really just looking to solve this problem.
This code returns the error pasted above when there are two Kinect V1's connected to the computer.
Running Mac OS11.6.8 on an Intel MacBook Pro
Using Daniel Schiffman's OpenKinect for Processing as a starting point for the code.
I've run a successful iteration of this code with a slimmed down version of Daniel Schiffman's Depth Threshold example.
import org.openkinect.freenect.*;
import org.openkinect.processing.*;
Kinect kinect;
// Depth image
PImage depthImg;
// Which pixels do we care about?
// These thresholds can also be found with a variaty of methods
float minDepth = 996;
float maxDepth = 2493;
// What is the kinect's angle
float angle;
void setup() {
size(1280, 480);
kinect = new Kinect(this);
kinect.initDepth();
angle = kinect.getTilt();
// Blank image
depthImg = new PImage(kinect.width, kinect.height);
}
void draw() {
// Draw the raw image
image(kinect.getDepthImage(), 0, 0);
// Calibration
//minDepth = map(mouseX,0,width, 0, 4500);
//maxDepth = map(mouseY,0,height, 0, 4500);
// Threshold the depth image
int[] rawDepth = kinect.getRawDepth();
for (int i=0; i < rawDepth.length; i++) {
if (rawDepth[i] >= minDepth && rawDepth[i] <= maxDepth) {
depthImg.pixels[i] = color(255);
} else {
depthImg.pixels[i] = color(0);
}
}
// Draw the thresholded image
depthImg.updatePixels();
image(depthImg, kinect.width, 0);
//Comment for Calibration
fill(0);
text("TILT: " + angle, 10, 20);
text("THRESHOLD: [" + minDepth + ", " + maxDepth + "]", 10, 36);
//Calibration Text
//fill(255);
//textSize(32);
//text(minDepth + " " + maxDepth, 10, 64);
}
Using this code, I was able to get both cameras operating using the following process:
Connect a single Kinect v1 to the computer
Open and run the above code
Duplicate the sketch file
Connect the second Kinect V1 to the computer
Open and run the duplicated sketch of the same code
This worked for my purposes and remained stable for an extended period of time. However, this isn't a sustainable solution if anyone other than me wants to utilize this program.
Any help with this problem would be greatly appreciated

Camera doesnt rotate x axis using javafx

ive been using javafx recently and while i was doing so ive caught a problem in my code but spending a lot of time on it (mostly googling it) i cannot find the solution to my problem.
The problem happens when i try to rotate the camera using the x axis but instead of doing what i was wanting to happen instead it rotates around (0,0,0). Im not sure if it does rotate around (0,0,0) but that was the solution i could figure out. My camera starts staring at a cube but when tun left (adds 2 to the x axis) and the box goes a big circle. When turning right the box moves the other way around the circle. When applying the axis to the box, the box goes around fine.
My code is a bit messy but what i tried is to get the movement of turning and the box should go left if i turn right and right if i turn left as if in real life how it works.
public class javafx extends Application {
int ze = 0;
int ye = 0;
int xe = 0;
PerspectiveCamera cam = new PerspectiveCamera();
//the rotation angles//
Rotate rx = new Rotate();
{ rx.setAxis(Rotate.X_AXIS); }
Rotate ry = new Rotate();
{ ry.setAxis(Rotate.Y_AXIS); }
Rotate rz = new Rotate();
{ rz.setAxis(Rotate.Z_AXIS); }
int xt = 0;
int yt = 0;
int one;
int two;
boolean flip = false;
public static void addRotate(Node node, Point3D rotationAxis,
double angle) {
ObservableList<Transform> transforms = node.getTransforms();
try {
for (Transform t : transforms) {
rotationAxis = t.inverseDeltaTransform(rotationAxis);
}
} catch (NonInvertibleTransformException ex) {
throw new IllegalStateException(ex);
}
transforms.add(new Rotate(angle, rotationAxis));
}
public void start(Stage stage) {
Box cube = new Box();
cam.getTransforms().addAll(rx, rz, ry);
cube.setDepth(100.0);
cube.setHeight(100.0);
cube.setWidth(200.0);
cube.setCullFace(CullFace.BACK);
cube.setDrawMode(DrawMode.FILL);
PhongMaterial material = new PhongMaterial();
material.setDiffuseColor(Color.BROWN);
cube.setMaterial(material);
cube.setTranslateX(1500.0);
cube.setTranslateY(500.0);
cube.setTranslateZ(0.0);
cam.setTranslateX(0);
cam.setTranslateY(0);
cam.setTranslateZ(0);
cam.setScaleX(2);
cam.setScaleY(2);
cam.setScaleZ(2);
Group root = new Group(cube, cam);
Dimension dimension =
Toolkit.getDefaultToolkit().getScreenSize();
double screenHeight = dimension.getHeight();
double screenWidth = dimension.getWidth();
Scene scene = new Scene(root, 0,0);
stage.setFullScreen(true);
scene.setCamera(cam);
stage.setTitle("3d space");
stage.setScene(scene);
stage.show();
stage.setOnHiding( event -> { System.exit(0);} );
//to get the input from a mouse vvvv //
ScheduledExecutorService scheduler =
Executors.newScheduledThreadPool(1);
Runnable toRun;
toRun = new Runnable() {
public void run() {
if(!flip){
one = MouseInfo.getPointerInfo().getLocation().x;
two = MouseInfo.getPointerInfo().getLocation().x;
flip = true;
}else{
flip = false;
if(one > MouseInfo.getPointerInfo().getLocation().x){
xt = xt +2;
ry.setAngle(xt);
System.out.println("left");
}else{
if(one < MouseInfo.getPointerInfo().getLocation().x){
System.out.println("right");
xt = xt -2;
ry.setAngle(xt);
}
}
}
}
};
ScheduledFuture<?> handle = scheduler.scheduleAtFixedRate(toRun, 1, 1, TimeUnit.MILLISECONDS);
}
public static void main(String args[]){
launch(args);
}
}
the answer is cam.set.pivot(222) to the area it circles around, also you can rotate everything around the camera

Libgdx sidebar like in Tibia

I'm new to LibGDX and I'm trying to make a simple RPG game.
I've implemented a basic movement & combat system.
Now I would like to add a sidebar with inventory, character information etc. (like in Tibia).
Then I would like to add a bottom bar too.
However, I don't know how to accomplish that. I've read that adding 2nd stage could be a solution, but I don't know how implement it into my code.
screen how that supposed to look like
Here is my current code with render method:
public class Game extends ApplicationAdapter {
private final static int TURN_DURATION_IN_MILLIS = 2000;
TiledMap tiledMap;
OrthographicCamera gameCamera;
OrthographicCamera guiCamera;
private Map renderer;
Player player;
Monster rat;
private Map.Drawing playerDrawing;
private Map.Drawing ratDrawing;
private SpriteBatch sb;
BitmapFont font;
BitmapFont font2;
Stage stage;
float guiToCameraRatioX;
float guiToCameraRatioY;
long lastTurn;
#Override
public void create() {
sb = new SpriteBatch();
tiledMap = new TmxMapLoader().load("map.tmx");
renderer = new Map(tiledMap, 1 / TILE_CELL_IN_PX, sb);
gameCamera = new OrthographicCamera(NUMBER_OF_TILES_HORIZONTALLY, NUMBER_OF_TILES_VERTICALLY);
gameCamera.update();
guiCamera = new OrthographicCamera(GAME_WINDOW_WIDTH, GAME_WINDOW_HEIGHT);
guiCamera.update();
guiToCameraRatioX = guiCamera.viewportWidth / gameCamera.viewportWidth;
guiToCameraRatioY = guiCamera.viewportHeight / gameCamera.viewportHeight;
player = new Player();
playerDrawing = new Map.Drawing(true, null, player.positionX - 0.5f, player.positionY + 0.5f, player.width, player.height, gameCamera, guiCamera);
player.initHealthPointsBar();
renderer.addCreature(player);
stage = new TiledMapStage(tiledMap, player);
Gdx.input.setInputProcessor(stage);
stage.getViewport().setCamera(gameCamera);
rat = new Monster(MonsterType.RAT);
ratDrawing = new Map.Drawing(false, null, rat.positionX, rat.positionY, rat.width, rat.height, gameCamera, guiCamera);
renderer.addDrawing(ratDrawing);
renderer.addDrawing(playerDrawing);
rat.initHealthPointsBar();
renderer.addCreature(rat);
initFont();
}
private void initFont() {
FreeTypeFontGenerator generator = new FreeTypeFontGenerator(Gdx.files.internal("martel.ttf"));
FreeTypeFontGenerator.FreeTypeFontParameter parameter = new FreeTypeFontGenerator.FreeTypeFontParameter();
parameter.size = 10;
parameter.color = new Color(0, 0.75f, 0.15f, 1);
parameter.borderWidth = 1.2f;
font = generator.generateFont(parameter);
parameter.size = 12;
parameter.color = new Color(0.8f, 0.1f, 0.1f, 1);
font2 = generator.generateFont(parameter);
generator.dispose();
}
#Override
public void render() {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
float deltaTime = Gdx.graphics.getDeltaTime();
player.updateState(deltaTime);
rat.updateState(deltaTime);
gameCamera.position.set(player.positionX + 0.5f, player.positionY + 0.5f, 0);
gameCamera.update();
renderer.setView(gameCamera);
renderer.render();
stage.act();
playerDrawing.x = player.positionX;
playerDrawing.y = player.positionY;
ratDrawing.x = rat.positionX;
ratDrawing.y = rat.positionY;
//TODO implement real combat system
if (System.currentTimeMillis() - lastTurn >= TURN_DURATION_IN_MILLIS) {
lastTurn = System.currentTimeMillis();
if (rat.state != Creature.State.DEAD && Math.abs(rat.positionX - player.positionX) < 2 && Math.abs(rat.positionY - player.positionY) < 2) {
player.givenHit = (int) (Math.random() * rat.attack + 1) * 2 - player.defence / 2;
player.currentHealthPoints -= player.givenHit;
rat.givenHit = (int) (Math.random() * player.attack + 1) * 2 - rat.defence / 2;
rat.currentHealthPoints -= rat.givenHit;
if (rat.currentHealthPoints <= 0) {
rat.currentHealthPoints = 0;
rat.state = Creature.State.DEAD;
rat.moveDestinationX = -1;
rat.moveDestinationY = -1;
}
} else {
player.givenHit = 0;
rat.givenHit = 0;
}
}
// used solution below https://stackoverflow.com/questions/20595558/libgdx-sprite-batch-font-bad-scale-rendering
player.renderPlayer(font, font2, playerDrawing, sb, guiCamera.position.x - (gameCamera.position.x - player.positionX) * guiToCameraRatioX, guiCamera.position.y - (gameCamera.position.y - player.positionY) * guiToCameraRatioY, player.givenHit, System.currentTimeMillis() - lastTurn);
rat.renderMonster(font, font2, ratDrawing, sb, guiCamera.position.x - (gameCamera.position.x - rat.positionX) * guiToCameraRatioX, guiCamera.position.y - (gameCamera.position.y - rat.positionY) * guiToCameraRatioY, rat.givenHit, System.currentTimeMillis() - lastTurn);
}
#Override
public void dispose() { // SpriteBatches and Textures must always be disposed
sb.dispose();
}
I appreciate any help :)
You already have a guiCamera in your Game class. This one can be used to draw the sidebar (or anything else that doesn't move with the rest of the map).
If this camera is already used (e.g. for a menu), you could create a new one, so it can be changed if needed (without changing the menu, or whatever it is used for).
Basically you just need to set the camera's projection matrix to you SpriteBatch (maybe better use a new SpriteBatch for this) and start drawing.
A solution could look like this:
private SpriteBatch sb2; // better use a different sprite batch here (and initialize it in your create method, just like the other one)
// ...
#Override
public void render() {
// ... other rendering stuff ...
// set the projection matrix
sb2.setProjectionMatrix(guiCamera.combined);
sb2.begin();
// draw whatever you want on your sidebar to appear
// all things you draw here will be static on the screen, because the guiCamera doesn't move with the player, but stays in it's position
// when you are ready drawing, end the SpriteBatch, so everything is actually drawn
}
sb2.end();

LibGDX: boundsInFrustrum and BoundingBox not working as expected

I am loading a box2d scene from a json file. This scene contains a fixture marking the bounding box that the camera is allowed to travel in. Using this mechanism works fine for the lower and left bounds, yet fails completely for the upper and right bounds, which is rather odd.
Here is the part that loads the bounding box from the file:
PolygonShape shape = ((PolygonShape) fixture.getShape());
Vector2 vertex = new Vector2();
float boundLeft = world.startX, boundRight = world.startX, boundUp = world.startY, boundLow = world.startY; // The location of the camera as initial value
for (int i = 0; i < shape.getVertexCount(); i++) { // Itarate over each vertex in the fixture and set the boundary values
shape.getVertex(i, vertex);
vertex.add(body.getPosition());
boundLeft = Math.min(vertex.x, boundLeft);
boundLow = Math.min(vertex.y, boundLow);
boundRight = Math.max(vertex.x, boundRight);
boundUp = Math.max(vertex.y, boundUp);
}
// Build the bounding boxes with enough thickness to prevent tunneling on fast pans
world.boundLeft = new BoundingBox(new Vector3(boundLeft - 5, boundLow - 5, 0).scl(RenderingSystem.PPM), new Vector3(boundLeft, boundUp + 5, 0).scl(RenderingSystem.PPM));
world.boundRight = new BoundingBox(new Vector3(boundRight, boundLow - 5, 0).scl(RenderingSystem.PPM), new Vector3(boundRight + 5, boundUp + 5, 0).scl(RenderingSystem.PPM));
world.boundUp = new BoundingBox(new Vector3(boundLeft - 5, boundUp, 0).scl(RenderingSystem.PPM), new Vector3(boundRight + 5, boundUp + 5, 0).scl(RenderingSystem.PPM));
world.boundLow = new BoundingBox(new Vector3(boundLeft - 5, boundLow - 5, 0).scl(RenderingSystem.PPM), new Vector3(boundRight + 5, boundLow, 0).scl(RenderingSystem.PPM));
// world is a class containing some properties, including these BoundingBoxes
// RenderingSystem.PPM is the amount of pixels per metre, in this case 64
And the following part is called when the camera is panned around:
public void pan(float x, float y) {
Vector3 current = new Vector3(camera.position);
camera.translate(-x, y);
camera.update(true);
if (camera.frustum.boundsInFrustum(world.boundLeft) || camera.frustum.boundsInFrustum(world.boundRight)) {
camera.position.x = current.x; // Broke bounds on x axis, set camera back to old x
camera.update();
}
if (camera.frustum.boundsInFrustum(world.boundLow) || camera.frustum.boundsInFrustum(world.boundUp)) {
camera.position.y = current.y; // Broke bounds on y axis, set camera back to old y
camera.update();
}
game.batch.setProjectionMatrix(camera.combined);
}
Well, I figured it out. Guess what my world.startx and world.startY were defined as? That's right, they were in screen coordinates:
world.startX = start.getPosition().x * RenderingSystem.PPM;
world.startY = start.getPosition().y * RenderingSystem.PPM;
This was causing the Math.max to always pick the world.startX and world.startY as these values were absolutely massive in comparison.

PulleyJoint odd behaviour Box2D

I am trying to build a lever in an android game using box2d and libgdx. When the game starts, the 2 platforms of the lever are balancing perfectly and when I move a box on one platform of the lever, it goes down as expected but when I move the body out, the 2 platforms doesn't balance again as before.
I am using this code to create the 2 platforms:
private Body setupShape(World world, float cx, float cy, float cw, float ch){
Body ptf;
PolygonShape shape = new PolygonShape();
shape.setAsBox(cw / 2, ch / 2);
FixtureDef fdef = new FixtureDef();
fdef.shape = shape;
fdef.density = 1.0f;
fdef.friction = 1.0f;
fdef.restitution = 0.0f;
BodyDef bd = new BodyDef();
//bd.allowSleep = false;
bd.position.set(cx, cy);
bd.fixedRotation = true;
ptf = world.createBody(bd);
//lever.setGravityScale(10);
ptf.createFixture(fdef);
ptf.setType(BodyDef.BodyType.DynamicBody);
ptf.setUserData("Lever");
shape.dispose();
return ptf;
}
And this code for creating the lever using "PulleyJoint":
PulleyJointDef pulleyDef = new PulleyJointDef();
Vector2 bodyoneanchor = new Vector2(Constants.Pixel2SIf(360), Constants.Pixel2SIf(400));
Vector2 bodytwoanchor = new Vector2(Constants.Pixel2SIf(660), Constants.Pixel2SIf(400));
pulleyDef.initialize(bodyA, bodyB, bodyoneanchor, bodytwoanchor, bodyA.getWorldCenter(), bodyB.getWorldCenter(), 1);
world.createJoint(pulleyDef);
I would like to know what's wrong with my code and how to make the lever re-balance again after moving out objects from it.
Here's a drawing to demonstrate my problem more clearly:
http://costheta.net/quest.png
It will be very much appreciated if you could help me fixing that problem.
Best regards!
UPDATE:
Here's my new code after adding Prismatic joints:
PulleyJointDef pulleyDef = new PulleyJointDef();
Vector2 bodyoneanchor = new Vector2(Constants.Pixel2SIf(360), Constants.Pixel2SIf(400));
Vector2 bodytwoanchor = new Vector2(Constants.Pixel2SIf(660), Constants.Pixel2SIf(400));
pulleyDef.initialize(bodyA, bodyB, bodyoneanchor, bodytwoanchor, bodyA.getWorldCenter(), bodyB.getWorldCenter(), 1);
world.createJoint(pulleyDef);
BodyDef bd0 = new BodyDef();
bd0.position.set(bodyoneanchor.x, bodyoneanchor.y);
Body ptf0 = world.createBody(bd0);
PrismaticJointDef pjd0 = new PrismaticJointDef();
pjd0.initialize(ptf0, bodyA, ptf0.getWorldCenter(), new Vector2(0, 1));
pjd0.motorSpeed = 200f;
pjd0.maxMotorForce = 30.0f;
pjd0.enableMotor = true;
pjd0.lowerTranslation = -Math.abs(bodyA.getWorldCenter().y - bodyoneanchor.y);
pjd0.upperTranslation = 0;//Math.abs(bodyA.getWorldCenter().y - bodyoneanchor.y);
pjd0.enableLimit = true;
world.createJoint(pjd0);
BodyDef bd1 = new BodyDef();
bd1.position.set(bodytwoanchor.x, bodytwoanchor.y);
Body ptf1 = world.createBody(bd1);
PrismaticJointDef pjd1 = new PrismaticJointDef();
pjd1.initialize(ptf1, bodyB, ptf1.getWorldCenter(), new Vector2(0, 1));
pjd1.motorSpeed = 200f;
pjd1.maxMotorForce = 30.0f;
pjd1.enableMotor = true;
pjd1.lowerTranslation = -Math.abs(bodyB.getWorldCenter().y - bodytwoanchor.y);
pjd1.upperTranslation = 0;//Math.abs(bodyB.getWorldCenter().y - bodytwoanchor.y);
pjd1.enableLimit = true;
world.createJoint(pjd1);
They shouldn't re-balance because the weight of each side is the same and the tensions cancel each other out, resulting in no movement (get some string and build the setup in real life).
If you want it to re-balance, add a spring on each platform with a length of zero placed on the initial position and center of the box.

Categories

Resources