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.
Related
At this moment I have 2 screens: MainScreen (it's the main menu of the game) and GameScreen. I have a "button" (it's an image) that when the user clicks on it, the MainScreen switchs to the GameScreen.
The problem is that all the images of the MainScreen don't disappear when the second screen appears (the button and the main title). I have been working on this for days and I don't know what more to do.
Main class of the game:
public class MyGame extends Game {
#Override
public void create () {
Sounds.load();
Texts.load();
Buttons.load();
setScreen(new MainScreen(this));
}
#Override
public void dispose () {
super.dispose();
Sounds.dispose();
Texts.dispose();
Buttons.dispose();
}
}
MainScreen:
public class MainScreen implements Screen {
private MyGame game;
private Stage stage;
private OrthographicCamera camera;
private Viewport viewport;
public static Image tituloPrincipal, botonPlay;
public MainScreen(final MyGame game) {
this.game = game;
//stage
camera = new OrthographicCamera(Settings.SCREEN_WIDTH, Settings.SCREEN_HEIGHT);
viewport = new StretchViewport(Settings.SCREEN_WIDTH, Settings.SCREEN_HEIGHT, camera);
stage = new Stage(viewport);
//background
stage.addActor(new Image(Sprites.mainBackground));
//Title of the game
tituloPrincipal = new Image();
tituloPrincipal.setPosition(Settings.SCREEN_WIDTH * 1 / 6, Settings.SCREEN_HEIGHT * 4 / 12);
tituloPrincipal.setDrawable(new TextureRegionDrawable(new TextureRegion(Texts.tituloPrincipal)));
tituloPrincipal.setSize(Texts.tituloPrincipal.getWidth()/3,
Texts.tituloPrincipal.getHeight()/3);
stage.addActor(tituloPrincipal);
//Play Button
botonPlay = new Image();
botonPlay.setPosition(Settings.SCREEN_WIDTH * 4 / 10, Settings.SCREEN_HEIGHT / 16);
botonPlay.setDrawable(new TextureRegionDrawable(new TextureRegion(Buttons.playbutton)));
botonPlay.setSize(Buttons.playbutton.getWidth()/16,
Buttons.playbutton.getHeight()/18);
stage.addActor(botonPlay);
//Song
Sounds.musicMainScreen.play();
}
#Override
public void show() {
Gdx.input.setInputProcessor(stage);
}
#Override
public void render(float delta) {
botonPlay.addListener(new ClickListener(){
#Override
public void clicked(InputEvent event, float x, float y) {
game.setScreen(new GameScreen(game));
dispose();
}
});
stage.draw();
stage.act(delta);
}
#Override
public void resize ( int width, int height){
}
#Override
public void pause () {
}
#Override
public void resume () {
}
#Override
public void hide () {
}
#Override
public void dispose () {
}
}
GameScreen:
public class GameScreen implements Screen {
private Game game;
private Stage stage;
public GameScreen(Game game) {
this.game = game;
stage = new Stage();
Gdx.input.setInputProcessor(stage);
deleteMainScreenSources();
//song
Sounds.musicGameScreen.play();
}
public void deleteMainScreenSources() {
Sounds.musicMainScreen.stop();
}
#Override
public void show() {
}
#Override
public void render(float delta) {
}
#Override
public void resize ( int width, int height){
}
#Override
public void pause () {
}
#Override
public void resume () {
}
#Override
public void hide () {
}
#Override
public void dispose () {
}
}
Button class:
public class Buttons {
public static Texture playbutton;
public static void load() {
playbutton = new Texture(Gdx.files.internal("playbutton.png"));
playbutton.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest);
}
public static void dispose() {
playbutton.dispose();
}
}
The class of the title it's like the class of the button.
Your render method is what draws your screen. If you are not aware, it is kind of a game loop , which gets executed non stop ( around 60/sec by default I believe). So all your drawing and redrawing goes here.Usually , you would be clearing your screen at first and then draw other images on the screen. Libgdx provide interfacing to opengl to clear the screen. In my case, I always clear screen at the very first line of render method and draw additional things on it so that it makes sure my stale content of the screens are gone.In your GameScreen , your render method is empty , so your previous screen is not yet wiped out. I believe adding clear and drawing your new stage in GameScreen will resolve your issue.
Make your code in GameScreen render something like this and try ,
#Override
public void render(float delta) {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act();
stage.draw();
}
Also, I would try to avoid creation of any new object in 'render` method for the same reason. Your addListener method in your menu screen can go in it's constructor. So that you don't create anonymous listener in every game loop execution. This may not impact by that much in your current scenario, but if you create some heavy object or some Sprites in this way in game loop, that can drag your game perfomance a lot.
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.
I'm developing a new application with libgdx and in my source code i'm using the shaperenderer class but since I've bought my new tablet (Acer Iconia One 10 B3-A20), my application always crash without displaying any errors after calling the "shaperenderer.end()" method . Even when I create a simple class as the following one, have I missing something?
public class Test implements Screen {
private ShapeRenderer shapeRenderer = new ShapeRenderer();
#Override
public void show() {
}
#Override
public void render(float delta) {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
shapeRenderer.begin(ShapeRenderer.ShapeType.Line);
shapeRenderer.rect(30,30,200,200);
shapeRenderer.end();
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
shapeRenderer.dispose();
}
}
Thanks
EDIT:
After placing some breakpoints into the "shaperenderer.end()"method i have noticed that the program crash after calling the "mesh.render()" method, and particularly when it call the "bind" method of the Mesh class (for binding the shaders).
Is it normal?
You need to create a camera first on your show method:
OrthographicCamera camera;
[...]
camera = new OrthographicCamera();
camera.setToOrtho(false);
and on render method set the projectionMatrix before draw:
camera.update();
shapeRenderer.setProjectionMatrix(camera.combined);
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.
I need to know how i would go about setting up a stage and adding actors to it for my main menu.
Here is my code so far
public class MainMenu implements Screen {
CrazyZombies game;
Stage stage;
TextureAtlas atlas;
SpriteBatch batch;
Skin skin;
Button button;
TextureRegion firstLayer, secondLayer, thirdLayer, fourthLayer,
fifthLayer, sixthLayer, seventhLayer, eighthLayer, ninthLayer,
tenthLayer, eleventhLayer;
Sprite road, backTrees, sideTrees, bottemTrees, light, poles,
play, quit, store, custom, options;
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);
batch.begin();
road.draw(batch);
backTrees.draw(batch);
sideTrees.draw(batch);
bottemTrees.draw(batch);
light.draw(batch);
poles.draw(batch);
play.draw(batch);
quit.draw(batch);
store.draw(batch);
custom.draw(batch);
options.draw(batch);
batch.end();
}
#Override
public void resize(int width, int height) {
Gdx.input.setInputProcessor(stage);
}
#Override
public void show() {
Audio.playMusic(true);
batch = new SpriteBatch();
atlas = new TextureAtlas("data/mainmenu/MainMenu.pack");
firstLayer = atlas.findRegion("1layer");
secondLayer = atlas.findRegion("2layer");
thirdLayer = atlas.findRegion("3layer");
fourthLayer = atlas.findRegion("4layer");
fifthLayer = atlas.findRegion("5layer");
sixthLayer = atlas.findRegion("6layer");
seventhLayer = atlas.findRegion("7layer");
eighthLayer = atlas.findRegion("8layer");
ninthLayer = atlas.findRegion("9layer");
tenthLayer = atlas.findRegion("10layer");
eleventhLayer = atlas.findRegion("11layer");
road = new Sprite(firstLayer);
backTrees = new Sprite(secondLayer);
sideTrees = new Sprite(thirdLayer);
bottemTrees = new Sprite(fourthLayer);
light = new Sprite(fifthLayer);
poles = new Sprite(sixthLayer);
play = new Sprite(seventhLayer);
quit = new Sprite(eighthLayer);
store = new Sprite(ninthLayer);
custom = new Sprite(tenthLayer);
options = new Sprite(eleventhLayer);
}
#Override
public void hide() {
dispose();
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void dispose() {
batch.dispose();
atlas.dispose();
Audio.dispose();
}
}
The bits that i need to become actors are:
- play
- quit
- store
- custom
- options
All my code does at the moment is just display my main menu i need to get the stage and actors setup in order to get the buttons working.
Take a look at TableLayout and also take a look at TextButton or maybe Button.
Here is a good tutorial. Work through it and you will understand how to work with the Screen2D and how to create a simple menu. -> Direkt link to Menucreation of the Blog