Moving a sprite in LibGDX - java

I've got a few years experience in Java and Slick2D, and I'm attempting to port a game over to libgdx due to the fact that it is a much better library. However, I'm having a simple issue with moving a sprite on the screen. There must be some paradigm I don't understand with this API. I've distilled my code into the following. It recognizes input and runs it through my entire entity and networking systems both to and from the server, and yet the sprite stays at the same location. Any help would be wonderful.
My create() method:
public void create() {
//Check to see if we are using external server or localhost
ClientNetworkManager.setLocalhostAsHost(Constant.useLocalhost, this);
//Begin application setup
float w = Gdx.graphics.getWidth();
float h = Gdx.graphics.getHeight();
camera = new OrthographicCamera(1280,900);
batch = new SpriteBatch();
//Load assets into memory
texture = new Texture(Gdx.files.internal("Sprites/Ash.png"));
//texture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
sprite = new Sprite(texture);
sprite.setSize(256,256);
sprite.setPosition(44, 666);
//Begin external network setup
setPlayerPointer(null);
this.connection = new ClientConnectionThread(this);
getClientConnectionThread().setCurrentPing(0);
}
My render() method:
public void render() {
//Render logic
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
if (connection.isActive() && !Constant.performEssentialTasksOnly) {
InputManager.handlePlayerInput(this);
batch.setProjectionMatrix(camera.combined);
camera.update();
batch.begin();
batch.draw(sprite,playerPointer.getCurrentX(),playerPointer.getCurrentY());
System.out.println(playerPointer.getCurrentX());
batch.end();
}
}
The values for the getCurrentX/Y methods are all reporting correctly, so that's not the issue. I feel it must be something obvious.

