How to create a proper ortographic camera in libgdx - java

So I am having a little hard time understanding how ortographic cameras work in libgdx.
what I want is to have a camera that will only render things within a square while having another camera set the bounds for my whole screen.
So here, I was able to do what I wanted on the whole screen for the game pad. But, the thing you see on the top right is the background map of the game and i want to render the parts only fall within the red square you see here. How do I achieve that?
Are cameras supposed to do that or do I need to figure out a way to do it manually? I am really confused as to how cameras and projection matrices work.
Here on this screen, The red square and the green pad on the left are being drawn using the projection matrix of my screen camera. The map(top right) is drawn using my map cam.
Map cam is a view port of 400x400 but as you can see , the tiles are rectangular and that isnt the aspect ration i want. If someone can briefly explain how cameras work , I'd greatly appreciate it.
The reason I am not posting my code here is because I feel like I need to understand how camera mechanics work to even code it properly so I want to address that issue first.
Following #Tenfour04's advice worked perfectly. In case anyone wonders what I wanted to achieve. Here's a picture.

A camera alone cannot crop off part of the screen. For that you need to use glViewport. There is already a Viewport class in Libgdx that can do that for you. You will need two orthographic cameras (one for the map and one for the GUI), but the viewport can create its own.
private Viewport viewport;
//in create:
viewport = new FitViewport(400, 400);
//in resize:
viewport.update(width, height);
//in render:
viewport.getCamera().position.set(/*...move your map camera as needed*/);
viewport.apply(); //viewport cropped to your red square
batch.setProjectionMatrix(viewport.getCamera().combined);
batch.begin();
//draw map
batch.end();
//return to full screen viewport
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
batch.setProjectionMatrix(yourGUICamera.combined);
batch.begin();
//draw gui
batch.end();

What happens, is the camera will fit itself to the size of the screen. In order to change this, you would want to use a FrameBuffer. The frame buffer will constrain the camera into the desired size, then can be drawn as a texture.
Create the frame buffer with the dimensions being in pixels.
//Initialize the buffer
FrameBuffer fbo = new FrameBuffer(Format.RGB565, width, helght, false);
Render the world within the buffer.
fbo.begin();
//Draw the world here
fbo.end();
Draw the buffer to the screen with a batch.
batch.begin();
batch.draw(fbo.getColorBufferTexture(), x, y);
batch.end();

Related

Fitviewport Wrong Camera Positioning

I have developed a game on my phone which has 1080x1920(portrait) resolution. And I set my fitviewport according to it. It looks like this on my phone:
But on any other phone or on desktop camera has wrong positioning. It looks like this on other devices:
I have used fitviewport in other projects before but never encountered that problem. May it be because of portrait mode?
EDIT
Related code is here:
//in create
camera = new Orthographiccamera();
camera.setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeigth());
viewport = new FitViewport(1080,1920,camera);
//in resize
viewport.update(width,height);
//before starting batch
batch.setProjectionMatrix(camera.combined);
You have two contradicting statements in your code: camera.setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeigth()). This will set the camera's viewport size to the display size and then center the camera.
On the other hand, you want to use a FitViewport with a fixed size of 1080x1920.
If your screen size is exactly 1080x1920, there's no problem, because the center will be the same. If the screen size differs from the one you use in FitViewport, then setToOrtho() will set the camera's center to a position that's not the center of 1080x1920 and that's why you notice the offset.
Using viewport.update(width, height, true) will correct this. The last parameter will center the camera correctly and override what happened in setToOrtho().
Let the viewport manage your camera and remove the call of camera.setToOrth().

LibGDX Scaling and Rendering Sprites from TextureAtlas

I am currently experiencing issues when drawing and scaling sprites.
I am loading my assets from a texture-atlas, which I packed no problem with the LibGDX texture packer gui tool. My texture atlas image currently looks like this.
These images are supposed to be buttons, but as you can see, the image is very small, so when the sprites are loaded, they load a sprite of say, 34x16 pixels. When I render these buttons, on a canvas of 1920x1080, they are much too small. I use sprite.scale(int scale) to scale the sprites, but when I scale them, they appear blurry. What I would like to happen, is when they are scaled, each pixel is scaled proportionally, keeping the pixelated effect on the button, rather than a blurry resized image from a really small texture. I currently render the sprites using sprite.render(SpriteBatch batch). Is this the proper way of rendering a sprite, after they are loaded using atlas.createSprite(String name)? I am new to using sprites, and loading textures from a texture-atlas, so i am wondering if this is the correct way of doing things.
Also, when I initialize my game, I load numerous different Sprite objects from a TextureAtlas. Each sprite holds a texture that will represent a game object, however it is my understanding that you render a sprite using sprite.render(SpriteBatch batch), so therefore I could only use a sprite, loaded from the TextureAtlas for one game object, because I would also have to set the scale, and position of the sprite, as it represents the game object. I am used to loading a Texture, then rendering this texture using batch.render(), at a given position, but I don't see how this is possible if I am using a sprite. Even if I use batch.render(Sprite, x, y), I am unable to scale the sprite properly, because as I mentioned before, I would like to scale the sprite while maintaining a pixelated effect, and even so, using the Sprite.scale() method, this would scale the Sprite object as a whole, making it impossible to use the Sprite's texture multiple times for numerous game objects.
Any suggestions would be greatly appreciated.
The code I am currently using to render/load the sprites is as follows:
Loading from TextureAtlas:
public static TextureAtlas atlas = new TextureAtlas(Gdx.files.internal("data/texture/pack/output/pack.pack"));
public static Sprite sprite = atlas.createSprite("buttonUp");
sprite.setScale(10);
Rendering Sprite: GdxGame.WIDTH/HEIGHT are 1920x1080. Though the Desktop window is scaled down from that size. Thus, everything is rendered as if the screen were 1920x1080.
batch = new SpriteBatch();
camera = new OrthographicCamera(GdxGame.WIDTH, GdxGame.HEIGHT);
camera.position.set(GdxGame.WIDTH/2, GdxGame.HEIGHT/2, 0);
camera.setToOrtho(false, GdxGame.WIDTH, GdxGame.HEIGHT);
public void render(float delta){
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(camera.combined);
batch.begin();
camera.update();
sprite.draw(batch);
batch.end();
}
After further investigation, I have discovered that I can use Sprite.set(Sprite sprite) to make Sprite x a copy of Sprite y, and therefore render each sprite multiple times. However, this does not solve the issue of scaling the sprite. I must emphasize further that when rendering a scaled sprite, the scaling is not done by pixel, meaning that it is blurry. But, when rendering a TextureRegion, like: batch.draw(TextureRegion, x, y, width, height) if the width and height are greater than that of the original texture, it will scale each pixel, rather than blur the whole thing to try and make it look better. The following is an image of the blurriness I am talking about:
Notice how this sprite is scaled to be blurry, even though the original image is small, and pixelated.
What TextureFilter settings are you using in your code or in the texturepacker? Try the "Nearest" filter. If you have set it to "Linear" or alike, it will always take 4 texture pixels (texels) and interpolate them to get the color of the pixel to be drawn.
That might help against the blur, but I am not sure if it will produce exactly that 8-bit look you are aiming for...

