Asynchronously Loading Screen Libgdx - java

I store all of my assets in a class and load them at the start of my game, I am trying to create a loading screen in a separate class.
Asset manager class:
public class Assets {
public static AssetManager manager = new AssetManager();
public static void queueLoading() {
(..)
manager.load("sound/buttonpress.mp3", Sound.class);
(..)
while(!manager.update())
{
System.out.println("Loaded: " + manager.getProgress() *100 + "%");
}
}
public static boolean update() {
return manager.update();
}
}
Loading screen class:
public class LoadingScreen implements Screen{
final Game1 game;
Sprite LdScreen;
OrthographicCamera camera;
public LoadingScreen(Game1 gam){
game=gam;
camera = new OrthographicCamera();
camera.setToOrtho(false, 1920, 1080);
}
public void show() {
Texture LdscreenTexture = new Texture(Gdx.files.internal("data/Background.png"));
LdScreen = new Sprite (LdscreenTexture);
Assets.queueLoading();
}
#Override
public void render(float delta) {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
game.batch.setProjectionMatrix(camera.combined);
game.batch.begin();
game.batch.draw(LdScreen, 0,0);
game.batch.end();
// Assets.queueLoading();
if(Assets.update()){
game.setScreen(new MainMenuScreen(game));
System.out.print("hllasgsgsag");
}
Assets.update();
}
#Override
public void resize(int width, int height) {
}
#Override
public void hide() {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void dispose() {
}
}
Problem:
When i run it in the console i get the progress percentage, but the screen stays black whilst it is loading (stuck at Assets class), then it flashes to the loading screen, and changes to MainMenuScreen.
How do I stop the black screen when the assets are loading?

The problem that you are having is because you are loading all the Assets straight away and this isn't done in a different thread and is run whilst the screen is being shown. I would advise using manager.update(delta) which should be called during your game loop and getting the update percentage. The full source would be a bit difficult for me to explain but I have done something similar in my previous projects, the sources are available on GitHub below:
The Assets class:
https://github.com/basimkhajwal/NinjaTower/blob/master/NinjaTower/core/src/net/net63/codearcade/NinjaTower/utils/Assets.java
The Loading Screen:
https://github.com/basimkhajwal/NinjaTower/blob/master/NinjaTower/core/src/net/net63/codearcade/NinjaTower/screens/MainMenuScreen.java

Related

LibGDX - Camera scaling does not work

I have a problem with LibGDX. I am trying to create an application, and for ease of use I want to draw everything at a fixed resolution (1920x1080).
To do this, I am trying to create a FitViewport and an OrthographicCamera so that the viewport always fits nicely to the screen size, and everything automatically scales.
In my Screen class I create such a viewport and a camera:
AbstractScreen() {
camera = new OrthographicCamera(Constants.VIRTUAL_WIDTH, Constants.VIRTUAL_HEIGHT);
viewport = new FitViewport(Constants.VIRTUAL_WIDTH, Constants.VIRTUAL_HEIGHT, camera);
}
(where VIRTUAL_WIDTH is 1920 and VIRTUAL_HEIGHT is 1080)
Now, when I try to render an image that is 1920x1080px, only one third of that image is drawn!
Here is a screenshot of what should be drawn: screenshot
Here is the image that should be fully drawn: image
public abstract class AbstractScreen implements Screen {
private Viewport viewport;
private OrthographicCamera camera;
protected SpriteBatch spriteBatch;
AbstractScreen() {
camera = new OrthographicCamera(Constants.VIRTUAL_WIDTH, Constants.VIRTUAL_HEIGHT);
viewport = new FitViewport(Constants.VIRTUAL_WIDTH, Constants.VIRTUAL_HEIGHT, camera);
spriteBatch = new SpriteBatch();
}
#Override
public void show() {
viewport.apply();
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
spriteBatch.setProjectionMatrix(camera.combined);
}
#Override
public void resize(int width, int height) {
viewport.update(width, height);
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
}
}
And here is the actual screen implementation:
class LoadingScreen extends AbstractScreen {
private SpriteBatch spriteBatch;
private Texture texture;
#Override
public void show() {
super.show();
spriteBatch = new SpriteBatch();
texture = new Texture("textures/test.png");
}
#Override
public void render(float delta) {
super.render(delta);
spriteBatch.begin();
spriteBatch.draw(texture, 0, 0);
spriteBatch.end();
}
}
Thank you!
Your LoadingScreen is creating its own SpriteBatch named spriteBatch, which hides the spriteBatch in the AbstractScreen superclass.
So your LoadingScreen.render() calls super.render(), which sets up the appropriate projection matrix in AbstractScreen.spriteBatch, but then you are using LoadingScreen.spriteBatch to draw with.
So remove the spriteBatch field in LoadingScreen, and don't instantiate it there. Make the spriteBatch in AbstractScreen protected so you can access it from the subclass.
By the way, SpriteBatches must be disposed in dispose() or you will leak memory. Better yet, don't instantiate SpriteBatch inside your Screen. Instantiate a single SpriteBatch in your Game and pass it to your Screen's constructor so everything can share the same instance, rather that wasting time disposing and instantiating new ones every time you switch screens. SpriteBatch is a heavy object.

Clickable textures

I'm kind of new to LibGdx and android studio.
I'm trying to create clickable textures, one for play and one for credits.
Both should be opening a new empty screen/event.
public void create() {
batch = new SpriteBatch();
img = new Texture("Main_Screen.png");
music = Gdx.audio.newMusic(Gdx.files.internal("bgmusic.wav"));
music.play();
music.setLooping(true);
credits = new Texture("credits.png");
play = new Texture("play.png");
}
#Override
public void render() {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(img, 0, 0);
batch.draw(play, 340, 1400);
batch.draw(credits, 340, 400);
batch.end();
}
However i'm unsure on how to do this since i'm also creating the background with a texture, so i'd be very happy if someone could assist me with helping me out.
Use Sprite instead of Texture, that holds the geometry, color, and texture information for drawing 2D sprites.
MyGdxGame
public class MyGdxGame extends Game {
public Screen menuScreen,creditsScreen,playScreen;
#Override
public void create () {
menuScreen=new MenuScreen(this);
creditsScreen=new CreditsScreen();
playScreen=new PlayScreen();
setScreen(menuScreen);
}
}
MenuScreen
public class MenuScreen extends InputAdapter implements Screen {
SpriteBatch batch;
Texture background,play,credits;
Sprite backgoundSprite,playSprite,creditsSprite;
private ExtendViewport extendViewport;
OrthographicCamera cam;
private float w=480;
private float h=800;
private Vector3 vector3;
MyGdxGame game;
Music music;
public MenuScreen(MyGdxGame game){
this.game=game;
}
#Override
public void show() {
batch = new SpriteBatch();
cam = new OrthographicCamera();
extendViewport=new ExtendViewport(w,h,cam);
vector3=new Vector3();
background = new Texture("Main_Screen.png");
play=new Texture("play.png");
credits=new Texture("credits.png");
backgoundSprite=new Sprite(background);
backgoundSprite.setSize(w,h); // If resources are not in context of your viewport
backgoundSprite.setPosition(0,0); //Default Position
playSprite=new Sprite(play);
playSprite.setSize(100,100);
playSprite.setPosition(w/2-playSprite.getWidth()/2,h/2+100);
creditsSprite=new Sprite(credits);
creditsSprite.setSize(100,100);
creditsSprite.setPosition(w/2-creditsSprite.getWidth()/2,h/2-100);
Gdx.input.setInputProcessor(this);
music = Gdx.audio.newMusic(Gdx.files.internal("bgmusic.wav"));
music.play();
music.setLooping(true);
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(cam.combined);
batch.begin();
backgoundSprite.draw(batch);
playSprite.draw(batch);
creditsSprite.draw(batch);
batch.end();
}
#Override
public void resize(int width, int height) {
extendViewport.update(width,height);
cam.position.x = w /2;
cam.position.y = h/2;
cam.update();
}
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
vector3.set(screenX,screenY,0);
Vector3 position=cam.unproject(vector3);
if(playSprite.getBoundingRectangle().contains(position.x,position.y)) {
game.setScreen(game.playScreen);
}
if(creditsSprite.getBoundingRectangle().contains(position.x,position.y)){
game.setScreen(game.creditsScreen);
}
return super.touchDown(screenX, screenY, pointer, button);
}
#Override
public void pause() { }
#Override
public void resume() { }
#Override
public void hide() { }
#Override
public void dispose() {
batch.dispose();
background.dispose();
play.dispose();
credits.dispose();
}
}
CreditsScreen
public class CreditsScreen implements Screen {
#Override
public void show() {
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
}
#Override
public void resize(int width, int height) { }
#Override
public void pause() { }
#Override
public void resume() { }
#Override
public void hide() { }
#Override
public void dispose() { }
}
PlayScreen
public class PlayScreen implements Screen {
#Override
public void show() {
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
}
#Override
public void resize(int width, int height) { }
#Override
public void pause() { }
#Override
public void resume() { }
#Override
public void hide() { }
#Override
public void dispose() { }
}
Welcome to libGDX!
If I understand your question correctly, you are trying to figure out how to change screens in your game. At a high level, this is what you'd need to do:
Draw your button texture on the screen.
Use Gdx.input to detect when the player lifts their mouse button (and if it's over one of your buttons when they do it)
Switch to the new screen (presumably with a new background) when this happens.
I would recommend that you first complete the "A Simple Game" and "Extending the Simple Game" tutorials in order to familiarize yourself with the basics of libGDX and the Game and Screen classes.
Next, try using Scene2D.UI (there are links at the bottom of the second tutorial) to add a Stage and TextButtons to your main menu.
Hopefully that helps you get started- there is a lot of helpful information on that libGDX wiki which I think you will find helpful.

Libgdx Switching Screens and Viewports

I am having an issue when switching screens in libgdx. I am building a asteroids game clone. So first my MainMenuScreen class (which uses a Fitviewport) is rendered and then I call setScreen() to GameScreen (GameScreen doesn't use a Fitviewport) and that works except that the second screen renders as if its using a Fitviewport. If I resize the second screen then the whole window is used for rendering. Why is this happening? Here are some pictures:
MainMenuScreen class:
GameScreen class after switching screens, the screen has black bars on the side (I colored the boundary in red for you) which I don't want:
I want the GameScreen to use all the window area for rendering, and not have black bars like the MainMenu. I am not using any Fitviewport in GameScreen also.
Here are relevant parts of my MainMenuScreen class:
public class MainMenuScreen implements Screen
{
private static final String TAG = "MainMenu";
private static final int VIRTUAL_WIDTH = 400;
private static final int VIRTUAL_HEIGHT = 400;
MyGdxGame game;
...
public MainMenuScreen(MyGdxGame game)
{
this.game = game;
viewport = new FitViewport(VIRTUAL_WIDTH, VIRTUAL_HEIGHT);
stage = new Stage(viewport);
// Play button listener
btnPlay.addListener( new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) {
Gdx.app.log(TAG, "PLAY");
MainMenuScreen.this.game.setScreen(MainMenuScreen.this.game.gameScreen);
};
});
....
}
Here is my GameScreen class:
MyGdxGame game;
OrthographicCamera guiCam;
World world;
WorldRenderer renderer;
public GameScreen(MyGdxGame game, SpriteBatch batch)
{
this.game = game;
guiCam = new OrthographicCamera(400, 400);
guiCam.position.set(400 / 2, 400 / 2, 0);
world = new World();
renderer = new WorldRenderer(game, batch, world);
}
public void draw()
{
GL20 gl = Gdx.gl;
gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
renderer.render();
}
#Override
public void show()
{
world.createLevel();
}
#Override
public void render(float delta)
{
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()
{
}
The problem is this line of code:
public void resize(int width, int height)
{
viewport.update(width, height, true);
}
Whenever you update the viewport, you are also updating the underlying opengl viewport and this causes the black bars to persist to the second screen (https://github.com/libgdx/libgdx/wiki/Viewports). Thus if you want to reset it back to normal you must use the following line of code in your second screen show() method (https://github.com/libgdx/libgdx/wiki/Scene2d):
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());

How to add child image to sprite in Libgdx as we can do in Cocos2d?

While i was learning about Libgdx i came across this problem of adding a child sprite to parent sprite in Libgdx as i did the same in Cocos2d it had no problem of doing it.
How can the same be achieved in Libgdx, so that i can perform operation on parent sprite and it will be followed by the child added to it.
EDIT : I have seen at https://github.com/libgdx/libgdx/wiki/Scene2d of scene2d, but they havn't mentioned how to make use of Group.
This is what i tried earlier but its coming white screen
public class TestScreen implements Screen{
private MainGame game;
private Sprite sprite;
public Group group;
private Stage stage;
private SpriteBatch batch;
public TextureAtlas atlas1;
public Skin skin;
public Image bg;
public Sprite sprite1;
public TestScreen(MainGame game)
{
this.game=game;
group = new Group();
batch = new SpriteBatch();
circle=AssestLoader.circle1;
}
#Override
public void render(float delta)
{
// TODO Auto-generated method stub
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
stage.act(delta);
batch.begin();
stage.addActor(group);
batch.end();
}
#Override
public void show() {
// TODO Auto-generated method stub
atlas1 = new TextureAtlas("test/gamescreentest.pack");
skin = new Skin();
skin.addRegions(atlas1);
bg = new Image();
bg.setDrawable(skin, "playbg_hdpi");
bg.setHeight(460f);
bg.setWidth(460f);
group.addActor(bg);
}
#Override
public void hide() {}
#Override
public void resize(int width, int height) {}
#Override
public void pause() {}
#Override
public void resume() {}
#Override
public void dispose() {}}
Its coming white screen without image
You could use scene2d and actors (https://github.com/libgdx/libgdx/wiki/Scene2d). But this would require you to (maybe) rewrite parts of your application.
If your images are static and don't change I'd recommend you to draw the child ontop of the parent using a framebuffer. That'd be best in case of performance.
EDIT: The blog post at http://www.gamefromscratch.com/post/2013/12/11/LibGDX-Tutorial-3C-Scene-management.aspx has a very good example of groups.

Low framerate on simple libgdx example in desktop application

I just started learning libGDX, and was following the example from http://steigert.blogspot.in/2012/02/2-libgdx-tutorial-game-screens.html (the second link on libGdx help page).
As of now, I just display a logo of 512x512. There is nothing else happening in the application but when I run the application in desktop mode,I get a FPS of 15-16. When I remove the image, I get 60fps for the blank screen. For android its even worse, I get 3-4 fps in Galaxy SL - GT-i9003 (Temple Run runs on playable speed on the device).
My laptop plays World of Warcraft without any hiccups in high quality so its baffling that such a small app would only achieve 15fps.
public class SplashScreen extends AbstractScreen {
private Texture splashTexture;
private TextureRegion splashTextureRegion;
public SplashScreen(MyGDXGame game){
super(game);
}
#Override
public void show()
{
super.show();
// load the splash image and create the texture region
splashTexture = new Texture("splash.png");
// we set the linear texture filter to improve the stretching
splashTexture.setFilter( TextureFilter.Linear, TextureFilter.Linear );
// in the image atlas, our splash image begins at (0,0) at the
// upper-left corner and has a dimension of 512x301
splashTextureRegion = new TextureRegion( splashTexture, 0, 0, 512, 382 );
}
#Override
public void render(float delta ) {
super.render( delta );
// we use the SpriteBatch to draw 2D textures (it is defined in our base
// class: AbstractScreen)
batch.begin();
// we tell the batch to draw the region starting at (0,0) of the
// lower-left corner with the size of the screen
batch.draw( splashTextureRegion, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight() );
// the end method does the drawing
batch.end();
}
#Override
public void dispose()
{
super.dispose();
splashTexture.dispose();
}
}
Here is the relevant section of AbstractScreen class:
public class AbstractScreen implements Screen {
protected final MyGDXGame game;
protected final BitmapFont font;
protected final SpriteBatch batch;
public AbstractScreen(MyGDXGame game ){
this.game = game;
this.font = new BitmapFont();
this.batch = new SpriteBatch();
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor( 0f, 0f, 0f, 1f );
Gdx.gl.glClear( GL20.GL_COLOR_BUFFER_BIT );
}
...
}
And the desktop app:
public class Main {
public static void main(String[] args) {
LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
cfg.title = "First Game";
cfg.useGL20 = false;
cfg.width = 800;
cfg.height = 480;
new LwjglApplication(new MyGDXGame(), cfg);
}
MyGDXGame is as follows:
public class MyGDXGame extends Game {
private FPSLogger fpsLogger;
public SplashScreen getSplashScreen() {
return new SplashScreen( this );
}
#Override
public void create() {
fpsLogger = new FPSLogger();
}
#Override
public void dispose() {
super.dispose();
}
#Override
public void render() {
super.render();
setScreen(getSplashScreen());
fpsLogger.log();
}
#Override
public void resize(int width, int height) {
super.resize(width, height);
}
#Override
public void pause() {
super.pause();
}
#Override
public void resume() {
super.resume();
}
I have read so many good things about libGdx, so this issue seems baffling to me. What am I doing wrong to get such a low frame rate?
I think setScreen(getSplashScreen()); in your render() method might be the problem. Move it to the create() method of MyGDXGame.
Right now you are switching the screen in every single frame and recreate a SpriteBatch every single time which is a very heavy object (see my comment to your question).

Categories

Resources