Center Justify Text in libgdx - java

I have just started with LibGdx and I have figured out how to center text with it. Now I am having trouble with center justifying text. I was wondering if someone can help. I have attach my code for centering. Thank you in advance.
package com.tutorials.game;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
public class TextDemo extends ApplicationAdapter {
SpriteBatch batch;
BitmapFont font;
String myText;
GlyphLayout layout = new GlyphLayout();
#Override
public void create () {
batch = new SpriteBatch();
font = new BitmapFont(Gdx.files.internal("myFont.fnt"));
myText = "I took one, one cause you left me\n"
+ "Two, two for my family\n"
+ "Three, three for my heartache";
layout.setText(font,myText);
}
#Override
public void render () {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
float x = Gdx.graphics.getWidth()/2 - layout.width/2;
float y = Gdx.graphics.getHeight()/2 + layout.height/2;
batch.begin();
font.draw(batch,layout,x,y);//Center Text
batch.end();
}

You can use following setText() method instead and set targetWidth to screen width, Aligh.center, and set wrap to true. Also, set x = 0 so the text is centered across the whole screen.
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
public void setText(BitmapFont font,
java.lang.CharSequence str,
Color color,
float targetWidth,
int halign,
boolean wrap)
Updated example:
#Override
public void create () {
batch = new SpriteBatch();
font = new BitmapFont(Gdx.files.internal("myFont.fnt"));
myText = "I took one, one cause you left me\n"
+ "Two, two for my family\n"
+ "Three, three for my heartache";
layout.setText(font,myText,Color.BLACK,Gdx.graphics.getWidth(),Align.center,true);
}
#Override
public void render () {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
float x = 0;
float y = Gdx.graphics.getHeight()/2 + layout.height/2;
batch.begin();
font.draw(batch,layout,x,y);//Center Text
batch.end();
}

Instead of using the font.draw method, use the following one instead...
public TextBounds drawMultiLine (Batch batch, CharSequence str, float x, float y, float alignmentWidth, HAlignment alignment)
alignmentWidth is the max width you want your text to take up. Any more than that and it will wrap. Set it to something stupidly high if you don't want wrapping.
'alignment' is the key thing and takes an HAlignment enum and can be either LEFT, RIGHT or CENTER
The batch, str, x and y parameters are the same as you're already doing.

Related

Displaying score in libgdx game

So i am having trouble keeping a display of the score in a game i am creating. I was wondering how would i go about doing that? this is what i have so far:
package com.catgame.game;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
public class CatGame extends ApplicationAdapter implements InputProcessor {
SpriteBatch batch;
Sprite cat;
OrthographicCamera camera;
final float CAT_WIDTH = 0.75f;
final float CAT_HEIGHT = 0.50f;
Sound meow;
int score = 0;
String scorePrint;
BitmapFont scoreFont;
#Override
public void create () {
batch = new SpriteBatch();
cat = new Sprite(new Texture(Gdx.files.internal("Cat.png")));
cat.setSize(CAT_WIDTH,CAT_HEIGHT);
scoreFont = new BitmapFont(Gdx.files.internal("score.fnt"));
float aspectRatio = (float)Gdx.graphics.getHeight()/
(float)Gdx.graphics.getWidth();
scoreFont.getData().setScale(0.5f);
camera = new OrthographicCamera(CAT_HEIGHT * aspectRatio,
CAT_HEIGHT);
camera.position.set(CAT_WIDTH/2,CAT_HEIGHT/2,0);
meow = Gdx.audio.newSound(Gdx.files.internal("Meow.wav"));
Gdx.input.setInputProcessor(this);
scorePrint = "Hello";
}
#Override
public void render () {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
batch.begin();
batch.setProjectionMatrix(camera.combined);
//cat.draw(batch);
scoreFont.draw(batch,scorePrint,camera.position.x,camera.position.y);
batch.end();
}
I have tried scoreFont.draw() method but it doesn't seem to work. not sure why, maybe my positioning is wrong since I have an ortho camera or something. But When i tried to used the draw font, nothing appeared. The red circle in the image below shows where i would want the score around.
http://imgur.com/gallery/ywFF6SZ/new
Draw your font in render method and change your font colour or background colour.It might be possible because you black background colour match with BitmapFont colour.
You need to draw the score (or whatever you want to see on screen) inside the render function, because each render clears the canvas and redraws.
You are drawing the font too big. When you don't specify a scale for the font before drawing it, it draws it at a scale of one font pixel to one world unit. In your case, your camera height is less than one, so you are only seeing a fraction of one pixel of the first letter in your text, which is likely just empty space. Call setScale on the font after setting up your camera, using the appropriate scale to get it down to the size you want.

Design a Path for cropping an ImageView

Ok, I need to crop an ImageView in a particular shape, and I can't do this by adding over a png, because the background can be variable (ex. a pattern). So, I need that the area outside the shape is transparent.
The shape must be this:
I thought to use Path() to draw this shape and use it to mask the ImageView, but I have absolutely no idea how to draw a complex shape like this with Path().
Many thanks.
So I was bored and this looked like fun, so I've thrown together a simple Drawable you can use to do this. You could get fancier and add strokes and whatnot to it, but this works for the basic case you've suggested, and allows you to set the arrow to be pointing to any of the corners, and will also scale your image to fit the bounds of the Drawable. Here's the result:
You can use it by:
BubbleDrawable bubbleDrawable = new BubbleDrawable(
this, R.drawable.your_image, BubbleDrawable.Corner.TOP_RIGHT);
myImageView.setImageDrawable(bubbleDrawable);
And here's the code for BubbleDrawable:
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import static android.graphics.Matrix.ScaleToFit.FILL;
import static android.graphics.Paint.ANTI_ALIAS_FLAG;
import static android.graphics.Path.Direction.CW;
import static android.graphics.PixelFormat.TRANSPARENT;
import static android.graphics.Shader.TileMode.CLAMP;
import static test.com.testrotationanimation.BubbleDrawable.Corner.TOP_LEFT;
public final class BubbleDrawable extends Drawable {
private final Matrix mMatrix = new Matrix();
private final Paint mPaint = new Paint(ANTI_ALIAS_FLAG);
private final Path mPath = new Path();
private final RectF mSrcRect = new RectF();
private final RectF mDstRect = new RectF();
private final Shader mShader;
private Corner mArrowCorner = TOP_LEFT;
public BubbleDrawable(Bitmap bitmap, Corner arrowCorner) {
// Initialize a BitmapShader with the image you wish to draw
// (you can use other TileModes like REPEAT or MIRROR if you prefer)
mShader = new BitmapShader(bitmap, CLAMP, CLAMP);
mPaint.setShader(mShader);
// Save the bounds of the bitmap as the src rectangle -- will
// be used later to update the matrix when the bounds change
// so that the image fits within the bounds of this drawable
mSrcRect.set(0, 0, bitmap.getWidth(), bitmap.getHeight());
// Set the corner in which the arrow will be drawn
mArrowCorner = arrowCorner;
}
public BubbleDrawable(Context ctx, int drawableResource, Corner arrowCorner) {
this(BitmapFactory.decodeResource(ctx.getResources(), drawableResource), arrowCorner);
}
public Corner getArrowCorner() {
return mArrowCorner;
}
public void setArrowCorner(Corner corner) {
mArrowCorner = corner;
updatePath();
invalidateSelf();
}
#Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
updateMatrix(bounds);
updatePath();
}
private void updateMatrix(Rect bounds) {
// Set the destination rectangle for the bitmap to be the
// new drawable bounds
mDstRect.set(bounds);
// Scale the bitmap's rectangle to the bounds of this drawable
mMatrix.setRectToRect(mSrcRect, mDstRect, FILL);
// Update the shader's matrix (to draw the bitmap at the right size)
mShader.setLocalMatrix(mMatrix);
}
private void updatePath() {
final Rect bounds = getBounds();
final float x = bounds.exactCenterX();
final float y = bounds.exactCenterY();
// Draw the initial circle (same for all corners)
mPath.reset();
mPath.addCircle(x, y, Math.min(x, y), CW);
// Add the rectangle which intersects with the center,
// based on the corner in which the arrow should draw
switch (mArrowCorner) {
case TOP_LEFT:
mPath.addRect(bounds.left, bounds.top, x, y, CW);
break;
case TOP_RIGHT:
mPath.addRect(x, bounds.top, bounds.right, y, CW);
break;
case BOTTOM_LEFT:
mPath.addRect(bounds.left, y, x, bounds.bottom, CW);
break;
case BOTTOM_RIGHT:
mPath.addRect(x, y, bounds.right, bounds.bottom, CW);
break;
}
}
#Override
public void draw(Canvas canvas) {
// Easy enough, just draw the path using the paint.
// It already has the BitmapShader applied which
// will do the work for you.
canvas.drawPath(mPath, mPaint);
}
#Override
public int getOpacity() {
// Indicate that this Drawable has fully-transparent pixel values
return TRANSPARENT;
}
#Override
public void setColorFilter(ColorFilter colorFilter) {
// Yay, you can even support color filters for your drawable
mPaint.setColorFilter(colorFilter);
}
#Override
public void setAlpha(int i) {
// You could do this by doing some canvas magic but I'm
// lazy and don't feel like it. Exercise for the reader. :)
throw new UnsupportedOperationException("Not implemented.");
}
public enum Corner {
TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT
}
}

Exception in thread "LWJGL Application" java.lang.NullPointerException

I am following a tutorial on creating a game with LibGdx from some ebook. the tutorial has steps for creating a game called "Canyon Bunny". Its a simple 2D game. but i keep getting this annoying error! (i also used to get the error on a different tutorial of the same genre)
i am in the early stages of the development for this game. and i am doing some test (of which i follow to the letter from the tutorial). I use a MAC and a i have tried many solutions with no luck at all.
Exception in thread "LWJGL Application" java.lang.NullPointerException
at com.Adel.CanyonBunny.game.WorldUpdater.updateTestObjects(WorldUpdater.java:83)
at com.Adel.CanyonBunny.game.WorldUpdater.update(WorldUpdater.java:76)
at com.Adel.CanyonBunny.CanyonBunnyMain.render(CanyonBunnyMain.java:39)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:207)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:114)
It is truly one of the most frustrating things a striving programmer can face.
ill get the code of all the classes in case that's related somehow...
This is CanyonBunnyMain in the general program:
package com.Adel.CanyonBunny;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.Texture.TextureFilter;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.Adel.CanyonBunny.game.*;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.Application;
public class CanyonBunnyMain implements ApplicationListener {
private static final String TAG = CanyonBunnyMain.class.getName();
private WorldUpdater worldUpdater;
private WorldRenderer worldRenderer ;
private boolean paused ;
public void create() {
//I'll set the log to debug for the developing process
Gdx.app.setLogLevel(Application.LOG_DEBUG) ;
worldUpdater = new WorldUpdater();
worldRenderer = new WorldRenderer() ;
// since, upon creation, the game is not paused, then:
paused = false ;
}
public void render() {
if (paused = true) {
//update the game by the time passed since the last update
worldUpdater.update(Gdx.graphics.getDeltaTime()) ;
}
//sets the screen color to: CornFlower Blue
Gdx.gl.glClearColor(0x64 / 255.0f, 0x95 / 255.0f, 0xed / 255.0f, 0xff / 255.0f);
//clears the screen to prevent flickering
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT) ;
//Render the game to the screen
worldRenderer.render();
}
public void resize (int w, int h) {
worldRenderer.resize(w, h) ;
}
public void pause () {
paused = true ;
}
public void resume() {
paused = false ;
}
public void dispose() {
worldRenderer.dispose() ;
} }
this is the WorldRenderer (general program too) :
package com.Adel.CanyonBunny.game;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.MathUtils;
public class WorldRenderer {
private OrthographicCamera cam;
private SpriteBatch batch ;
private WorldUpdater updater;
public void WorldRenderer(WorldUpdater worldUpdater) { }
public void init() { }
public void render() { }
public void resize(int w, int h) { }
public void dispose() { }
}
this is the main class (from the desktop project: the one that i run on my MAC) :
package com.Adel.CanyonBunny;
import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
public class Main {
public static void main(String[] args) {
LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
cfg.title = "CanyonBunny";
cfg.useGL20 = false;
cfg.width = 800;
cfg.height = 480;
new LwjglApplication(new CanyonBunnyMain(), cfg);
}
}
Any help will be wonderful.
tell me should you need extra data
this is the WorldUpdater class for those who asked:
package com.Adel.CanyonBunny.game;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.math.MathUtils;
public class WorldUpdater {
private final String TAG = WorldUpdater.class.getName();
public Sprite[] testSprites;
public int selectedSprite;
public WorldRenderer worldRenderer;
public void worldUpdater() {
init() ;
}
public void init() {
initTestObjects() ;
}
private void initTestObjects() {
// create new array of 5 sprites
testSprites = new Sprite[5] ;
// Create empty POT-sized Pixmap with 8 bit RGBA pixel data
int w = 32;
int h = 32;
Pixmap pixmap = createProceduralPixmap(w, h) ;
//create a new texture from Pixmap data
Texture texture = new Texture(pixmap) ;
//create sprites using the just created texture
for (int i = 0; i < testSprites.length; i++) {
Sprite spr = new Sprite(texture) ;
spr.setSize(1,1) ;
//set origin to sprite's center
spr.setOrigin(spr.getWidth() / 2.0f, spr.getHeight() / 2.0f) ;
float randomX = MathUtils.random(-2.0f, 2.0f) ;
float randomY = MathUtils.random(-2.0f, 2.0f) ;
spr.setPosition(randomX, randomY) ;
//put new sprite into array
testSprites[i] = spr ;
}
//set first sprite as the selected one
selectedSprite = 0 ;
}
private Pixmap createProceduralPixmap(int width, int height) {
Pixmap pixmap = new Pixmap(width, height , Format.RGBA8888) ;
//fill the square with red color at 50% opacity
pixmap.setColor(1, 0, 0, 0.5f) ;
pixmap.fill() ;
//draw a yellow X in the pixmap
pixmap.setColor(1, 1, 0 , 1) ;
pixmap.drawLine(0, 0, width, height) ;
pixmap.drawLine(width, 0, 0, height);
//draw a cyan-colored border around the square
pixmap.setColor(0, 1, 1, 1) ;
pixmap.drawRectangle(0, 0, width, height) ;
return pixmap;
}
public void update(float deltaTime) {
updateTestObjects(deltaTime);
}
private void updateTestObjects(float deltaTime) {
//get current rotation from the selected sprite
float rotation = testSprites[selectedSprite].getRotation();
//rotate sprite by 90 degrees per second
rotation += 90 * deltaTime;
//wrap around at 360 degrees
rotation %= 360 ;
testSprites[selectedSprite].setRotation(rotation);
}
}
Also, when i check this line out in Debugging mode:
testSprites = new Sprite[5] ;
"testSprites" keeps showing null.
i hope this clears up some details!
thanks again.
The problem is with your "constructors", mainly in the updater (as the renderer does nothing):
public void worldUpdater() { ... }
Constructors should not specify return types - that's part of how the compiler recognizes them as constructors. As it is in your code, it's just a method you could call on an existing object instance. Change it like so:
public WorldUpdater() { ... }
Note the lack of a return type and the uppercase W.
You can change the renderer the same way. (But then you will have to pass the updater to its constructor in the main class.)
Also, Nine Magics is right that the way you store renderer and updater references in each other doesn't make much sense, even if it's not related to this problem. I see no reason why an updater class would need to know about its renderer, I'd remove that field.
In your WorldRenderer you specify this:
public void WorldRenderer(WorldUpdater worldUpdater) { }
And WorldRendere also carries an instance of an worldUpdater?
private WorldUpdater updater;
But on your main file you create an instance of both renderer and updater?
worldUpdater = new WorldUpdater();
worldRenderer = new WorldRenderer() ;
I don't know, I might have tired eyes or something but this seems too complex. Can it be that you are refering to a wrong instance of WorldUpdater? Might edit this if I can wrap my head around it better.

