This might be a simple question being addressed somewhere, but I can’t find it. I do hope someone can lead me to the right path. The design resolution for my application is 800x480. To maintain the correct aspect ratio on devices with higher resolution, I followed this post and managed to get the “black bar” (I used blue for testing) on both side on a bigger screen (nexus 7). However, it seems that the stage is not scaled to cover the screen. Please see screen shot bellow, blue colour are the Gdx.gl.glClearColor(0.5f, 1, 1, 1); black rectangular (800x480) is the actual Sprite.
Link to image
I am not sure where I went wrong. Any help is much appreciated. Code below:
private SpriteBatch batch;
private Texture splashTexture;
private Sprite splashSp;
TextureRegion splashTr;
Stage stage;
#Override
public void create() {
stage = new Stage();
batch = new SpriteBatch();
splashTexture = new Texture(Gdx.files.internal("img/splashTexture.png"));
splashTexture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
TextureRegion splashTr = new TextureRegion(splashTexture, 0, 0, 800, 480);
splashSp = new Sprite(splashTr);
Gdx.app.log("myapp", "Creating game");
}
#Override
public void render() {
Gdx.gl.glClearColor(0.5f, 1, 1, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
stage.draw();
batch.begin();
batch.draw(splashSp, 0, 0);
batch.end();
}
#Override
public void resize(int width, int height) {
Gdx.app.log("myapp", "width:" + width + " height:" + height);
Vector2 size = Scaling.fit.apply(800, 480, width, height);
int viewportX = (int)(width - size.x) / 2;
int viewportY = (int)(height - size.y) / 2;
int viewportWidth = (int)size.x;
int viewportHeight = (int)size.y;
Gdx.app.log("myapp", "viewportWidth:" + viewportWidth + " viewportHeight:" + viewportHeight);
Gdx.app.log("myapp", "viewportX:" + viewportX + " viewportY:" + viewportY);
Gdx.gl.glViewport(viewportX, viewportY, viewportWidth, viewportHeight);
stage.setViewport(800, 480, true);
Gdx.app.log("myapp", "Resizing game");
}
You need to set the camera and stage.
first declare a variable of camera like this
OrthographicCamera camera;
then in create method do this
camera = new OrthographicCamera();
camera.setToOrtho(false, 800, 480);
camera.update();
mystage = new Stage(800, 480, false);
and in render method update the camera
camera.update();
worked fine for mee..
Related
I'm rendering sprites (game cards with one image and a table) on Android for a game and pack them with a PixmapPacker afterwards. When I am running the code with the Android emulator, the sprites are drawn well on the png file of the atlas, but the background of the file is completely black with some glitchy yellow pixels on the side of the sprites. Running the same code on my phone results in an almost completely black png with all my sprites black (only my "back.png" is drawn).
Have I cleared all buffers correctly or am I doing something wrong with the order of m_fbo.begin() and m_fbo.end()? Also I am not sure if it is necessary to call spriteBatch.begin() and spriteBatch.end() everytime inside the loop.
Any help would be very much appreciated.
Sprite sprite;
BitmapFont font;
Texture texture;
OrthographicCamera cam;
FrameBuffer m_fbo = null;
SpriteBatch spriteBatch;
Pixmap pixmap;
Skin skin;
public AtlasGenerator() {
cam = new OrthographicCamera(w, h);
cam.position.set(new Vector2(w / 2, h / 2), 1);
cam.update();
PixmapPacker packer = new PixmapPacker(packer_width, packer_height, Pixmap.Format.RGB565, padding, true);
//packer.setTransparentColor(Color.BLACK); // Is this necessary?
font = new BitmapFont();
spriteBatch = new SpriteBatch();
cam.update();
spriteBatch.setProjectionMatrix(cam.combined);
Table table = new Table(skin);
m_fbo = new FrameBuffer(Pixmap.Format.RGB565, w, h, false);
m_fbo.begin();
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
Gdx.gl.glClearColor(1f, 1f, 1f, 1);
Gdx.gl.glEnable(GL20.GL_BLEND);
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
//Gdx.gl.glColorMask(false, false, false, true);
int cardsCounter = game.getCounter();
for (int cardID = 0; cardID < cardsCounter; cardID++) {
System.out.println("Generating card " + (cardID + 1) + " of " + cardsCounter);
texture = new Texture(Gdx.files.internal(game.get(cardID).getImages().get(0).getFilename()));
sprite = new Sprite(texture);
/* adding data to table here...*/
/* Rendering */
spriteBatch.begin();
Gdx.gl.glClear(GL_COLOR_BUFFER_BIT);
Gdx.gl.glClearColor(1f, 1, 1, 1f);
spriteBatch.draw(sprite, 0, h - newh, neww, newh);
table.draw(spriteBatch, 1f);
spriteBatch.end();
ByteBuffer buf;
pixmap = new Pixmap(w, h, Pixmap.Format.RGB888);
buf = pixmap.getPixels();
Gdx.gl.glReadPixels(1, 1, w, h, GL20.GL_RGB, GL20.GL_UNSIGNED_BYTE, buf);
pixmap = flipPixmap(pixmap);
// convert pixmap to RGB565
Pixmap.Format format = Pixmap.Format.RGB565; //desired format
if (pixmap.getFormat()!=format) { //perform conversion if necessary
Pixmap tmp = new Pixmap(pixmap.getWidth(), pixmap.getHeight(), format);
tmp.drawPixmap(pixmap, 0, 0); //copy pix to tmp
pixmap.dispose(); //dispose old pix
pixmap = tmp; //swap values
}
//packer.updatePageTextures();
//packer.updateTextureAtlas();
//packer.updateTextureRegions();
packer.pack(String.valueOf(cardID), pixmap);
}
m_fbo.end();
System.out.println("Finished generating cards");
System.out.println("Start generating card pack...");
PixmapPackerIO.SaveParameters saveParameters = new PixmapPackerIO.SaveParameters();
saveParameters.magFilter = Texture.TextureFilter.Nearest;
saveParameters.minFilter = Texture.TextureFilter.Nearest;
packer.pack("back", new Pixmap(Gdx.files.internal("back.png")));
PixmapPackerIO pixmapPackerIO = new PixmapPackerIO();
try {
pixmapPackerIO.save(Gdx.files.external("cards.atlas"), packer, saveParameters);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Finished generating card pack");
packer.dispose();
dispose();
}
I fixed it by removing the OpenGL code and working with a TextureRegion:
m_fboRegion = new TextureRegion(m_fbo.getColorBufferTexture());
m_fboRegion.flip(false, true);
m_fbo.begin();
Gdx.gl.glClearColor(1f, 1f, 1f, 1);
Gdx.gl.glClear(GL_COLOR_BUFFER_BIT);
/* adding some data to sprite and table */
spriteBatch.begin();
Gdx.gl.glClear(GL_COLOR_BUFFER_BIT);
Gdx.gl.glClearColor(1f, 1, 1, 1f);
spriteBatch.draw(sprite, 0, h - newh, neww, newh);
table.draw(spriteBatch, 1f);
spriteBatch.end();
pixmap = ScreenUtils.getFrameBufferPixmap(0, 0, w, h);
pixmap = flipPixmap(pixmap);
m_fbo.end();
I have a simple LibGdx application with two sprites. One is a simple texture which is repeated to fill the background. This one works. The other is a texture which is alpha blended so the corners look darker than the center. It is stretched to cover the entire screen. For some reason, this one appears in the wrong location and is just a big white box.
Here is my code:
public class TestGame extends ApplicationAdapter {
SpriteBatch batch;
boolean showingMenu;
Texture background;
Sprite edgeBlur;
Texture edgeBlurTex;
#Override
public void create() {
showingMenu = true;
batch = new SpriteBatch();
background = new Texture(Gdx.files.internal("blue1.png"));
edgeBlurTex = new Texture(Gdx.files.internal("edge_blur.png"));
edgeBlur = new Sprite(edgeBlurTex);
edgeBlur.setSize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
}
#Override
public void resize(int width, int height) {
super.resize(width, height);
edgeBlur.setSize(width, height);
}
#Override
public void dispose() {
background.dispose();
edgeBlurTex.dispose();
super.dispose();
}
#Override
public void render() {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
drawBackground();
batch.end();
}
private void drawBackground() {
for (float x = 0; x < Gdx.graphics.getWidth(); x += background.getWidth()) {
for (float y = 0; y < Gdx.graphics.getHeight(); y += background.getHeight()) {
batch.draw(background, x, y);
}
}
edgeBlur.draw(batch);
}
}
Edit:
I fixed it by changing the draw command to:
batch.draw(edgeBlurTex, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
However the if I attempt to do any drawing after drawing these textures, such as:
ShapeRenderer shapeRenderer = new ShapeRenderer();
shapeRenderer.begin(ShapeRenderer.ShapeType.Line);
shapeRenderer.setColor(0, 0, 0, 1);
float unitHeight = Gdx.graphics.getHeight() / 9;
float indent = Gdx.graphics.getWidth() / 20;
shapeRenderer.rect(indent, unitHeight, Gdx.graphics.getWidth() - indent * 2, unitHeight);
shapeRenderer.rect(indent, unitHeight * 3, Gdx.graphics.getWidth() - indent * 2, unitHeight);
shapeRenderer.rect(indent, unitHeight * 5, Gdx.graphics.getWidth() - indent * 2, unitHeight);
shapeRenderer.rect(indent, unitHeight * 7, Gdx.graphics.getWidth() - indent * 2, unitHeight);
shapeRenderer.end();
It just stops working and goes back to drawing a white box. It seems very random, like something is seriously misconfigured with libgdx. Is there any way to debug this thing to work out what is wrong?
you should add enableBlending before your blended texture draw
batch.enableBlending();
edgeBlur.draw(batch);
batch.disableBlending();
you can also try to set the batch blending func by using setBlendFunction method after batch is created
update due to edit:
the SpriteBatch should be ended when starting Shaperenderer
I'm having problems with the libgdx viewport system on Android. I want to set a FitViewport on my camera, and all i get is a black screen. I tried with just the camera, without the viewport and it is working. I just can't manage to get it right on the viewport.
Here's my code:
Variables declaration:
private Texture texture;
private Sprite sprite;
private OrthographicCamera camera;
private float virtualWidth, virtualHeight;
private float aspectRatio;
private SpriteBatch batch;
private Viewport viewport;
Initialization
virtualWidth = 200;
virtualHeight = 200;
aspectRatio = Gdx.graphics.getHeight() / Gdx.graphics.getWidth();
texture = new Texture(Gdx.files.internal("mapa.jpg"));
sprite = new Sprite(texture);
camera = new OrthographicCamera();
viewport = new StretchViewport(virtualWidth * aspectRatio, virtualHeight, camera);
viewport.apply();
camera.position.set(virtualWidth / 2, virtualHeight / 2, 0);
batch = new SpriteBatch();
My render method:
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
batch.setProjectionMatrix(camera.combined);
batch.begin();
sprite.draw(batch);
batch.end();
And finally, the resize method:
viewport.update(width, height);
Plz can you point out what is wrong with my code?
I was wondering if there was a way to make Android games in libgdx so they all share the same resolution of 480x800. Using Gdx.graphics.setDisplayMode(480, 800, true) doesn't seem to change anything. Creating an OrthographicCamera of 480 by 800 makes it so the game is 480 by 800, but doesn't zoom into fullscreen and take up the entire screen like I expected it would. When I tested it out on my phone, the phone just used blank space to fill up the rest of the screen while the game in 480x800 resolution. Here is the code that I'm using.
public class GameScreen implements Screen {
private Game game;
private OrthographicCamera guiCam;
private SpriteBatch batch;
private Texture texture;
private Rectangle glViewport;
public GameScreen (Game game)
{
this.game = game;
guiCam = new OrthographicCamera(GAME_WIDTH, GAME_HEIGHT);
guiCam.position.set(GAME_WIDTH / 2, GAME_HEIGHT / 2, 0);
batch = new SpriteBatch();
texture = new Texture(Gdx.files.internal("data/c2.png"));
glViewport = new Rectangle(0, 0, GAME_WIDTH, GAME_HEIGHT);
}
#Override
public void render(float delta) {
if (Gdx.input.justTouched()) {
texture = new Texture(Gdx.files.internal("data/c1.png"));
}
GL10 gl = Gdx.graphics.getGL10();
gl.glClearColor(1, 0, 0, 1);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
gl.glViewport((int) glViewport.x, (int) glViewport.y,
(int) glViewport.width, (int) glViewport.height);
guiCam.update();
guiCam.apply(gl);
batch.setProjectionMatrix(guiCam.combined);
batch.begin();
batch.draw(texture, 0, 0, 0, 0, 142, 192);
batch.end();
}
private static final int GAME_WIDTH = 480;
private static final int GAME_HEIGHT = 800;
}
Thanks in advance.
You've set your glViewport to 480x800, that means you're asking the phone hardware for a 480x800 window to draw on. Because most (all?) phone hardware doesn't do screen scaling (like your desktop monitor does), they just give you a 480x800 area on the screen.
You need to get OpenGL to "zoom" your screen, and you do that by setting the glViewport() to the physical resolution of your device (modulo aspect ratio caveats!). You should leave the camera at the 'virtual' resolution you prefer (so 480x800 in this case). Now OpenGL will scale all your primitives up to the screen's resolution.
As a quick test, try this:
gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
The next problem is that if the hardware aspect ratio doesn't match your 'virtual' aspect ratio. In that case you need to decide between stretching, leaving black bars on one side, or changing your virtual aspect ratio. See this blog post for more details on the camera/viewport setup, and some solutions to the aspect ratio issue: http://blog.acamara.es/2012/02/05/keep-screen-aspect-ratio-with-different-resolutions-using-libgdx/
I'm creating a game with libgdx that I want to run at a higher resolution on the desktop, but I want it to scale everything down correctly when I run it on android at smaller resolutions. I've read that the best way to do this is to not use a pixel perfect camera, and instead to use world coordinates, but I'm not sure how to correctly do that.
This is the code I have right now:
#Override
public void create() {
characterTexture = new Texture(Gdx.files.internal("character.png"));
characterTextureRegion = new TextureRegion(characterTexture, 0, 0, 100, 150);
batch = new SpriteBatch();
Gdx.gl10.glClearColor(0.4f, 0.6f, 0.9f, 1);
float aspectRatio = (float)Gdx.graphics.getWidth() / (float)Gdx.graphics.getHeight();
camera= new OrthographicCamera(aspectRatio, 1.0f);
}
#Override
public void render() {
GL10 gl = Gdx.graphics.getGL10();
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
camera.update();
camera.apply(gl);
batch.setProjectionMatrix(camera.combined);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
draw();
}
private void draw() {
//batch.getProjectionMatrix().set(camera.combined);
batch.begin();
batch.draw(characterTextureRegion, 0, 0, // the bottom left corner of the box, unrotated
1f, 1f, // the rotation center relative to the bottom left corner of the box
0.390625f, 0.5859375f, // the width and height of the box
1, 1, // the scale on the x- and y-axis
0); // the rotation angle
batch.end();
}
The texture I'm use is 256x256 with the actual image in it being 100x150.
This is the result I get when I run the game: http://i.imgur.com/HV9Bi.png
The sprite that gets rendered is massive, considering this is the original image: http://i.imgur.com/q1cZT.png
What's the best way to go about making it so that the sprites get rendered at their original size while still keeping the ability to have the game scale correctly when played in different resolutions?
I've only found two solutions, both of which I don't like.
The image showed up how it was supposed to if I used pixel coordinates for the camera, but then that didn't scale at all when I put it on my phone with a different resolution.
I can scale the texture region down when I draw it, but it seems like there is a better way because it is extremely tedious trying to figure out the correct number to scale it by.
Have you ever used the Libgdx setup tool? When you create a project with it, it has a sample image that is displayed. It seems to keep it's ratio correct no matter what size you change the screen to.
public class RotationTest implements ApplicationListener {
private OrthographicCamera camera;
private SpriteBatch batch;
private Texture texture;
private Sprite sprite;
Stage stage;
public boolean leonAiming = true;
#Override
public void create() {
float w = Gdx.graphics.getWidth();
float h = Gdx.graphics.getHeight();
camera = new OrthographicCamera(1, h/w);
batch = new SpriteBatch();
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.9f, 0.9f * sprite.getHeight() / sprite.getWidth());
sprite.setOrigin(sprite.getWidth()/2, sprite.getHeight()/2);
sprite.setPosition(-sprite.getWidth()/2, -sprite.getHeight()/2); }....
#Override
public void render() {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(camera.combined);
batch.begin();
sprite.draw(batch);
batch.end();
First of all you need to fix boundaries to the world (I mean to your game ). In that world only you actors(game characters) should play. If you are crossing boundaries, manage it with camera like showing up, down, left and right.