Centering an animation [libGDX] - java

I have the following class:
public class AnimationDemo implements ApplicationListener {
private SpriteBatch batch;
private TextureAtlas textureAtlas;
private Animation animation;
private float elapsedTime = 0;
private OrthographicCamera camera;
private int width;
private int height;
private int texturewidth;
private int textureheight;
#Override
public void create() {
width = Gdx.graphics.getWidth();
height = Gdx.graphics.getHeight();
camera = new OrthographicCamera(width, height);
camera.position.set(width / 2, height / 2, 0);
camera.update();
batch = new SpriteBatch();
textureAtlas = new TextureAtlas(Gdx.files.internal("data/packone.atlas"));
textureAtlas.getRegions().sort(new Comparator<TextureAtlas.AtlasRegion>() {
#Override
public int compare(TextureAtlas.AtlasRegion o1, TextureAtlas.AtlasRegion o2) {
return Integer.parseInt(o1.name) > Integer.parseInt(o2.name) ? 1 : -1;
}
});
animation = new Animation(1 / 15f, textureAtlas.getRegions());
}
#Override
public void dispose() {
batch.dispose();
textureAtlas.dispose();
}
#Override
public void render() {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL30.GL_COLOR_BUFFER_BIT);
batch.begin();
elapsedTime += Gdx.graphics.getDeltaTime();
batch.draw(animation.getKeyFrame(elapsedTime, true), 0, 0);
batch.end();
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
}
In the above I am using the Animation class to simply draw from a texture atlas. I am following an example from another SO question which is here but the co-ordinates don't fit my equation. How should I set these:
private int texturewidth;
private int textureheight;
Any help would be great :)

you need to care about proper offset - the origin is always at the left bottom corner and that is why you need to subtract half of width and height when drawing.
In a nutshell it should be like:
TextureRegion region = animation.getKeyFrame(elapsedTime, true);
batch.draw(region, 0 - (region.getRegionWidth()/2f), 0 - (region.getRegionHeight()/2f));

Related

Why is my create() Method Not Recognizing a Global Variable? - Java LibGDX

