libgdx, movement specific - java

I have issue with movement. My goal is to make player move once key is pressed for its own width/height. For example:
if (Gdx.input.isKeyJustPressed(Input.Keys.A))
player.position.x = player.position.x-moveSpeed;
that works precise, but I want it more smooth, to move exact distance in a second, but each millisecond a bit, not all at once.
This makes player move smooth, but it's not precise:
if (Gdx.input.isKeyJustPressed(Input.Keys.A))
player.position.x = player.position.x-moveSpeed*deltaTime;
How can I make smooth transition, but precise?

Change (or extend) your player class, so that it contains the following:
class Player {
public final Vector2 position = new Vector2(); // you already have this
public final Vector2 target = new Vector2();
private final float speed = 10f; // adjust this to your needs
private final static Vector2 tmp = new Vector2();
public void update(final float deltaTime) {
tmp.set(target).sub(position);
if (!tmp.isZero()) {
position.add(tmp.limit(speed*deltaTime));
}
}
//The remainder of your Player class
}
Then in your render method you call:
if (Gdx.input.isKeyJustPressed(Input.Keys.A)) {
player.target.x -= moveSpeed; //consider renaming moveSpeed to moveDistance
}
player.update(deltaTime);

Related

problems with multiple cameras and viewports in libgdx

