LibGDX multiple cameras - java

So, I am working with LiBGDX and Box2D, using the PixelsPerMeter conversion, and I have a camera that follows the player around, but when I turn debug mode on I need to be able to draw a font with the fps on screen, so I always can see it in the corner. The problem is that when I try to scale the BitmapFont down, so it looks normal, cause everything else is scaled down, because of the Box2D. I found something that said something about using multiple cameras, so I don't have to scale the font down, but it didn't have any documentation. I tried to figure how to do it, but with no luck. How should I draw the font to the screen?
Here is my game state in which I tried the multiple cameras:
package com.platformer.gamestates;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Box2DDebugRenderer;
import com.badlogic.gdx.physics.box2d.World;
import com.platformer.Entities.Player;
import com.platformer.game.Game;
import com.platformer.generation.MenuTiles;
import com.platformer.generation.TiledMaps;
import com.platformer.managers.GameContacts;
import com.platformer.managers.GameStateManager;
import static com.platformer.managers.B2DVars.PPM;
public class MenuState extends GameState {
World world;
Box2DDebugRenderer debugRenderer;
Texture close, far, house;
BitmapFont font;
OrthographicCamera fontCam;
public static Player player;
MenuTiles menuTiles;
SpriteBatch batch;
float camx,camy;
float lerp=0.1f,lerpy=0.2f;
GameContacts gameContacts;
public MenuState(GameStateManager gsm){
super(gsm);
}
public void init(){
close=new Texture(Gdx.files.internal("menu_backgrounds/background_close.png"));
far=new Texture(Gdx.files.internal("menu_backgrounds/background_far.png"));
house=new Texture(Gdx.files.internal("menu_backgrounds/house_selected.png"));
batch=new SpriteBatch();
font=new BitmapFont();
fontCam=new OrthographicCamera();
fontCam.setToOrtho(false,Game.WIDTH,Game.HEIGHT);
fontCam.position.set(Game.WIDTH/2/PPM,Game.HEIGHT/2/PPM,0);
world=new World(new Vector2(0,-9.81f),true);
world.setVelocityThreshold(0);
gameContacts=new GameContacts();
world.setContactListener(gameContacts);
debugRenderer=new Box2DDebugRenderer();
player=new Player(world,960/2,49+20);
menuTiles=new MenuTiles(world);
}
public void update(float dt){
world.step(1/60f,6,2);
player.update(dt,gameContacts);
if(player.shouldPlay){gsm.setState(GameStateManager.PLAY);dispose();}
camx+=(player.x-camx)*lerp;
camy+=(player.y-camy)*lerpy;
}
public void draw(OrthographicCamera camera){
camera.position.x=Math.min(Math.max(camx,Game.WIDTH/2/PPM),(MenuTiles.levelWidth/PPM)-(Game.WIDTH/2/PPM));
camera.position.y=Math.min(Math.max(camy,Game.HEIGHT/2/PPM),(MenuTiles.levelHeight/PPM)-(Game.HEIGHT/2/PPM));
batch.begin();
batch.draw(far, 0, 0, 960 / PPM, 720 / PPM);
batch.draw(close,0,0,960/PPM,720/PPM);
batch.end();
//draw map
menuTiles.draw(camera);
batch.begin();
if(gameContacts.isOnHouse())batch.draw(house,192/PPM,48/PPM,2*MenuTiles.tileSize/PPM,2*MenuTiles.tileSize/PPM);
batch.end();
//draw player
player.draw(batch);
if(player.DebugOn){
debugRenderer.render(world, camera.combined);
batch.setProjectionMatrix(fontCam.combined);
batch.begin();
font.draw(batch,"fps",0,0);
batch.end();
System.out.println(Gdx.graphics.getFramesPerSecond()+" fps");
}
camera.update();
batch.setProjectionMatrix(camera.combined);
}
public void handleInput(){}
public void dispose(){
menuTiles.dispose();
close.dispose();
far.dispose();
house.dispose();
}
}

I don't think you want to divide by PPM in this line...
fontCam.position.set(Game.WIDTH/2/PPM,Game.HEIGHT/2/PPM,0);
I'm assuming the Game.WIDHT and HEIGHT are in pixels (this is not clear from your code snippet). If that's not teh case, then you should include the divide by PPM into this line...
fontCam.setToOrtho(false,Game.WIDTH,Game.HEIGHT);
At present it's not being consistently applied.
Also, you need to call fontcam.update() after setting its position.
Additionally: This is not to do with your question per se, but I'm not sure why you have the following lines at the end of teh render. I would place them right after I've changed the position of the standard camera.
camera.update();
batch.setProjectionMatrix(camera.combined);

