I am creating my first game in LibGDX and for my splash screen, I am making use of Universal tween engine. I am using Aurelien Ribon
's demo except for my own images. The problem occurs when the splash screen ends, it Gives a call to Launcher
and from there on, it call the various classes extending the Test
class. I found no clean way of giving the control to my LevelSelector
class which implements screen and uses stage for rendering. Whenever the control goes to my class, it calls its show()
and without entering the render(), it calls hide()
. This continues till application is stopped. All the while the App
class (i.e. the main class) render() continues to be called continuosly. i have figured out a work around for this but it causes memory problems and is making the game slow. can anyone please tell me how to stop the rendering of App
& transfer control to my class?
My workaround works as follows :
- When click on Play (extends
test
), in its initialize static flag of App : inPlay is set.
- in App render(), if isPlay is set, setScreen as LevelSelector.
- in LevelSelector, if click on any level, set static flag of App : inLevel.
- in App render(), if inLevel is set, setscreen to that level.
this works, but LevelSelector render, App render & level render are all being called even when after screen is set to a level which causes delays and memory problems in my app,
Is there a solution to this problem without using the work around?
My Code :
//APP class
import aurelienribon.tweenengine.BaseTween;
import aurelienribon.tweenengine.Tween;
import aurelienribon.tweenengine.TweenCallback;
import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
/**
* @author Aurelien Ribon | http://www.aurelienribon.com/
*/
public class App extends Game {
private SplashScreen splashScreen;
private Launcher launcherScreen;
private boolean isLoaded = false;
static boolean inPlay = false;
static boolean levelStarted = false;
static int levelIndex;
LevelSelector ls;
Screen screen;
Level level;
@Override
public void create() {
System.out.println("********App create********");
Tween.setWaypointsLimit(10);
Tween.setCombinedAttributesLimit(3);
Tween.registerAccessor(Sprite.class, new SpriteAccessor());
Assets.inst().load("data/splash/pack", TextureAtlas.class);
Assets.inst().load("data/launcher/pack", TextureAtlas.class);
Assets.inst().load("data/test/pack", TextureAtlas.class);
Assets.inst().load("data/arial-16.fnt", BitmapFont.class);
Assets.inst().load("data/arial-18.fnt", BitmapFont.class);
Assets.inst().load("data/arial-20.fnt", BitmapFont.class);
Assets.inst().load("data/arial-24.fnt", BitmapFont.class);
}
@Override
public void dispose() {
Assets.inst().dispose();
if (splashScreen != null) splashScreen.dispose();
if (launcherScreen != null) launcherScreen.dispose();
if(screen != null) screen.dispose();
}
@Override
public void render() {
if (isLoaded) {
screen = null;
if (splashScreen != null) splashScreen.render();
if(inPlay && levelStarted==false){
splashScreen = null;
launcherScreen = null;
Gdx.graphics.setContinuousRendering(false);
Gdx.input.setInputProcessor(pspt.stage);
this.setScreen(ls);
}
else if(inPlay && levelStarted)
{
level.setLevelIndex(levelIndex);
screen = level.getLevelScreen();
if(screen != null)
{
splashScreen = null;
launcherScreen = null;
Gdx.graphics.setContinuousRendering(false);
this.setScreen(screen);
}
}
if (launcherScreen != null) launcherScreen.render();
} else {
if (Assets.inst().getProgress() < 1) {
Assets.inst().update(); //update returns true when asset manager finishes loading all assets
} else {
launch();
isLoaded = true;
inPlay = false;
}
}
}
@Override public void resize(int width, int height) {}
@Override public void pause() {}
@Override public void resume() {}
private void launch() {
System.out.println("********App Launch********");
ls = new LevelSelector(this);
screen = null;
level = new Level();
splashScreen = new SplashScreen(new TweenCallback() {
@Override public void onEvent(int type, BaseTween source) {
Test[] tests = new Test[] {
new Info(),
new Help(),
new PlayScreen()
};
splashScreen.dispose();
splashScreen = null;
launcherScreen = new Launcher(tests);
}
});
}
}
//TEST class
public abstract class Test {
private final TweenManager tweenManager = new TweenManager();
private final TextureAtlas atlas;
private final Sprite background;
private final Sprite veil;
private final Sprite infoBack;
private final List<Sprite> dots = new ArrayList<Sprite>(50);
private boolean[] useDots;
private Callback callback;
protected final OrthographicCamera camera = new OrthographicCamera();
protected final SpriteBatch batch = new SpriteBatch();
protected final Random rand = new Random();
protected final BitmapFont font;
protected final float wpw = 10;
protected final float wph = 10 * Gdx.graphics.getHeight() / Gdx.graphics.getWidth();
protected Sprite[] sprites;
public Test() {
System.out.println("********Test Constructor********");
atlas = Assets.inst().get("data/test/pack", TextureAtlas.class);
background = atlas.createSprite("background");
veil = atlas.createSprite("white");
infoBack = atlas.createSprite("white");
int w = Gdx.graphics.getWidth();
if (w > 600) font = Assets.inst().get("data/arial-24.fnt", BitmapFont.class);
else font = Assets.inst().get("data/arial-16.fnt", BitmapFont.class);
}
// -------------------------------------------------------------------------
// Abstract API
// -------------------------------------------------------------------------
public abstract String getTitle();
public abstract String getInfo();
public abstract String getImageName();
public abstract InputProcessor getInput();
protected abstract void initializeOverride();
protected abstract void disposeOverride();
protected abstract void renderOverride();
// -------------------------------------------------------------------------
// Public API
// -------------------------------------------------------------------------
public static interface Callback {
public void closeRequested(Test source);
}
public void setCallback(Callback callback) {
System.out.println("********Test setCallback********");
this.callback = callback;
}
public void initialize() {
System.out.println("********Test initialize********");
if (isCustomDisplay()) {
initializeOverride();
return;
}
camera.viewportWidth = wpw;
camera.viewportHeight = wph;
camera.update();
background.setSize(wpw, wpw * background.getHeight() / background.getWidth());
background.setPosition(-wpw/2, -background.getHeight()/2);
veil.setSize(wpw, wph);
veil.setPosition(-wpw/2, -wph/2);
infoBack.setColor(0, 0, 0, 0.3f);
infoBack.setPosition(0, 0);
initializeOverride();
Tween.set(veil, SpriteAccessor.OPACITY).target(1).start(tweenManager);
Tween.to(veil, SpriteAccessor.OPACITY, 0.5f).target(0).start(tweenManager);
}
public void dispose() {
System.out.println("###Test dispose###");
tweenManager.killAll();
dots.clear();
sprites = null;
useDots = null;
disposeOverride();
}
public void render() {
System.out.println("********Test render********");
if(App.inPlay == false)
{
if (isCustomDisplay()) {
System.out.println("CustomDisplay : True");
renderOverride();
return;
}
// update
tweenManager.update(Gdx.graphics.getDeltaTime());
for (int i=0; i<dots.size(); i++) {
if (dots.get(i).getScaleX() < 0.1f) {
dots.remove(i);
}
}
// render
GLCommon gl = Gdx.gl;
gl.glClearColor(1, 1, 1, 1);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
int w = Gdx.graphics.getWidth();
int h = Gdx.graphics.getHeight();
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.disableBlending();
background.draw(batch);
batch.enableBlending();
for (int i=0; i<dots.size(); i++) dots.get(i).draw(batch);
for (int i=0; i<sprites.length; i++) sprites[i].draw(batch);
batch.end();
System.out.println("********Test call renderOverride********");
renderOverride();
if (getInfo() != null) {
int padding = 15;
BitmapFont.TextBounds bs = font.getWrappedBounds(getInfo(), w - padding*2);
infoBack.setSize(w, bs.height + padding*2);
font.setColor(Color.WHITE);
batch.getProjectionMatrix().setToOrtho2D(0, 0, w, h);
batch.begin();
infoBack.draw(batch);
font.drawWrapped(batch, getInfo(), padding, bs.height + padding, w - padding*2);
batch.end();
}
if (veil.getColor().a > 0.1f) {
batch.setProjectionMatrix(camera.combined);
batch.begin();
veil.draw(batch);
batch.end();
}
}
}
// -------------------------------------------------------------------------
// Helpers
// -------------------------------------------------------------------------
protected boolean isCustomDisplay() {
return false;
}
protected void forceClose() {
System.out.println("#######Test forceClose########");
if (callback != null) callback.closeRequested(this);
}
protected void createSprites(int cnt) {
System.out.println("********Test create Sprites : "+cnt+"********");
sprites = new Sprite[cnt];
useDots = new boolean[cnt];
for (int i=0; i<cnt; i++) {
int idx = rand.nextInt(400)/100 + 1;
sprites[i] = atlas.createSprite("sprite" + idx);
sprites[i].setSize(1f, 1f * sprites[i].getHeight() / sprites[i].getWidth());
sprites[i].setOrigin(sprites[i].getWidth()/2, sprites[i].getHeight()/2);
useDots[i] = false;
}
}
protected void center(Sprite sp, float x, float y) {
sp.setPosition(x - sp.getWidth()/2, y - sp.getHeight()/2);
}
protected void enableDots(int spriteId) {
useDots[spriteId] = true;
Tween.call(dotCallback)
.delay(0.02f)
.repeat(-1, 0.02f)
.setUserData(spriteId)
.start(tweenManager);
}
protected void disableDots(int spriteId) {
useDots[spriteId] = false;
}
private final Vector2 v2 = new Vector2();
private final Vector3 v3 = new Vector3();
protected Vector2 touch2world(int x, int y) {
v3.set(x, y, 0);
camera.unproject(v3);
return v2.set(v3.x, v3.y);
}
// -------------------------------------------------------------------------
// Helpers
// -------------------------------------------------------------------------
private final TweenCallback dotCallback = new TweenCallback() {
@Override
public void onEvent(int type, BaseTween source) {
System.out.println("********Test dotCallback : onEvent********");
int spriteId = (Integer) source.getUserData();
if (useDots[spriteId] == false) source.kill();
Sprite sp = sprites[spriteId];
Sprite dot = atlas.createSprite("dot");
dot.setSize(0.2f, 0.2f);
dot.setOrigin(0.1f, 0.1f);
dot.setPosition(sp.getX(), sp.getY());
dot.translate(sp.getWidth()/2, sp.getHeight()/2);
dot.translate(-dot.getWidth()/2, -dot.getHeight()/2);
dots.add(dot);
Tween.to(dot, SpriteAccessor.SCALE_XY, 1.0f).target(0, 0).start(tweenManager);
}
};
// -------------------------------------------------------------------------
// Dummy
// -------------------------------------------------------------------------
public static final Test dummy = new Test() {
@Override public String getTitle() {
System.out.println("********Test dummy getTitle********");
return "Dummy test";}
@Override public String getInfo() {
System.out.println("********Test dummy getInfo********");
return null;}
@Override public String getImageName() {
System.out.println("********Test dummy getImageName********");
return null;}
@Override public InputProcessor getInput() {
System.out.println("********Test dummy getInput********");
return null;}
@Override protected void initializeOverride() {System.out.println("********Test dummy initOverride********");}
@Override protected void disposeOverride() {System.out.println("********Test dummy disposeOverride********");}
@Override protected void renderOverride() {System.out.println("********Test dummy renderOverride********");}
};
}
//LevelSelector
public class LevelSelector implements Screen {
private Skin skin;
Stage stage;
private Table container;
Game game;
// Level_1_1 level1;
PagedScrollPane scroll ;
int rank=0,leveldone;
Table starTable;
Utils Utils;
public LevelSelector(Game game){
// System.out.println("########In pagedScrollPaneTest construct (App)##########");
Gdx.input.setInputProcessor(stage);
this.game = game;
Utils = new Utils();
stage = new Stage(0, 0, false);
skin = new Skin(Gdx.files.internal("data/uiskin.json"));
skin.add("top", skin.newDrawable("default-round", Color.RED), Drawable.class);
skin.add("star-filled", skin.newDrawable("white", Color.YELLOW), Drawable.class);
skin.add("star-unfilled", skin.newDrawable("white", Color.GRAY), Drawable.class);
Gdx.input.setInputProcessor(stage);
container = new Table();
stage.addActor(container);
container.setFillParent(true);
scroll= new PagedScrollPane();
scroll.setFlingTime(0.1f);
scroll.setPageSpacing(25);
int c = 1;
for (int l =0; l < 5; l++) {
Table levels = new Table().pad(50);
levels.defaults().pad(20, 40, 20, 40);
for (int y = 0; y <3; y++) {
levels.row();
for (int x = 0; x < 1; x++) {
levels.add(getLevelButton(c++)).expand().fill();
}
}
scroll.addPage(levels);
}
container.add(scroll).expand().fill();
}
public void resize (int width, int height) {
stage.setViewport(width, height, true);
}
public void dispose () {
System.out.println("In selector dispose ####");
Gdx.input.setInputProcessor(null);
stage.dispose();
skin.dispose();
}
public boolean needsGL20 () {
return false;
}
/**
* Creates a button to represent the level
*
* @param level
* @return The button to use for the level
*/
public Button getLevelButton(int level) {
Button button = new Button(skin);
ButtonStyle style = button.getStyle();
style.up = style.down = null;
// Create the label to show the level number
Label label = new Label(Integer.toString(level), skin);
label.setFontScale(2f);
label.setAlignment(Align.center);
// Stack the image and the label at the top of our button
button.stack(new Image(skin.getDrawable("top")), label).expand().fill();
// Randomize the number of stars earned for demonstration purposes
int stars = rank;
starTable = new Table();
int j=level;
starTable.defaults().pad(5);
if (Utils.prefs.getInteger("rank"+j) >= 0) {
for (int star = 0; star < 3; star++) {
if (Utils.prefs.getInteger("rank"+j) > star && level== Utils.prefs.getInteger("level"+j)) {
System.out.println("\n\nHAd saved option Level:: "+Utils.prefs.getInteger("level"+j));
System.out.println("HAd saved option Rank :: "+Utils.prefs.getInteger("rank"+j));
starTable.add(new Image(skin.getDrawable("star-filled"))).width(20).height(20);
}
else {
starTable.add(new Image(skin.getDrawable("star-unfilled"))).width(20).height(20);
}
}
}
button.row();
button.add(starTable).height(30);
button.setName("level" + Integer.toString(level));
button.addListener(levelClickListener);
return button;
}
/**
* Handle the click - in real life, we'd go to the level
*/
public ClickListener levelClickListener = new ClickListener() {
@Override
public void clicked (InputEvent event, float x, float y) {
System.out.println("Click: " + event.getListenerActor().getName());
String levelSelected = event.getListenerActor().getName();
if(levelSelected.equalsIgnoreCase("level1"))
{
App.levelStarted = true;
game.dispose();
App.whichLevel = levelSelected;
App.levelIndex = 1;
}
if(levelSelected.equalsIgnoreCase("level2"))
{
App.levelStarted = true;
game.dispose();
App.whichLevel = levelSelected;
App.levelIndex = 2;
}
}
};
@Override
public void show() {
System.out.println("########In pagedScrollPaneTest show##########");
render(Gdx.graphics.getDeltaTime());
}
@Override
public void hide() {
System.out.println("########In pagedScrollPaneTest hide##########");
}
@Override
public void render(float delta) {
GLCommon gl = Gdx.gl;
gl.glClearColor(1, 1, 1, 1);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
Gdx.input.setInputProcessor(stage);
// System.out.println("########In pagedScrollPaneTest renderer(float)##########");
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
stage.act();
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
Table.drawDebug(stage);
}
@Override
public void pause() {}
@Override
public void resume() {}
}
//PlayScreen
public class PlayScreen extends Test {
private final TweenManager tweenManager = new TweenManager();
@Override
public String getTitle() {
return "Play";
}
@Override
public String getInfo() {
return "Select which level you want to play.";
}
@Override
public String getImageName() {
return "tile-path";
}
@Override
public InputProcessor getInput() {
return null;
}
@Override
protected void initializeOverride() {
System.out.println("#####Play Screen#####");
App.inPlay = true;
}
@Override
protected void disposeOverride() {
tweenManager.killAll();
super.dispose();
}
@Override
protected void renderOverride() {
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
tweenManager.update(Gdx.graphics.getDeltaTime());
}
}