I'm new to LibGDX and I am taking it slowly. I'm still trying to understand most things which is why typically google searches don't help due to the fact that their too complicated. I have a main menu that has text that I want centered no matter what the screen size is. Here is the code that I have for that menu.
public class Menu implements Screen {
SlingshotSteve game;
OrthographicCamera camera;
public Menu(final SlingshotSteve gam) {
this.game = gam;
camera = new OrthographicCamera();
camera.setToOrtho(false, 800, 480);
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0.2f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
game.batch.setProjectionMatrix(camera.combined);
game.batch.begin();
game.font.draw(game.batch, "Welcome to Slingshot Steve!!! ", 100, 150);
game.font.draw(game.batch, "Tap anywhere to begin!", 100, 100);
game.batch.end();
if (Gdx.input.isTouched()) {
game.setScreen((Screen) new GameScreen(game));
dispose();
}
}
#Override
public void resize(int width, int height) {
}
#Override
public void show() {
}
#Override
public void hide() {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void dispose() {
}
}
I'm here to save you!
To get width / height from a String drawn with your BitmapFont you can utilize this super nice method:
game.font.getBounds(String string)
And to use it in your case, it would be something like this:
game.font.getBounds("Tap anywhere to begin!").width / 2;
Cheers!
It is possible to do it the way Nine Magics suggested, however one would usually do it via a Stage, which is part of scene2d.
More specifically one would use scene2d.ui which is a bunch of Actors like Button, Image, Label etc. You can attach a ClickListener to a Button for example and react on this event.
Furthermore, for layouting there is one very powerful Actor, namely Table which you can very easily use to center things on the screen.
Some very minimalistic code:
// do this once, in create() or show()
Skin skin = new Skin("uiskin.json"); // get the demo skin from the libgdx test resources
Stage stage = new Stage();
Table table = new Table(skin);
table.add("Welcome to Slingshot Steve!!!");
table.row();
table.add("Tap anywhere to begin!");
stage.addActor(table);
// do this in your render loop
stage.act();
stage.draw();
You can find the "default" skin resources here. You need to get all the uiskin.* files.
Related
I'm kinda new to LibGDX.
I'm just learning the ropes.
Trying to get a basic TextButton to display at a reasonable size on screen.
Working exclusively on Android IDE (AIDE).
Using only default skins and what-not, I've tried to set width and height as well as setScale() but only the text size seems to increase on the command.
What am I doing wrong?
https://oi1161.photobucket.com/albums/q501/StudioGilliam/Screenshot_20190423-184819_LibGDXButtonsTest.jpg
public class MyGdxGame implements ApplicationListener
{
private Stage stage;
private Table table;
private TextButton btn;
#Override
public void create()
{
stage = new Stage(new ScreenViewport());
Gdx.input.setInputProcessor(stage);
table = new Table();
table.setBounds(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
TextButton.TextButtonStyle style = new TextButton.TextButtonStyle();
style.font = new BitmapFont();
btn = new TextButton("Button", style);
btn.pad(20);
btn.setTransform(true);
btn.setScale(5.0f);
btn.setTouchable(Touchable.enabled);
table.add(btn);
table.debug();
stage.addActor(table);
}
#Override
public void render()
{
Gdx.gl.glClearColor(0, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act();
stage.draw();
}
#Override
public void dispose()
{
stage.dispose();
}
#Override
public void resize(int width, int height){}
#Override
public void pause(){}
#Override
public void resume(){}
}
EDIT:
I realised that parent objects like stages and tables control the properties of their children, so I added:
table.add(btn).width(300).height(100);
And now it looks better but the text is way off centre...
https://oi1161.photobucket.com/albums/q501/StudioGilliam/Screenshot_20190423-191104_LibGDXButtonsTest.jpg
On a Textbutton, you should use setFontScale() and pack() to resize the button to the font size.
However, for supporting different screen sizes without any own coding, consider using FitViewport/ExtendViewport
On my 854 x 480 LG Leon it renders fine, but on a larger screen resolution (2560 x 1440) this happens: http://imgur.com/a/rcbJK.
The code for processing the text is: http://imgur.com/a/c316e.
I've tried expanding the bounds of the Label because I thought that it might be constricting the text, but it still won't display properly.
What could be causing this?
The different mobile phone has the different aspect ratio in their screen size . that is the reason it shows different different screen. to avoid this problem you must use the viewPort. So you will be able to handle the different screen size. for more details, you must read the libgdx documentation. here I'm posting a sample code which can help you to handle the different screen size. there are three kinds of viewports mainly using
1) fillviewport
2) fitviewPort
3)stretchviewport
here is the documentation in detail.
https://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/utils/viewport/FillViewport.html
public class myGame extends ApplicationAdapter {
public OrthographicCamera camera;
public Viewport viewPort;
private SpriteBatch batch;
public myGame() {
}
#Override
public void create() {
float w = Gdx.graphics.getWidth();
float h = Gdx.graphics.getHeight();
camera = new OrthographicCamera();
camera.position.set(0, 0, 0);
camera.update();
camera.setToOrtho(false, 1280, 800);
viewPort = new FillViewport(1280, 800, camera);
}
#Override
public void dispose() {
batch.dispose();
}
#Override
public void render() {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL30.GL_COLOR_BUFFER_BIT);
float deltaTime = Gdx.graphics.getDeltaTime();
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.draw(sprie,0,0)
batch.end();
}
#Override
public void resize(int width, int height) {
viewPort.update(width, height);
}
#Override
public void pause() {
}
#Override
public void resume() {
}
}
// don't copy paste it . just try to understand and implement it.
You should use Scene2D and ViewPort.
Also , be careful to use coordinates (i.e : x: 64 , y:32 changes in every different screen size)
This is the common issue when your running your game in multiple devices. Because your game is running in different aspect ratios in different screens . it's generally called the multi screen issue. To solve this problem the libgdx is providing it's on class called the viewPort. Mainly you can see three viewpors.
1)Fill viewPort.
2)Fit viewPort.
3)stretch viewport.
For more details you can go through the libgdx documentation. Here im posting some example code which can solve your multi screen issues.
public class myGame extends ApplicationAdapter {
public OrthographicCamera camera;
public Viewport viewPort;
private SpriteBatch batch;
private BitmapFont myScoreFont;
//General screen resolution
public int APP_WIDTH=1280;
public int APP_HEIGHT=800;
public int fontPositionIn_X=600;
public int fontPositionIn_Y=400;
public myGame() {
}
#Override
public void create() {
myScoreFont = new BitmapFont(Gdx.files.internal(Constants.PATH_TO_MY_SCORE_FONT), true);
batch = new SpriteBatch();
float w = Gdx.graphics.getWidth();
float h = Gdx.graphics.getHeight();
camera = new OrthographicCamera();
camera.position.set(0, 0, 0);
camera.update();
camera.setToOrtho(false, APP_WIDTH, APP_HEIGHT);
viewPort = new fillViewPort(1280, 800, camera);
}
#Override
public void dispose() {
batch.dispose();
}
#Override
public void render() {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL30.GL_COLOR_BUFFER_BIT);
float deltaTime = Gdx.graphics.getDeltaTime();
batch.setProjectionMatrix(camera.combined);
batch.begin();
myScoreFont.draw(batch,"any texts", fontPositionIn_X, fontPositionIn_Y)
batch.end();
}
#Override
public void resize(int width, int height) {
viewPort.update(width, height);
}
#Override
public void pause() {
}
#Override
public void resume() {
}
}
so by using the viewPort you can be able to play your game in all the different screens.
At the moment desktop version of application is fine, the buttons are scaled quite nice but when I deploy to android they're tiny and barely usable.
DesktopLauncher ..
public class DesktopLauncher {
public static void main (String[] arg) {
LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
config.title = "Color Catchin";
config.width = 800;
config.height = 480;
new LwjglApplication(new ColorCatch(), config);
}
}
AndroidLauncher ..
public class AndroidLauncher extends AndroidApplication {
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
config.useAccelerometer = false;
config.useCompass = false;
initialize(new ColorCatch(), config);
}
}
Core code ..
public class MainMenu implements Screen {
Skin skin = new Skin(Gdx.files.internal("ui/uiskin.json"));
Stage stage = new Stage();
final private ColorCatch game;
public MainMenu(final ColorCatch gam) {
game = gam;
Gdx.input.setInputProcessor(stage);
Table table = new Table();
table.setFillParent(true);
stage.addActor(table);
final TextButton play = new TextButton("Play", skin);
final TextButton quit = new TextButton("Quit", skin);
table.add(play).pad(10);
table.row();
table.add(quit).pad(10);
play.addListener(new ChangeListener() {
public void changed(ChangeEvent event, Actor actor) {
game.setScreen(new GameScreen(game));
dispose();
}
});
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act(delta);
stage.draw();
}
#Override
public void resize(int width, int height) {
stage.getViewport().update(width, height, true);
}
}
desktop ..
android ..
By default Stage will have a ScalingViewport set to Scaling.stretch with a virtual viewport size of Gdx.graphics.getWidth() x Gdx.graphics.getHeight (see here).
On Desktop you will start with a size of 800x480, because that's what you told your launcher. On Android, this is dynamic and depends on the device. On your device it might be 1920x1080.
Since you do not change your button sizes, they will have the same size on both devices in terms of pixels. because of the totally different screen density though, on Android the buttons will appear to be much smaller.
The easiest solution to get both to the same level would be to use a Viewport with a fixed virtual size. For example a new FitViewport(800, 480). You can supply that viewport to the stage via new Stage(viewport).
However, scaling up or down depending on the screens size to keep the aspect ratio and the virtual resolution is usually not a good idea for UIs. It might be better to use a ScreenViewport instead and set your actors' sizes relative to each other. You can use Value.percentWidth(0.5f, rootTable) for example, to set the width of a widget to 50% of the root table, that takes the whole screen (via setFillParent(true)).
So i want to create a mainmenu for my game and i'm stuck on what to do next i have all the art done and it's all in layers and packed in a .pack
public class MainMenu implements Screen {
CrazyZombies game;
Stage stage;
BitmapFont font;
TextureAtlas MainMenu;
Texture road;
Skin skin;
SpriteBatch batch;
public MainMenu(CrazyZombies game){
this.game = game;
}
#Override
public void render(float delta) {
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
Gdx.gl.glClearColor(0.09f, 0.28f, 0.2f, 1);
stage.act(delta);
batch.begin();
stage.draw();
batch.end();
}
#Override
public void resize(int width, int height) {
if(stage == null)
stage = new Stage(width, height, true);
stage.clear();
Gdx.input.setInputProcessor(stage);
}
#Override
public void show() {
batch = new SpriteBatch();
skin = new Skin();
MainMenu = new TextureAtlas("data/mainmenu/MainMenu.pack");
}
#Override
public void hide() {
dispose();
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void dispose() {
batch.dispose();
skin.dispose();
MainMenu.dispose();
stage.dispose();
}
}
If anyone could give me some guidelines or tutorials on what to do now it would be great i've looked in a lot of places but they have not given me the required answers.
Have a look at this tutorial which sums up what you want exactly:
LibGDX: Using a Splash Screen or Menu
i think it will be easy if u use scene2D that will handle all the complexity and help you to create a nice looking UI with a little bit of code .
you may need to check this link
https://github.com/libgdx/libgdx/wiki/Scene2d.ui
Basically, you need to
create a skin, and
we need to add buttionTextureStyle to it.
Don't forget to add fonts, it took me a hour to figure out that fonts are not set by default like other parameters of buttonTextureStyle
and then you create a button with created skin
and then add that button to the stage.
libGDX using Stage and Actor produces different camera angles on desktop and Android Phone.
Here are pictures demonstrating the problem: http://brandonyuh.minus.com/mFpdTSgN17VUq
On the desktop version, the image takes up almost all the screen. On the Android phone it only takes up a bit of the screen.
Here's the code (not my actual project but I isolated the problem):
package com.me.mygdxgame2;
import com.badlogic.gdx.*;
import com.badlogic.gdx.graphics.*;
import com.badlogic.gdx.graphics.Texture.TextureFilter;
import com.badlogic.gdx.graphics.g2d.*;
import com.badlogic.gdx.scenes.scene2d.*;
public class MyGdxGame2 implements ApplicationListener {
private Stage stage;
public void create() {
stage = new Stage();
stage.addActor(new ActorHi());
}
public void render() {
Gdx.gl.glClearColor(0, 1, 0, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
stage.draw();
}
public void dispose() {}
public void resize(int width, int height) {}
public void pause() {}
public void resume() {}
public class ActorHi extends Actor {
private Sprite sprite;
public ActorHi() {
Texture texture = new Texture(Gdx.files.internal("data/hi.png"));
texture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
sprite = new Sprite(new TextureRegion(texture, 0, 0, 128, 128));
sprite.setBounds(0, 0, 300.0f, 300.0f);
}
public void draw(SpriteBatch batch, float parentAlpha) {
sprite.draw(batch);
}
}
}
hi.png is included in the above link
Thank you very much for answering my question. I've spent 3 days trying to figure it out.
stage = new Stage();
initializes the stage with a camera that maps its viewport to the real screen resolution. If desktop and device don't have the same resolution they won't look the same.
Try setting fixed values to the stage. Use this: (you can check javadoc here
public void setViewport (float width, float height, boolean keepAspectRatio);
eg. Use some fixed value like
setViewport (800, 600, true);
This will also fill the screen, but will always show a 800x600 world, no matter the resolution. (actually it would be "at least" 800x600 because of the keepAspectRation = true that prevents distortion)