Related

I am using Libgdx to build a mobile game. Can someone please show me how set the screen to one size?

package com.test.game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
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.Rectangle;
import com.badlogic.gdx.math.Vector2;
public class Splash implements Screen {
private Sprite splash;
private SpriteBatch batch;
private float height = 1920;
private float width = 1080;
private float aspectratio = width/height;
#Override
public void render(float delta){
Gdx.gl.glClearColor(0,0,0,1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
splash.draw(batch);
batch.end();
}
#Override
public void resize(int width, int height){
}
#Override
public void show(){
batch = new SpriteBatch();
Texture splashTexture = new Texture("zeuswallpaperphone1.jpg");
splash = new Sprite(splashTexture);
//splash.setSize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
splash.rotate(90);
splash.setPosition(Gdx.graphics.getWidth()/2 - splashTexture.getWidth()/2, Gdx.graphics.getHeight()/2 - splashTexture.getHeight()/2);
}
#Override
public void hide(){
}
#Override
public void pause(){
}
#Override
public void resume(){
}
#Override
public void dispose(){
}
}
This is the splash screen of my game. I am trying to get the splash screen image to adjust for different screen sizes. Is there a way that I set the screen to one size? I want to set the screen to a size of 1280 x 720. And also will this keep the touch inputs the same? I do not understand why this is so hard in android. I have searched the internet vigorously trying to find a solution. I am also sorry if this question was already answered in another post. It seems that most answers to this problem are really old. I have not been able to find an answer the the problem that I have. I am looking for any help so please someone help me out. I have tried various methods and nothing seems to be working. Thank you in advance for your help. I hate that stack overflow makes you type a certain amount. There are a few libgdx tutorials out there. So if someone could watch one and get back to me that would be great. I have tried playing with the Viewport and Orthographic camera but when I run the game it will not adjust. On iOS you just set the screen size and you are good to go on all devices. They need that in android studio. Nothing seems to be working.
This is the code I have. Thanks for your help. This is crazy they still want me to type more.
I think you need to use a camera and viewport:
OrthographicCamera hudCamera = new OrthographicCamera();
Viewport hudViewport = new ScreenViewport(hudCamera);
public void create {
// Your code
hudViewport.apply(true);
}
public void render(float delta){
Gdx.gl.glClearColor(0,0,0,1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(hudCamera.combined);
batch.begin();
splash.draw(batch);
batch.end();
}
public void resize(int width, int height) {
hudViewport.update(width, height);
hudViewport.apply(true);
}
Make sure you are setting the correct size in your main method.

Image moving side to side

My question is I'm creating a game where I have to get an image moving from one side of the screen to the other, and then coming back from the same side of the screen. For example I have an image of a jellyfish, it starts moving from the right side of the screen, to the left side, and then I want it to come back from the right side. I'm stuck and don't know what to do. I'm using LIBGDX and JAVA.
My code so far is :
package gdx.game;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.GL20;
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;
import java.awt.Graphics;
public class Main extends ApplicationAdapter {
SpriteBatch batch;
Texture img;
Sprite sprite;
float fGrav, fVelo, fX, fY;
#Override
public void create() {
batch = new SpriteBatch();
img = new Texture("JellyFish.png");
sprite = new Sprite(img);
sprite.setScale(0.3f);
fX=0;
fY=0;
}
#Override
public void render() {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
sprite.draw(batch);
batch.end();
}
#Override
public void dispose() {
batch.dispose();
img.dispose();
}
}
If you want to continuously bounce an image from left to right, create an infinite loop that increases x until it is >= your display width, and then decrease it until it is <= 0, and then repeat.
I've never worked with LIBGDX, but if you wanted to use the Graphics class it would be as follows:
Example:
boolean f = true;
int x = 0;
while (f) {
while (x <= SCREEN_WIDTH) {
x++;
}
while (x >= 0) {
x--;
}
}
This should loop indefinitely.

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.

Libgdx Filling Screen With Image

I'm new to Libgdx and am having some problems filling an image to the entire screen. If I import a 1900x1200 image, it fills the screen, but if instead the image is 1024x512, the image is not stretched to the screen. The following is the code I've used. I thought that ''background.setSize(stageWidth, stageHeight)'' would scale the image to the screen but this doesn't happen. Could you please inform me of what I'm doing wrong? I've tried toggling with the ''setFillParent'' (as mentioned in another post) but it still doesn't work. Here's also included a screenshot of what currently appears (both on the Desktop implementation and Android): http://tinypic.com/r/b7j20z/8
Thank You for your help!
package com.mygdx.game;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import com.badlogic.gdx.scenes.scene2d.actions.MoveToAction;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.utils.viewport.FitViewport;
import com.badlogic.gdx.utils.viewport.StretchViewport;
import com.badlogic.gdx.utils.viewport.Viewport;
public class MyGdxGame implements ApplicationListener{
private Stage stage;
#Override
public void create() {
stage = new Stage();
float stageHeight = Gdx.graphics.getHeight();
float stageWidth = Gdx.graphics.getWidth();
// Background
Texture board = new Texture(Gdx.files.internal("data/frame.png"));
Image background = new Image(board);
background.setOrigin(0, 0);
background.setSize(stageWidth, stageHeight);
background.rotateBy(0);
background.setPosition(0, 0);
stage.addActor(background);
}
#Override
public void dispose() {
stage.dispose();
}
#Override
public void render() {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
}
After thinking about it for a bit, the most likely cause of your problem is that you're adding your image directly to the root of the stage. The root of the stage is a Group that doesn't handle any kind of layout managing, which is probably why your image isn't sized correctly.
I'd recommend instead that you create a Table, and then use setFillParent() so it takes up the entire screen. You can then simply use the Table's built in function, table.background(drawable), to set a background. However, you have to keep in mind that a Texture doesn't count as drawable for the table, so you have to use the class TextureRegionDrawable to get a valid drawable for the background. Here's an example:
table.background(new TextureRegionDrawable(new TextureRegion(board)));

LibGDX font not appearing on screen

I've tried to get my text to appear, but I cannot get it on screen. I've played with the numbers a few times and found out that LibGDX drew the font to abnormally large sizes, but I don't exactly know if I still need to scale the font size smaller, or if I'm drawing them offscreen. I've copied the entire code and pasted it below.
I used Hiero to make a 256x256 bitmapfont of ariel black on white background.
package com.me.manners;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.Texture.TextureFilter;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.me.input.Input;
public class Choice implements Screen
{
private PerspectiveCamera camera;
private SpriteBatch batch;
private Texture arrowT;
private Sprite arrowS;
private BitmapFont font;
private String str1 = "Hello World!";
private Input input = new Input();
private Manners game;
public Choice(Manners game)
{
this.game = game;
camera = new PerspectiveCamera();
batch = new SpriteBatch();
font = new BitmapFont(Gdx.files.internal("data/choice/ariel.fnt"), Gdx.files.internal("data/choice/ariel.png"),false);
Gdx.input.setInputProcessor(input);
arrowT = new Texture(Gdx.files.internal("data/choice/arrow.png"));
arrowT.setFilter(TextureFilter.Linear, TextureFilter.Linear);
arrowS = new Sprite(new TextureRegion(arrowT, 0, 0, 64, 64));
arrowS.setSize(0.125f, 0.25f);
arrowS.setPosition(-0.75f, 0);
}
#Override
public void dispose() {
batch.dispose();
arrowT.dispose();
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(camera.combined);
batch.begin();
arrowS.draw(batch);
font.setColor(1.0f,1.0f,0.0f,1.0f);
font.setScale(0.5f,0.5f);
font.draw(batch, str1, Gdx.graphics.getWidth()*0.5f, Gdx.graphics.getHeight()*0.5f);
batch.end();
}
}
I think your game is 2D game, so using camera = new OrthographicCamera(viewportWidth, viewportHeight) can fix your problem.
phucvin makes a very good observation. It seems your game is 2d ,so you should use an OrtographicCamera. I would recommend you to use big numbers, because the BitmapFont will render using its correct pixel size (thus thats the reason you saw very big letters).
camera = new OrthographicCamera(480, 320); //for example.
Of course you will need to change the Sprite size to something bigger
arrowS.setSize(100, 20); //for example
Or using a second camera with low viewport values for the sprites.

Categories