Screen does not save its progress when switched - android

So, this is too hard for me to explain this in short, so the title looks so creepy. Well, I am writing a small android application and i have like three screens: the main-menu one, and two in-game screens. I can switch between the last two ones with a switch button. The problem is, that when i switch back to the last screen I've been to, all its acting stuff starts again from the very beginning. I have also seen a similar question here, but i did not work for me(( So, is there any way to keep the screen rendering, while I am using the other one?
Thank you!
The first screen:
public class InGameScreen implements Screen {
TinyBattles game;
public static OrthographicCamera camera;
public static Button switchButton1;
public InGameScreen(TinyBattles game) {
this.game = game;
}
#Override
public void show() {
camera = new OrthographicCamera(Global.VIEWPORT_WIDTH, Global.VIEWPORT_WIDTH*Global.actualHeight/Global.actualWidth);
camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0);
camera.update();
switchButton1 = new Button();
switchButton1.create(10, 800, 150, 150);
Assets.loadSwitchButton();
}
#Override
public void render(float delta) {
Global.cleanScreen();
touchHandler(camera, Global.touch);
switchButton1.act();
switchButton1.render(Assets.buttonSwitchStateUpSprite, Assets.buttonSwitchStateDownSprite);
Global.debugRender();
localDebugRender();
leaveScreen();
Global.batch.getProjectionMatrix().setToOrtho2D(0, 0, Global.actualWidth, Global.actualHeight);
Global.batch.setProjectionMatrix(camera.combined);
Global.shapeRenderer.setProjectionMatrix(camera.combined);
}
public void localDebugRender(){
switchButton1.debugRender();
}
public void touchHandler(OrthographicCamera camera, Vector3 touch){
if (Gdx.input.isTouched()){
touch.set(Gdx.input.getX(), Gdx.input.getY(), 0);
camera.unproject(touch);
Global.finger.bounds.x = touch.x - 64;
Global.finger.bounds.y = touch.y - 64;
}else{
Global.finger.bounds.x = 10000;
Global.finger.bounds.y = 10000;
}
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
}
public void leaveScreen(){
if (switchButton1.isPressed == true){
game.setScreen(TinyBattles.inGameVirtualScreen);
}
}
}
The second screen:
public class InGameVirtualScreen implements Screen {
TinyBattles game;
public static World world;
public static OrthographicCamera camera;
public static Button switchButton2;
public static Balls balls;
public InGameVirtualScreen(TinyBattles game) {
this.game = game;
}
#Override
public void show() {
world = new World(new Vector2(0, 0), true);
camera = new OrthographicCamera(Global.VIEWPORT_WIDTH, Global.VIEWPORT_WIDTH*Global.actualHeight/Global.actualWidth);
camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0);
camera.update();
switchButton2 = new Button();
switchButton2.create(10, 800, 150, 150);
balls = new Balls();
Assets.loadBallSprites();
balls.create();
balls.setup();
}
#Override
public void render(float delta) {
Global.tweenManager.update(1 / 60f);
Global.cleanScreen();
world.step(1 / 60f, 10, 10);
touchHandler(camera, Global.touch);
switchButton2.act();
balls.act();
renderLayerOne();
renderInterfaceLayer();
renderDebugLayer();
leaveScreen();
Global.batch.getProjectionMatrix().setToOrtho2D(0, 0, Global.actualWidth, Global.actualHeight);
Global.batch.setProjectionMatrix(camera.combined);
Global.shapeRenderer.setProjectionMatrix(camera.combined);
}
public void renderLayerOne(){
balls.render();
}
public void renderInterfaceLayer(){
switchButton2.render(Assets.buttonSwitchStateUpSprite, Assets.buttonSwitchStateDownSprite);
}
public void renderDebugLayer(){
Global.debugRender();
localDebugRender();
}
public void localDebugRender(){
switchButton2.debugRender();
}
public void touchHandler(OrthographicCamera camera, Vector3 touch){
if (Gdx.input.isTouched()){
touch.set(Gdx.input.getX(), Gdx.input.getY(), 0);
camera.unproject(touch);
Global.finger.bounds.x = touch.x - 64;
Global.finger.bounds.y = touch.y - 64;
}else{
Global.finger.bounds.x = 10000;
Global.finger.bounds.y = 10000;
}
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
}
public void leaveScreen(){
if (switchButton2.isPressed){
game.setScreen(TinyBattles.inGameScreen);
}
}
}
There is a leaveScreen() method at the bottom of the each class

