I am trying to implement the AssetsManager to my app. It should only load all the font files and a background music. All this works perfectly. My problem is that sometimes on android the AssetsManger files are away/wrong/buggy when I leave the App and rejoin it later on. I know this is because the life time of the assets is different on Android as the static Variable, thats why this issues occure. My question is how to fix this? The AssetsManager HAS to be static, otherwise I am not able to get the assets from an other class.
My code so far (how to improve?):
public class Colors extends ApplicationAdapter {
//MAIN
private GameStateManager gsm;
private SpriteBatch sb;
private boolean tomenu = false;
//STATIC
public static int WIDTH = 480;
public static int HEIGHT = 800;
//Generell
private FreeTypeFontGenerator fontGenerator;
private FreeTypeFontGenerator.FreeTypeFontParameter fontParameter;
private BitmapFont font;
private Texture loaderb;
private Texture loader;
private Texture timelablogo;
//Asset Manager
public static AssetManager manager = new AssetManager();
#Override
public void create () {
Gdx.gl.glClearColor(71/255f, 92/255f, 141/255f, 1);
WIDTH = Gdx.graphics.getWidth();
HEIGHT = Gdx.graphics.getHeight();
Gdx.input.setCatchBackKey(true); //Backkey is catched and does not close the App
gsm = new GameStateManager();
sb = new SpriteBatch();
font = new BitmapFont();
loaderb = new Texture("Buttons/loadingbackground.png");
loader = new Texture("Buttons/loader.png");
timelablogo = new Texture("timelab.png");
//ASSETMANAGER (alle assets[texturen,schirftne,sounds,..])
manager.load("Sound/menubackground.ogg", Music.class);
//FreetypeFontGenerator zum AssetManager hinzufügen
FileHandleResolver resolver = new InternalFileHandleResolver();
manager.setLoader(FreeTypeFontGenerator.class, new FreeTypeFontGeneratorLoader(resolver));
manager.setLoader(BitmapFont.class, ".ttf", new FreetypeFontLoader(resolver));
//Create Fonts and give them to the AssetManager
FreetypeFontLoader.FreeTypeFontLoaderParameter params1 = new FreetypeFontLoader.FreeTypeFontLoaderParameter();
params1.fontFileName = "Fonts/kenvector_future1.ttf";
params1.fontParameters.size = WIDTH/7;
params1.fontParameters.color = Color.DARK_GRAY;
manager.load("Fonts/kenvector_future1.ttf", BitmapFont.class, params1);
FreetypeFontLoader.FreeTypeFontLoaderParameter params2 = new FreetypeFontLoader.FreeTypeFontLoaderParameter();
params2.fontFileName = "Fonts/kenvector_future2.ttf";
params2.fontParameters.size = WIDTH/25;
params2.fontParameters.color = Color.DARK_GRAY;
manager.load("Fonts/kenvector_future2.ttf", BitmapFont.class, params2);
FreetypeFontLoader.FreeTypeFontLoaderParameter params3 = new FreetypeFontLoader.FreeTypeFontLoaderParameter();
params3.fontFileName = "Fonts/kenvector_future3.ttf";
params3.fontParameters.size = WIDTH/15;
params3.fontParameters.color = Color.DARK_GRAY;
manager.load("Fonts/kenvector_future3.ttf", BitmapFont.class, params3);
FreetypeFontLoader.FreeTypeFontLoaderParameter params4 = new FreetypeFontLoader.FreeTypeFontLoaderParameter();
params4.fontFileName = "Fonts/kenvector_future4.ttf";
params4.fontParameters.size = WIDTH/12;
params4.fontParameters.color = Color.DARK_GRAY;
manager.load("Fonts/kenvector_future4.ttf", BitmapFont.class, params4);
FreetypeFontLoader.FreeTypeFontLoaderParameter params5 = new FreetypeFontLoader.FreeTypeFontLoaderParameter();
params5.fontFileName = "Fonts/kenvector_future5.ttf";
params5.fontParameters.size = WIDTH/18;
params5.fontParameters.color = Color.DARK_GRAY;
manager.load("Fonts/kenvector_future5.ttf", BitmapFont.class, params5);
FreetypeFontLoader.FreeTypeFontLoaderParameter params6 = new FreetypeFontLoader.FreeTypeFontLoaderParameter();
params6.fontFileName = "Fonts/kenvector_future6.ttf";
params6.fontParameters.size = WIDTH/15;
params6.fontParameters.color.set(99/255f, 99/255f, 99/255f, 1);
manager.load("Fonts/kenvector_future6.ttf", BitmapFont.class, params6);
}
#Override
public void render () {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
if(manager.update()) {
if(!tomenu) {
tomenu = true;
manager.get("Sound/menubackground.ogg",Music.class).setLooping(true);
manager.get("Sound/menubackground.ogg",Music.class).setVolume(0.7f);
manager.get("Sound/menubackground.ogg",Music.class).play();
//When everything is loaded a new State is pushed, which uses the font assets from this Assetsmanger
gsm.push(new MenuStateNew(gsm,0,0,false,1));
}
gsm.update(Gdx.graphics.getDeltaTime());
gsm.render(sb);
sb.begin();
font.draw(sb,WIDTH+"px*"+HEIGHT+"px closed BETA v11 "+String.valueOf((int)(1/Gdx.graphics.getDeltaTime()))+" FPS",5,20);
sb.end();
} else {
sb.begin();
font.draw(sb,WIDTH+"px*"+HEIGHT+"px closed BETA v11 "+String.valueOf((int)(1/Gdx.graphics.getDeltaTime()))+" FPS",5,20);
sb.draw(loaderb,0,0,WIDTH,WIDTH*0.25f);
sb.draw(loader,0,0,WIDTH*manager.getProgress(),WIDTH*0.25f);
sb.draw(timelablogo,WIDTH/2-WIDTH/6,HEIGHT/2-WIDTH/6,WIDTH/3,WIDTH/3);
sb.end();
}
}
#Override
public void pause() {
gsm.pause();
}
#Override
public void dispose () {
sb.dispose();
manager.dispose();
font.dispose();
}
}
EDIT 1:
I implemented the code as you sayed but know the whole game is more dark (no erros)
My code now looks like this (and causes this darker screen :/)
public class Colors extends ApplicationAdapter {
//MAIN
private GameStateManager gsm;
private SpriteBatch sb;
private boolean tomenu = false;
//STATIC
public static int WIDTH = 480;
public static int HEIGHT = 800;
//Generell
private BitmapFont font;
private Texture loaderb;
private Texture loader;
private Texture timelablogo;
//Asset Manager
private Assets assets;
#Override
public void create () {
Gdx.gl.glClearColor(71/255f, 92/255f, 141/255f, 1);
WIDTH = Gdx.graphics.getWidth();
HEIGHT = Gdx.graphics.getHeight();
//Assetmanager
assets = new Assets();
getAssets().load(); //starts loading assets
Gdx.input.setCatchBackKey(true); //Backkey is catched and does not close the App
gsm = new GameStateManager();
sb = new SpriteBatch();
font = new BitmapFont();
loaderb = new Texture("Buttons/loadingbackground.png");
loader = new Texture("Buttons/loader.png");
timelablogo = new Texture("timelab.png");
}
public static Assets getAssets() {
return ((Colors) Gdx.app.getApplicationListener()).assets;
}
#Override
public void render () {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
if(getAssets().manager.update()) {
if(!tomenu) {
tomenu = true;
getAssets().manager.get("Sound/menubackground.ogg",Music.class).setLooping(true);
getAssets().manager.get("Sound/menubackground.ogg",Music.class).setVolume(0.7f);
getAssets().manager.get("Sound/menubackground.ogg",Music.class).play();
gsm.push(new MenuStateNew(gsm,0,0,false,1));
}
gsm.update(Gdx.graphics.getDeltaTime());
gsm.render(sb);
sb.begin();
font.draw(sb,WIDTH+"px*"+HEIGHT+"px closed BETA v12 "+String.valueOf((int)(1/Gdx.graphics.getDeltaTime()))+" FPS",5,20);
sb.end();
} else {
sb.begin();
font.draw(sb,WIDTH+"px*"+HEIGHT+"px closed BETA v12 "+String.valueOf((int)(1/Gdx.graphics.getDeltaTime()))+" FPS",5,20);
sb.draw(loaderb,0,0,WIDTH,WIDTH*0.25f);
sb.draw(loader,0,0,WIDTH*getAssets().manager.getProgress(),WIDTH*0.25f);
sb.draw(timelablogo,WIDTH/2-WIDTH/6,HEIGHT/2-WIDTH/6,WIDTH/3,WIDTH/3);
sb.end();
}
}
#Override
public void pause() {
gsm.pause();
}
#Override
public void resume() { assets.manager.finishLoading(); }
#Override
public void dispose () {
sb.dispose();
assets.dispose();
font.dispose();
}
}
And the Assets Class:
public class Assets implements Disposable {
public AssetManager manager = new AssetManager();
public void load() {
loadMusics();
loadSounds();
loadFonts();
}
private void loadSounds() {
manager.load("Sound/menubackground.ogg", Music.class);
}
private void loadMusics() {
manager.load("Sound/menubackground.ogg", Music.class);
}
private void loadFonts() {
//FreetypeFontGenerator zum AssetManager hinzufügen
FileHandleResolver resolver = new InternalFileHandleResolver();
manager.setLoader(FreeTypeFontGenerator.class, new FreeTypeFontGeneratorLoader(resolver));
manager.setLoader(BitmapFont.class, ".ttf", new FreetypeFontLoader(resolver));
//Create Fonts and give them to the AssetManager
FreetypeFontLoader.FreeTypeFontLoaderParameter params1 = new FreetypeFontLoader.FreeTypeFontLoaderParameter();
params1.fontFileName = "Fonts/kenvector_future1.ttf";
params1.fontParameters.size = WIDTH/7;
params1.fontParameters.color = Color.DARK_GRAY;
manager.load("Fonts/kenvector_future1.ttf", BitmapFont.class, params1);
FreetypeFontLoader.FreeTypeFontLoaderParameter params2 = new FreetypeFontLoader.FreeTypeFontLoaderParameter();
params2.fontFileName = "Fonts/kenvector_future2.ttf";
params2.fontParameters.size = WIDTH/25;
params2.fontParameters.color = Color.DARK_GRAY;
manager.load("Fonts/kenvector_future2.ttf", BitmapFont.class, params2);
FreetypeFontLoader.FreeTypeFontLoaderParameter params3 = new FreetypeFontLoader.FreeTypeFontLoaderParameter();
params3.fontFileName = "Fonts/kenvector_future3.ttf";
params3.fontParameters.size = WIDTH/15;
params3.fontParameters.color = Color.DARK_GRAY;
manager.load("Fonts/kenvector_future3.ttf", BitmapFont.class, params3);
FreetypeFontLoader.FreeTypeFontLoaderParameter params4 = new FreetypeFontLoader.FreeTypeFontLoaderParameter();
params4.fontFileName = "Fonts/kenvector_future4.ttf";
params4.fontParameters.size = WIDTH/12;
params4.fontParameters.color = Color.DARK_GRAY;
manager.load("Fonts/kenvector_future4.ttf", BitmapFont.class, params4);
FreetypeFontLoader.FreeTypeFontLoaderParameter params5 = new FreetypeFontLoader.FreeTypeFontLoaderParameter();
params5.fontFileName = "Fonts/kenvector_future5.ttf";
params5.fontParameters.size = WIDTH/18;
params5.fontParameters.color = Color.DARK_GRAY;
manager.load("Fonts/kenvector_future5.ttf", BitmapFont.class, params5);
FreetypeFontLoader.FreeTypeFontLoaderParameter params6 = new FreetypeFontLoader.FreeTypeFontLoaderParameter();
params6.fontFileName = "Fonts/kenvector_future6.ttf";
params6.fontParameters.size = WIDTH/15;
params6.fontParameters.color.set(99/255f, 99/255f, 99/255f, 1);
manager.load("Fonts/kenvector_future6.ttf", BitmapFont.class, params6);
}
#Override
public void dispose() {
manager.dispose();
}
}
MenuStateNew Class (only an except):
public class MenuStateNew extends State implements GestureDetector.GestureListener {
//Generel
private int width = Colors.WIDTH;
private int height = Colors.HEIGHT;
private GestureDetector gsdt;
private float zeit;
private int mode;
//Buttons
private Texture btn_settings;
private Texture btn_settingsh;
private Sprite sp_settings;
private Rectangle ra_settings;
private Texture btn_easy;
private Texture btn_easyh;
private Texture btn_hard;
private Texture btn_hardh;
private Sprite sp_easy;
private Rectangle ra_easy;
private Texture btn_start;
private Texture btn_starth;
private Sprite sp_start;
private Rectangle ra_start;
private Texture btn_list;
private Rectangle ra_list;
//Fonts
private BitmapFont menufont = Colors.getAssets().manager.get("Fonts/kenvector_future6.ttf", BitmapFont.class);
//Background
private Array<Backgrounddot> backgrounddots;
//Sounds
private Sound s_click;
//Particle Effects
private ParticleEffect pe1;
private ParticleEffect pe2;
//Speicher
Preferences prefs;
public MenuStateNew(GameStateManager pgsm,int plastscore,int plastlevel,boolean highscore,int pmode) {
super(pgsm);
//Generell
gsdt = new GestureDetector(this);
Gdx.input.setInputProcessor(gsdt);
mode = pmode;//1: easy,0: hard
}
#Override
public void render(SpriteBatch sb) {
sb.begin();
//Particles
pe1.draw(sb);
pe2.draw(sb);
//BackgroundDots
for(Backgrounddot bgd : backgrounddots) {
sb.draw(bgd.getTxt_dot(),bgd.getDotposition().x,bgd.getDotposition().y,bgd.getDotwidth(),bgd.getDotwidth());
}
sb.draw(sp_settings,ra_settings.getX(),height-ra_settings.getY()-ra_settings.getHeight(),ra_settings.getWidth(),ra_settings.getHeight());
sb.draw(btn_list,ra_list.getX(),height-ra_list.getY()-ra_list.getHeight(),ra_list.getWidth(),ra_list.getHeight());
sb.draw(sp_easy,ra_easy.getX(),height-ra_easy.getY()-ra_easy.getHeight(),ra_easy.getWidth(),ra_easy.getHeight());
sb.draw(sp_start,ra_start.getX(),height-ra_start.getY()-ra_start.getHeight(),ra_start.getWidth(),ra_start.getHeight());
if(mode == 1) {
menufont.draw(sb,"Last: "+prefs.getInteger("lastscore2")+" ("+prefs.getInteger("lastlevel2")+")",width/6,height*0.63f);
menufont.draw(sb,"Best: "+prefs.getInteger("highscore2"),width/6,height*0.515f);
menufont.draw(sb,"Level "+prefs.getInteger("level2"),width/6,height*0.4f);
} else if(mode == 0) {
menufont.draw(sb,"Last: "+prefs.getInteger("lastscore")+" ("+prefs.getInteger("lastlevel")+")",width/6,height*0.63f);
menufont.draw(sb,"Best: "+prefs.getInteger("highscore"),width/6,height*0.515f);
menufont.draw(sb,"Level "+prefs.getInteger("level"),width/6,height*0.4f);
}
sb.end();
}
Did I somethign wrong?
I will expand on Abhishek's answer by providing a workaround for having to pass an Assets class around to all of your game objects.
This approach is most certainly not the 'best design', but it is convenient, and safe (to the best of my knowledge).
Follow Abhishek's steps in creating an Assets class, and from there you can add the following function in your GdxGame class (the base class)
public static Assets getAssets() {
return ((GdxGame) Gdx.app.getApplicationListener()).assets;
}
Now, whenever you need an texture or some asset, you can call GdxGame.getAssets().getTextureRegion(...). This way you can actually access the assets on a static basis (convenient) and still have the asset manager as an instance variable (safe).
PS. Am on a mobile device, so, apologies for any poor formatting.
You should make a class where you store your assets.
public class Assets implements Disposable {
public AssetManager manager = new AssetManager();
public void load() {
manager.load("data/mytexture.png", Texture.class);
manager.load("data/myfont.fnt", BitmapFont.class);
manager.load("data/mymusic.ogg", Music.class);
}
#Override
public void dispose() {
manager.dispose();
}
}
Keep reference of Your Assets object in Game(Main) class and pass it as reference where it needed.
public class Colors extends ApplicationAdapter {
Assets assets;
#Override
public void create() {
assets = new Assets();
assets.load(); //starts loading assets
assets.manager.finishLoading(); //Continues when done loading.
//it won't continue until all assets are finished loading.
}
#Override
public void dispose() {
assets.dispose();
}
}
EDIT
Get or initialize all your Private data member(resources) in constructor and then use in render method.
private BitmapFont menufont;
public MenuStateNew(GameStateManager pgsm,int plastscore,int plastlevel,boolean highscore,int pmode) {
super(pgsm);
//Generell
gsdt = new GestureDetector(this);
Gdx.input.setInputProcessor(gsdt);
mode = pmode;//1: easy,0: hard
menufont = Colors.getAssets().manager.get("Fonts/kenvector_future6.ttf", BitmapFont.class);
}
This is just one example for menufont, same like you need to initialize all required resources in MenuStateNew in his constructor.
Related
I made the game flappy bird on Android studio with the libgdx library and now i want to connect it to a mysql database. My point is to send the score and a name when the player dies. I've done a lot of searching so my last hope is here, thanks.
Here is my gameplay screen:
public class GameplayScreen extends ScreenAdapter {
public static final float PIPE_SPACING = 200f;
public static final int PIPE_SETS = 3;
protected OrthographicCamera camera;
protected FlappyGame game;
private Stage gameplayStage;
private Stage uiStage;
private Label scoreLabel;
private Label tapToRetry;
private Label best;
private Label tapToFlap;
private Image whitePixel;
private Image backgroundBuildings;
public int score;
private Bird bird;
private Array<PipePair> pipePairs;
private Ground ground;
private boolean justTouched;
private Color backgroundColor;
private State screenState = State.PREGAME;
private boolean allowRestart = false;
private enum State {PREGAME, PLAYING, DYING, DEAD}
;
public GameplayScreen(FlappyGame game) {
this.game = game;
camera = new OrthographicCamera(FlappyGame.WIDTH, FlappyGame.HEIGHT);
gameplayStage = new Stage(new StretchViewport(FlappyGame.WIDTH, FlappyGame.HEIGHT, camera));
uiStage = new Stage(new StretchViewport(FlappyGame.WIDTH, FlappyGame.HEIGHT));
bird = new Bird();
bird.setPosition(FlappyGame.WIDTH * .25f, FlappyGame.HEIGHT / 2, Align.center);
bird.addAction(Utils.getFloatyAction());
bird.setState(Bird.State.PREGAME);
whitePixel = new Image(Assets.whitePixel);
scoreLabel = new Label("0", new Label.LabelStyle(Assets.fontMedium, Color.WHITE));
scoreLabel.setPosition(FlappyGame.WIDTH / 2, FlappyGame.HEIGHT * .9f, Align.center);
uiStage.addActor(scoreLabel);
tapToRetry = new Label("Tap To Retry!", new Label.LabelStyle(Assets.fontMedium, Color.WHITE));
tapToRetry.setPosition(FlappyGame.WIDTH / 2, 0, Align.top);
uiStage.addActor(tapToRetry);
best = new Label("Best: ", new Label.LabelStyle(Assets.fontMedium, Color.WHITE));
best.setPosition(FlappyGame.WIDTH / 2, 0, Align.top);
uiStage.addActor(best);
tapToFlap = new Label("Tap To Flap!", new Label.LabelStyle(Assets.fontMedium, Color.WHITE));
tapToFlap.setPosition(FlappyGame.WIDTH / 2, FlappyGame.HEIGHT, Align.bottom);
uiStage.addActor(tapToFlap);
initBackgroundBuildings();
pipePairs = new Array<PipePair>();
ground = new Ground();
ground.setPosition(0, 0);
backgroundColor = Utils.getRandomBackgroundColor();
gameplayStage.addActor(ground);
gameplayStage.addActor(backgroundBuildings);
gameplayStage.addActor(bird);
initInputProcessor();
}
private void initBackgroundBuildings() {
backgroundBuildings = new Image(Assets.backgroundBuildings);
backgroundBuildings.setWidth(FlappyGame.WIDTH);
backgroundBuildings.setHeight(backgroundBuildings.getHeight()*2f);
backgroundBuildings.setY(Ground.HEIGHT);
}
#Override
public void show() {
tapToFlap.addAction(Actions.moveToAligned(FlappyGame.CENTER_X, FlappyGame.CENTER_Y + 100f, Align.center, .75f, Interpolation.sine));
Assets.playWooshSound();
}
#Override
public void render(float delta) {
Gdx.graphics.getGL20().glClearColor(backgroundColor.r, backgroundColor.g, backgroundColor.b, 1f);
Gdx.graphics.getGL20().glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
switch (screenState) {
case PREGAME:
updateAndDrawStages();
break;
case PLAYING:
renderPlaying();
break;
case DYING:
case DEAD:
renderDeadOrDying();
break;
}
}
private void renderDeadOrDying() {
if (bird.getState() == Bird.State.DEAD) {
screenState = State.DEAD;
}
updateAndDrawStages();
}
private void renderPlaying() {
if (justTouched) {
bird.jump();
justTouched = false;
}
updatePipePairs();
gameplayStage.act();
uiStage.act();
checkCollisions();
if (bird.getState() == Bird.State.DYING) {
stopTheWorld();
RunnableAction playWooshAction = Actions.run(new Runnable() {
#Override
public void run() {
Assets.playWooshSound();
}
});
SequenceAction actions = Actions.sequence(Actions.delay(1f), playWooshAction, Actions.moveToAligned(FlappyGame.CENTER_X, FlappyGame.CENTER_Y, Align.bottom,
.75f, Interpolation.sine), Actions.run(new Runnable() {
#Override
public void run() {
allowRestart = true;
}
}));
tapToRetry.addAction(actions);
best.setText("Best: " + SavedDataManager.getInstance().getHighScore());
best.setPosition(FlappyGame.CENTER_X, 0, Align.top);
best.addAction(Actions.delay(1f, Actions.moveToAligned(FlappyGame.CENTER_X, FlappyGame.CENTER_Y, Align.top,
.75f, Interpolation.sine)));
screenState = State.DYING;
}
gameplayStage.draw();
uiStage.draw();
}
private void updateAndDrawStages() {
gameplayStage.act();
gameplayStage.draw();
uiStage.act();
uiStage.draw();
}
#Override
public void resize(int width, int height) {
camera.setToOrtho(false, width, height);
Assets.batch.setProjectionMatrix(camera.combined);
gameplayStage.getViewport().update(width, height, true);
uiStage.getViewport().update(width, height, true);
}
#Override
public void dispose() {
gameplayStage.dispose();
uiStage.dispose();
}
private void checkCollisions() {
for (int i = 0; i < pipePairs.size; i++) {
PipePair pair = pipePairs.get(i);
if (pair.getBottomPipe().getBounds().overlaps(bird.getBounds()) || pair.getTopPipe().getBounds().overlaps(bird.getBounds())) {
stopTheWorld();
SavedDataManager.getInstance().setHighScore(score);
showWhiteScreen();
} else if (bird.isBelowGround()) {
bird.setY(FlappyGame.GROUND_LEVEL);
bird.clearActions();
bird.setToDying();
showWhiteScreen();
} else if (bird.isAboveCeiling()) {
bird.setY(FlappyGame.HEIGHT - bird.getHeight());
bird.setToDying();
showWhiteScreen();
} else if (pair.getRuby().getBounds().overlaps(bird.getBounds())) {
score++;
updateScoreLabel();
pair.moveCoinOffscreen();
Assets.playBingSound();
}
}
}
private void showWhiteScreen() {
whitePixel.setWidth(FlappyGame.WIDTH);
whitePixel.setHeight(FlappyGame.HEIGHT);
gameplayStage.addActor(whitePixel);
whitePixel.addAction(Actions.fadeOut(.5f));
}
private void updateScoreLabel() {
scoreLabel.setText(String.valueOf(score));
scoreLabel.setPosition(FlappyGame.WIDTH / 2, FlappyGame.HEIGHT * .9f, Align.center);
}
private void stopTheWorld() {
bird.setToDying();
killPipePairs();
stopTheGround();
screenState = State.DYING;
}
private void stopTheGround() {
ground.vel.x = 0;
}
private void killPipePairs() {
for (PipePair pair : pipePairs) {
pair.getBottomPipe().setState(Pipe.State.dead);
pair.getTopPipe().setState(Pipe.State.dead);
pair.getRuby().setVel(0, 0);
}
}
private void updatePipePairs() {
for (int i = 0; i < pipePairs.size; i++) {
pipePairs.get(i).update();
}
}
private void addPipes(Stage gameplayStage) {
for (int i = 0; i < pipePairs.size; i++) {
gameplayStage.addActor(pipePairs.get(i).getBottomPipe());
gameplayStage.addActor(pipePairs.get(i).getTopPipe());
gameplayStage.addActor(pipePairs.get(i).getRuby());
}
}
private void initThirdSetOfPipes() {
Pipe topPipe = new Pipe();
Pipe bottomPipe = new Pipe();
topPipe.getRegion().flip(false, true);
PipePair pair = new PipePair(topPipe, bottomPipe);
pair.initThird();
pipePairs.add(pair);
}
private void initSecondSetOfPipes() {
Pipe topPipe = new Pipe();
Pipe bottomPipe = new Pipe();
topPipe.getRegion().flip(false, true);
PipePair pair = new PipePair(topPipe, bottomPipe);
pair.initSecond();
pipePairs.add(pair);
}
private void initFirstSetOfPipes() {
Pipe topPipe = new Pipe();
Pipe bottomPipe = new Pipe();
topPipe.getRegion().flip(false, true);
PipePair pair = new PipePair(topPipe, bottomPipe);
pair.initFirst();
pipePairs.add(pair);
}
private void initInputProcessor() {
Gdx.input.setInputProcessor(new InputAdapter() {
// We only care about the touch down event
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
switch (screenState) {
case DYING:
justTouched = true;
break;
case DEAD:
if (allowRestart) {
game.setScreen(new GameplayScreen(game));
}
justTouched = true;
break;
case PLAYING:
justTouched = true;
break;
case PREGAME:
justTouched = true;
screenState = State.PLAYING;
bird.setState(Bird.State.ALIVE);
bird.clearActions();
tapToFlap.addAction(Actions.moveToAligned(FlappyGame.CENTER_X, FlappyGame.HEIGHT, Align.bottom, .75f, Interpolation.sine));
initFirstSetOfPipes();
initSecondSetOfPipes();
initThirdSetOfPipes();
addPipes(gameplayStage);
gameplayStage.addActor(ground);
gameplayStage.addActor(bird);
break;
}
return true;
}
});
}
}
You can connect to your Mysql server with Java JDBC. But it means you have to write your Mysql server username and password in your program. It's not safe.
I am using Exo Player ExtractorMediaSource for playing video in my android app. I am downloading media from server and save in local database and on a specific time Alarm i play this media using ConcatenatingMediaSource in exo player. but first i check that all video file downloaded or not and start player with downloaded media source . and if any video is not downloaded then i want to download it in background at when it downloaded then i want to add this video in my already created playlist
This is sample code
private void playAndUpdateVideo(ArrayList<String> mediaSourc) {
simpleExoPlayerView.setVisibility(View.VISIBLE);
simpleExoPlayerView.setDefaultArtwork(null);
mainHandler = new Handler();
DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveVideoTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector( videoTrackSelectionFactory);
dataSourceFactory = new DefaultDataSourceFactory(context,
Util.getUserAgent(context, "com.cloveritservices.hype"), bandwidthMeter);
// 2. Create a default LoadControl
extractorsFactory = new DefaultExtractorsFactory();
LoadControl loadControl = new DefaultLoadControl();
// 3. Create the player
player = ExoPlayerFactory.newSimpleInstance(this, trackSelector, loadControl);
player.addListener(this);
//Set media controller
simpleExoPlayerView.setUseController(false);
simpleExoPlayerView.requestFocus();
// Bind the player to the view.
simpleExoPlayerView.setPlayer(player);
MediaSource[] mediaSources = new MediaSource[mediaSourc.size()];
for (int i=0;i<mediaSourc.size();i++)
{
mediaSources[i]= buildMediaSource(Uri.parse(mediaSourc.get(i)));
}
MediaSource mediaSource = mediaSources.length == 1 ? mediaSources[0]
: new ConcatenatingMediaSource(mediaSources);
LoopingMediaSource loopingSource = new LoopingMediaSource(mediaSource);
player.prepare(loopingSource);
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
boolean isChecked = settings.getBoolean("switch", false);
if (!isChecked)
player.setVolume(0f);
else player.setVolume(2f);
player.setPlayWhenReady(true);
}
And here i am checking for video file that it is downloaded or not
if (CommonUtils.isExternalStorageExistAndWritable()) {
for (int i = 0; i < videoUrl.size(); i++) {
if (!new File(Environment.getExternalStorageDirectory().toString() + Constants.PROFILE_VIDEO_FOLDER + CommonUtils.fileFromUrl(videoUrl.get(i))).exists() && !CommonUtils.currentlyDownloading(context,CommonUtils.fileFromUrl(videoUrl.get(i)))) {
downloadByDownloadManager(videoUrl.get(i), CommonUtils.fileFromUrl(videoUrl.get(i)));
if (flag==Constants.FLAG_PLAY){downloadFlag=true;}
}
}
} else {
Toast.makeText(getApplicationContext(), "SD Card not mounted.Please Mount SD Card", Toast.LENGTH_SHORT).show();
}
if (flag==Constants.FLAG_PLAY && !downloadFlag)
{
playAndUpdateVideo(videoUrl);
}
public void downloadByDownloadManager(String url, String fileName1) {
downloadUrl=url;
fileName=fileName1;
request = new DownloadManager.Request(Uri.parse(url));
request.setDescription("video file");
request.setTitle(fileName);
request.setNotificationVisibility(2);
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);
request.setDestinationInExternalPublicDir(Constants.PROFILE_VIDEO_FOLDER, fileName);
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);
// get download service and enqueue file
}
Please help that how to add missing video file later to playlist if it is not downloaded.
To add new video files to your playlist, you need a new MediaSource implementation which can handle a list of sources to enable resizing. This is fairly simple to achieve, the easiest way to do so is to create a modified implementation of ConcaternatingMediaSource which uses lists instead of arrays to store and iterate over media sources. You then replace the ConcaternatingMediaSource in playAndUpdateVideo with the new implementation using lists. This will allow you to add and remove from your playlist as you wish, you can append new media files when your download complete listener is triggered. Here is the full class for a media source implementation using lists:
public final class DynamicMediaSource implements MediaSource {
private List<MediaSource> mediaSources;
private SparseArray<Timeline> timelines;
private SparseArray<Object> manifests;
private Map<MediaPeriod, Integer> sourceIndexByMediaPeriod;
private SparseArray<Boolean> duplicateFlags;
private boolean isRepeatOneAtomic;
private Listener listener;
private DynamicTimeline timeline;
/**
* #param mediaSources The {#link MediaSource}s to concatenate. It is valid for the same
* {#link MediaSource} instance to be present more than once in the array.
*/
public DynamicMediaSource(List<MediaSource> mediaSources) {
this(false, mediaSources);
}
/**
* #param isRepeatOneAtomic Whether the concatenated media source shall be treated as atomic
* (i.e., repeated in its entirety) when repeat mode is set to {#code Player.REPEAT_MODE_ONE}.
* #param mediaSources The {#link MediaSource}s to concatenate. It is valid for the same
* {#link MediaSource} instance to be present more than once in the array.
*/
public DynamicMediaSource(boolean isRepeatOneAtomic, List<MediaSource> mediaSources) {
for (MediaSource mediaSource : mediaSources) {
Assertions.checkNotNull(mediaSource);
}
this.mediaSources = mediaSources;
this.isRepeatOneAtomic = isRepeatOneAtomic;
timelines = new SparseArray<Timeline>();
manifests = new SparseArray<Object>();
sourceIndexByMediaPeriod = new HashMap<>();
duplicateFlags = buildDuplicateFlags(mediaSources);
}
#Override
public void prepareSource(ExoPlayer player, boolean isTopLevelSource, Listener listener) {
this.listener = listener;
for (int i = 0; i < mediaSources.size(); i++) {
if (!duplicateFlags.get(i)) {
final int index = i;
mediaSources.get(i).prepareSource(player, false, new Listener() {
#Override
public void onSourceInfoRefreshed(Timeline timeline, Object manifest) {
handleSourceInfoRefreshed(index, timeline, manifest);
}
});
}
}
}
#Override
public void maybeThrowSourceInfoRefreshError() throws IOException {
for (int i = 0; i < mediaSources.size(); i++) {
if (!duplicateFlags.get(i)) {
mediaSources.get(i).maybeThrowSourceInfoRefreshError();
}
}
}
#Override
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator) {
int sourceIndex = timeline.getChildIndexByPeriodIndex(id.periodIndex);
MediaPeriodId periodIdInSource =
new MediaPeriodId(id.periodIndex - timeline.getFirstPeriodIndexByChildIndex(sourceIndex));
MediaPeriod mediaPeriod = mediaSources.get(sourceIndex).createPeriod(periodIdInSource, allocator);
sourceIndexByMediaPeriod.put(mediaPeriod, sourceIndex);
return mediaPeriod;
}
#Override
public void releasePeriod(MediaPeriod mediaPeriod) {
int sourceIndex = sourceIndexByMediaPeriod.get(mediaPeriod);
sourceIndexByMediaPeriod.remove(mediaPeriod);
mediaSources.get(sourceIndex).releasePeriod(mediaPeriod);
}
#Override
public void releaseSource() {
for (int i = 0; i < mediaSources.size(); i++) {
if (!duplicateFlags.get(i)) {
mediaSources.get(i).releaseSource();
}
}
}
private void handleSourceInfoRefreshed(int sourceFirstIndex, Timeline sourceTimeline,
Object sourceManifest) {
// Set the timeline and manifest.
timelines.put(sourceFirstIndex, sourceTimeline);
manifests.put(sourceFirstIndex, sourceManifest);
// Also set the timeline and manifest for any duplicate entries of the same source.
for (int i = sourceFirstIndex + 1; i < mediaSources.size(); i++) {
if (mediaSources.get(i).equals(mediaSources.get(sourceFirstIndex))) {
timelines.put(i, sourceTimeline);
manifests.put(i, sourceManifest);
}
}
for(int i= 0; i<mediaSources.size(); i++){
if(timelines.get(i) == null){
// Don't invoke the listener until all sources have timelines.
return;
}
}
timeline = new DynamicTimeline(timelines, isRepeatOneAtomic);
listener.onSourceInfoRefreshed(timeline, new ArrayList(asList(manifests)));
}
private static SparseArray<Boolean> buildDuplicateFlags(List<MediaSource> mediaSources) {
SparseArray<Boolean> duplicateFlags = new SparseArray<Boolean>();
IdentityHashMap<MediaSource, Void> sources = new IdentityHashMap<>(mediaSources.size());
for (int i = 0; i < mediaSources.size(); i++) {
MediaSource source = mediaSources.get(i);
if (!sources.containsKey(source)) {
sources.put(source, null);
duplicateFlags.append(i,false);
} else {
duplicateFlags.append(i,true);
}
}
return duplicateFlags;
}
/**
* A {#link Timeline} that is the concatenation of one or more {#link Timeline}s.
*/
public static final class DynamicTimeline extends AbstractConcatenatedTimeline {
private final SparseArray<Timeline> timelines;
private final int[] sourcePeriodOffsets;
private final int[] sourceWindowOffsets;
private final boolean isRepeatOneAtomic;
public DynamicTimeline(SparseArray<Timeline> timelines, boolean isRepeatOneAtomic) {
super(timelines.size());
int[] sourcePeriodOffsets = new int[timelines.size()];
int[] sourceWindowOffsets = new int[timelines.size()];
long periodCount = 0;
int windowCount = 0;
for (int i = 0; i < timelines.size(); i++) {
Timeline timeline = timelines.get(i);
periodCount += timeline.getPeriodCount();
Assertions.checkState(periodCount <= Integer.MAX_VALUE,
"ConcatenatingMediaSource children contain too many periods");
sourcePeriodOffsets[i] = (int) periodCount;
windowCount += timeline.getWindowCount();
sourceWindowOffsets[i] = windowCount;
}
this.timelines = timelines;
this.sourcePeriodOffsets = sourcePeriodOffsets;
this.sourceWindowOffsets = sourceWindowOffsets;
this.isRepeatOneAtomic = isRepeatOneAtomic;
}
#Override
public int getWindowCount() {
return sourceWindowOffsets[sourceWindowOffsets.length - 1];
}
#Override
public int getPeriodCount() {
return sourcePeriodOffsets[sourcePeriodOffsets.length - 1];
}
#Override
public int getNextWindowIndex(int windowIndex, #Player.RepeatMode int repeatMode) {
if (isRepeatOneAtomic && repeatMode == Player.REPEAT_MODE_ONE) {
repeatMode = Player.REPEAT_MODE_ALL;
}
return super.getNextWindowIndex(windowIndex, repeatMode);
}
#Override
public int getPreviousWindowIndex(int windowIndex, #Player.RepeatMode int repeatMode) {
if (isRepeatOneAtomic && repeatMode == Player.REPEAT_MODE_ONE) {
repeatMode = Player.REPEAT_MODE_ALL;
}
return super.getPreviousWindowIndex(windowIndex, repeatMode);
}
#Override
public int getChildIndexByPeriodIndex(int periodIndex) {
return Util.binarySearchFloor(sourcePeriodOffsets, periodIndex, true, false) + 1;
}
#Override
protected int getChildIndexByWindowIndex(int windowIndex) {
return Util.binarySearchFloor(sourceWindowOffsets, windowIndex, true, false) + 1;
}
#Override
protected int getChildIndexByChildUid(Object childUid) {
if (!(childUid instanceof Integer)) {
return C.INDEX_UNSET;
}
return (Integer) childUid;
}
#Override
protected Timeline getTimelineByChildIndex(int childIndex) {
return timelines.get(childIndex);
}
#Override
public int getFirstPeriodIndexByChildIndex(int childIndex) {
return childIndex == 0 ? 0 : sourcePeriodOffsets[childIndex - 1];
}
#Override
protected int getFirstWindowIndexByChildIndex(int childIndex) {
return childIndex == 0 ? 0 : sourceWindowOffsets[childIndex - 1];
}
#Override
protected Object getChildUidByChildIndex(int childIndex) {
return childIndex;
}
}
}
To check when the file is downloaded and set a download completed listener, you can use a BroadcastReceiver. A detailed example of how to set up the BroadcastReceiver is provided here.
I have used the following animation class because i have multiple images to make an animation. After the 7th animation i get OutofMemoryError. androidgraphics.Bitmap.createBitmap
public class AnimationsContainer {
public int FPS = 30; // animation FPS
// single instance procedures
private static AnimationsContainer mInstance;
private AnimationsContainer() {
};
public static AnimationsContainer getInstance() {
if (mInstance == null)
mInstance = new AnimationsContainer();
return mInstance;
}
// animation progress dialog frames
private int[] mProgressAnimFrames = {};
// animation splash screen frames
/**
* #param imageView
* #return progress dialog animation
*/
public FramesSequenceAnimation createProgressDialogAnim(ImageView imageView) {
return new FramesSequenceAnimation(imageView, mProgressAnimFrames);
}
/**
* #param imageView
* #return splash screen animation
*/
public FramesSequenceAnimation createSplashAnim(ImageView imageView, int[] n) {
return new FramesSequenceAnimation(imageView, n);
}
/**
* AnimationPlayer. Plays animation frames sequence in loop
*/
public class FramesSequenceAnimation {
private int[] mFrames; // animation frames
private int mIndex; // current frame
private boolean mShouldRun; // true if the animation should continue running. Used to stop the animation
private boolean mIsRunning; // true if the animation currently running. prevents starting the animation twice
private SoftReference<ImageView> mSoftReferenceImageView; // Used to prevent holding ImageView when it should be dead.
private Handler mHandler;
private int mDelayMillis;
private OnAnimationStoppedListener mOnAnimationStoppedListener;
private Bitmap mBitmap = null;
private BitmapFactory.Options mBitmapOptions;
public FramesSequenceAnimation(ImageView imageView, int[] frames) {
mHandler = new Handler();
mFrames = frames;
mIndex = -1;
mSoftReferenceImageView = new SoftReference<ImageView>(imageView);
mShouldRun = false;
mIsRunning = false;
mDelayMillis = 50;
imageView.setImageResource(mFrames[0]);
// use in place bitmap to save GC work (when animation images are the same size & type)
if (Build.VERSION.SDK_INT >= 11) {
Bitmap bmp = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
int width = bmp.getWidth();
int height = bmp.getHeight();
Bitmap.Config config = bmp.getConfig();
mBitmap = Bitmap.createBitmap(width, height, config);
mBitmapOptions = new BitmapFactory.Options();
// setup bitmap reuse options.
mBitmapOptions.inBitmap = mBitmap;
mBitmapOptions.inMutable = true;
mBitmapOptions.inSampleSize = 1;
}
}
private int getNext() {
mIndex++;
if (mIndex == mFrames.length){
mIndex = mIndex - 1;
mShouldRun = false;
}
return mFrames[mIndex];
}
/**
* Starts the animation
*/
public synchronized void start() {
mShouldRun = true;
if (mIsRunning)
return;
Runnable runnable = new Runnable() {
#Override
public void run() {
ImageView imageView = mSoftReferenceImageView.get();
if (!mShouldRun || imageView == null) {
mIsRunning = false;
if (mOnAnimationStoppedListener != null) {
mOnAnimationStoppedListener.onAnimationStopped();
}
return;
}
mIsRunning = true;
mHandler.postDelayed(this, mDelayMillis);
if (imageView.isShown()) {
int imageRes = getNext();
if (mBitmap != null) { // so Build.VERSION.SDK_INT >= 11
Bitmap bitmap = null;
try {
bitmap = BitmapFactory.decodeResource(imageView.getResources(), imageRes, mBitmapOptions);
} catch (Exception e) {
e.printStackTrace();
}
if (bitmap != null) {
imageView.setImageBitmap(bitmap);
} else {
imageView.setImageResource(imageRes);
mBitmap.recycle();
mBitmap = null;
}
} else {
imageView.setImageResource(imageRes);
}
}
}
};
mHandler.post(runnable);
}
/**
* Stops the animation
*/
public synchronized void stop() {
mShouldRun = false;
}
}
}
Can anyone explain me why and tell me how to fix it? I already added
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
to my manifest file.
It might help to be sure that you are not keeping references to unneeded images. This is happening because you probably have the "standard" memory heap of 32MB or something similar (maybe 64MB or maybe 16MB). If you consider that most images are 5MB or more, it's not surprising you are out of memory.
You can increase the heap size using android:largeHeap="true" like this:
How to increase heap size of an android application?
I have a small problem with android & andengine.
This is my source code of my main menu
// AbstractScene is extending Scene
public class MainMenuScene extends AbstractScene implements
IOnMenuItemClickListener {
private static final int MENU_CREATE = 10;
private static final int MENU_JOIN = 20;
private static final int MENU_ABOUT = 30;
private static final int MENU_SETTINGS = 40;
MenuScene scene;
#Override
public void loadResources() {
res.loadMenuResources();
}
#Override
public void create() {
// Background
setBackground(new Background(0.09804f, 0.6274f, 0.8784f));
// Buttons
scene = new MenuScene(res.camera);
//scene.setPosition(GameActivity.WIDTH_CENTER, GameActivity.HEIGHT_CENTER);
final SpriteMenuItem createGameMenuItem = new SpriteMenuItem(
MENU_CREATE, res.createRegion, res.vbom);
final SpriteMenuItem joinGameMenuItem = new SpriteMenuItem(MENU_JOIN,
res.joinRegion, res.vbom);
final SpriteMenuItem aboutMenuItem = new SpriteMenuItem(MENU_ABOUT,
res.aboutRegion, res.vbom);
final SpriteMenuItem settingsMenuItem = new SpriteMenuItem(
MENU_SETTINGS, res.settingsRegion, res.vbom);
scene.addMenuItem(createGameMenuItem);
scene.addMenuItem(joinGameMenuItem);
scene.addMenuItem(aboutMenuItem);
scene.addMenuItem(settingsMenuItem);
scene.buildAnimations();
scene.setBackgroundEnabled(false);
scene.setOnMenuItemClickListener(this);
setChildScene(scene, false, true, true);
}
#Override
public boolean onMenuItemClicked(MenuScene pMenuScene, IMenuItem pMenuItem,
float pMenuItemLocalX, float pMenuItemLocalY) {
Log.d("Menuitem", "click");
switch (pMenuItem.getID()) {
case MENU_CREATE:
return true;
case MENU_JOIN:
SceneManager.getInstance().showScene(SceneType.LISTGAMES);
return true;
case MENU_ABOUT:
return true;
case MENU_SETTINGS:
return true;
default:
return false;
}
}
}
And this is my code from the ResourceManager
// menu ressources
public void loadMenuResources() {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");
menuAtlas = new BuildableBitmapTextureAtlas(activity.getTextureManager(),
1024, 1024, BitmapTextureFormat.RGBA_8888, TextureOptions.BILINEAR);
createRegion = BitmapTextureAtlasTextureRegionFactory
.createFromAsset(menuAtlas, activity.getAssets(), "btn_create_game.png");
joinRegion = BitmapTextureAtlasTextureRegionFactory
.createFromAsset(menuAtlas, activity.getAssets(), "btn_join_game.png");
settingsRegion = BitmapTextureAtlasTextureRegionFactory
.createFromAsset(menuAtlas, activity.getAssets(), "btn_settings.png");
aboutRegion = BitmapTextureAtlasTextureRegionFactory
.createFromAsset(menuAtlas, activity.getAssets(), "btn_about.png");
try {
menuAtlas.build(new BlackPawnTextureAtlasBuilder<IBitmapTextureAtlasSource, BitmapTextureAtlas>(0, 0, 0));
menuAtlas.load();
} catch (TextureAtlasBuilderException e) {
throw new RuntimeException("Error while loading menu resources", e);
}
}
My problem is, that the OnMenuItemClickListener is not called and i don't know why. The most code is copied from the official example. My app shows the background menus button etc but i cant click at one.
Does anybody knows why? Thx!
You are missing a register touch area call
scene.registerTouchArea(createGameMenuItem);
scene.registerTouchArea(joinGameMenuItem);
scene.registerTouchArea(aboutMenuItem);
scene.registerTouchArea(settingsMenuItem);
I'm downloading images over the network and add them to my libgdx UI as Image actors using this:
Pixmap pm = new Pixmap(data, 0, data.length);
Texture t = new Texture(pm);
TextureRegion tr = new TextureRegion(t,200,300);
TextureRegionDrawable trd = new TextureRegionDrawable(tr);
Image icon = new Image();
icon.setDrawable(trd);
Given this I need some way of reloading the texture data since it is lost when the OpenGL context is lost (e.g. because the screen goes to sleep).
I've tried making my own manager class, adding
DynamicTextureManager.register(t, pm); // Register texture together with the source pixmap
to the above snippet, and in resume() I do:
DynamicTextureManager.reload();
The manager class:
public class DynamicTextureManager {
private static LinkedHashMap<Texture, Pixmap> theMap = new
LinkedHashMap<Texture,Pixmap>();
public static void reload() {
Set<Entry<Texture,Pixmap>> es = theMap.entrySet();
for(Entry<Texture,Pixmap> e : es) {
Texture t = e.getKey();
Pixmap p = e.getValue();
t.draw(p, 0, 0);
}
}
public static void register(Texture t, Pixmap p) {
theMap.put(t, p);
}
}
But this doesn't help - I still end up with the texture being unloaded and white areas instead of the image.
How should this be done? I haven't been able to find any code demonstrating this!
Adding my solution as a reference. I now register the Image object and the Pixmap object with my manager, on reload() the Texture is re-created from the Pixmap and I set the new Texture for the old Image. Works for me, but more elegant solutions are welcome.
import java.util.Map.Entry;
public class DynamicTextureManager {
private static final class MapData {
Pixmap pixmap;
int width;
int height;
}
private static WeakHashMap<Image, MapData> theMap = new WeakHashMap<Image, MapData>();
public static void reload() {
Set<Entry<Image, MapData>> es = theMap.entrySet();
for (Entry<Image, MapData> e : es) {
Image i = e.getKey();
MapData d = e.getValue();
Texture t = new Texture(d.pixmap);
TextureRegion tr;
if(d.width == -1 || d.height == -1) {
tr = new TextureRegion(t);
}
else {
tr = new TextureRegion(t,d.width, d.height);
}
TextureRegionDrawable trd = new TextureRegionDrawable(tr);
i.setDrawable(trd);
}
}
public static void register(Image i, Pixmap p) {
MapData d = new MapData();
d.pixmap = p;
d.width = -1;
d.height = -1;
theMap.put(i, d);
}
public static void register(Image i, Pixmap p, int width, int height) {
MapData d = new MapData();
d.pixmap = p;
d.width = width;
d.height = height;
theMap.put(i, d);
}
}