You aren't using the Sprite position to render it, you are actually using it like if it was a regular TextureRegion.
batch.draw(sprite,playerPointer.getCurrentX(),playerPointer.getCurrentY());
System.out.println(playerPointer.getCurrentX());
Where are you changing this playerPointer?
Do it more like this:
sprite.setPosition(playerPointer.getCurrentX(),playerPointer.getCurrentY())
sprite.draw(batch);
But again, the problem is that playerPointer doesnt have the correct values (they aren't changing).

You can call
sprite.setX(xpos);
to change the actual position.
If you are going to use a tiledmap, don't forget to push in the right SpriteBatch, which should be returned by the renderer.getSpriteBatch() method.

Related

libGDX problem with getWidth() and getHeight() after resizing

Problem recorded and uploaded to Youtube
libGDX resizing problem
I am starting out with libGDX and wanted to make a game.
However... when I was just experimenting around... this happened.
I don't know why it does that or what I should do to eliminate this.
I don't know what to google either. It's almost as if libGDX's default width and height methods doesn't update correctly when the screen is being resized.
Am I doing something wrong here?
Code :
public class Metroidvania extends ApplicationAdapter {
ShapeRenderer s;
#Override
public void create () {
s = new ShapeRenderer();
}
#Override
public void render () {
ScreenUtils.clear(1, 1, 1, 1);
s.begin(ShapeRenderer.ShapeType.Filled);
s.setColor(0, 0, 0, 1);
s.rect(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
s.end();
}
#Override
public void dispose () {
s.dispose();
}
}
The video is currently stuck at 97% uploaded... Even Youtube is against me now
Basically, The code is supposed to cover the entire screen in black... even when resized. But here, when resised Gdx.graphics.getWidth() and Height() returns wrong values, causing white spaces to show.
The rect()'s shape depends on which direction you resize in.
Resize the screen smaller and the rect() become's smaller at R times the rate of resizing (R is unknown). Vice versa for reisizing it larger.
LibGDX usually uses a virtual screen and viewports i.e. you render to a different width and height than are the real ones in pixel terms.
Maybe have a look here Libgdx Window Resizing: Keeping Aspect Ratio as there is a resize method you can hook into to dynamically update your own coordinate system.

LibGDX how to use different batches in one Stage

I'm using LibGDX with Scene2D for my java game. I know my issue is connected to Scene2D, because I used the EXACT same class passing it normally to SpriteBatch (not through Stage instance) and it worked as expected.
I let Stage manage all of my drawables entities which are actors. It draws everything using implementor of Batch; SpriteBatch is the default. And it was working until I wanted to draw a polygon, which has to be drawn by PolygonSpriteBatch, not SpriteBatch.. So during one Stage.draw() call I need to use them both.
I made a CheckedPolygon class which is basically two PolygonSprites drawn on top of each other (one is semi-transparent). SpriteBatch passed in draw() method is temporarily ended to enable PolygonSpriteBatch for a moment, draw the polygon and disable it.
And the output is empty screen, I get nothing. Again, it worked when I wasn't using Stage class.
Here's the class, so you get a better understanding.
NOTE: I know this is bad in terms of performance, because I don't dispose of Texture and keep Batch for one object but it's for the sake of simplicity.
NOTE2: Yes, I passed it properly to stage, the code is executed, I checked through debugging.
public class CheckedPolygon extends Actor {
private final PolygonSprite mBackground, mCross;
private final PolygonSpriteBatch mPolygonSpriteBatch;
private final Camera mCamera;
public CheckedPolygon(Camera camera, float[] vertices, short[] triangles) {
super();
mCamera = camera;
mPolygonSpriteBatch = new PolygonSpriteBatch();
Texture textureBack = new Texture(Gdx.files.internal("source/back.png"));
textureBack.setWrap(Texture.TextureWrap.Repeat, Texture.TextureWrap.Repeat);
PolygonRegion regionBack = new PolygonRegion(new TextureRegion(textureBack), vertices, triangles);
mBackground = new PolygonSprite(regionBack);
Texture textureCross = new Texture(Gdx.files.internal("source/cross.png"));
textureCross.setWrap(Texture.TextureWrap.Repeat, Texture.TextureWrap.Repeat);
PolygonRegion regionCross = new PolygonRegion(new TextureRegion(textureCross), vertices, triangles);
mCross = new PolygonSprite(regionCross);
}
#Override
public void draw(Batch batch, float parentAlpha) {
batch.end();
mPolygonSpriteBatch.setProjectionMatrix(mCamera.combined);
mPolygonSpriteBatch.begin();
mBackground.draw(mPolygonSpriteBatch);
mCross.draw(mPolygonSpriteBatch);
mPolygonSpriteBatch.end();
batch.begin();
}
}
And I use it like this:
CheckedPolygon polygon = new CheckedPolygon(mStage.getCamera(), mTextureAtlas, new float[]{0, 500, 0, 0, 0, 500}, new short[]{0, 1, 2});
mStage.addActor(polygon);
I checked values from methods PolygonSprite.getVertices() and PolygonSprite.getBoundingRectangle() and got some weird outputs...
You create an invalid polygon with 0,500 being the first and last point.
So you need to chose valid vertices, for example:
new float[] {0, 0, 0, 500, 500, 500}
I created a small image to visualize it. The line on top is your "polygon", the triangle below is a polygon with the vertices from above:
The vertices you get back from the polygon sprite are otherwise ok, since they contain x, y, color, u, v.

LibGDX - Drawing to a FrameBuffer does not work

So I'm trying to make custom buttons, for which I need to combine different parts of the button background. To do this I figured using a FrameBuffer would work, however it did not give viable results. Therefore I attempted to test my FrameBuffer drawing method, by writing a simple test method, which returns a texture that is drawn to the display at every render() call. This method is here (note that it is a test method, so it may be a little poorly optimized):
private Texture test()
{
BitmapFont f = ReverseBlade.fontTitle;
f.setColor(Color.LIGHT_GRAY);
FrameBuffer fbo = new FrameBuffer(Format.RGBA8888, (int)f.getBounds("Hi").width, (int)f.getBounds("Hi").height, false);
Batch b = ReverseBlade.batch;
OrthographicCamera c = new OrthographicCamera(fbo.getWidth(), fbo.getHeight());
c.setToOrtho(false);
c.update();
b.setProjectionMatrix(c.combined);
fbo.begin();
b.begin();
f.draw(b, "Hi", 0, 0);
b.end();
fbo.end();
Texture t = fbo.getColorBufferTexture();
fbo.dispose();
b.setProjectionMatrix(ReverseBlade.camera.combined);
return t;
}
However, nothing is displayed. The screen is dark... I have tried without the camera and multiple other variations that I can no longer remember. What am I doing wrong?
Half Solution
What I ended up having to do is to make a new Matrix4 object for the FrameBuffer like this:
Matrix4 m = new Matrix4();
m.setToOrtho2D(0, 0, fbo.getWidth(), fbo.getHeight());
batch.setProjectionMatrix(m);
However, this makes everything that is drawn be upside down, like this:
I think the fbo.dispose() call is destroying more than you want.
See the source and notice where it destroys the colorTexture, which is the result of getColorBufferTexture().
I think this could be considered a bug in Libgdx. The color texture is generally something that should have a very different lifetime than the FBO, so cleaning up the texture seems a bit too aggressive. However, trying to figure out which cases to clean the texture up is probably complicated.....
So following what I added with the Half Solution, all I had to do was create a new Sprite object with the texture from the FBo and call flip(false, true)!
May be this is a workaround to dispose() the framebuffer and keeping the texture alive. I do the following:
public class TextureSaveFBO extends FrameBuffer {
static final Texture DUMMY = new Texture(1, 1, Format.RGB565) {
public void dispose() {
};
};
public TextureSaveFBO(Format format, int width, int height,
boolean hasDepth) {
super(format, width, height, hasDepth);
}
#Override
public void dispose() {
// prevents the real texture of dispose()
Texture t = colorTexture;
colorTexture = DUMMY;
super.dispose();
colorTexture = t;
}
}
Just a precisation:
OrthographicCamera c = new OrthographicCamera(fbo.getWidth(), fbo.getHeight());
c.setToOrtho(false);
This is potentially harmful unless you know what you are doing: c.setOrtho(false) does the following:
Sets this camera to an orthographic projection using a viewport fitting the screen resolution, centered at (Gdx.graphics.getWidth()/2, Gdx.graphics.getHeight()/2), with the y-axis pointing up or down.
So even if you specified in the OrthographicCamera's constructor that you want the viewport to be of the frame buffer size, you are overwriting that with the following call to a viewport covering the screen size and centered to the screen center.
You should probably do:
camera.setToOrtho(false, fbo.getWidth(), fbo.getHeight());
Issue solved since LibGDX 1.6.5.
It's now possible to override disposeColorBuffer method to not dispose rendered texture.

libgdx and android application. Image as background

I am new and I just start my journey with libgdx. I would like to know how I can do image.png in resolution 960x640 as background in my game? This is possible? Thx for advices and forbearance. Maybe you hava a simply tutorial?
This is my render class:
public void render() {
texture = new Texture(Gdx.files.internal("E:/background.png"));
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(texture, 0, 0);
batch.end();
}
Second question. I need to insert two active images, active means when I click on that image, the next image show me on the screen. I want to implement action when I click on that picture.
In your create() method, create a new Texture referencing your image.png, and then use your existing SpriteBatch to render it in the render() loop. Immediately after your GL.clear() call, go your batch.draw(backgroundTexture, 0. 0) and make sure you're in OrthographicProjection mode for your camera.
first you have to set the view port
do this in your create method
`float scrw = 960;
float scrh = 640;
camera = new OrthographicCamera();
camera.viewportHeight = scrh;
camera.viewportWidth = scrw;
camera.position.set(camera.viewportWidth * .5f,
camera.viewportHeight * .5f, 0f);
camera.update();`
create a texture
texture = new Texture("data/background.png");
put this texture in a sprite like this
sprite=new sprite(texture);
and then set the size like this
sprite.setsize(960,640);
and draw it in your render methods between batch.begin
and batch.end
sprite.draw(batch);

Changing the Coordinate System in LibGDX (Java)

LibGDX has a coordinate system where (0,0) is at the bottom-left. (like this image: http://i.stack.imgur.com/jVrJ0.png)
This has me beating my head against a wall, mainly because I'm porting a game I had already made with the usual coordinate system (where 0,0 is in the Top Left Corner).
My question: Is there any simple way of changing this coordinate system?
If you use a Camera (which you should) changing the coordinate system is pretty simple:
camera= new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
camera.setToOrtho(true, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
If you use TextureRegions and/or a TextureAtlas, all you need to do in addition to that is call region.flip(false, true).
The reasons we use y-up by default (which you can easily change as illustrated above) are as follows:
your simulation code will most likely use a standard euclidian coordinate system with y-up
if you go 3D you have y-up
The default coordinate system is a right handed one in OpenGL, with y-up. You can of course easily change that with some matrix magic.
The only two places in libgdx where we use y-down are:
Pixmap coordinates (top upper left origin, y-down)
Touch event coordinates which are given in window coordinates (top upper left origin, y-down)
Again, you can easily change the used coordinate system to whatever you want using either Camera or a tiny bit of matrix math.
Just to expand a little on what badlogic said above, if you are using a TextureAtlas (with TextureRegions) you need to flip them, as badlogic said, in addition to the camera work. If you are using a TextureAtlas, you can use this code right after loading your atlas:
String textureFile = "data/textures.txt";
atlas = new TextureAtlas(Gdx.files.internal(textureFile), Gdx.files.internal("data"));
// Let's flip all the regions. Required for y=0 is TOP
Array<AtlasRegion> tr = atlas.getRegions();
for (int i = 0; i < tr.size; i++) {
TextureRegion t = tr.get(i);
t.flip(false, true);
}
If you want to hide the transformation and not think about it after setting it up once, you can make a class that inherits all of the functionalities you need, but first transforms the coordinates before passing it to its parent class's function. Unfortunately, this would take a lot of time.
You could alternatively make a method that does the simple y' = height - y transformation on the whole Coordinate object (or whatever it is you're using), and call it once before each operation.
Interesting graphics library, I would say. I found this assessment from the link below:
Another issue was that different coordinate systems were used in different parts of Libgdx. Sometimes the origin of the axes was in the
bottom left corner with the y-axis pointing upwards and sometimes in
the top left corner of the sprite pointing downwards. When drawing
Meshes the origin was even in the center of the screen. This caused
quite a bit of confusion and extra work to get everything in the
correct place on the screen.
http://www.csc.kth.se/utbildning/kandidatexjobb/datateknik/2011/rapport/ahmed_rakiv_OCH_aule_jonas_K11072.pdf
I just made a class that extends SpriteBatch that overides certain methods adding y = Gdx.graphics.getHeight() - y - height. Simple but effective.
I was able to get textures and fonts rendering correctly using the suggested flipped coordinate system via OrthographicCamera. Here's what I did:
private SpriteBatch batch;
private BitmapFont font;
private OrthographicCamera cam;
private Texture tex;
#Override
public void create () {
batch = new SpriteBatch();
font = new BitmapFont(true);
font.setColor(Color.WHITE);
cam = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
cam.setToOrtho(true, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
tex = new Texture("badlogic.jpg");
}
#Override
public void dispose() {
batch.dispose();
font.dispose();
tex.dispose();
}
#Override
public void render () {
cam.update();
batch.setProjectionMatrix(cam.combined);
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
font.draw(batch, "Test", 50, 50);
batch.draw(tex, 100, 100, tex.getWidth(), tex.getHeight(), 0, 0, tex.getWidth(), tex.getHeight(), false, true);
batch.end();
}
Important things to notice are:
The BitmapFont constructor, the boolean flips the font
For batch.draw() you need to use all those parameters because you need a boolean flipY at the end to flip the texture (I may extend SpriteBatch or make a utility method to avoid passing so many parameters all the time.)
Notice batch.setProjectionMatrix(cam.combined); in render()
Now we will see if I am back here later tonight doing edits to fix any other issues or discoveries with doing all this.

Categories