You should move all your code in each screen from show() to the constructor. show() is called every time the screen becomes the active screen, so you don't want to do initialization there.
By the way, you should never keep static references to anything that implements Disposable, such as SpriteBatch, or anything that keeps a reference to something that implements Disposable, such as Button or Stage. If you do, when the user backs out of your game activity and reopens it, there will be memory leaks and incorrect textures, etc.

Its been a while since I used libgdx, but it seems you are creating a new screen on each leaveScreen function.
See here for a better approach, where when you create the Game class you create the screens as well:
public class MyGame extends Game {
MainMenuScreen mainMenuScreen;
AnotherScreen anotherScreen;
#Override
public void create() {
mainMenuScreen = new MainMenuScreen(this);
anotherScreen = new AnotherScreen(this);
setScreen(mainMenuScreen);
}
}
Then, you change the screens like this:
public void leaveScreen(){
if (switchButton2.isPressed){
game.setScreen(game.anotherScreen);
}
}
As I said it's been a while, but give it a shot :)

Related

libgdx android game not rendering properly

My game works fine on desktop, but when I load it on an android device or the emulator I get a black screen. The game is working; I can hear the sounds and click the UI buttons. When testing on my android phone, I can turn the screen off and on again, and then the game renders fine. I would appreciate an explanation of what I'm doing wrong.
public class TestProject extends Game {
GameScreen gameScreen;
EndScreen endScreen;
MenuScreen menuScreen;
#Override
public void create () {
Gdx.app.log("TestProject", "created");
AssetLoader.load();
gameScreen = new GameScreen(this);
endScreen = new EndScreen(this);
menuScreen = new MenuScreen(this);
setScreen(menuScreen);
}
#Override
public void dispose() {
super.dispose();
AssetLoader.dispose();
}
}
public class MenuScreen implements Screen{
private SpriteBatch spriteBatch;
final static float GAME_WIDTH = 200;
final static float GAME_HEIGHT = 100;
public static final float UNIT_SCALE = 1/8f;
static float aspectRatio;
private OrthographicCamera cam;
Viewport viewport;
Stage stage;
TestProject project;
public MenuScreen(TestProject theProject){
project = new TestProject();
this.project = theProject;
aspectRatio = (float)Gdx.graphics.getHeight() / (float)Gdx.graphics.getWidth();
spriteBatch = new SpriteBatch();
stage = new Stage();
Gdx.input.setInputProcessor(stage);
cam = new OrthographicCamera();
viewport = new ExtendViewport(GAME_WIDTH * aspectRatio, GAME_HEIGHT, cam);
viewport.apply();
cam.setToOrtho(false, GAME_WIDTH, GAME_HEIGHT);
cam.position.set(GAME_WIDTH / 2, GAME_HEIGHT / 2, 0);
stage.addActor(AssetLoader.playButton);
}
#Override
public void render(float delta){
//Clear screen
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
spriteBatch.setProjectionMatrix(cam.combined);
AssetLoader.font.getData().setScale(.25f, -.25f);
AssetLoader.playButton.setPosition((Gdx.graphics.getWidth() / 2) - AssetLoader.playButton.getWidth() / 2,
(Gdx.graphics.getHeight() / 3) - AssetLoader.playButton.getHeight() / 2);
spriteBatch.begin();
spriteBatch.draw(AssetLoader.menuBG, 0, 0, 200, 100);
AssetLoader.font.draw(spriteBatch, "Shark Run", 55, 85);
spriteBatch.end();
stage.draw();
}
#Override
public void show() {
AssetLoader.playButton.addListener(new ChangeListener() {
#Override
public void changed(ChangeEvent event, Actor actor) {
project.setScreen(project.gameScreen);
}
});
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
}
}

