Libgdx - game closing immediately after start when using Screen - java

I am trying to get my main class to setscreen to my gamescreen class.when I try to run the desktop application the only thing that happens is that a window with a black background opens and stays up for half a second and then closes down and I have no idea why it doesn't work. I'm using Netbeans if that has anything to do with it.
Here is my main class:
public class MyGdxGame extends Game {
public SpriteBatch batch;
#Override
public void create () {
batch = new SpriteBatch();
this.setScreen(new GameScreen(this));
}
#Override
public void render () {
super.render();
}
}
and here is my screen class:
public class GameScreen implements Screen{
Texture texture;
private MyGdxGame game;
public GameScreen(MyGdxGame game) {
this.game = game;
texture = new Texture("badlogic.jpg");
}
#Override
public void show() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
#Override
public void render(float f) {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
game.batch.begin();
game.batch.draw(texture, 0, 0);
game.batch.end();
}
//I havn't touched the other methods so I didn't paste them.
I haven't touched the desktop class.
I get this error message:
Exception in thread "LWJGL Application" java.lang.UnsupportedOperationException: Not supported yet.
at com.mygdx.game.GameScreen.show(GameScreen.java:27)
at com.badlogic.gdx.Game.setScreen(Game.java:61)
at com.mygdx.game.MyGdxGame.create(MyGdxGame.java:14)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:147)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:124)

You are basically throwing an exception in method show(), which is called right after setting the screen to MyGdxGame class.
#Override
public void show() {
throw new UnsupportedOperationException("Not supported yet.");
}
Never used NetBeans, but it looks like it overrides show() with an exception. As the comment in the code suggest, change the body of generated methods in Tools | Templates to avoid this kind of errors.

Related

Receiving java.lang.UnsatisfiedLinkError on badlogic.BufferUtils

When lunching the application with DesktopLuncher i experience UnsatisfiedLinkError on root class (Main) in core module inside the project.
public class Main extends Game {
#Override
public void create() {
this.cameraBuilder = ...
setScreen(new LandingMenu(this));
}
#Override
public void render() {
super.render();
}
#Override
public void dispose() {
batch.dispose();
}
public World getWorld() {
return world;
}
public SpriteBatch getBatch() {
return batch;
}
public CameraBuilder<OrthographicCamera> getCameraBuilder() {
return cameraBuilder;
}
private final SpriteBatch batch = new SpriteBatch();;
private CameraBuilder<OrthographicCamera> cameraBuilder;
private final World world = new World(new Vector2(0, -9.8f), true);
}
any answer will be appreciated.
The exception is a cause and issue lives on create method on ApplicationListener Called when the Application is first created, on the other hand SpriteBatch is a Batch which is used for drawing Sprites, more specifically, it deals with drawing a bunch of textures on Quads in OpenGL thus is must be initialized inside of create method and not in the root class level.
#Override
public void create() {
batch = new SpriteBatch();
setScreen(new LandingMenu(this));
}
...
private SpriteBatch batch;
Find more in here.

android app freezes on activity switch