Lwjgl Font Upside down

My rendered text appears upside down. I understand that the bottom left corner is position (0,0) and the entirety of my code is based around this. I have a feeling that the reason my text is rendered upside down is because I am using java's awt font class instead of newdawn.slick.Font. Is there a simple way to accomplish flipping is over? I tried using
glScalef(1, -1, 1);
to flip it however that cause everything to stop rendering.
Code below
import static org.lwjgl.opengl.GL11.*;
import java.awt.Font;
import org.newdawn.slick.Color;
import org.newdawn.slick.TrueTypeFont;
public class FontRenderer {
private TrueTypeFont font;
public FontRenderer(){
Font awtFont = new Font("Times New Roman", java.awt.Font.PLAIN, 24);
font = new TrueTypeFont(awtFont, false);
}
public void render(float x, float y, String text){
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
font.drawString(x, y, text);
}
public void render(float x, float y, String text, float r, float g, float b)
{
Color color = new Color(r, g, b);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
font.drawString(x, y, text, color);
}
}
Your fonts are drawing upside down because Slick uses a origin in the top left corner, whereas by default LWJGL uses a origin in the bottom left. You stated that you know your origin is in the bottom left, so why would you expect your rendering code to work?

Draw a sprite onto the map not to the screen

I'm using libgdx and I have a tiled map which i want to draw the sprite onto. However the sprite is drawn onto the actual window so when I move the camera, the sprite stays in the same place. ?I want to the sprite to move on the map.
This is how i currently render my objects
#Override
public void render(float delta) {
translateCamera();
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
camera.update();
renderer.setView(camera);
renderer.render(bgLayers);
batch.begin();
batch.draw(splayerSprite, Gdx.graphics.getWidth() / 2,
Gdx.graphics.getHeight() / 2);
batch.end();
renderer.render(fgLayers);
}
It always end up being in the middle of the screen, however I want to be able to move them seperatly like for example the camera with (W,A,S,D) and move my player with the direction keys. Then if I want the camera locks onto the player but other wise its free.
I'm new to libgdx so please bear with me, Thanks
The problem is the SpriteBatch projection matrix isn't being set to the Camera projection matrix. This means the Sprite is not being rendered relative to the Camera. This is why the camera is moving, but the sprite is not; the correct matrix is not being used.
Also the sprite is being rendered always at half the screen's width, and half the screen's height. To fix this Call sprite.draw. This will use the Sprite's internal position.
Set the SpriteBatch projection matrix via batch.setProjectionMatrix(camera.combined). This will cause the sprite to be rendered relative to the camera.
#Override
public void render(float delta) {
translateCamera();
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
camera.update();
renderer.setView(camera);
renderer.render(bgLayers);
//here's the line that was missing.
batch.setProjectionMatrix(camera.combined);
batch.begin();
//be sure to call this instead of specifying position yourself!
splayerSprite.draw(batch);
batch.end();
renderer.render(fgLayers);
}
You'll still need to handle snapping the camera's position to the sprite's position whenever WASD is pressed, but that's trivial.
//snap the camera to the sprite's center.
if(wasd_isDown){
float centerX = sprite.getX()+sprite.getWidth()/2;
float centerY = sprite.getY()+sprite.getHeight()/2;
camera.position.set(x,y, 0);
}
If direction keys are pressed, just translate the camera's position vector via Vector3.add like so:
if(!wasd_isDown){
float deltaX = 0;
float deltaY = 0;
float MOVE_DIST = 10;//or whatever you need.
if(leftPressed) deltaX = -MOVE_DIST;
else if(rightPressed) deltaX = MOVE_DIST;
if(upPressed)deltaY = MOVE_DIST;
else if(downPressed)deltaY = -MOVE_DIST;
camera.position.add(deltaX, deltaY, 0);
}
This will allow the camera to move independently only when the player uses directional keys, and will allow the sprite be be rendered in relation to the camera's orientation. It will also snap the camera immediately back to the sprite when WASD is pressed.
batch.draw(splayerSprite, Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 2);
You are telling the code to draw it to the center of your screen every time. You need to change Gdx.graphics.getWidth() / 2 and Gdx.graphics.getHeight() / 2 to actual values that change based on your input.
Edit #2: The line batch.setProjectionmatrix(camera.combined); is needed in addition to everything I have mentioned, I both did not notice that specific line was already in my code (it is included in the default libGDX project), and did not try running my demo with that line removed. I hope that clears up any confusion I may have caused.
Edit: Since apparently nobody really liked my answer, I went and wrote a demo using the controls specified in a clean libGDX game. Regardless of where the camera is aimed at (since it is being translated), the sprite was always being rendered in the center of the global screen. It is very much necessary to use the sprite's position in the batch.draw() instead of a static position, otherwise it will not move.
package com.me.mygdxgame;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.Texture.TextureFilter;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Vector2;
public class MyGdxGame implements ApplicationListener {
private OrthographicCamera camera;
private SpriteBatch batch;
private Texture texture;
private Sprite sprite;
private Sprite background;
private boolean lockToSprite;
private Vector2 vecCamera;
private Vector2 vecSprite;
#Override
public void create() {
float w = Gdx.graphics.getWidth();
float h = Gdx.graphics.getHeight();
camera = new OrthographicCamera(w, h);
batch = new SpriteBatch();
lockToSprite = true;
vecCamera = new Vector2();
vecSprite = new Vector2();
texture = new Texture(Gdx.files.internal("data/libgdx.png"));
texture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
TextureRegion region = new TextureRegion(texture, 0, 0, 512, 275);
sprite = new Sprite(region);
sprite.setSize(0.1f * sprite.getWidth(), 0.1f * sprite.getHeight());
sprite.setOrigin(sprite.getWidth()/2, sprite.getHeight()/2);
sprite.setPosition(-sprite.getWidth()/2, -sprite.getHeight()/2);
background = new Sprite(region);
background.setOrigin(background.getWidth() / 2, background.getHeight() / 2);
System.out.println(background.getOriginX());
background.setPosition(-background.getWidth() / 2, -background.getHeight() / 2);
}
#Override
public void dispose() {
batch.dispose();
texture.dispose();
}
#Override
public void render() {
camera.translate(vecCamera);
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
camera.update();
camera.translate(vecCamera.cpy().mul(-1));
float moveSensitivity = 0.9f;
Vector2 vecInputSprite = new Vector2();
if (Gdx.input.isKeyPressed(Keys.UP))
vecInputSprite.y += moveSensitivity;
if (Gdx.input.isKeyPressed(Keys.DOWN))
vecInputSprite.y -= moveSensitivity;
if (Gdx.input.isKeyPressed(Keys.LEFT))
vecInputSprite.x -= moveSensitivity;
if (Gdx.input.isKeyPressed(Keys.RIGHT))
vecInputSprite.x += moveSensitivity;
if (Gdx.input.isKeyPressed(Keys.N))
vecSprite.set(new Vector2());
Vector2 vecInputCamera = new Vector2();
if (Gdx.input.isKeyPressed(Keys.W))
vecInputCamera.y += moveSensitivity;
if (Gdx.input.isKeyPressed(Keys.S))
vecInputCamera.y -= moveSensitivity;
if (Gdx.input.isKeyPressed(Keys.A))
vecInputCamera.x -= moveSensitivity;
if (Gdx.input.isKeyPressed(Keys.D))
vecInputCamera.x += moveSensitivity;
if (Gdx.input.isKeyPressed(Keys.R)) {
vecCamera.set(new Vector2());
lockToSprite = false;
}
if (vecInputCamera.len2() != 0)
lockToSprite = false;
else if (Gdx.input.isKeyPressed(Keys.L))
lockToSprite = true;
if (lockToSprite) {
vecCamera.set(vecSprite);
} else {
vecCamera.add(vecInputCamera);
}
vecSprite.add(vecInputSprite);
batch.setProjectionMatrix(camera.combined);
batch.begin();
background.draw(batch);
sprite.setPosition(vecSprite.x, vecSprite.y);
sprite.draw(batch);
//batch.draw(sprite, vecSprite.x, vecSprite.y);
batch.end();
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
}

Categories