When I run the android version of my app, the text that is drawn using Bitmap is displayed in a (way) different position in my desktop version than in my android version of the app. I have already looked this issue up and read that I had to set the Projectmatrix to combined, but this hasn't helped. No clue what could be the reason that it displays the texts in different positions crossplatform-wise.
public class HighScoresScreen implements Screen{
private CrossplatformApp game;
private Stage stage;
private TextButton backButton;
private OrthographicCamera camera;
private Table table;
BitmapFont font = new BitmapFont();
private Skin skin;
private Texture background;
private String[] data;
private String[] playerscores;
String nm = "";
String sc = "";
public HighScoresScreen (CrossplatformApp game) {
this.game = game;
this.camera = new OrthographicCamera(Constants.WIDTH, Constants.HEIGHT);
this.camera.position.set(Constants.WIDTH/2, Constants.HEIGHT/2, 0);
this.camera.update();
game.batch.setProjectionMatrix(this.camera.combined);
this.skin = new Skin(Gdx.files.internal("skin/uiskin.json"));
this.background = new Texture("Screens/HighscoresScreen/highscores.png");
}
#Override
public void show() {
backButton = new TextButton("back", skin);
backButton.addListener(new ClickListener(){
#Override
public void clicked(InputEvent event, float x, float y) {
game.setScreen(new MenuScreen(game));
MenuScreen.musicHandler.stopMusic();
}
});
Gdx.input.setInputProcessor(stage);
JSONfunctions json = new JSONfunctions();
parseJSON parse = new parseJSON(json.doInBackground());
for (String i : parse.getNames()){
if(i != null) {
nm += i;
nm += "\n\n";
} else {
break;
}
}
System.out.println(nm);
//
for (String i : parse.getScores()){
if(i != null) {
sc += i;
sc += "\n\n";
} else {
break;
}
}
table = new Table();
table.setFillParent(true);
table.bottom();
table.add(backButton).size(100, 100);
stage.addActor(table);
}
#Override
public void render(float delta) {
game.batch.begin();
game.batch.draw(background, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
font.draw(game.batch, nm, 100, 300);
font.draw(game.batch, sc, 480, 300);
game.batch.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() {
stage.dispose();
}
}
You need to update viewport of camera and then update projectionmatrix of SpriteBatch with updated viewport.
#Override
public void resize(int width, int height) {
camera.setToOrtho(false, width, height);
game.batch.setProjectionMatrix(camera.combined);
}
Also you need to update Stage's viewport with screen with and height.
You should use Label for nm and sc text.
It's better to use ExtendViewprot instead of FillViewport, take a look of this answer.
Related
EDIT: First Cemmentator "Second" was right. I forgot to set Gdx.input.setInputProcessor(stage); - Now everything is working as it should. Thanks!
My Libgdx Buttons "Back", "Menu" and "TryAgain" (which bring you back to another Screen) are not working.
I worked through every solution that I could find but they still not work properly. I also use Buttons and stages in my other Screens and they all work like a charm.
Do you guys see any mistakes in the code? CreateStage() creates the stage and they get displayed through the render Method.
Any Help is greatly appreciated!
public class HighscoreScreen extends ScreenAdapter {
private final GameClass game;
private int score;
private String name;
private boolean menuView;
private SpriteBatch batch;
private BitmapFont scoreFont;
private String[] players;
private int[] scores;
private int counter = 0;
private OrthographicCamera camera;
private Stage stage;
private ScreenViewport v;
public HighscoreScreen (GameClass game, OrthographicCamera camera, int score, String name) {
this.camera = camera;
this.game = game;
this.score = score;
this.name = name;
this.batch = new SpriteBatch();
menuView = false;
batch = new SpriteBatch();
scoreFont = new BitmapFont(Gdx.files.internal("Fonts/score.fnt"),
Gdx.files.internal("Fonts/score.png"),false);
createStage();
}
public HighscoreScreen (GameClass game, OrthographicCamera camera){
this.game = game;
this.camera = camera;
this.batch = new SpriteBatch();
menuView = true;
scoreFont = new BitmapFont(Gdx.files.internal("Fonts/score.fnt"),
Gdx.files.internal("Fonts/score.png"),false);
}
public void createStage(){
v = new ScreenViewport();
v.setCamera(camera);
stage = new Stage(v, batch);
if (menuView) {
Buttons back = new Buttons("Back");
stage.addActor(back.createButton(GameInfo.WIDTH / 2 - 100,
GameInfo.HEIGHT / 2 - 200));
back.addListener(new ChangeListener() {
#Override
public void changed(ChangeEvent event, Actor actor) {
game.setScreen(new MenuScreen(game));
}
});
} else {
Buttons tryAgain = new Buttons("Try Again");
stage.addActor(tryAgain.createButton(GameInfo.WIDTH / 2 - 200,
GameInfo.HEIGHT / 2 - 200));
tryAgain.addListener(new ChangeListener() {
#Override
public void changed(ChangeEvent event, Actor actor) {
game.setScreen(new SurvivalScreen(game, name));
}
});
Buttons menu = new Buttons("Menu");
stage.addActor(menu.createButton(GameInfo.WIDTH / 2,
GameInfo.HEIGHT / 2 - 200));
menu.addListener(new ChangeListener() {
#Override
public void changed(ChangeEvent event, Actor actor) {
game.setScreen(new MenuScreen(game));
}
});
}
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
if (menuView) {
if (counter == 0) {
createStage();
writeScoresToFile();
readHighscore();
counter++;
}
batch.begin();
highscoreToFont();
batch.end();
stage.act();
stage.draw();
} else {
if (counter == 0) {
createStage();
writeScoresToFile();
readHighscore();
compareHighscore();
writeHighscore();
counter++;
}
batch.begin();
highscoreToFont();
batch.end();
stage.act();
stage.draw();
}
}
public void dispose(){
batch.dispose();
stage.dispose();
}
You are probably missing the settings of the input processor to your stage (at least it's not in the code you have posted).
Gdx.input.setInputProcessor(stage);
Note:
Assuming the the Buttons class returns a proper actor.
(see my comment above)
I successfully implemented a gifdecoder in my project and wrote a gifloader for it to use it with the assetmanager. I am able to load the gif in the assetmanager and I am also able to draw it. But everytime I try to load gifs in my assetmanager with manager.update() I can not draw animations anymore, only non animated textures.
Here is my code I hope somebody has an idea
public class Load implements Screen {
private SpriteBatch batch;
private Animation<TextureRegion> loadingAnimation;
private TextureAtlas atlasLoading = new TextureAtlas(Gdx.files.internal("atlas/loadingAnimation.atlas"));
float stateTime;
MainExecute lr;
public FileHandleResolver resolver = new InternalFileHandleResolver();
public AssetManager manager = new AssetManager();
private final Animation animation = GifDecoder.loadGIFAnimation(Animation.PlayMode.NORMAL, Gdx.files.internal("data/loading.gif").read());
public Load(MainExecute lr){
this.lr = lr;
}
public Texture Bg1;
#Override
public void show() {
Bg1 = new Texture(Gdx.files.internal("bggamescreen.png"));
batch = new SpriteBatch();
manager.setLoader(GIF.class,new Gifloader(resolver));
manager.load("data/BackgroundAnim.gif",GIF.class);
stateTime = 0f;
}
#Override
public void render(float delta) {
if (manager.update())
{
lr.setScreen(new MainMenu(lr));
}
stateTime += delta;
// loadingAnimation = new Animation<TextureRegion>(0.5f, atlasLoading.findRegions("loading"),Animation.PlayMode.LOOP);
TextureRegion currentFrame = (TextureRegion) animation.getKeyFrame(stateTime, true);
batch.begin();
batch.draw(Bg1,0,0,Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
batch.draw(currentFrame, 0, 0, 200, 200);
batch.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() {
}
}
Strange code, you are drawing animation before it finish loading. You need to waiting to load your animation, try smth like this.
if (manager.update())
{
loadingAnimation = new Animation<TextureRegion>(0.5f, atlasLoading.findRegions("loading"),Animation.PlayMode.LOOP);
TextureRegion currentFrame = (TextureRegion) animation.getKeyFrame(stateTime, true);
lr.setScreen(new MainMenu(lr));
}
I have global variables called:
private int currentLevel;
private int mapHeight;
I have a constructor for my game, where currentLevel = level entered when setScreen() method is called:
public ElevatorLevel(Game g, int level)
{
super(g, level);
currentLevel = level;
}
In my create() method, I set mapHeight to 750 * currentLevel (which starts as one), however when I try to spawn in the blades as seen below, they spawn between -200 and 300. This is because the program is not recognizing currentLevel (I am assuming), so it is multiplying it by nothing, resulting with -200.
public void create()
{
world = new World(new Vector2(0, -9.8f), true);
timeElapsed = 0;
mapHeight = 750 * currentLevel;
blade = new PhysicsActor();
blade.storeAnimation( "", exTex );
blade.setOriginCenter();
blade.circularBoundary();
blade.setMaxSpeed(50);
blade.setDeceleration(50);
bladesList = new ArrayList<PhysicsActor>();
for (int i = 0; i < 3 ; i++)
{
blades = blade.clone();
float xCoord = randomFloatGenerator(440, 20);
float yCoord = randomFloatGenerator(mapHeight - 200, 300);
blades.setPosition(xCoord, yCoord);
mainStage.addActor(blades);
bladesList.add(blades);
}
I also have a Label in my update(float dt) method that is set to:
timeLabel.setText("Level: " + currentLevel);
As seen in the image above, currentLevel is recognized by the label, but not by mapHeight in create().
How do I get currentLevel to be recognized by the create() method?
Below is the standart portrait app code that i use almost in every libgdx project. I never use create method. Instead I use constructor, this code is the most bugfree one that i could have found.
GAME OR MENU SCREEN:
public class TutorialScreen implements Screen {
private OrthographicCamera camera;
public static final float WORLD_HEIGHT = 240;
public static final float WORLD_WIDTH = 135;
private Viewport viewport;
private Stage stage;
private EntryPoint game;
private AdsController adsController;
public TutorialScreen(final EntryPoint game, final AdsController adsController){
this.adsController = adsController;
this.game = game;
adsController.hideBannerAd();
float aspectRatio = (float) (Gdx.graphics.getHeight() / Gdx.graphics.getWidth());
camera = new OrthographicCamera(aspectRatio * WORLD_WIDTH, WORLD_HEIGHT);
camera.setToOrtho(false);
viewport = new FitViewport(WORLD_WIDTH , WORLD_HEIGHT,camera );
stage = new Stage(viewport, game.batch);
}
#Override
public void show() {
}
#Override
public void render(float delta) {
stage.draw();
stage.act();
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
}
}
ENTRY POINT THAT YOUR APP WILL OPEN FIRST:
package some.package;
public class EntryPoint extends Game {
SpriteBatch batch;
final AdsController adsController;
public EntryPoint(final AdsController adsController ){
this.adsController = adsController; //Interface for admob
}
#Override
public void create () {
batch = new SpriteBatch();
this.setScreen(new YourScreenClass(this,adsController)); //Above is tutorial so this would be new TutorialScreen(this,adsController)
}
#Override
public void render () {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.end();
super.render();
}
#Override
public void dispose () {
batch.dispose();
}
}
Might have missed some curly brackets or ";" but you get the idea. This way you would not encounter any reference issues.
I'm trying to make a simple main menu with clickable play and exit labels, but clickable area is always above labels. To click "play" label I need to click about 20 pixels above it.
How can I align clickable area with labels?
There is my MainMenuButton class
public class MainMenuButtons {
private MainGame game;
private Stage stage;
private Viewport gameViewport;
private Label mainGameLabel, playLabel, exitLabel;
public MainMenuButtons(MainGame game) {
this.game = game;
gameViewport = new FillViewport(GameInfo.WIDTH, GameInfo.HEIGHT, new OrthographicCamera());
stage = new Stage(gameViewport, game.getBatch());
Gdx.input.setInputProcessor(stage);
createLabelsAndButtons();
addAllListeners();
Table menuTable = new Table();
menuTable.center().center();
menuTable.setFillParent(true);
menuTable.add(playLabel);
menuTable.row();
menuTable.add(exitLabel).padTop(40);
Table gameTitle = new Table();
gameTitle.center().top();
gameTitle.setFillParent(true);
gameTitle.add(mainGameLabel).padTop(40);
menuTable.debug();
stage.addActor(menuTable);
stage.addActor(gameTitle);
}
void createLabelsAndButtons() {
FreeTypeFontGenerator generator = new FreeTypeFontGenerator(Gdx.files.internal("Fonts/PressStart2P.ttf"));
FreeTypeFontGenerator.FreeTypeFontParameter parameter = new FreeTypeFontGenerator.FreeTypeFontParameter();
parameter.size = 45;
BitmapFont font = generator.generateFont(parameter);
mainGameLabel = new Label("Road Racer", new Label.LabelStyle(font, Color.WHITE));
parameter.size = 25;
font = generator.generateFont(parameter);
playLabel = new Label("Play", new Label.LabelStyle(font, Color.WHITE));
exitLabel = new Label("Exit", new Label.LabelStyle(font, Color.WHITE));
}
void addAllListeners() {
playLabel.addListener(new ClickListener(){
#Override
public void clicked(InputEvent event, float x, float y) {
super.clicked(event, x, y);
System.out.println("Play label clicked " + y);
// game.setScreen(new GamePlay(game));
}
});
exitLabel.addListener(new ClickListener(){
#Override
public void clicked(InputEvent event, float x, float y) {
super.clicked(event, x, y);
System.out.println("Exit label clicked " + y);
// Gdx.app.exit();
}
});
}
public Stage getStage() {
return this.stage;
}
}
And I call it in the MainMenu class
/**
* Created by vladk on 24/09/16.
*/
public class MainMenu implements Screen {
private MainGame game;
private OrthographicCamera mainCamera;
private Viewport gameViewport;
private MainMenuButtons btns;
public MainMenu(MainGame game) {
this.game = game;
mainCamera = new OrthographicCamera();
mainCamera.setToOrtho(false, GameInfo.WIDTH, GameInfo.HEIGHT);
mainCamera.position.set(GameInfo.WIDTH / 2f, GameInfo.HEIGHT / 2f, 0);
gameViewport = new StretchViewport(GameInfo.WIDTH, GameInfo.HEIGHT, mainCamera);
// background ??
// buttons
btns = new MainMenuButtons(game);
}
#Override
public void show() {
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
// game.getBatch().begin();
// game.getBatch().end();
game.getBatch().setProjectionMatrix(btns.getStage().getCamera().combined);
btns.getStage().draw();
btns.getStage().act();
}
#Override
public void resize(int width, int height) {
gameViewport.update(width, height);
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
// bg
// buttons
btns.getStage().dispose();
}
}
I found a solution. I needed to update view port for the MainMenuButtons, so I created a new method
// in the MainMenuButtons class
public void viewportUpdate(int width, int height) {
gameViewport.update(width, height);
}
and call if from the MainMenu class
#Override
public void resize(int width, int height) {
gameViewport.update(width, height);
btns.viewportUpdate(width, height);
}
image of problem http://imgur.com/ZNpHiiu so I succesfully rendered a background for my game , now i tried to render some sprites on top of it and screen gets all messed up big Blue L.
code main
public class WizardGame extends Game {
public static final String TITLE = "Are you a bad enough wizard to save the princess?!", VERISION = "0.0.0.0.PREALPHA";
PlayTest pt = new PlayTest();
private FPSLogger fps;
public void create() {
Gdx.gl20.glClearColor(0, 0, 0, 1);
Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT);
fps = new FPSLogger();
fps.log();
pt.create();
}
public void dispose() {
super.dispose();
}
public void render() {
super.render();
pt.render();
}
public void resize(int width, int height) {
super.resize(width, height);
}
public void pause() {
super.pause();
}
public void resume() {
super.resume();
}
}
playtest code
public class PlayTest implements Screen {
private TextureAtlas atlas;
private AtlasRegion floor;
private SpriteBatch batch;
private OrthographicCamera camera;
private Sprite background;
private BitmapFont font;
private String fps;
Blocks block = new Blocks();
public void render() {
Gdx.gl20.glClearColor(0, 0, 05, 1);
Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
background.setBounds(0, 0, 720, 1280);
background.draw(batch);
block.renderBlocks();
batch.end();
}
public void resize(int width, int height) {
// TODO Auto-generated method stub
}
public void show() {
}
public void hide() {
}
public void pause() {
}
public void resume() {
}
public void dispose() {
atlas.dispose();
batch.dispose();
}
public void create() {
atlas = new TextureAtlas(Gdx.files.internal("data/wizardpack.pack"));
floor = atlas.findRegion("Backfloor");
background = new Sprite(floor);
batch = new SpriteBatch();
font = new BitmapFont(Gdx.files.internal("data/magicdebug48.fnt"));
block.create();
}
#Override
public void render(float delta) {
// TODO Auto-generated method stub
}
}
block code
public class Blocks extends Game {
private TextureAtlas atlas;
private SpriteBatch batch;
private AtlasRegion sword,shield,staff,fireball,iceball;
private Sprite sprSword,sprShield,sprStaff,sprFireball,sprIceball;
#Override
public void create() {
atlas = new TextureAtlas(Gdx.files.internal("data/wizardpack.pack"));
batch = new SpriteBatch();
sword = atlas.findRegion("Sword");
shield = atlas.findRegion("Shield");
staff = atlas.findRegion("Staff");
fireball = atlas.findRegion("flame");
iceball = atlas.findRegion("icespell");
sprSword = new Sprite(sword);
sprShield = new Sprite(shield);
sprStaff = new Sprite(staff);
sprFireball = new Sprite(fireball);
sprIceball = new Sprite(iceball);
}
public void renderBlocks(){
Gdx.gl20.glClearColor(0, 0, 05, 1);
Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(sword, 0, 0, 0, 0, 32, 32, 1, 1, 0);
//sprShield.setBounds(15, 15, 32, 32);
// sprShield.draw(batch);
batch.end();
}
public void dispose(){
atlas.dispose();
batch.dispose();
}
}
I fixed it :D the call to renderBlocks has to be after the end of batch.