I've got myself a mediocre game going for myself. It has a main menu activity that when you click play starts a new game play activity. When you lose the game you can either retry or go back to the main menu. the back button on the gameplay activity is just a ractangle with this coding.
if (GlobalVariables.GAMEOVER && backButton.contains((int)(event.getX()), (int)(event.getY())))
{
Intent backButtonIntent = new Intent(context, MainMenuActivity.class);
context.startActivity(backButtonIntent);
}
The program does not crash and it does switch to the mainmenu activity but it is frozen and no buttons are clickable. and here is the error i get.
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.graphics.Canvas.drawColor(int, android.graphics.PorterDuff$Mode)' on a null object reference
at android.view.SurfaceView.dispatchDraw(SurfaceView.java:451)
at android.view.View.draw(View.java:17472)
at android.view.SurfaceView.draw(SurfaceView.java:442)
at com.example.jordanschanzenbach.myapplication.GamePanel.draw(GamePanel.java:84)
at com.example.jordanschanzenbach.myapplication.MainThread.run(MainThread.java:52)
here is the code that it is pointing to in the game panel. "super.draw(canvas)"
public void draw(Canvas canvas)
{
super.draw(canvas);
backGround.draw(canvas);
gameFloor.draw(canvas);
gamePlayScene.draw(canvas);
}
i understand that this is a nullpointerexception and a duplicate question. but i dont understand why when i switch to my main menu activity it is causing this error when the game panel isn't even linked to the main menu activity. Please help a young student :) thank you and if you would like to see any other code i will edit this post immediately.
Check if the thread responsible for calling the draw method was left running before starting another activity. I'm not quite sure but it probably still tries to render on the SurfaceView even if it has already been detached from the window.
Edit:
I was able to replicate your problem. The thread that handles the drawing does not always instantly get the updated value of the variable you use as a while loop condition. You can choose to perform synchronization and/or other threading stuff, but you can simply try to break the while loop like how I did in the code below. Also, try to stop your drawing thread by making your while loop condition false inside the SurfaceHolder.Callback#surfaceDestroyed(SurfaceHolder).
public class GamePanel extends SurfaceView implements SurfaceHolder.Callback {
private TextPaint paint;
private volatile boolean isDrawing;
private DrawingThread drawingThread;
public GamePanel(Context context) {
super(context);
initialize();
}
// omitted the other constructors for brevity
private void initialize() {
...
drawingThread = new DrawingThread();
// do this so that you can get an surface updates
getHolder().addCallback(this);
}
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
canvas.drawText("Hello, world", 20, 20, paint);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
isDrawing = true;
drawingThread.start();
// start drawing only after the surface was created
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { }
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
isDrawing = false;
// try to stop the drawing thread when the surface
// is destroyed
}
private class DrawingThread extends Thread {
#Override
public void run() {
while (isDrawing) {
try {
Canvas canvas = getHolder().lockCanvas();
// check if canvas is null just to make sure
if (canvas == null) break;
draw(canvas);
getHolder().unlockCanvasAndPost(canvas);
} catch (IllegalArgumentException e) {
// This is thrown by SurfaceHolder#lockCanvas().
// Break when the surface has already been destroyed
// but the variable `isDrawing` is still true.
break;
}
}
}
}
}

How to manage screens