I have global variables called:
private int currentLevel;
private int mapHeight;
I have a constructor for my game, where currentLevel = level entered when setScreen() method is called:
public ElevatorLevel(Game g, int level)
{
super(g, level);
currentLevel = level;
}
In my create() method, I set mapHeight to 750 * currentLevel (which starts as one), however when I try to spawn in the blades as seen below, they spawn between -200 and 300. This is because the program is not recognizing currentLevel (I am assuming), so it is multiplying it by nothing, resulting with -200.
public void create()
{
world = new World(new Vector2(0, -9.8f), true);
timeElapsed = 0;
mapHeight = 750 * currentLevel;
blade = new PhysicsActor();
blade.storeAnimation( "", exTex );
blade.setOriginCenter();
blade.circularBoundary();
blade.setMaxSpeed(50);
blade.setDeceleration(50);
bladesList = new ArrayList<PhysicsActor>();
for (int i = 0; i < 3 ; i++)
{
blades = blade.clone();
float xCoord = randomFloatGenerator(440, 20);
float yCoord = randomFloatGenerator(mapHeight - 200, 300);
blades.setPosition(xCoord, yCoord);
mainStage.addActor(blades);
bladesList.add(blades);
}
I also have a Label in my update(float dt) method that is set to:
timeLabel.setText("Level: " + currentLevel);
As seen in the image above, currentLevel is recognized by the label, but not by mapHeight in create().
How do I get currentLevel to be recognized by the create() method?
Below is the standart portrait app code that i use almost in every libgdx project. I never use create method. Instead I use constructor, this code is the most bugfree one that i could have found.
GAME OR MENU SCREEN:
public class TutorialScreen implements Screen {
private OrthographicCamera camera;
public static final float WORLD_HEIGHT = 240;
public static final float WORLD_WIDTH = 135;
private Viewport viewport;
private Stage stage;
private EntryPoint game;
private AdsController adsController;
public TutorialScreen(final EntryPoint game, final AdsController adsController){
this.adsController = adsController;
this.game = game;
adsController.hideBannerAd();
float aspectRatio = (float) (Gdx.graphics.getHeight() / Gdx.graphics.getWidth());
camera = new OrthographicCamera(aspectRatio * WORLD_WIDTH, WORLD_HEIGHT);
camera.setToOrtho(false);
viewport = new FitViewport(WORLD_WIDTH , WORLD_HEIGHT,camera );
stage = new Stage(viewport, game.batch);
}
#Override
public void show() {
}
#Override
public void render(float delta) {
stage.draw();
stage.act();
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
}
}
ENTRY POINT THAT YOUR APP WILL OPEN FIRST:
package some.package;
public class EntryPoint extends Game {
SpriteBatch batch;
final AdsController adsController;
public EntryPoint(final AdsController adsController ){
this.adsController = adsController; //Interface for admob
}
#Override
public void create () {
batch = new SpriteBatch();
this.setScreen(new YourScreenClass(this,adsController)); //Above is tutorial so this would be new TutorialScreen(this,adsController)
}
#Override
public void render () {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.end();
super.render();
}
#Override
public void dispose () {
batch.dispose();
}
}
Might have missed some curly brackets or ";" but you get the idea. This way you would not encounter any reference issues.

Why is my background image stretched out in libGDX?

This is my first try in libGDX and I've not seen an issue like this before, googling didn't help either. What I'm trying to to display a background, Later on I'll make this move, but for me it was a great start to actually display the image. It displays, but it's streched out (See picture below)
And my code is:
private BombArrangement game;
private OrthographicCamera gameCamera;
private Viewport gamePort;
private Texture backGroundTexture;
public PlayScreen(BombArrangement game) {
this.game = game;
gameCamera = new OrthographicCamera();
gamePort = new FitViewport(BombArrangement.V_WIDTH, BombArrangement.V_HEIGHT, gameCamera);
backGroundTexture = new Texture("startbackground.png");
}
#Override
public void show() {
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
game.batch.begin();
game.batch.draw(new TextureRegion(backGroundTexture, 0, 0, BombArrangement.V_WIDTH, BombArrangement.V_HEIGHT), 0, 0);
game.batch.end();
}
#Override
public void resize(int width, int height) {
gamePort.update(width, height);
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
}
}
I tried several things like textureregions, sprites and more but all of them give this result.
not exactly sure what your want to do but i use this to render my background in my main menu:
//Camera
camera = new OrthographicCamera();
camera.setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
//Viewport
ScreenViewport viewport = new ScreenViewport(camera);
//Background
backgroundImage = new Texture(pathToImage);
//Stage
stage = new Stage();
stage.setViewport(viewport);
(this is located in my constructor and camera, backgroundImage and stage are fields in my class)
in render method
(ConfigData holds data of settings applied to the game; DEFAULT_WIDHT and -HEIGHT are just some values I use to initialize the window when not in fullscreen mode; Replace them with your values used in the DesktopLauncher for
config.widht
and
config.height
):
#Override
public void render(float delta) {
//Clear screen
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act();
stage.getBatch().begin();
stage.getBatch().draw(backgroundImage, 0, 0, ConfigData.DEFAULT_WIDTH, ConfigData.DEFAULT_HEIGHT);
stage.getBatch().end();
stage.draw();
}
my resize method:
#Override
public void resize(int width, int height) {
camera.setToOrtho(false, width, height);
stage.getViewport().update(width, height);
}
hopes this helps somehow someone because i figured out this by myself and it costed some effort (:
As a response to your last comment:
You are now scaling down the height correctly but the width remains the same. Try to multiply the width by the same amount you scale the height down, so with some alterations to the code you linked in the comment (not tested):
private Texture texture;
private int x1, x2, speed, scaledHeight, scaledWidth;
public StartBackground() {
texture = new Texture("startbackground.png");
x1 = 0;
x2 = texture.getWidth();
speed = 5;
float imageRatio = Gdx.graphics.getHeight() / texture.getHeight();
scaledHeight = (int) (texture.getHeight() * imageRatio);
scaledWidth = (int) (texture.getWidth() * imageRatio);
}
public void updateAndRender(float deltaTime, SpriteBatch spriteBatch) {
x1 -= speed;
x2 -= speed;
// If image is off screen and not visible
if (x1 + texture.getWidth() <= 0) x1 = x2 + texture.getWidth();
if (x2 + texture.getWidth() <= 0) x2 = x1 + texture.getWidth();
// Render
spriteBatch.draw(texture, x1, 0, scaledWidth, scaledHeight);
spriteBatch.draw(texture, x2, 0, scaledWidth, scaledHeight);
}

how to get the below mentioned screen on all android devices?

I am a beginner to libgdx android and I want to achieve the below screen in my game
And I wrote the following code
public class MyGdxGame implements ApplicationListener {
private static final int VIRTUAL_WIDTH = 480;
private static final int VIRTUAL_HEIGHT = 800;
private static final float ASPECT_RATIO =(float)VIRTUAL_WIDTH/(float)VIRTUAL_HEIGHT;
private Camera camera;
private Rectangle viewport;
private SpriteBatch sb;
ShapeRenderer sp;
#Override
public void create()
{
sb = new SpriteBatch();
camera = new OrthographicCamera(VIRTUAL_WIDTH, VIRTUAL_HEIGHT);
sp=new ShapeRenderer();
}
#Override
public void render()
{
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
// update camera
camera.update();
// camera.apply(Gdx.gl10);
// set viewport
Gdx.gl.glViewport((int) viewport.x, (int) viewport.y, (int) viewport.width, (int) viewport.height);
// clear previous frame
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
// DRAW EVERYTHING
float sx=viewport.x;
float sy=viewport.y;
float ex=viewport.getWidth();
float ey=viewport.getHeight();
sp.begin(ShapeRenderer.ShapeType.Line);
sp.setColor(Color.BLACK);
sp.rect(sx,sy,ex,ey);
sp.line(sx,sy,ex,ey);
sp.line(1,1,480,800);
sp.line(1,ey/2,ex-1,ey/2);
sp.line(ex/2,1,ex/2,ey-1);
sp.line(1,ey-1,ex-1,1);
sp.circle(ex/2,ey/2,40);
sp.end();
}
#Override
public void dispose()
{
sp.dispose();
}
#Override
public void resize(int width, int height)
{
// calculate new viewport
float aspectRatio = (float)width/(float)height;
float scale = 1f;
Vector2 crop = new Vector2(0f, 0f);
sb = new SpriteBatch();
camera = new OrthographicCamera(VIRTUAL_WIDTH, VIRTUAL_HEIGHT);
if(aspectRatio > ASPECT_RATIO)
{
scale = (float)height/(float)VIRTUAL_HEIGHT;
crop.x = (width - VIRTUAL_WIDTH * scale) / 2f;
}
else if(aspectRatio < ASPECT_RATIO)
{
scale = (float)width/(float)VIRTUAL_WIDTH;
crop.y = (height - VIRTUAL_HEIGHT*scale)/2f;
}
else
{
scale = (float)width/(float)VIRTUAL_WIDTH;
}
float w = (float)VIRTUAL_WIDTH*scale;
float h = (float)VIRTUAL_HEIGHT*scale;
viewport = new Rectangle(crop.x, crop.y, w, h);
}
}
With the above code I got the actual screen in my device which is correctly fits in my device.
When I run this on some other devices, the lines and rects are unaligned. Like this
How to resolve this?
You can use in this way :
public class GdxTest extends ApplicationAdapter {
OrthographicCamera camera;
ShapeRenderer shapeRenderer;
float screenOffset=10,circleRadius=30;
#Override
public void create() {
camera=new OrthographicCamera();
shapeRenderer=new ShapeRenderer();
shapeRenderer.setAutoShapeType(true);
}
#Override
public void render() {
Gdx.gl.glClearColor(1,1,1,1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
shapeRenderer.setProjectionMatrix(camera.combined);
shapeRenderer.begin();
shapeRenderer.setColor(Color.BLACK);
shapeRenderer.circle(camera.viewportWidth/2,camera.viewportHeight/2,circleRadius);
shapeRenderer.rect(screenOffset,screenOffset,camera.viewportWidth-2*screenOffset,camera.viewportHeight-2*screenOffset);
shapeRenderer.line(screenOffset,screenOffset,camera.viewportWidth-screenOffset,camera.viewportHeight-screenOffset);
shapeRenderer.line(screenOffset,camera.viewportHeight-screenOffset,camera.viewportWidth-screenOffset,screenOffset);
shapeRenderer.line(screenOffset,camera.viewportHeight/2,camera.viewportWidth-screenOffset,camera.viewportHeight/2);
shapeRenderer.line(camera.viewportWidth/2,screenOffset,camera.viewportWidth/2,camera.viewportHeight-screenOffset);
shapeRenderer.end();
}
#Override
public void resize(int width, int height) {
camera.setToOrtho(false,width,height);
screenOffset=width<height?width*.04f:height*.04f;
circleRadius=width<height?width*.075f:height*.075f;
}
#Override
public void dispose() {
shapeRenderer.dispose();
}
}
And the output is :

LibGdx: Shaperenderer Rect not being drawn on Screen

Trying to create a simple loading Screen. The below code prints the correct progress, so I know that part works. But the rectangle is not being drawn. Not sure what is wrong.
Full LoadingScreen:
public class LoadingScreen implements Screen {
private static final float PROGRESS_BAR_WIDTH = MyGdxGame.WIDTH / 2f;
private static final float PROGRESS_BAR_HEIGHT = 50f;
GdxAssetManager assetManager;
Stage stage;
//Table mainTable;
private ShapeRenderer shapeRenderer;
private MyGdxGame game;
public LoadingScreen(MyGdxGame game){
this.game = game;
assetManager = game.getAssetManager();
shapeRenderer = new ShapeRenderer();
stage = new Stage(new StretchViewport(MyGdxGame.WIDTH, MyGdxGame.HEIGHT));
}
#Override
public void show() {
assetManager.loadGeneral();
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
renderProgressBar();
if (assetManager.getManager().update()) {
game.setScreen(new LoginScreen(game));
}
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
}
private void renderProgressBar() {
float progress = assetManager.getManager().getProgress();
System.out.println(PROGRESS_BAR_WIDTH * progress);
shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
shapeRenderer.setColor(Color.RED);
shapeRenderer.rect(
(MyGdxGame.WIDTH - PROGRESS_BAR_WIDTH) / 2f,
(MyGdxGame.HEIGHT - PROGRESS_BAR_HEIGHT) / 2f,
PROGRESS_BAR_WIDTH * progress,
PROGRESS_BAR_HEIGHT
);
shapeRenderer.end();
}
#Override
public void resize(int width, int height) {
stage.getViewport().update(width, height);
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
dispose();
}
#Override
public void dispose() {
stage.dispose();
shapeRenderer.dispose();
}
}
I guess methods of interest are render and renderProgressBar. Like I said, all I get is a white background until the loading is finished, but the print inside renderProgressBar prints the correct values.
Set projectionMatrix of ShapeRenderer using stage camera.
shapeRenderer.setProjectionMatrix(stage.getCamera().combined);

Java libGDX Game - Animation doesn't flip

I have a animation which i want to flip to the left if key LEFT is pressed, but it doesnt stay flipped. It only flips like 1 frame then turns back again.
Here is my GameScreen where i draw everything:
public class GameScreen extends ScreenManager{
//For the view of the game and the rendering
private SpriteBatch batch;
private OrthographicCamera cam;
//DEBUG
private Box2DDebugRenderer b2dr;
//World, Player and so on
private GameWorld world;
private Player player;
private Ground ground;
//player animations
private TextureRegion currFrame;
public static float w, h;
public GameScreen(Game game) {
super(game);
//vars
w = Gdx.graphics.getWidth();
h = Gdx.graphics.getHeight();
//view and rendering
batch = new SpriteBatch();
cam = new OrthographicCamera();
cam.setToOrtho(false, w/2, h/2);
//debug
b2dr = new Box2DDebugRenderer();
//world, bodies ...
world = new GameWorld();
player = new Player(world);
ground = new Ground(world);
}
#Override
public void pause() {
}
#Override
public void show() {
}
#Override
public void render(float delta) {
//clearing the screen
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
//updating
update(Gdx.graphics.getDeltaTime());
player.stateTime += Gdx.graphics.getDeltaTime();
//render
batch.setProjectionMatrix(cam.combined);
currFrame = Player.anim.getKeyFrame(Player.stateTime, true);
batch.begin();
batch.draw(currFrame, Player.body.getPosition().x * PPM - 64, Player.getBody().getPosition().y * PPM- 72);
batch.end();
//debug
b2dr.render(GameWorld.getWorld(), cam.combined.scl(PPM));
}
#Override
public void resize(int width, int height) {
}
#Override
public void hide() {
}
#Override
public void dispose() {
}
#Override
public void onKlick(float delta) {
}
public void update(float delta){
world.update(delta);
updateCam(delta);
Player.keyInput(delta);
System.out.println("X-POS" + Player.getBody().getPosition().x);
System.out.println("Y-POS" + Player.getBody().getPosition().y);
}
public void updateCam(float delta){
Vector3 pos = cam.position;
pos.x = Player.getBody().getPosition().x * PPM;
pos.y = Player.getBody().getPosition().y * PPM;
cam.position.set(pos);
cam.update();
}
}
and this is the Player class where the animation is:
public class Player {
public static Body body;
public static BodyDef def;
private FixtureDef fd;
//textures
public static Texture texture;
public static Sprite sprite;
public static TextureRegion[][] region;
public static TextureRegion[] idle;
public static Animation<TextureRegion> anim;
public static float stateTime;
//set form
private PolygonShape shape;
private GameScreen gs;
public Player(GameWorld world){
texture = new Texture(Gdx.files.internal("player/char_animation_standing.png"));
region = TextureRegion.split(texture, texture.getWidth() / 3, texture.getHeight() / 2);
idle = new TextureRegion[6];
int index = 0;
for(int i = 0; i < 2; i++){
for(int j = 0; j < 3; j++){
sprite = new Sprite(region[i][j]);
idle[index++] = sprite;
}
}
anim = new Animation<TextureRegion>(1 / 8f, idle);
stateTime = 0f;
def = new BodyDef();
def.fixedRotation = true;
def.position.set(gs.w / 4, gs.h / 4);
def.type = BodyType.DynamicBody;
body = world.getWorld().createBody(def);
shape = new PolygonShape();
shape.setAsBox(32 / 2 / PPM, 64/ 2 / PPM);
fd = new FixtureDef();
fd.shape = shape;
fd.density = 30;
body.createFixture(fd);
shape.dispose();
}
public static Body getBody() {
return body;
}
public static BodyDef getDef() {
return def;
}
public static Texture getTexture() {
return texture;
}
public static void keyInput(float delta){
int horizonForce = 0;
if(Gdx.input.isKeyJustPressed(Input.Keys.UP)){
body.applyLinearImpulse(0, 300f, body.getWorldCenter().x, body.getWorldCenter().y, true);
//body.applyForceToCenter(0, 1200f, true);
System.out.println("PRESSED");
}
if(Gdx.input.isKeyPressed(Input.Keys.LEFT)){
horizonForce -= 1;
sprite.flip(!sprite.isFlipX(), sprite.isFlipY());
}
if(Gdx.input.isKeyPressed(Input.Keys.RIGHT)){
horizonForce += 1;
}
body.setLinearVelocity(horizonForce * 20, body.getLinearVelocity().y);
}
}
thank you in advance and any answer is appreciated :D
Your sprite variable contain only one frame at the time of pressing left key. So, it flip that current sprite of your animation frame.
To solve the Problem you have to flip all the animation frame on pressing the left key.
You're only flipping last frame of Animation by sprite reference, You need to flip all frames of your Animation anim. You can flip in this way :
if(keycode== Input.Keys.RIGHT) {
for (TextureRegion textureRegion:anim.getKeyFrames())
if(!textureRegion.isFlipX()) textureRegion.flip(true,false);
}
else if(keycode==Input.Keys.LEFT) {
for (TextureRegion textureRegion:anim.getKeyFrames())
if(textureRegion.isFlipX()) textureRegion.flip(true,false);
}

Categories