libgdx: main menu doesn't show game class libgdx

I am a newbie in libgdx and I have a little problem with screens and main menu.
I have a mainmenu class and it work with click on actors. The code for click is:
pulsanteplay.addListener(
new InputListener() {
#Override
public boolean touchDown(InputEvent event, float x, `float y, int pointer, int button) {
System.out.println("click play");
game.setScreen(new GameClass());
return false;
}
});
and it works. If I call Gdx.app.exit(); it works. If I call the next class, works
public class SplashScreen implements Screen {
private SpriteBatch batch;
private Texture ttrSplash;
private Timer timer;
private MainMenu mainMenuScreen;
public SplashScreen() {
super();
batch = new SpriteBatch();
ttrSplash = new Texture("quadrato.png");
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(ttrSplash, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
batch.end();
}
#Override
public void hide() { }
#Override
public void pause() { }
#Override
public void resume() { }
#Override
public void show() { }
#Override
public void resize(int width, int height) { }
#Override
public void dispose() {
ttrSplash.dispose();
batch.dispose();
}
When I call a class that extends game and have a render method don't work. The screen don't change but the events of the game class are really generated.
Someone could explain me why this? How do I fix this bad behavior?
Thanks for your attention
Have that class that extends Game just implement Screen and put your code in it's corresponding methods. A screen offers everything a Game does so you should have no trouble converting. your onCreate code can be put in the show method or the constructor of your new Screen class. Now just call setScreen() to show this screen.

LIBGDX Camera doesn't move

My game sets this screen and I see the actor that I create.
However can anyone tell me why the camera doesn't seem to be moving? I would expect the actor to move to the right as I pressed the Left key.
The Gdx.input.isKeyPressed(Input.Keys.LEFT) does resolve to true and the translate function does get called.
public class MainScreen implements Screen {
private Stage mainStage;
private Camera orthCamera;
#Override
public void show() {
orthCamera = new OrthographicCamera();
mainStage = new Stage(new ScreenViewport());
mainStage.getViewport().setCamera(orthCamera);
MyGameActorObject s = new MyGameActorObject();
s.setPosition(100, 100);
mainStage.addActor(s);
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0,0,0,1); //sets clear
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
processKeyboardInput();
mainStage.act(delta);
mainStage.draw();
}
private void processKeyboardInput()
{
if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) {
orthCamera.translate(-30, 0, 0);
orthCamera.update();
}
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
mainStage.dispose();
}
}
I am trying to acheieve being able to pan around the 2d game world using keyboard input.
This is the contents of the custom Actor object:
public class MyGameActorObject extends Actor
{
#Override
public void act(float delta) {
super.act(delta);
}
#Override
public void draw(Batch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
ShapeRenderer r = new ShapeRenderer();
r.begin(ShapeRenderer.ShapeType.Filled);
r.setColor(Color.RED);
r.circle(this.getX() - 50.0f, this.getY() - 50.0f, 100.0f);
r.end();
}
}
I believe I have to add something like
r.setProjectionMatrix(batch.getProjectionMatrix());
in my custom actor object. So the draw function on my object would now be.
#Override
public void draw(Batch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
ShapeRenderer r = new ShapeRenderer();
r.setProjectionMatrix(batch.getProjectionMatrix());
r.begin(ShapeRenderer.ShapeType.Filled);
r.setColor(Color.RED);
r.circle(this.getX() - 50.0f, this.getY() - 50.0f, 100.0f);
r.end();
}
I think your problem is that you haven't set the InputProcessor.
Gdx.input.setInputProcessor(...) is the method you're looking for. Put it in your show() method and pass it an InputProcessor reference. InputProcessor is an interface that goes through all the different types of click-based input and allows you to determine what happens in them. So for instance:
#Override
public boolean keyDown(int keycode)
{
switch(keycode)
{
case Keys.D:
screen.universe.entity_handler.player.moving_right = true;
break;
case Keys.A:
screen.universe.entity_handler.player.moving_left = true;
break;
case Keys.SPACE:
screen.universe.entity_handler.player.jumping = true;
break;
...
}
...
}
The above code is part of an InputProcessor-implementing class for a game I'm making. When the input in-question is pressed (keyDown in this case), the game looks at your input button (the keycode) and sends it through the switch statement.
Keep in mind that you must return true for all the input events that you want to use. That's what the boolean return value for this method is.

launchMode="singleTask" on libgdx isn't working and game restarts on phone lock

I have a project on libgdx and I'm using a splash screen. The problem is, every time I block my phone on main menu and unlock it again, game shows splash screen again and I'd like it not to "restart" the game but stay where it is
EDIT: to avoid publishing all unnecessary code, I'll explain how I made it:
simple class extending game calls setScreen to splash screen, then after 3 seconds splash screen calls main menu, and I'd like the splash screen not to appear again unless the game is DESTROYED and opened again
code:
public MainMenuScreen(final TowerConquest gam) {
game = gam;
}
#Override
public void show() {
stage = new Stage(new FillViewport(800, 480));
Gdx.input.setInputProcessor(stage);
//((OrthographicCamera)stage.getCamera()).setToOrtho(false, 800, 480);
atlas = new TextureAtlas("skins/userInterface.pack");
skin = new Skin(atlas);
table = new Table(skin);
table.setBounds(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
white = new BitmapFont(Gdx.files.internal("font/white.fnt"), false);
black = new BitmapFont(Gdx.files.internal("font/black.fnt"), false);
TextButtonStyle textButtonStyle = new TextButtonStyle();
textButtonStyle.up = skin.getDrawable("normalbutton");
textButtonStyle.down = skin.getDrawable("pressedbutton");
textButtonStyle.disabled = skin.getDrawable("dissabledbutton");
textButtonStyle.pressedOffsetX = 1;
textButtonStyle.pressedOffsetY = -1;
textButtonStyle.font = black;
buttonPlay = new TextButton("PLAY", textButtonStyle);
buttonPlay.pad(20);
buttonPlay.addListener(new ClickListener(){
#Override
public void clicked(InputEvent event, float x, float y) {
game.setScreen(new testGame(game));
//Gdx.input.vibrate(150);
dispose();
}
});
buttonExit = new TextButton("EXIT", textButtonStyle);
buttonExit.pad(20);
buttonExit.addListener(new ClickListener(){
#Override
public void clicked(InputEvent event, float x, float y) {
dispose();
Gdx.app.exit();
}
});
LabelStyle headingStyle = new LabelStyle(white, Color.WHITE);
heading = new Label("Tower Conquest", headingStyle);
table.add(heading);
table.getCell(heading).padBottom(50);
table.row();
table.add(buttonPlay);
table.getCell(buttonPlay).spaceBottom(15);
table.row();
table.add(buttonExit);
table.debug();
table.setOrigin(table.getWidth()/2, table.getHeight()/2);
table.setFillParent(true);
stage.addActor(table);
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0.2f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act(delta);
stage.draw();
}
#Override
public void resize(int width, int height) {
my resizes...
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
all disposes..
}
I found the answer, add this on manifest file
android:configChanges="keyboard|keyboardHidden|screenSize|orientation">
it is because when the screen gets locked it changes orientation to portrait so it restarts the app, with that option on, it won't restart the application

Libgdx time lag and delta value issue ( used with Spine to run Skeleton animation)

I am using the Libgdx framework along with Spine to do Skeleton animation using Atlas and exported Json file. In the file there are many animations. I am able to load animations from the json file. But there are 2 issues :
Lag when animation starts : there is a lag of 3-4 seconds before the animation starts. I see a black screen and then the animation works.
Delta - i have some issues with the delta time. Only some animations are running from the default delta value, however if i change ( increment or decrease the delta value), different animations give different results.
Cant understand what to do ? I have searched thoroughly in the internet but haven't found the solution.
I am posting my code below:
This is my Main Class
public class AndroidLauncher extends AndroidApplication
{
SpriteBatch batch;
Texture img;
ShapeRenderer renderer;
TextureAtlas atlas;
Skeleton skeleton;
Animation animation;
float time;
Bone root;
float x,y;
View spine_view;
private Screen curScreen; // the current screen
#Override
protected void onCreate (Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
//initialize(new Main(20), config);
spine_view=initializeForView(new ApplicationListener()
{
#Override
public void resume()
{
curScreen.resume();
}
#Override
public void resize(int width, int height)
{
}
#Override
public void render()
{
curScreen.render((Gdx.graphics.getDeltaTime()/(1.5f))); //call the rendermethod with the delta time as parameter
}
#Override
public void pause()
{
curScreen.pause();
}
#Override
public void dispose()
{
curScreen.dispose();
}
#Override
public void create()
{
Gdx.graphics.getWidth();
Gdx.graphics.getHeight();
Firstscreen temp = new Firstscreen();//just an example of the first screen to load up
setScreen(temp);
}
}, config);
LinearLayout l1 = (LinearLayout) findViewById(R.id.container);
l1.addView(spine_view);
}
public void setScreen(Screen s) {
if (curScreen != null) {
curScreen.hide();
curScreen.dispose();
}
curScreen = s;
curScreen.show();
}
}
...............................................
And this is the screen Iam rendering
public class Firstscreen implements Screen
{
SpriteBatch batch;
Texture img;
ShapeRenderer renderer;
TextureAtlas atlas;
Skeleton skeleton;
Animation animation;
float time;
Bone root;
float x,y;
int count =0;
#Override
public void render(float delta)
{
// track
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
time += delta;
animation.apply(skeleton,delta,time, false, null);
SkeletonRenderer render = new SkeletonRenderer();
batch.begin();
render.draw(batch, skeleton);
skeleton.updateWorldTransform();
batch.end();
}
#Override
public void resize(int width, int height)
{
}
#Override
public void show()
{
batch = new SpriteBatch();
renderer = new ShapeRenderer();
atlas = new TextureAtlas(Gdx.files.internal("abc.atlas"));
SkeletonJson json = new SkeletonJson(atlas);
// set the scale of skeleton
json.setScale(0.3f);
SkeletonData skeletonData = json.readSkeletonData(Gdx.files.internal("skeleton.json"));
skeleton = new Skeleton(skeletonData);
skeleton.setToSetupPose();
skeleton.setSkin("Carla");
// set the position of the skeleton to render( here middle)
skeleton.setPosition((Gdx.graphics.getWidth()/2)-(x/2),( Gdx.graphics.getHeight()/2)-(y/2));
//animation = skeletonData.findAnimation("KID-LEVEL 2 - Couch potato");
animation = skeletonData.findAnimation("LEVEL 91- Around a world");
//animation = skeletonData.findAnimation("KID-LEVEL 7 - Super Hero");
}
#Override
public void hide()
{
}
#Override
public void pause()
{
}
#Override
public void resume()
{
}
#Override
public void dispose()
{
batch.dispose();
}
}
That's happens beacuse you are managing a timeline manually.
Use AnimationState instead:
Skeleton skeleton = new Skeleton(skeletonData);
// sctruct for mix animations
AnimationStateData stateData = new AnimationStateData(skeletonData);
// and state
AnimationState state = new AnimationState(stateData);
In some update method (or render, if you prefer update while rendering) call something like this:
state.update(delta);
And in the actual render method:
// apply the state to skeleton
state.apply(skeleton);
// update transformations
skeleton.updateWorldTransform();
// draw then
render.draw(batch, skeleton);
So, AnimationState isn't designed not for managing the delta only, you can play&mix animations using it:
state.setAnimation(0, "LEVEL 91- Around a world", isLoop);
To change animation speed use setTimeScale:
state.setTimeScale(0.5f); // set any time scale you want
Also, you may have some perfomance issues because you calling new SkeletonRenderer() in render method. To fix that, move this code to constructor.

Categories

Resources