i'm making a game in libgdx but i'm new and i donĀ“t know if my code is the correct form or the best way to do it.
i'm trying to make the basis of the game:
a screen manager to implement a Menu,
an option screen
a loading screen
a game screen
a pause Screem
a game over screen
In the loading screen I like to do something like Dragon Ball when the loading screen allow us to make goku eat rice, the pause screen needs to draw some statistics and options something like Megaman or Castlevania, the menu do something when the player touch a button something like move the camera or open a door, or move to another "scenario" showing another options, and the game over screen needs to previously gives the player the opportunity to win some life to not lose the game.
I try to make this in this form:
I have the main class of the game with the constructor, and the overriden metods create(), render(), resize() and dispose(), the variables for a camera, a viewport, a Spritebatch, a int to store the current screen, and a manager for the screens.
public class BOS_Project extends Game {
OrthographicCamera camera;
Viewport viewport;
SpriteBatch batch;
AssetManager manager = new AssetManager();
int actualScreen = 0;
public BOS_Project(){
camera = new OrthographicCamera();
camera.setToOrtho(false, screenWidth, screenHeight);
viewport = new FitViewport(screenWidth, screenHeight);
}
#Override
public void create(){
batch = new SpriteBatch();
}
#Override
public void render(){
actualScreen = 1;
ScreenManager.getInstance().showScreen(1, this);
super.render();
}
#Override
public void resize(int width, int height){
viewport.update(width, height);
}
#Override
public void dispose(){
batch.dispose();
}
}
Also the class ScreenManager is singleton, and
public class ScreenManager{
private static ScreenManager instance;
private Game game;
Screen screen;
private ScreenManager(){
super();
}
public static ScreenManager getInstance(){
if(instance == null){
instance = new ScreenManager();
}
return instance;
}
public void initialize(Game game){
this.game = game;
}
public void showScreen(int currentscreen, BOS_Project game){
if(currentscreen == 1){
if(screen!=null)
screen.dispose();
screen = new LoadingScreen(game, game.actualScreen);
game.setScreen(screen);
}else if(currentscreen == 2){
if(screen!=null)
screen.dispose();
screen = new GameScreen(game);
game.setScreen(screen);
}else{
if(screen!=null)
screen.dispose();
screen = new MenuScreen(game);
game.setScreen(screen);
}
}
The other classes are the MenuScreen, GameScreen and Loading Screen.
Loading Screen:
public LoadingScreen(BOS_Project game2, int screen2){
game = game2;
screen = screen2;
game.manager.load("button.png", Texture.class);
game.manager.finishLoadingAsset("button.png");
sprite1 = new Sprite(game.manager.get("button.png", Texture.class));
sprite1.setPosition(0, 0);
//This is a method to load the assets for the especific screen
game.load(screen);
}
#Override
public void render(float delta){
if(game.manager.getProgress()==1) {
if (time < 3) {
Gdx.app.log("Loading: ", "90.0");
}
}else {
Gdx.app.log("Loading: ", String.valueOf(game.manager.getProgress() * 100));
}
game.manager.update();
batch = game.batch;
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
sprite1.draw(batch);
if(game.manager.getProgress()==1 && time > 3){
if(screen==1) {
ScreenManager.getInstance().showScreen(2, game);
}else{
ScreenManager.getInstance().showScreen(3, game);
}
}else{
time += delta;
}
batch.end();
super.render(delta);
}
The Menu and Game classes are similar to loading, only call the assets and draw some sprite on the render method.
This code function well to change screens but I don't know if is the correct form, and another big question is how to manage the pause screen, because I manage this only storing a variable if the variable is pause the render method draw something, if not draw the normal game, but if I want to change the options and images of the pause I need to check variables to know what the pause needs to draw.
if(pause){
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
spritePause.draw(batch);
batch.end();
}else if(game){
batch.begin();
spriteGame.draw(batch);
batch.end();
}
So, am i doing it right? or what would you recommend me? Some examples or maybe specific tutorials to achieve this would be great.
There is not only one correct way of managing screens. Libido gives you the freedom to do it exactly how you please. You can extend the Screen class to make screens for the different needs of your project. You can manage your screens as states and manage them with a state manager.
Regarding the Pause and Game Over screen, you can do that in different ways too.
You can have a dedicated screen to switch to or you can have a Pause and GameOver state in your Game state/screen and show the Pause/GameOver elements on top of your gamescreen while the game is still in the background.
So there is not a single correct way of doing it. The correct way is what works for your game.
For some inspiration:
pixnbgames.com : How to manage screens
Brent Aureli : Game State Manager
As #IronMonkey has answered, there is no "correct" way.
I do it with one GameScreen class only, and have a lot of different states inside the GameScreen class. The GameScreen class is very simple and short (100-200 LOC), and is responsible for switching between states. States are similar to the GameScreen class, but they can be entered and exited without the need to instantiate new objecs.
class GameScreen extends ScreenAdapter implements Disposable {
GameState menuState;
GameState playState;
GameState currentState;
public GameScreen(final MyGame game) {
menuState = new MenuState(this);
playState = new PlayState(this);
}
public void setState(GameState state) {
if(currentState == state) return;
// states have a method 'exit' where you can pause them or finalize something
if(currentState != null)
currentState.exit();
currentState = state;
// also states have 'enter' where you can unpause or init something when entering
currentState.enter();
}
public void render(float delta) {
currentState.render(delta);
}
}
First, this is very resource efficient, because the needed states are created only once when the game is started. Second, because you never destroy the states, but just change them and call enter/exit, they always retain perfectly their current state, i.e. variables, objects and everything and when you go back to a state, it is exactly as it was before you left it.
GameState is interface and you are free to implement it as you wish.
public interface GameState
{
public void enter();
public void exit();
public void update(float delta);
public void render(SpriteBatch batch, float delta);
public String toString();
public void dispose();
}

libGDX Android white screen after back button pressed

I am having a problem with libGDX where when I resume the application after exiting with the back button, I get only a white screen.
The actual app runs, accepts touch input, and plays sounds, but the screen is just white.
I have read that keeping static references to Textures may cause this problem but I am not doing that.
Below is a simplified version of how my asset code works.
public class GdxGame extends Game {
private Assets assets;
#Override
public void onCreate() {
assets = new Asstes();
assets.startLoading();
/*
*Within SplashScreen, GdxGame.getAssets() is accessed, and
*manager.update() is called
*/
setScreen(new SplashScreen());
}
#Override
public void dispose() {
assets.dispose();
assets = null;
}
//Perhaps a problem??
public static Assets getAssets() {
return ((GdxGame) Gdx.app.getApplicationListener()).assets;
}
}
public class Assets implements Disposable{
private AssetManager manager;
public Assets() {
manager = new AssetManager();
}
public void startLoading() {
manager.load(....);
}
#Override
public void dispose() {
manager.dispose();
}
}
Upon returning to the application after the back button is pressed, the AssetManager is recreated, the SplashScreen is reopened (as white), and the AssetManager updates until all assets are reloaded (takes about 2 seconds).
So when the application is reopened, a new AssetManager is loading all of the necessary textures, but for some reason everything is still white.
Could it have something to do with how I access the AssetManager from my UI and Game classes?
//In GdxGame
public Assets getAssets() {
return ((GdxGame) Gdx.app.getApplicationListener()).assets;
}
That is the only place where I could see something going wrong, but even still, I don't understand what could be wrong with that.
Any help would be much appreciated.
Edit:
Here is the SplashScreen class. This makes the issue even more confusing. In the SplashScreen class I load, draw, and dispose a new Texture for the logo. Nothing to do with the AssetManager. Returning after the back button is pressed, this new Texture does not appear either.
public class SplashScreen extends Screen {
private Texture logo;
private Assets assets;
#Override
public void show() {
assets = GdxGame.getAssets();
logo = new Texture(Gdx.files.internal("data/logo.png"));
}
#Override
public void render(float delta) {
super.render(float delta);
if(assets.load()) {
//Switch screens
}
//getBatch() is the same form as getAssets() ((GdxGame) Gdx.app.getApplicationListener()).batch)
GdxGame.getBatch().draw(logo, 100, 100, 250, 250);
}
#Override
public void hide() {
super.hide();
logo.dispose();
}
}
It turns out the issue was to do with how I was managing screens. I had a convenience method in my GdxGame class that allowed me to switch screens based on a ScreenType enum.
Within the enum, I would create a new screen with reflection, given the screen's class in the enum constructor.
The problem is that I stored the screens in the enums, and only created them once. This means that I was keeping and using screens from the old context when I returned after pressing back.
To solve this, I simply had to change it so that a new screen is created every time the enum is accessed, instead of storing one at the start.

LibGDX not running render() method

I'm experiencing a problem using LibGDX.
I have a Screen and in its render method I have:
public class LoadingScreen implements Screen{
private OrthographicCamera guiCam;
private TankChallenge tankChallenge;
private SpriteBatch batcher;
private GL10 OpenGL;
public LoadingScreen(TankChallenge tankChallenge) {
this.tankChallenge=tankChallenge;
Gdx.graphics.setTitle("RobotChallange Beta - Loading");
float AR = Gdx.graphics.getHeight()/Gdx.graphics.getWidth();
guiCam = new OrthographicCamera(10,10 * AR);
guiCam.position.set(10f/2,AR*10f/2,0);
batcher = new SpriteBatch();
OpenGL = Gdx.graphics.getGL10();
//loadAssets();
}
#Override
public void render(float delta) {
OpenGL.glClearColor(1, 0.5f, 1, 1);
OpenGL.glClear(GL10.GL_COLOR_BUFFER_BIT);
System.out.print("e");
guiCam.update();
Sprite sp = new Sprite();
sp.setColor(1f,1f,0, 1);
sp.setSize(100,100);
sp.setOrigin(20, 0);
batcher.setProjectionMatrix(guiCam.combined);
batcher.begin();
batcher.disableBlending();
sp.draw(batcher);
batcher.end();
}
I call this by setting it in the implementes ApplicationListener class. I know it is arriving the LoadingScreen because Title is actually set to "RobotChallenge Beta - Loading".
I found a solution for both problems. I added to the Game extending class this:
public void render() {
super.render();
}
Thanks to this the problem is solved and I don't need to override the SetScreen method. Thanks!
Immediately after setting this as your screen, you need to call super.render() in your Game extending class. For instance, I use the following method in my main Game extending class for setting the screen:
#Override
public void setScreen(Screen screen)
{
super.setScreen(screen);
super.render();
}
This seems to kick off render() being called.
Just remove #Override render() in your Game extending class, that fixes the problem. Overriding setScreen method causes flickering you mentioned.

Categories

Resources