Difficulty drawing a background sprite using LWJGL

I'm trying to render a background image for a new game I'm creating. To do this, I thought I'd just create a simple Quad and draw it first so that it stretched over the background of my game. The problem is that the quad doesn't draw to it's correct size and draws at the complete wrong place on the screen. I am using LWJGL and an added slick-util library for loading textures.
background = TextureHandler.getTexture("background", "png");
This is the line of code which basically gets my background texture using a class that I wrote using slick-util. I then bind the texture to a quad and draw it using glBegin() and glEnd() like this:
// Draw the background.
background.bind();
glBegin(GL_QUADS);
{
glTexCoord2d(0.0, 0.0);
glVertex2d(0, 0);
glTexCoord2d(1.0, 0.0);
glVertex2d(Game.WIDTH, 0);
glTexCoord2d(1.0, 1.0);
glVertex2d(Game.WIDTH, Game.HEIGHT);
glTexCoord2d(0.0, 1.0);
glVertex2d(0, Game.HEIGHT);
}
glEnd();
You'd expect this block to draw the quad so that it covered the entire screen, but it actually doesn't do this. It draws it in the middle of the screen, like so:
http://imgur.com/Xw9Xs9Z
The large, multicolored sprite that takes up the larger portion of the screen is my background, but it isn't taking up the full space like I want it to.
A few things I've tried:
Checking, double-checking, and triple-checking to make sure that the sprite's size and the window's size are identical
Resizing the sprite so that it is both larger and smaller than my target size. Nothing seems to change when I do this.
Positioning the sprite at different intervals or messing with the parameters of the glTexCoord2d() and glVertex2d(). This is just messy, and looks unnatural.
Why won't this background sprite draw to it's correct size?
If you have not created your own orthogonal projection (I.E. using glOrtho()), then your vertex coordinates will need to range from -1 to +1. Right now you're only drawing on the left half of that projection, thus giving you this result.

Libgdx SpriteBatch.SetProjectionMatrix makes spritebatch not draw

SpriteBatch.SetProjectionMatrix(cam.combined) makes Spritebatch not draw blocks and my character but camera movement works, but if I don't use this line of code everything is drawn but camera is not working? Does anyone know the solution, because if simply can't see it.
EDIT: sorry for the messy first post
Here is the piece of code that is troublesome:
public void render()
{
cam.update();
spriteBatch.setProjectionMatrix(cam.combined);
spriteBatch.begin();
drawBlocks();
drawBob();
spriteBatch.end();
cam.position.x = world.bob.GetPosition().x;
cam.update();
drawCollisionBlocks();
if(debug)
drawDebug();
}
I found the solution but for anyone who may have this kind of problem in the future, the problem was in drawing methods where i was drawing
textures like this:
CODE:
spriteBatch.draw(bobFrame, bob.GetPosition().x * PPuX, bob.GetPosition().y*PPuY ,Bob.SIZE*PPuX , Bob.SIZE*PPuY );
PPuX,PPuY were of type int and were used for different screen sizes and that was messing spriteBatch up when i was setting the projection matrix
The spriteBatch.setProjectionMatrix(cam.combined) lets spriteBatch use the coordinate system that specified by cam instead of the default ones. This is because the both's coordinate system are different and the cam.combined will do the maths for you.
I believe you actually ARE drawing the sprites, however you are not seeing them because your camera viewports are not set(ie. you are looking at the wrong coordinate area).
Adding
cam.setToOrtho(false); //true to invert y axis
"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."
Link to JavaDOC here

OpenGL Rotate Box

I most likely have this wrong, but in my camera class, I rotate and translate the whole scene around the camera so it looks like the camera is actually moving. This works fine since all of the boxes in my game are axis aligned. I now want to rotate one of the boxes, but glRotate isn't working since I am using in the camera to rotate the scene. Does anyone know any ways to rotate the whole scene and then rotate a part individually?
When you are drawing the object you want to rotate you can do a push matrix, rotate, draw, and a pop matrix.
void display() { // display callback function
glPushMatrix();
glRotate(...); // rotation
myObject.draw(); // draw the objects you want to rotate
glPopMatrix();
}
Before you push matrix:
You may first need to change the matrix mode from projection to modelview or call glLoadIdentity();

Categories