Search code examples
javaandroidfontslibgdx

Text In-screen Implementation in java-libGDX


I have some trouble with implementing a feature to show and use the player's username. I'm making a crossplatform app between windows and android where I'm trying to showcase the player's name as soon as they start typing and can press enter to proceed or press the Level Selection-button to proceed to the next screen. Every time I press ''Enter'' though, it crashes. Also, doesn't it display or take in the player's name. I know the code is not optimal as I made multiple tables for example but I was hoping somebody could tell me where I made my mistake so it would maybe work. Thanks in advance!

This is the code:

package com.paladinzzz.game.screens;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.Screen;
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.TextureRegion;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.ImageButton;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.scenes.scene2d.utils.Drawable;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
import com.badlogic.gdx.utils.viewport.FillViewport;
import com.paladinzzz.game.CrossplatformApp;
import com.paladinzzz.game.util.Constants;
import com.paladinzzz.game.audio.MusicHandler;
import static com.badlogic.gdx.Gdx.input;
import static com.paladinzzz.game.screens.MenuScreen.musicHandler;


public class LoginScreen implements Screen {

private CrossplatformApp game;
private Stage stage;
private ImageButton backButton, playButton;
private Texture backTexture, playTexture, background;
private Drawable drawableBack, drawablePlay;
private OrthographicCamera camera;
BitmapFont font = new BitmapFont();
int[] x = new int[255];
public static boolean inPlayscreen = false;
public static String playername = "";
private boolean isConverted = false;
private Table table, table2;

public LoginScreen(CrossplatformApp game) {
    this.game = game;
    this.camera = new OrthographicCamera();
    this.stage = new Stage(new FillViewport(Constants.WIDTH, Constants.HEIGHT, camera));
    this.playTexture = new Texture("Screens/LoginScreen/LvlSelection.png");
    this.backTexture = new Texture("Screens/BackButton.png");
    this.background = new Texture("Screens/LoginScreen/loginscreen.png");
}

@Override
public void show() {

    //Give the texture of the backButton to a new ImageButton
    drawableBack = new TextureRegionDrawable(new TextureRegion(backTexture));
    backButton = new ImageButton(drawableBack);
    backButton.addListener(new ClickListener(){
        @Override
        public void clicked(InputEvent event, float x, float y) {
            game.setScreen(new MenuScreen(game));
            MenuScreen.musicHandler.stopMusic();
        }
    });

    //Give the texture of the playButton to a new ImageButton
    drawablePlay = new TextureRegionDrawable(new TextureRegion(playTexture));
    playButton = new ImageButton(drawablePlay);
    playButton.addListener(new ClickListener(){
        @Override
        public void clicked(InputEvent event, float x, float y) {
            game.setScreen(new LevelScreen(game));
            inPlayscreen = true;
        }
    });


    //Elements can be added here to the stage
    input.setInputProcessor(stage);

    //A table gets made with the button which leads to the level selection screen
    table = new Table();
    table.bottom();
    table.setFillParent(true);
    table.add(playButton).padBottom(40);
    stage.addActor(table);

    //A table gets made with the button which leads back to the main menu
    table2 = new Table();
    table2.bottom();
    table2.setFillParent(true);
    table2.add(backButton).padBottom(13).padRight(640);
    table2.row();
    stage.addActor((table2));
}

@Override
public void render(float delta) {

    Gdx.gl.glClearColor(1, 0, 0, 1);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

    if(Gdx.input.isKeyJustPressed(Input.Keys.ENTER)){
        game.setScreen(new LevelScreen(game));
        inPlayscreen = true;


        if (!isConverted){
            playername = playername.substring(0, 1).toUpperCase() + playername.substring(1, playername.length()).toLowerCase();
            isConverted = true;
        }
    }

    game.batch.begin();

    //A possibility gets made to insert the name of the player
    game.batch.draw(background, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
    for (int i : x) {
        if (input.isKeyJustPressed(i)){
            if (i != 62 && i != 67 && i!= 66) {
                playername += Input.Keys.toString(i).toLowerCase();
            } else if (i == 67 & playername.length() > 0){
                playername = playername.substring(0, playername.length() - 1).toLowerCase();
            } else {
                playername += " ";
            }
        }
    }

    font.draw(game.batch, playername, 0, 0);

    game.batch.end();
    stage.draw();
}

@Override
public void resize(int width, int height) {

}

@Override
public void pause() {

}

@Override
public void resume() {

}

@Override
public void hide() {

}

@Override
public void dispose() {
    stage.dispose();

}
}

This is how the ''LoginScreen'' looks like: GameScreen

This is the error message:

Exception in thread "LWJGL Application" 
java.lang.StringIndexOutOfBoundsException: String index out of range: 1
at java.lang.String.substring(String.java:1963)
at com.paladinzzz.game.screens.LoginScreen.render(LoginScreen.java:108)
at com.badlogic.gdx.Game.render(Game.java:46)
at com.paladinzzz.game.CrossplatformApp.render(CrossplatformApp.java:30)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:225)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:126)

Debugging with breakpoint:

enter image description here


Solution

  • The crash solution is for this line:

    playername = playername.substring(0, 1).toUpperCase() + playername.substring(1, playername.length()).toLowerCase();
    

    your second substring needs to use

    playername.length()-1