【问题标题】:libGDX game stuck on screen show() - hide() looplibGDX 游戏卡在屏幕上 show() - hide() 循环
【发布时间】:2014-03-24 12:09:16
【问题描述】:

我正在 LibGDX 中创建我的第一个游戏,对于我的启动画面,我正在使用通用补间引擎。我正在使用Aurelien Ribondemo,除了我自己的图像。当初始屏幕结束时会出现问题,它会调用Launcher,然后从那里调用扩展Test 类的各种类。我没有找到将控制权交给我的LevelSelector 类的干净方法,该类实现了屏幕并使用舞台进行渲染。每当控件进入我的班级时,它就会调用它的show(),并且在不输入render() 的情况下,它会调用hide()。这一直持续到应用程序停止。一直以来,App 类(即主类) render() 继续被连续调用。我已经想出了一个解决方法,但它会导致内存问题并使游戏变慢。谁能告诉我如何停止App 的渲染并将控制权转移到我的班级?

我的解决方法如下:

  1. 当点击播放(扩展test)时,在其初始化应用的静态标志:inPlay 被设置。
  2. 在App render()中,如果设置了isPlay,则将Screen设置为LevelSelector。
  3. 在LevelSelector中,如果点击任何一个关卡,设置App的静态标志:inLevel。
  4. 在 App render() 中,如果设置了 inLevel,则将屏幕设置为该级别。

这可行,但 LevelSelector 渲染、应用渲染和关卡渲染都被调用,即使在屏幕设置为导致我的应用出现延迟和内存问题的级别后,

在不使用变通方法的情况下是否有解决此问题的方法?

我的代码:

//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());
}
}

【问题讨论】:

  • 我的水晶球说....什么都没有,因为没有任何代码即使它在这里也无济于事...
  • 您必须向我们展示您的 show() 方法的代码,该方法进入循环。如果没有此代码,我们无法告诉您出了什么问题
  • 添加所有类的代码

标签: libgdx tween


【解决方案1】:

我在我的代码中发现了问题。覆盖类扩展 Game 的 render() 方法将导致在每个屏幕的渲染之前调用该渲染。这也会导致大量内存问题,因为同时调用了 3 个渲染方法: 1>游戏类 2>测试类 3>屏幕扩展Test类。

我通过创建一个扩展 Screen 的新 MainScreen 类解决了这个问题,并在其中执行了在扩展 Game 的类中完成的所有任务。

现在,在任何给定时间,只有 1 个渲染方法被调用,游戏运行速度更快。 这也减少了我的代码,因为我现在不再需要在游戏的渲染中设置屏幕,但可以遵循正常流程。

游戏类

import com.badlogic.gdx.Game;

public class PacketJourney extends Game {

    @Override
    public void create() 
    {
        setScreen(new MainScreen(this));
    }   
}

MainScreen 类

import aurelienribon.tweenengine.BaseTween;
import aurelienribon.tweenengine.Tween;
import aurelienribon.tweenengine.TweenCallback;

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;

public class MainScreen implements Screen { private SplashScreen splashScreen; private ScreenLauncher launcherScreen; Utils utils;

private boolean isLoaded = false; public MainScreen() { utils = new Utils(null); } public MainScreen(PacketJourney game) { utils = new Utils(game); } @Override public void render(float delta) { if (isLoaded) { if (splashScreen != null) splashScreen.render(); 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; } } } @Override public void resize(int width, int height) { } @Override public void show() { 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/launcher/screenLauncher", 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 hide() { } @Override public void pause() { } @Override public void resume() { } private void launch() { splashScreen = new SplashScreen(new TweenCallback() { @Override public void onEvent(int type, BaseTween source) { String str= ""; switch(type) { case TweenCallback.BEGIN : str = "BEGIN"; break; case TweenCallback.COMPLETE : str = "COMPLETE"; break; case TweenCallback.END : str = "END"; break; case TweenCallback.ANY : str = "ANY"; break; } splashScreen.dispose(); splashScreen = null; if(utils.game != null) launcherScreen = new ScreenLauncher(utils.screens,utils.spriteNames,utils); } }); } @Override public void dispose() { Assets.inst().dispose(); if (splashScreen != null) splashScreen.dispose(); if (launcherScreen != null) launcherScreen.dispose(); } }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多