so I am doing what is suppose to be a simple game but I think I might be complicating things. I have a camera for the GameScreen and a viewPort which follow the position of the player and when it reaches to points on the sides, the camera stops following the player and stays in one point.
This by itself works fine, but then I wanted to add the pause menu and some other features in the game, creating a hud class with its own camera and viewport as well as a Stage and a shapeRenderer.
The problem comes when I create the instance of this hud inside my gameScreen, the camera that I am looking while I am playing looks like is the hudCam, which does not follow the player and basically does not let me see the player when it reaches the edges of the screen.
This is my GameScreen Class:
public class GameScreen implements Screen {
WowInvasion game;
ScrollingBackground background;
private OrthographicCamera gameCam;
private Viewport gameViewPort;
/*
Basically I wanna keep the same sprites running while in the menu, playing and till dead
therefore, I'll have a switch statement with cases on where the games at, inside the functions needed. That way I'll keep
the game has a background for the menu and there's no need for running a second screen.
*/
public static final int MAIN_MENU = 0;
public static final int GAME = 1;
private static int state = 1; //current state. starts with MAIN_MENU //DEBUGGING GAME SCREEN
//STAGES
private GameStage gameStage; //game ui
private menuStage mainMenu; //Main menu of the game
private Hud hud;
//Resources
private TextureAtlas atlas; //for the textures most
private Skin skin; //for the styles and fonts
//Sprites
private Player player;
//Shapes
private float progressPower; //for the power to build up
private final float POWER_CHARGED = 1000; //limit to get power
private final float DECREASING_POWER = 20; //limit to get power
public GameScreen(WowInvasion game){
this.game = game;
gameCam = new OrthographicCamera();
gameCam.setToOrtho(false, WowInvasion.WIDTH, WowInvasion.HEIGHT);
gameViewPort = new StretchViewport(WowInvasion.WIDTH, WowInvasion.HEIGHT, gameCam);
progressPower = 0f;
game.wowAssetManager.loadTexturesGameScreen(); // tells our asset manger that we want to load the images set in loadImages method
game.wowAssetManager.loadSkins(); //load the needed skins
game.wowAssetManager.manager.finishLoading(); // tells the asset manager to load the images and wait until finsihed loading.
skin = game.wowAssetManager.manager.get("ui/menuSkin.json");
}
#Override
public void show() {
game.batch.setProjectionMatrix(gameCam.combined);
background = new ScrollingBackground();
atlas = game.wowAssetManager.manager.get(WowAssetManager.GAME_ATLAS); //declaring atlas
mainMenu = new menuStage(gameViewPort, game.batch, skin, game); //pass it so that we only use one batch and one same viewport
gameStage = new GameStage(gameViewPort, game.batch, skin, game);
hud = new Hud(game.batch, skin);
player = new Player(atlas.findRegion("player"), (int) gameCam.viewportWidth / 2, (int) gameCam.viewportHeight / 2);
switch(state){
case MAIN_MENU:
Gdx.input.setInputProcessor(mainMenu);
break;
case GAME:
background.setFixedSpeed(false); //does not work in here
}
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
if(state == GAME) {
background.setFixedSpeed(false);
player.update(delta, gameCam.viewportWidth, gameCam.viewportHeight); //updating player for movement
//really cheap way to charge power with velocity
if(progressPower != POWER_CHARGED) {
progressPower += Math.abs(player.getVelocity().x) + Math.abs(player.getVelocity().y);
progressPower -= DECREASING_POWER;
}
else
progressPower = POWER_CHARGED / 4;
}
mainMenu.act(Math.min(Gdx.graphics.getDeltaTime(), 1 / 30f)); //updating while making sure delta won't be more than 1/30f.
gameStage.act(Math.min(Gdx.graphics.getDeltaTime(), 1 / 30f));
game.batch.begin();
background.updateAndRender(delta, game.batch); //updating scrolling background
player.draw(game.batch);
game.batch.end();
mainMenu.draw(); //draw the menu stage
gameStage.draw(); //draw the ui stage for the game
hud.getStage().draw();
hud.renderRotateMeter();
updateCamera(0, WowInvasion.WIDTH);
System.out.println(player.getPosition().x);
}
public void updateCamera(float startX, float endX){
Vector3 position = gameCam.position;
//linear interpolation : a + (b - a) * lerp
//b = player position
//a = current camera position
//lerp = interpolation factor
position.x = gameCam.position.x + (player.getPosition().x - gameCam.position.x) * .1f;
//making the camera stay when the player gets to close to the sides
if(position.x < startX) {
position.x = startX;
}
if(position.x > endX){
position.x = endX;
}
gameCam.position.set(position);
gameCam.update();
}
#Override
public void resize(int width, int height) {
gameViewPort.update(width, height);
//hud.getViewport().update(width, height);
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
dispose();
}
#Override
public void dispose() {
mainMenu.dispose();
gameStage.dispose();
game.dispose();
hud.dispose();
}
public static void setState(int state) {
GameScreen.state = state;
}
}
And this is my HUD:
public class Hud implements Disposable{
private Stage stage;
private Viewport viewport;
Button buttonPause, buttonResume;
private OrthographicCamera hudCam;
private ShapeRenderer sp; //like a batch for shapes
public Hud(SpriteBatch sb, Skin skin){
hudCam = new OrthographicCamera();
hudCam.setToOrtho(false, WowInvasion.WIDTH, WowInvasion.HEIGHT);
viewport = new StretchViewport(WowInvasion.WIDTH, WowInvasion.HEIGHT, hudCam);
stage = new Stage(viewport, sb);
sp = new ShapeRenderer();
Table table = new Table();
table.top();
//this makes the table the size of the stage
table.setFillParent(true);
buttonPause = new Button(skin, "pause");
buttonPause.setTransform(true);
buttonPause.addListener(new ClickListener(){ //listener to handle event
#Override
public void clicked(InputEvent event, float x, float y) {
}
});
buttonResume = new Button(skin, "resume");
buttonResume.setTransform(true);
buttonResume.setScale(0.5f);
buttonResume.addListener(new ClickListener(){
#Override
public void clicked(InputEvent event, float x, float y) {
buttonResume.setVisible(false);
}
});
table.add(buttonPause);
table.row();
table.add(buttonResume);
stage.addActor(table);
}
public void renderRotateMeter(){
sp.setProjectionMatrix(hudCam.combined);
sp.begin(ShapeRenderer.ShapeType.Filled);
sp.setColor(Color.YELLOW);
sp.rect(hudCam.position.x,hudCam.position.y, WowInvasion.WIDTH / 2, 20);
sp.end();
}
public Viewport getViewport() {
return viewport;
}
public Stage getStage() {
return stage;
}
#Override
public void dispose() {
stage.dispose();
sp.dispose();
}
}
thanks in advance!
EDIT
so I tried passing the gameCam has a parameter to the hud and instead of making a new OrthographicCamera I used that one has the hudCamara as well and well, the movement with the player is perfect except now the thins from the Hud do not move at all..
It looks like you only set projectionMatrix to only HUD camera as seen in
sp.setProjectionMatrix(hudCam.combined);
Try to set it the same to other stuff outside of the HUD class prior to draw call too.
Another thing to keep in mind is that, when you involve using multiple Viewport and Camera in the game as most of the time it will be 1 Viewport matching with 1 Camera and work with another set as in your case. In draw call, you need to call apply() or apply(true) of Viewport class too to tell the system that you will draw based on which viewport thus in turn it will adhere to screen coordinate that was set up by viewport's attaching camera.
So assume you have 2 objects that needed to be called in different viewport consecutively, do it like the following code. The methods call is correct according to libgdx API but variable names are fictional.
// draw objA adhering to viewportA (thus cameraA) <-- assume it's player cam
sb.setProjectionMatrix(cameraA.combined);
viewportA.apply();
objA.draw();
// draw objB adhering to viewportB (thus cameraB) <-- assume it's HUD cam
sb.setProjectionMatrix(cameraB.combined);
viewportB.apply(true); // send in true as for HUD, we always want to center the screen
objB.draw();
In summary, 2 things to keep in mind when drawing objects that use multiple of camera and viewport in consecutive draw call.
Set projection matrix to either SpriteBatch or ShapeRenderer.
Call apply() or apply(true) of Viewport class to let it know you work with this viewport.

how to move randomly generated object to the center of the screen in android Using LIBgdx

I'm a beginner android game programmer, I use LIBgdx
I have a playState class
public PlayState(GameStateManager gsm) {
super(gsm);
obj = new Objects();
cam.setToOrtho(false, Game.WIDTH , Game.HEIGHT);
}
#Override
public void update(float dt) {
obj.update(dt);
}
I have an Objects class
public class Objects {
private Vector2 posObj;
private static final int MOVEMENT = 2;
private Vector2 velo;
private Texture objTx;
private Random rand;
private static final int FLUCTUATION = 400;
public Objects(){
objTX = new Texture("objies.png");
rand = new Random();
posObj = new Vector2(rand.nextInt(FLUCTUATION),rand.nextInt(FLUCTUATION));
velo = new Vector2(0, 0);
}
public void update(float dt){
}
Now, What I'm tring to do is:
Move this randomly generated object to the center of the screen and then dispose.
Serious Help required! Thank-you
Well, you know where your object is and you know where the middle is (Game.WIDTH/2 , Game.HEIGHT/2)
If the center is to the left of the object move it to the left, if center is above move object up etc.
So a very simple solution:
public void update(float delta){
if(posObj.x < Game.WIDTH/2){
velocity.x = MOVEMENT;
}
else {
velocity.x = -MOVEMENT;
}
if(posObj.y < Game.HEIGHT/2){
velocity.y = MOVEMENT;
}
else {
velocity.y = -MOVEMENT;
}
posObj.y += velocity.y * delta;
posObj.x += velocity.x * delta;
}
This might cause your object to jump around the middle without ever really hitting the exact coordinates. So you can check the distance from the object to the middle by adding this method to your object:
public Vector2d getPosition(){
return posObj;
}
And then check for the distance:
if( obj.dst(Game.WIDTH , Game.HEIGHT) <= closeEnough ){
obj = new Objects();
}
closeEnough is a distance you set.

Libgdx multiTouch not working

I'm developing a game , and I'm using Libgdx Library in this game. It will work on Android and must play with two players on one screen. But I can't get the another player inputs. I can play with bottom or top player, but not both.
This is the get input codes:
public class PlayStateInput implements InputProcessor {
private PlayState playState;
private Vector2 touchPos;
private Vector2 bodyCord;
public PlayStateInput(PlayState playState){
this.playState = playState;
touchPos = new Vector2();
bodyCord = new Vector2();
touchPos.x=Gdx.input.getX();
touchPos.y=Gdx.input.getY();
bodyCord.x=playState.getGameWorld().getPaddle().getBody().getPosition().x;
bodyCord.y=playState.getGameWorld().getPaddle().getBody().getPosition().y;
}
#Override
public boolean keyDown(int keycode) {
return false;
}
#Override
public boolean keyUp(int keycode) {
return false;
}
#Override
public boolean keyTyped(char character) {
return false;
}
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
if(playState.getGameWorld().getPuck().getCircleRect().contains(screenX,screenY)){
System.out.println("collision");
}
if(screenY > Gdx.graphics.getHeight()/2 && (pointer <= 2)){
playState.getGameWorld().getPaddle2().setBottomPaddle(true);
}
if(screenY < Gdx.graphics.getHeight()/2 && (pointer <= 2)){
playState.getGameWorld().getPaddle().setTopPaddle(true);
}
return false;
}
And the use this inputs here:
public class Paddle implements GameObject {
private World world;
private Body body;
private Body body2;
private BodyDef bodyDef;
private BodyDef bodyDef2;
private Fixture fixture;
private Fixture fixture2;
private FixtureDef fixtureDef;
private FixtureDef fixtureDef2;
private Circle circleRect;
private Circle circleRect2;
boolean TopPaddle = false;
boolean BottomPaddle = false;
private float PPM=100f;
private float power=100f;
private Vector2 touchPos;
private Sprite sprite;
String koordinatlar;
public Paddle(World world){
this.world = world;
bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.DynamicBody;
bodyDef.position.set((Gdx.graphics.getWidth()/2)/PPM,(Gdx.graphics.getHeight()/3)/PPM);
body = world.createBody(bodyDef);
fixtureDef = new FixtureDef();
fixtureDef.density = 1.0f;
fixtureDef.friction = 1.0f;
fixtureDef.restitution=0.3f;
CircleShape circleShape = new CircleShape();
circleShape.setRadius((Gdx.graphics.getWidth()/16)/PPM);
fixtureDef.shape = circleShape;
fixture = body.createFixture(fixtureDef);
circleRect = new Circle(body.getPosition().x,body.getPosition().y,(Gdx.graphics.getWidth()/16));
Sprite.split(ImageLoader.playButtonRegion.getTexture(),20,20);
sprite = new Sprite(ImageLoader.paddle);
sprite.setSize((Gdx.graphics.getWidth()/8),(Gdx.graphics.getWidth()/8));
sprite.setPosition((Gdx.graphics.getWidth()/2)-30f,(Gdx.graphics.getHeight()/3)-30f);
touchPos = new Vector2();
}
#Override
public void render(SpriteBatch sb) {
sprite.draw(sb);
sprite.setPosition(body.getPosition().x*PPM-30f,body.getPosition().y*PPM-30f);
}
#Override
public void update(float delta) {
touchPos.x=Gdx.input.getX()/PPM;
touchPos.y=Gdx.input.getY()/PPM;
System.out.println(touchPos);
if (TopPaddle) {
body.setLinearVelocity(power*(touchPos.x-body.getPosition().x),power*(touchPos.y-body.getPosition().y));
body.setAngularVelocity(0.0f);
if(Gdx.input.getY()>Gdx.graphics.getHeight()/2){
body.setLinearVelocity(0f,0f);
}
//System.out.println(Gdx.input.getX()+" "+Gdx.input.getY());
}
}
I hope, I made myself clear.
I think I see your problem, you are relying on the fact that only one input is being taken at a time. As a result, you will be ignoring one of the two players if both are giving input simultaneously.
There are multiple ways to go about solving your multi-touch input problem but I'll go about explaining a simple technique - modified from this answer.
To allow both players to take in input you will need two variables - I'll call them topTouchPos and bottomTouchPos. Each of these will be a Vector2 like your current touchPos and they will be calculated as follows (inside your update method):
//Initialise both vectors to vectors that can't be touched (negative)
Vector2 topTouchPos = new Vector2(-1,-1), bottomTouchPos = new Vector2(-1,-1);
//Two people can have up to 20 fingers (most touchscreen devices will have a lower limit anyway)
for (int i = 0; i < 20; i++) {
//Check if this finger ID is touched
if (Gdx.input.isTouched(i)) {
//Classify it as either the top or bottom player
bool bottom = Gdx.input.getY(i) > Gdx.graphics.getHeight()/2;
if (bottom) bottomTouchPos.set(Gdx.input.getX(i), Gdx.input.getY(i));
else topTouchPos.set(Gdx.input.getX(i), Gdx.input.getY(i));
}
}
When you get into your main game code you will have to check for both players. If either topTouchPos or bottomTouchPos are not negative then use their touch values for their respective players.
Hope this helps (I haven't tested any code so beware of any typos).

Libgdx Box2d collision detection using physics body editor

Hy guys,
I am developing a game for android using libgdx. I am completely stuck at the part of detecting collision between two bodies.
I have a player which I create through the function below
public Body createPlayer(String file_path, String fixture_name) {
// 0. Create a loader for the file saved from the editor.
BodyEditorLoader loader = new BodyEditorLoader(Gdx.files.internal(file_path));
// 1. Create a BodyDef, as usual.
BodyDef bd = new BodyDef();
bd.type = BodyDef.BodyType.DynamicBody;
// 2. Create a FixtureDef, as usual.
FixtureDef fd = new FixtureDef();
fd.density = 1;
fd.friction = 0.5f;
fd.restitution = 0.3f;
// 3. Create a Body, as usual.
body= world.createBody(bd);
//body.setBullet(true);
// 4. Create the body fixture automatically by using the loader.
loader.attachFixture(body, fixture_name, fd, 1);
body.setUserData(this);
return body;
}
and an enemy that I create with the same function of the player where I change only the file_path and the fixture_name.
The file_path points to a .json file that I created with box2d editor (site: http://www.aurelienribon.com/blog/projects/physics-body-editor/).
After the creation of the body I draw the player and the enemy with two similar functions ( I only post one):
private void drawPlayer(){
player_sprite = new Sprite(player_TR);
player_sprite.setSize(player.getWidth(), player.getHeight());
player_sprite.setPosition(player.getX(), player.getY());
player_sprite.setOrigin(0, 0);
player_sprite.draw(sb);
}
If I start the game everything is drawn where it should be. Obviously if the player touches the enemy nothing happen.
So i started trying to search how to make the two bodies collides but I don't really understand how to use ContactListener and beginContact.
beginContact wants as input a Contact but what is a Contact?
I have found this code online which appears to solve my problem but I don't know how to use it:
worldbox.setContactListener(new ContactListener() {
#Override
public void beginContact(Contact contact) {
if(contact.getFixtureA().getBody().getUserData()== "body1" &&
contact.getFixtureB().getBody().getUserData()== "body2")
Colliding = true;
System.out.println("Contact detected");
}
Can you help me (if it is possible through some code) to solve my problem?
Thanks in advance,
Francesco
Update of my question
Here is my render method:
public class GameRenderer{
private GameWorld myWorld;
private ShapeRenderer shapeRenderer;
private SpriteBatch sb;
private Camera camera;
private Constants constant;
private Rectangle viewport;
//dichiaro le variabili per caricare gli asset
private Player player;
private ScrollHandler scroller;
private Bordo frontBordoSX_1, backBordoSX_1, frontBordoSX_2, backBordoSX_2;
private Bordo frontBordoDX_1, backBordoDX_1, frontBordoDX_2, backBordoDX_2;
/*
private Ostacolo ob1_sx, ob2_sx, ob3_sx;
private Ostacolo ob4_dx, ob5_dx, ob6_dx;
*/
private TextureRegion player_TR;
private TextureRegion bordoSX_1, bordoSX_2;
private TextureRegion bordoDX_1, bordoDX_2;
private TextureRegion obstacleSX, obstacleSX_flip;
private TextureRegion obstacleDX, obstacleDX_flip;
private TextureRegion enemyS;
private TextureRegion blackBar;
//box2dpart
private World worldbox;
private Sprite fbDx_1,fbDx_2,fbSx_1,fbSx_2;
private Sprite player_sprite;
private Body player_body, bordo_destro;
private MyContactListener contactListener;
public GameRenderer(GameWorld world) {
myWorld = world;
constant = new Constants();
camera = new OrthographicCamera(constant.getWidth(), constant.getHeight());
shapeRenderer = new ShapeRenderer();
shapeRenderer.setProjectionMatrix(camera.combined);
sb = new SpriteBatch();
sb.setProjectionMatrix(camera.combined);
contactListener = new MyContactListener();
worldbox= new World(new Vector2(0,-10),true);
worldbox.setContactListener(contactListener);
//initialize objects and assets
initGameObjects();
initAssets();
}
private void initGameObjects(){
player = myWorld.getPlayer();
scroller = myWorld.getScroller();
frontBordoSX_1 = scroller.getFrontBordoSX_1();
backBordoSX_1 = scroller.getBackBordoSX_1();
frontBordoSX_2 = scroller.getFrontBordoSX_2();
backBordoSX_2 = scroller.getBackBordoSX_2();
frontBordoDX_1 = scroller.getFrontBordoDX_1();
backBordoDX_1 = scroller.getBackBordoDX_1();
frontBordoDX_2 = scroller.getFrontBordoDX_2();
backBordoDX_2 = scroller.getBackBordoDX_2();
/* other objects
ob1_sx = scroller.getOb1_sx();
ob2_sx = scroller.getOb2_sx();
ob3_sx = scroller.getOb3_sx();
ob4_dx = scroller.getOb4_dx();
ob5_dx = scroller.getOb5_dx();
ob6_dx = scroller.getOb6_dx();
*/
}
private void initAssets(){
player_TR = AssetLoader.player;
bordoSX_1 = AssetLoader.bordoSX;
bordoSX_2 = AssetLoader.bordoSX;
bordoDX_1 = AssetLoader.bordoDX;
bordoDX_2 = AssetLoader.bordoDX;
obstacleDX = AssetLoader.obstacleDX;
obstacleSX = AssetLoader.obstacleSX;
obstacleDX_flip = AssetLoader.obstacleDX_flip;
obstacleSX_flip = AssetLoader.obstacleSX_flip;
enemyS = AssetLoader.enemyS;
blackBar = AssetLoader.blackBar;
//box2d part
}
private void drawMargin(){
//bordo SX
/*
sb.draw(bordoSX_1, frontBordoSX_2.getX(), frontBordoSX_2.getY(), frontBordoSX_2.getWidth(),
frontBordoSX_2.getHeight());
sb.draw(bordoSX_2, frontBordoSX_1.getX(), frontBordoSX_1.getY(), frontBordoSX_1.getWidth(),
frontBordoSX_1.getHeight());
*/
fbSx_1 = new Sprite(bordoSX_1);
fbSx_1.setSize(frontBordoSX_1.getWidth(),frontBordoSX_1.getHeight());
fbSx_1.setPosition(frontBordoSX_1.getX(), frontBordoSX_1.getY());
fbSx_1.setOrigin(0, 0);
fbSx_1.draw(sb);
fbSx_2 = new Sprite(bordoSX_2);
fbSx_2.setSize(frontBordoSX_2.getWidth(),frontBordoSX_2.getHeight());
fbSx_2.setPosition(frontBordoSX_2.getX(), frontBordoSX_2.getY());
fbSx_2.setOrigin(0, 0);
fbSx_2.draw(sb);
fbDx_1 = new Sprite(bordoDX_1);
fbDx_1.setSize(frontBordoDX_1.getWidth(),frontBordoDX_1.getHeight());
fbDx_1.setPosition(frontBordoDX_1.getX(), frontBordoDX_1.getY());
fbDx_1.setOrigin(0, 0);
fbDx_1.draw(sb);
fbDx_2 = new Sprite(bordoDX_2);
fbDx_2.setSize(frontBordoDX_2.getWidth(),frontBordoDX_2.getHeight());
fbDx_2.setPosition(frontBordoDX_2.getX(), frontBordoDX_2.getY());
fbDx_2.setOrigin(0, 0);
fbDx_2.draw(sb);
sb.draw(blackBar,-constant.getWidth()/2,-constant.getHeight()/2,
(float) (0.573913)*(constant.getWidth()/6),constant.getHeight());
sb.draw(blackBar,(float)(constant.getWidth()/2-(0.573913)*(constant.getWidth()/6)),-constant.getHeight()/2,
(float)(0.573913)*(constant.getWidth()/6),constant.getHeight());
}
private void drawPlayer(){
player_sprite = new Sprite(player_TR);
player_sprite.setSize(player.getWidth(), player.getHeight());
player_sprite.setPosition(player.getX(), player.getY());
player_sprite.setOrigin(0, 0);
player_sprite.draw(sb);
}
/*
private void drawOstacoli(){
sb.draw(obstacleSX_flip,ob1_sx.getX(),ob1_sx.getY(),ob1_sx.getWidth(),ob1_sx.getHeight());
sb.draw(obstacleSX,ob2_sx.getX(),ob2_sx.getY(),ob2_sx.getWidth(),ob2_sx.getHeight());
sb.draw(obstacleSX_flip,ob3_sx.getX(),ob3_sx.getY(),ob3_sx.getWidth(),ob3_sx.getHeight());
sb.draw(obstacleDX,ob4_dx.getX()+constant.getWidth()/2-ob4_dx.getWidth(),ob4_dx.getY(),ob4_dx.getWidth(),ob4_dx.getHeight());
sb.draw(obstacleDX_flip,ob5_dx.getX()+constant.getWidth()/2-ob5_dx.getWidth(),ob5_dx.getY(),ob5_dx.getWidth(),ob5_dx.getHeight());
sb.draw(obstacleDX,ob6_dx.getX()+constant.getWidth()/2-ob6_dx.getWidth(),ob6_dx.getY(),ob6_dx.getWidth(),ob6_dx.getHeight());
}
*/
public void render(float runTime) {
Box2D.init();
int width = constant.getWidth();
int height = constant.getHeight();
float ratio = constant.getRatio();
//viewport
float aspectRatio = (float) width / (float) height;
float scale = 1f;
Vector2 crop = new Vector2(0f, 0f);
if(aspectRatio > ratio)
{
scale = (float)height/(float)height;
crop.x = (width - width * scale) / 2f;
} else if (aspectRatio < ratio) {
scale = (float)width/(float)width;
crop.y = (height - height*scale)/2f;
}
else
{
scale = (float) width / (float) width;
}
float w = (float) width * scale;
float h = (float) height * scale;
viewport = new Rectangle(crop.x, crop.y, w, h);
// update camera
camera.update();
// clear previous frame
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
// Draw Background color
shapeRenderer.setColor(255 / 255.0f, 255 / 255.0f, 250 / 255.0f, 1);
shapeRenderer.rect(-constant.getWidth() / 2, -constant.getHeight() / 2, constant.getWidth(),
constant.getHeight());
// End ShapeRenderer
shapeRenderer.end();
// set viewport
Gdx.gl.glViewport((int) viewport.x, (int) viewport.y,
(int) viewport.width, (int) viewport.height);
// Begin SpriteBatch
sb.begin();
// The player needs transparency, so we enable that again.
sb.enableBlending();
// Draw player at its coordinates.
drawPlayer();
//draw right and left side
drawMargin();
// End SpriteBatch
sb.end();
worldbox.step(1 / 60f, 6, 2);
}
}
And if I start the program my view is my player in the middle and to margins ,one on the left and one on the right. (unfortunatly I cannot post images of my view because I don't have enough rep).
Everithing is fine. I move my player with the accelerometer and it works fine without any problem. The only problem is that if I move the player near the margin the two entities overlap instead of colliding and I don't understand why.
I also fixed the line:
loader.attachFixture(body, fixture_name, fd, 1);
to
loader.attachFixture(body, fixture_name, fd, player_width);
but nothing changes.
First, from here, the object Contact manages contact between two shapes, and from here, the listener ContactListener will be called when two fixtures begin to touch.
So, to make your code work, you should set a custom object to your bodies with the method: setUserData(Object userData). Usually this method is used to link the sprite or the actor with the physic body, but for example purpose you could just send a simple ID (like a string).
So in this part:
// 3. Create a Body, as usual.
body= world.createBody(bd);
//body.setBullet(true);
You could add an identificator to your object like this:
body.setUserData("player");
to idenfity your object, and then, when the listener get fired, you could retrieve this value:
#Override
public void beginContact(Contact contact) {
String userDataA = contact.getFixtureA().getBody().getUserData().toString();
String userDataB = contact.getFixtureB().getBody().getUserData().toString();
if(userDataA.equals("player") && userDataB.equals("otherEntity")){
colliding = true;
//do stuffs when collision has started
} else if(userDataB.equals("player") && userDataA.equals("otherEntity")){
colliding = true;
//do stuffs when collision has started
}
System.out.println("Contact detected");
}
After that, you could be able to do whatever you want to do with this collision.
Hope you find this useful!

Updating camera position with Libgdx

I am attempting to get an OrthographicCamera to follow a user controlled sprite. I can't get the camera to properly update position at all. I can't seem to see what is wrong with my code compared to what others have done.
I am still learning and at this point I would assume the problem is being caused by something simple I do not fully understand at this point.
Any help is appreciated, thank you.
This is my renderer:
public class WorldRenderer {
private static final float CAMERA_WIDTH = 10;
private static final float CAMERA_HEIGHT = 7;
private World world;
private OrthographicCamera oCam;
private Hero hero;
ShapeRenderer debugRenderer = new ShapeRenderer();
/** TEXTURES **/
private Texture heroTexture;
private Texture tileTexture;
private SpriteBatch spriteBatch;
private int width, height;
private float ppuX; // Pixels per unit on the X axis
private float ppuY; // Pixels per unit on the Y axis
public void setSize (int w, int h) {
this.width = w;
this.height = h;
ppuX = (float)width / CAMERA_WIDTH;
ppuY = (float)height / CAMERA_HEIGHT;
}
public WorldRenderer(World world, boolean debug) {
hero = world.getHero();
this.world = world;
spriteBatch = new SpriteBatch();
oCam = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
oCam.update();
loadTextures();
}
private void loadTextures() {
tileTexture = new Texture(Gdx.files.internal("images/tile.png"));
heroTexture = new Texture(Gdx.files.internal("images/hero_01.png"));
}
public void render() {
oCam.update();
spriteBatch.begin();
spriteBatch.disableBlending();
drawTiles();
spriteBatch.enableBlending();
drawHero();
spriteBatch.end();
}
private void drawHero() {
spriteBatch.draw(heroTexture, hero.getPosition().x * ppuX, hero.getPosition().y * ppuY, Hero.SIZE * ppuX, Hero.SIZE * ppuY);
oCam.position.set(hero.getPosition().x, hero.getPosition().y, 0);
}
}
SpriteBatch manages its own projection and transformation matrixes. So, you have to set its matrixes (if possible, before calling begin()).
Unless you need to access your matrixes separately (projection and model-view, eg. in shaders), setting the projection matrix to the projection-model-view matrix will be enough.
Anyway, this should work in your code:
oCam.update();
spriteBatch.setProjectionMatrix(oCam.combined);
try calling oCam.apply(Gdx.gl10); after your oCam.update();
update() only does the calculations but you never applied them.
In relation to idaNakav's answer, I can't see an apply function on cameras in LibGDX anymore, in case anyone else stumbles upon this! So update() should be sufficient now I would imagine.
My problem was a bit different, I was trying to put my camera in certain positions/lookAts with a perspective camera and it had to be actioned twice to work.
I was calling:
camera.lookAt(xyz), camera.position.set(xyz), camera.up.set(xyz)
The first call made the camera update to a really odd transform. I should have been doing:
camera.position.set(xyz), camera.lookAt(xyz), camera.up.set(xyz)

Categories

Resources