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 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.
How can I save my current ImageView when I press onClick?
Im currently having the problem that the image that is next in line is being saved instead of the current actual image..
My Code for saving onLike
public class MainActivity extends Activity implements SwipeView.OnCardSwipedListener {
// Declaring variables
private final static int CARDS_MAX_ELEMENTS = 5;
private FrameLayout contentLayout;
private SwipeView mSwipeView;
private View addCardc41;
private Firebase mRef;
public ImageView imageLogo;
public ImageView imageview;
private static final String TAG = "MyActivity";
// Creating array of meals, getting them from the drawable folder
private int[] meals = {
R.drawable.a,
R.drawable.b,
R.drawable.c,
R.drawable.d,
R.drawable.e,
R.drawable.f,
R.drawable.g,
R.drawable.h,
R.drawable.i,
R.drawable.j
};
// Declaring a counter for the next method
private int count = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_swipe_view_demo);
contentLayout = (FrameLayout) findViewById(R.id.contentLayout);
imageLogo = (ImageView) findViewById(R.id.imageView3);
imageview = (ImageView) findViewById(R.id.imageView);
// Add the swipe view
mSwipeView = new SwipeView(this, R.id.imgSwipeLike, R.id.imgSwipeNope,
this);
contentLayout.addView(mSwipeView);
// Adding the cards initially with the maximum limits of cards.
for (int i = 0; i < CARDS_MAX_ELEMENTS; i++) {
addCard(i);
}
}
/**
* On clicked view.
*
* #param clickedView
* the clicked view
*/
public void onClickedView(View clickedView) {
switch (clickedView.getId()) {
case R.id.imgDisLike: {
mSwipeView.dislikeCard();
break;
}
case R.id.imgLike: {
mSwipeView.likeCard();
break;
}
}
}
#Override
public void onLikes() {
imageview.setDrawingCacheEnabled(true); //Add this line.
imageview.buildDrawingCache();
Bitmap bm=imageview.getDrawingCache();
OutputStream fOut = null;
Uri outputFileUri;
try {
File root = new File(Environment.getExternalStorageDirectory()
+ File.separator + "folder_name" + File.separator);
root.mkdirs();
File sdImageMainDirectory = new File(root, "myPicName.jpg");
outputFileUri = Uri.fromFile(sdImageMainDirectory);
fOut = new FileOutputStream(sdImageMainDirectory);
MediaScannerConnection.scanFile(this, new String[] { sdImageMainDirectory.getAbsolutePath() }, null, null);
} catch (Exception e) {
Toast.makeText(this, "Error occured. Please try again later.",
Toast.LENGTH_SHORT).show();
}
try {
bm.compress(Bitmap.CompressFormat.PNG, 100, fOut);
fOut.flush();
fOut.close();
} catch (Exception e){}
System.out.println("An Card removed");
// Add a card if you needed after any previous card swiped
addCard(0);
}
#Override
public void onDisLikes() {
System.out.println("An Card removed");
// Add a card if you needed after any previous card swiped
addCard(0);
}
#Override
public void onSingleTap() {
}
/**
* Adds the card to the swipe.
*/
private void addCard(int position) {
final View cardView = LayoutInflater.from(this).inflate(
R.layout.item_swipe_view, null);
final ImageView imgMeal = (ImageView) cardView
.findViewById(R.id.imgMeals);
imgMeal.setImageResource(meals[count]);
count++;
if (count == meals.length) {
count = 0;
}
// Add a card to the swipe view..
mSwipeView.addCard(cardView, position);
// Create OnClickListener for the CookBookActivity
// Declare Button for the Cookbook
Button btn = (Button) findViewById(R.id.button3);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this, CookbookActivity.class));
}
});
// Check Authentication
mRef = new Firebase(Constants.FIREBASE_URL);
if (mRef.getAuth() == null) {
loadLoginView();
}
}
private void loadLoginView() {
Intent intent = new Intent(this, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
}
}
The Library that i'm using for the swiping
//
// credits to IntelliJ IDEA
// (powered by Fernflower decompiler)
package com.rk.lib.view;
import android.content.Context;
import android.os.Handler;
import android.os.Build.VERSION;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.View.OnTouchListener;
import android.view.animation.AlphaAnimation;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.FrameLayout.LayoutParams;
public class SwipeView extends FrameLayout {
private View mFocusedView;
private View mFocusedViewLike;
private View mFocusedViewNope;
private int mFocusedViewWidth;
private float mPreviousAlpha = 0.0F;
private Integer mLikeResource = Integer.valueOf(0);
private Integer mNopeResource = Integer.valueOf(0);
private static final int MAX_ELEMENTS = 3;
private static final long DELAY_SCROLL_RUNNABLE = 1L;
private static final int SCROLL_LENGTH = 5;
private int mScrolledPixelsX;
private int mScrolledPixelsY;
private int mNeedToScrollX;
private int mNeedToScrollY;
private int mTotalScrolledX;
private int mTotalScrolledY;
private int mScrollLengthX = 5;
private int mScrollLengthY = 5;
private boolean enableTouchSwipe = true;
private Context mContext;
private SwipeView.ScrollMode mScrollModeX;
private SwipeView.ScrollMode mScrollModeY;
private SwipeView.ScrollDirection mScrollDirection;
private int[] paddingX;
private int[] paddingYTop;
private int[] paddingYBottom;
private SwipeView.OnCardSwipedListener mOnCardSwipedListener;
private Handler mScrollHandler;
private Runnable mScrollRunnable;
private final SimpleOnGestureListener simpleOnGestureListener;
public SwipeView(Context context, Integer likeResource, Integer nopeResource, SwipeView.OnCardSwipedListener cardSwipeListener) {
super(context);
this.mScrollModeX = SwipeView.ScrollMode.NONE;
this.mScrollModeY = SwipeView.ScrollMode.NONE;
this.mScrollDirection = SwipeView.ScrollDirection.NONE;
this.paddingX = new int[]{0, 10, 20};
this.paddingYTop = new int[]{0, 10, 20};
this.paddingYBottom = new int[]{20, 10, 0};
this.mScrollHandler = new Handler();
this.mScrollRunnable = new Runnable() {
public void run() {
boolean scrollX;
boolean scrollY;
int scrollX1;
int scrollY1;
if(SwipeView.this.mScrollDirection == SwipeView.ScrollDirection.OUT) {
if(SwipeView.this.mNeedToScrollX <= 0 && SwipeView.this.mNeedToScrollY <= 0) {
SwipeView.this.mScrollHandler.removeCallbacks(SwipeView.this.mScrollRunnable);
SwipeView.this.removeView(SwipeView.this.mFocusedView);
if(SwipeView.this.mScrollModeX == SwipeView.ScrollMode.LEFT) {
SwipeView.this.mOnCardSwipedListener.onLikes();
} else if(SwipeView.this.mScrollModeX == SwipeView.ScrollMode.RIGHT) {
SwipeView.this.mOnCardSwipedListener.onDisLikes();
}
SwipeView.this.alignCardsPadding();
} else {
if(SwipeView.this.mNeedToScrollX < SwipeView.this.mScrollLengthX) {
SwipeView.this.mScrollLengthX = SwipeView.this.mNeedToScrollX;
SwipeView.this.mNeedToScrollX = 0;
} else {
SwipeView.this.mNeedToScrollX = SwipeView.this.mNeedToScrollX - SwipeView.this.mScrollLengthX;
}
if(SwipeView.this.mNeedToScrollY < SwipeView.this.mScrollLengthY) {
SwipeView.this.mScrollLengthY = SwipeView.this.mNeedToScrollY;
SwipeView.this.mNeedToScrollY = 0;
} else {
SwipeView.this.mNeedToScrollY = SwipeView.this.mNeedToScrollY - SwipeView.this.mScrollLengthY;
}
scrollX = false;
scrollY = false;
if(SwipeView.this.mScrollModeX == SwipeView.ScrollMode.LEFT) {
scrollX1 = -SwipeView.this.mScrollLengthX;
} else {
scrollX1 = SwipeView.this.mScrollLengthX;
}
if(SwipeView.this.mScrollModeY == SwipeView.ScrollMode.TOP) {
scrollY1 = -SwipeView.this.mScrollLengthY;
} else {
scrollY1 = SwipeView.this.mScrollLengthY;
}
SwipeView.this.mFocusedView.scrollBy(scrollX1, scrollY1);
SwipeView.this.mScrollHandler.postDelayed(SwipeView.this.mScrollRunnable, 1L);
}
} else if(SwipeView.this.mScrollDirection == SwipeView.ScrollDirection.IN) {
if(SwipeView.this.mTotalScrolledX <= 0 && SwipeView.this.mTotalScrolledY <= 0) {
SwipeView.this.mScrollHandler.removeCallbacks(SwipeView.this.mScrollRunnable);
SwipeView.this.mScrollDirection = SwipeView.ScrollDirection.NONE;
} else {
if(SwipeView.this.mTotalScrolledX < SwipeView.this.mScrollLengthX) {
SwipeView.this.mScrollLengthX = SwipeView.this.mTotalScrolledX;
SwipeView.this.mTotalScrolledX = 0;
} else {
SwipeView.this.mTotalScrolledX = SwipeView.this.mTotalScrolledX - SwipeView.this.mScrollLengthX;
}
if(SwipeView.this.mTotalScrolledY < SwipeView.this.mScrollLengthY) {
SwipeView.this.mScrollLengthY = SwipeView.this.mTotalScrolledY;
SwipeView.this.mTotalScrolledY = 0;
} else {
SwipeView.this.mTotalScrolledY = SwipeView.this.mTotalScrolledY - SwipeView.this.mScrollLengthY;
}
scrollX = false;
scrollY = false;
if(SwipeView.this.mScrollModeX == SwipeView.ScrollMode.LEFT) {
scrollX1 = SwipeView.this.mScrollLengthX;
} else {
scrollX1 = -SwipeView.this.mScrollLengthX;
}
if(SwipeView.this.mScrollModeY == SwipeView.ScrollMode.TOP) {
scrollY1 = -SwipeView.this.mScrollLengthY;
} else {
scrollY1 = SwipeView.this.mScrollLengthY;
}
SwipeView.this.mFocusedView.scrollBy(scrollX1, scrollY1);
SwipeView.this.mScrollHandler.postDelayed(SwipeView.this.mScrollRunnable, 1L);
}
}
}
};
this.simpleOnGestureListener = new SimpleOnGestureListener() {
public boolean onSingleTapConfirmed(MotionEvent e) {
SwipeView.this.mOnCardSwipedListener.onSingleTap();
return super.onSingleTapConfirmed(e);
}
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
if(SwipeView.this.mFocusedView != null) {
SwipeView.this.mScrolledPixelsX = SwipeView.this.mScrolledPixelsX + (int)distanceX;
SwipeView.this.mScrolledPixelsY = SwipeView.this.mScrolledPixelsY + (int)distanceY;
SwipeView.this.mFocusedView.scrollBy((int)distanceX, (int)distanceY);
float alpha = (float)SwipeView.this.mScrolledPixelsX / (float)SwipeView.this.mFocusedViewWidth;
if(alpha > 0.0F) {
SwipeView.this.mFocusedViewNope.setVisibility(0);
SwipeView.this.mFocusedViewLike.setVisibility(8);
SwipeView.setAlpha(SwipeView.this.mFocusedViewNope, SwipeView.this.mPreviousAlpha, alpha);
SwipeView.this.mPreviousAlpha = alpha;
} else {
SwipeView.this.mFocusedViewNope.setVisibility(8);
SwipeView.this.mFocusedViewLike.setVisibility(0);
SwipeView.setAlpha(SwipeView.this.mFocusedViewLike, SwipeView.this.mPreviousAlpha, -alpha);
SwipeView.this.mPreviousAlpha = -alpha;
}
}
return true;
}
};
this.mContext = context;
this.mLikeResource = likeResource;
this.mNopeResource = nopeResource;
this.mOnCardSwipedListener = cardSwipeListener;
float density = this.getResources().getDisplayMetrics().density;
for(int gestureDetector = 0; gestureDetector < this.paddingX.length; ++gestureDetector) {
this.paddingX[gestureDetector] = (int)((float)this.paddingX[gestureDetector] * density);
this.paddingYTop[gestureDetector] = (int)((float)this.paddingYTop[gestureDetector] * density);
this.paddingYBottom[gestureDetector] = (int)((float)this.paddingYBottom[gestureDetector] * density);
}
final GestureDetector var7 = new GestureDetector(this.mContext, this.simpleOnGestureListener);
this.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if(SwipeView.this.getChildCount() > 0) {
if(SwipeView.this.mScrollDirection != SwipeView.ScrollDirection.NONE) {
return false;
} else if(!SwipeView.this.enableTouchSwipe) {
return false;
} else {
var7.onTouchEvent(event);
switch(event.getAction()) {
case 0:
if(SwipeView.this.getChildCount() > 0) {
SwipeView.this.mFocusedView = SwipeView.this.getChildAt(SwipeView.this.getChildCount() - 1);
SwipeView.this.mFocusedViewLike = SwipeView.this.mFocusedView.findViewById(SwipeView.this.mLikeResource.intValue());
SwipeView.this.mFocusedViewNope = SwipeView.this.mFocusedView.findViewById(SwipeView.this.mNopeResource.intValue());
SwipeView.this.mFocusedViewWidth = SwipeView.this.mFocusedView.getWidth();
SwipeView.this.mFocusedView.setPadding(SwipeView.this.paddingX[0], 0, SwipeView.this.paddingX[0], 0);
}
SwipeView.this.resetScrollingValues();
break;
case 1:
SwipeView.this.alignCardsPadding();
if(SwipeView.this.mScrolledPixelsX < 0) {
SwipeView.this.mScrollModeX = SwipeView.ScrollMode.LEFT;
SwipeView.this.mTotalScrolledX = -SwipeView.this.mScrolledPixelsX;
} else {
SwipeView.this.mScrollModeX = SwipeView.ScrollMode.RIGHT;
SwipeView.this.mTotalScrolledX = SwipeView.this.mScrolledPixelsX;
}
if(SwipeView.this.mScrolledPixelsY < 0) {
SwipeView.this.mScrollModeY = SwipeView.ScrollMode.BOTTOM;
SwipeView.this.mTotalScrolledY = -SwipeView.this.mScrolledPixelsY;
} else {
SwipeView.this.mScrollModeY = SwipeView.ScrollMode.TOP;
SwipeView.this.mTotalScrolledY = SwipeView.this.mScrolledPixelsY;
}
SwipeView.this.detectSwipe();
}
return true;
}
} else {
return false;
}
}
});
}
public void addCard(View view, int position) {
if(this.getChildCount() <= 3 && position < 3) {
LinearLayout viewLayout = new LinearLayout(this.mContext);
viewLayout.setLayoutParams(new LayoutParams(-1, -1));
view.setLayoutParams(new LayoutParams(-1, -1));
viewLayout.addView(view);
viewLayout.setPadding(this.paddingX[position], this.paddingYTop[position], this.paddingX[position], this.paddingYBottom[position]);
this.addView(viewLayout, 0);
}
}
public void removeFocusedCard() {
this.removeView(this.mFocusedView);
this.alignCardsPadding();
}
private void alignCardsPadding() {
int i = 0;
for(int j = this.getChildCount() - 1; j >= 0; --j) {
this.getChildAt(j).setPadding(this.paddingX[i], this.paddingYTop[i], this.paddingX[i], this.paddingYBottom[i]);
++i;
}
this.mScrollDirection = SwipeView.ScrollDirection.NONE;
}
private void resetScrollingValues() {
this.mPreviousAlpha = 0.0F;
this.mNeedToScrollX = 0;
this.mScrolledPixelsX = 0;
this.mTotalScrolledX = 0;
this.mNeedToScrollY = 0;
this.mScrolledPixelsY = 0;
this.mTotalScrolledY = 0;
this.mScrollLengthX = 5;
this.mScrollLengthY = 5;
this.mScrollModeX = SwipeView.ScrollMode.NONE;
this.mScrollModeY = SwipeView.ScrollMode.NONE;
}
public void resetFocuedView() {
if(this.getChildCount() > 0) {
View mFocusedView = this.getChildAt(this.getChildCount() - 1);
View mFocusedViewLike = mFocusedView.findViewById(this.mLikeResource.intValue());
View mFocusedViewNope = mFocusedView.findViewById(this.mNopeResource.intValue());
setAlpha(mFocusedViewLike, 0.0F, 0.0F);
setAlpha(mFocusedViewNope, 0.0F, 0.0F);
mFocusedView.scrollTo(0, 0);
}
}
private void detectSwipe() {
int imageHalf = this.mFocusedView.getWidth() / 2;
this.mNeedToScrollX = this.mFocusedView.getWidth() - this.mTotalScrolledX;
if(this.mScrollDirection == SwipeView.ScrollDirection.NONE) {
if(this.mNeedToScrollX < imageHalf) {
this.mScrollDirection = SwipeView.ScrollDirection.OUT;
} else {
this.mScrollDirection = SwipeView.ScrollDirection.IN;
setAlpha(this.mFocusedViewLike, 0.0F, 0.0F);
setAlpha(this.mFocusedViewNope, 0.0F, 0.0F);
}
}
this.mScrollHandler.post(this.mScrollRunnable);
}
public void likeCard() {
if(this.getChildCount() > 0) {
this.mFocusedView = this.getChildAt(this.getChildCount() - 1);
this.mFocusedViewLike = this.mFocusedView.findViewById(this.mLikeResource.intValue());
this.mFocusedViewNope = this.mFocusedView.findViewById(this.mNopeResource.intValue());
if(this.mScrollDirection != SwipeView.ScrollDirection.NONE) {
return;
}
this.resetScrollingValues();
this.mScrollDirection = SwipeView.ScrollDirection.OUT;
this.mScrollModeX = SwipeView.ScrollMode.LEFT;
this.mFocusedViewLike.setVisibility(0);
setAlpha(this.mFocusedViewLike, 0.0F, 1.0F);
this.detectSwipe();
}
}
public void dislikeCard() {
if(this.getChildCount() > 0) {
this.mFocusedView = this.getChildAt(this.getChildCount() - 1);
this.mFocusedViewLike = this.mFocusedView.findViewById(this.mLikeResource.intValue());
this.mFocusedViewNope = this.mFocusedView.findViewById(this.mNopeResource.intValue());
if(this.mScrollDirection != SwipeView.ScrollDirection.NONE) {
return;
}
this.resetScrollingValues();
this.mScrollDirection = SwipeView.ScrollDirection.OUT;
this.mScrollModeX = SwipeView.ScrollMode.RIGHT;
this.mFocusedViewNope.setVisibility(0);
setAlpha(this.mFocusedViewNope, 0.0F, 1.0F);
this.detectSwipe();
}
}
public void setTouchable(boolean touchable) {
this.enableTouchSwipe = touchable;
}
public static void setAlpha(View view, float fromAlpha, float toAlpha) {
if(VERSION.SDK_INT < 11) {
AlphaAnimation alphaAnimation = new AlphaAnimation(fromAlpha, toAlpha);
alphaAnimation.setDuration(0L);
alphaAnimation.setFillAfter(true);
view.startAnimation(alphaAnimation);
} else {
view.setAlpha(toAlpha);
}
}
public interface OnCardSwipedListener {
void onLikes();
void onDisLikes();
void onSingleTap();
}
private static enum ScrollDirection {
IN,
OUT,
NONE;
private ScrollDirection() {
}
}
private static enum ScrollMode {
LEFT,
RIGHT,
TOP,
BOTTOM,
NONE;
private ScrollMode() {
}
}
}
ATTEMPT #3
This is the code that i've tried but I keep getting the same result (read comment below what I have done:
FrameLayout view = (FrameLayout)findViewById(R.id.contentLayout);
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap bitmap = view.getDrawingCache();
I believe the image you are trying to save is getting removed during the onSwipe due to the library code. I think you need to move your code to before the onLike is called.
You're also attempting to get a bitmap from the cache of the entire layout, rather than the wanted ImageView here:
bm=contentLayout.getDrawingCache();
You'll want to get your current card view as a View, then, from my understanding of your code, the ID of your actual ImageView containing the expected bitmap is R.id.imgMeals, so I the suggest replacing the line:
bm=contentLayout.getDrawingCache();
with the following:
ImageView imageView = (ImageView) cardView.findViewById(R.id.imgMeals);
BitmapDrawable drawable = (BitmapDrawable) imageView.getDrawable();
Bitmap bm = drawable.getBitmap();
Move all of the below code from where you have it, to where I have marked //HERE!! in the following part of your code (or better, move it to a new method and call the method here).
// If the imageview of like is clicked
case R.id.imgLike: {
// HERE!!
// The imageview in the contentlayout will be swiped to the right
mSwipeView.likeCard();
break;
}
This is the code to me moved including the change I mention above:
View cardView = mSwipeView.getChildAt(mSwipeView.getChildCount() - 1);
ImageView imageView = (ImageView) cardView.findViewById(R.id.imgMeals);
BitmapDrawable drawable = (BitmapDrawable) imageView.getDrawable();
Bitmap bm = drawable.getBitmap();
OutputStream fOut = null;
try {
// Save on my sd card
File root = new File(Environment.getExternalStorageDirectory()
// Making a folder name Food Inspiration
+ File.separator + "Food Inspiration" + File.separator);
root.mkdirs();
File sdImageMainDirectory = null;
// Loop for having a different name for every image
int i = 0;
do {
sdImageMainDirectory = new File(root, "pic-" + i + ".png");
i++;
} while (sdImageMainDirectory.exists());
fOut = new FileOutputStream(sdImageMainDirectory);
// Updates the gallery of your phone with the folder and the "liked" images in it
MediaScannerConnection.scanFile(this, new String[] { sdImageMainDirectory.getAbsolutePath() }, null, null);
// If something goes wrong
} catch (Exception e) {
Toast.makeText(this, "Error occured. Please try again later.",
Toast.LENGTH_SHORT).show();
}
// Compresses the actual bitmap image
try {
bm.compress(Bitmap.CompressFormat.PNG, 100, fOut);
fOut.flush();
fOut.close();
} catch (Exception e){}
I have a project that captures an image using OpenCV's CamerabridgeViewBase and another project that detects a pingpong ball. The problem is I can't combine those two projects. What I want is to capture a live feed, then return a single image that already has a detection in it.
Here are the classes of the project that can capture an image and store it in the gallery:
public final class MainActivity extends ActionBarActivity
implements CvCameraViewListener2 {
// A tag for log output.
private static final String TAG =
MainActivity.class.getSimpleName();
// A key for storing the index of the active camera.
private static final String STATE_CAMERA_INDEX = "cameraIndex";
// A key for storing the index of the active image size.
private static final String STATE_IMAGE_SIZE_INDEX =
"imageSizeIndex";
// An ID for items in the image size submenu.
private static final int MENU_GROUP_ID_SIZE = 2;
// The index of the active camera.
private int mCameraIndex;
// The index of the active image size.
private int mImageSizeIndex;
// Whether the active camera is front-facing.
// If so, the camera view should be mirrored.
private boolean mIsCameraFrontFacing;
// The number of cameras on the device.
private int mNumCameras;
// The image sizes supported by the active camera.
private List<Size> mSupportedImageSizes;
// The camera view.
private CameraBridgeViewBase mCameraView;
// Whether the next camera frame should be saved as a photo.
private boolean mIsPhotoPending;
// A matrix that is used when saving photos.
private Mat mBgr;
// Whether an asynchronous menu action is in progress.
// If so, menu interaction should be disabled.
private boolean mIsMenuLocked;
// The OpenCV loader callback.
private BaseLoaderCallback mLoaderCallback =
new BaseLoaderCallback(this) {
#Override
public void onManagerConnected(final int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS:
Log.d(TAG, "OpenCV loaded successfully");
mCameraView.enableView();
//mCameraView.enableFpsMeter();
mBgr = new Mat();
break;
default:
super.onManagerConnected(status);
break;
}
}
};
// Suppress backward incompatibility errors because we provide
// backward-compatible fallbacks.
#SuppressLint("NewApi")
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Window window = getWindow();
window.addFlags(
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
if (savedInstanceState != null) {
mCameraIndex = savedInstanceState.getInt(
STATE_CAMERA_INDEX, 0);
mImageSizeIndex = savedInstanceState.getInt(
STATE_IMAGE_SIZE_INDEX, 0);
} else {
mCameraIndex = 0;
mImageSizeIndex = 0;
}
final Camera camera;
if (Build.VERSION.SDK_INT >=
Build.VERSION_CODES.GINGERBREAD) {
CameraInfo cameraInfo = new CameraInfo();
Camera.getCameraInfo(mCameraIndex, cameraInfo);
mIsCameraFrontFacing =
(cameraInfo.facing ==
CameraInfo.CAMERA_FACING_FRONT);
mNumCameras = Camera.getNumberOfCameras();
camera = Camera.open(mCameraIndex);
} else { // pre-Gingerbread
// Assume there is only 1 camera and it is rear-facing.
mIsCameraFrontFacing = false;
mNumCameras = 1;
camera = Camera.open();
}
final Parameters parameters = camera.getParameters();
camera.release();
mSupportedImageSizes =
parameters.getSupportedPreviewSizes();
final Size size = mSupportedImageSizes.get(mImageSizeIndex);
mCameraView = new JavaCameraView(this, mCameraIndex);
mCameraView.setMaxFrameSize(size.width, size.height);
mCameraView.setCvCameraViewListener(this);
setContentView(mCameraView);
}
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save the current camera index.
savedInstanceState.putInt(STATE_CAMERA_INDEX, mCameraIndex);
// Save the current image size index.
savedInstanceState.putInt(STATE_IMAGE_SIZE_INDEX,
mImageSizeIndex);
super.onSaveInstanceState(savedInstanceState);
}
// Suppress backward incompatibility errors because we provide
// backward-compatible fallbacks.
#SuppressLint("NewApi")
#Override
public void recreate() {
if (Build.VERSION.SDK_INT >=
Build.VERSION_CODES.HONEYCOMB) {
super.recreate();
} else {
finish();
startActivity(getIntent());
}
}
#Override
public void onPause() {
if (mCameraView != null) {
mCameraView.disableView();
}
super.onPause();
}
#Override
public void onResume() {
super.onResume();
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0,
this, mLoaderCallback);
mIsMenuLocked = false;
}
#Override
public void onDestroy() {
if (mCameraView != null) {
mCameraView.disableView();
}
super.onDestroy();
}
#Override
public boolean onCreateOptionsMenu(final Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
if (mNumCameras < 2) {
// Remove the option to switch cameras, since there is
// only 1.
menu.removeItem(R.id.menu_next_camera);
}
int numSupportedImageSizes = mSupportedImageSizes.size();
if (numSupportedImageSizes > 1) {
final SubMenu sizeSubMenu = menu.addSubMenu(
R.string.menu_image_size);
for (int i = 0; i < numSupportedImageSizes; i++) {
final Size size = mSupportedImageSizes.get(i);
sizeSubMenu.add(MENU_GROUP_ID_SIZE, i, Menu.NONE,
String.format("%dx%d", size.width,
size.height));
}
}
return true;
}
// Suppress backward incompatibility errors because we provide
// backward-compatible fallbacks (for recreate).
#SuppressLint("NewApi")
#Override
public boolean onOptionsItemSelected(final MenuItem item) {
if (mIsMenuLocked) {
return true;
}
if (item.getGroupId() == MENU_GROUP_ID_SIZE) {
mImageSizeIndex = item.getItemId();
recreate();
return true;
}
switch (item.getItemId()) {
case R.id.menu_next_camera:
mIsMenuLocked = true;
// With another camera index, recreate the activity.
mCameraIndex++;
if (mCameraIndex == mNumCameras) {
mCameraIndex = 0;
}
mImageSizeIndex = 0;
recreate();
return true;
case R.id.menu_take_photo:
mIsMenuLocked = true;
// Next frame, take the photo.
mIsPhotoPending = true;
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public void onCameraViewStarted(final int width,
final int height) {
}
#Override
public void onCameraViewStopped() {
}
#Override
public Mat onCameraFrame(final CvCameraViewFrame inputFrame) {
final Mat rgba = inputFrame.rgba();
if (mIsPhotoPending) {
mIsPhotoPending = false;
takePhoto(rgba);
}
if (mIsCameraFrontFacing) {
// Mirror (horizontally flip) the preview.
Core.flip(rgba, rgba, 1);
}
return rgba;
}
private void takePhoto(final Mat rgba) {
// Determine the path and metadata for the photo.
final long currentTimeMillis = System.currentTimeMillis();
final String appName = getString(R.string.app_name);
final String galleryPath =
Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES).toString();
final String albumPath = galleryPath + File.separator +
appName;
final String photoPath = albumPath + File.separator +
currentTimeMillis + LabActivity.PHOTO_FILE_EXTENSION;
final ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DATA, photoPath);
values.put(Images.Media.MIME_TYPE,
LabActivity.PHOTO_MIME_TYPE);
values.put(Images.Media.TITLE, appName);
values.put(Images.Media.DESCRIPTION, appName);
values.put(Images.Media.DATE_TAKEN, currentTimeMillis);
// Ensure that the album directory exists.
File album = new File(albumPath);
if (!album.isDirectory() && !album.mkdirs()) {
Log.e(TAG, "Failed to create album directory at " +
albumPath);
onTakePhotoFailed();
return;
}
// Try to create the photo.
Imgproc.cvtColor(rgba, mBgr, Imgproc.COLOR_RGBA2BGR, 3);
if (!Imgcodecs.imwrite(photoPath, mBgr)) {
Log.e(TAG, "Failed to save photo to " + photoPath);
onTakePhotoFailed();
}
Log.d(TAG, "Photo saved successfully to " + photoPath);
// Try to insert the photo into the MediaStore.
Uri uri;
try {
uri = getContentResolver().insert(
Images.Media.EXTERNAL_CONTENT_URI, values);
} catch (final Exception e) {
Log.e(TAG, "Failed to insert photo into MediaStore");
e.printStackTrace();
// Since the insertion failed, delete the photo.
File photo = new File(photoPath);
if (!photo.delete()) {
Log.e(TAG, "Failed to delete non-inserted photo");
}
onTakePhotoFailed();
return;
}
// Open the photo in LabActivity.
final Intent intent = new Intent(this, LabActivity.class);
intent.putExtra(LabActivity.EXTRA_PHOTO_URI, uri);
intent.putExtra(LabActivity.EXTRA_PHOTO_DATA_PATH,
photoPath);
runOnUiThread(new Runnable() {
#Override
public void run() {
startActivity(intent);
}
});
}
private void onTakePhotoFailed() {
mIsMenuLocked = false;
// Show an error message.
final String errorMessage =
getString(R.string.photo_error_message);
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(MainActivity.this, errorMessage,
Toast.LENGTH_SHORT).show();
}
});
}
--
public final class LabActivity extends ActionBarActivity {
public static final String PHOTO_FILE_EXTENSION = ".png";
public static final String PHOTO_MIME_TYPE = "image/png";
public static final String EXTRA_PHOTO_URI =
"com.nummist.secondsight.LabActivity.extra.PHOTO_URI";
public static final String EXTRA_PHOTO_DATA_PATH =
"com.nummist.secondsight.LabActivity.extra.PHOTO_DATA_PATH";
private Uri mUri;
private String mDataPath;
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Intent intent = getIntent();
mUri = intent.getParcelableExtra(EXTRA_PHOTO_URI);
mDataPath = intent.getStringExtra(EXTRA_PHOTO_DATA_PATH);
final ImageView imageView = new ImageView(this);
imageView.setImageURI(mUri);
setContentView(imageView);
}
#Override
public boolean onCreateOptionsMenu(final Menu menu) {
getMenuInflater().inflate(R.menu.activity_lab, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(final MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_delete:
deletePhoto();
return true;
case R.id.menu_edit:
editPhoto();
return true;
case R.id.menu_share:
sharePhoto();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
/*
* Show a confirmation dialog. On confirmation ("Delete"), the
* photo is deleted and the activity finishes.
*/
private void deletePhoto() {
final AlertDialog.Builder alert = new AlertDialog.Builder(
LabActivity.this);
alert.setTitle(R.string.photo_delete_prompt_title);
alert.setMessage(R.string.photo_delete_prompt_message);
alert.setCancelable(false);
alert.setPositiveButton(R.string.delete,
new DialogInterface.OnClickListener() {
#Override
public void onClick(final DialogInterface dialog,
final int which) {
getContentResolver().delete(
Images.Media.EXTERNAL_CONTENT_URI,
MediaStore.MediaColumns.DATA + "=?",
new String[] { mDataPath });
finish();
}
});
alert.setNegativeButton(android.R.string.cancel, null);
alert.show();
}
/*
* Show a chooser so that the user may pick an app for editing
* the photo.
*/
private void editPhoto() {
final Intent intent = new Intent(Intent.ACTION_EDIT);
intent.setDataAndType(mUri, PHOTO_MIME_TYPE);
startActivity(Intent.createChooser(intent,
getString(R.string.photo_edit_chooser_title)));
}
/*
* Show a chooser so that the user may pick an app for sending
* the photo.
*/
private void sharePhoto() {
final Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType(PHOTO_MIME_TYPE);
intent.putExtra(Intent.EXTRA_STREAM, mUri);
intent.putExtra(Intent.EXTRA_SUBJECT,
getString(R.string.photo_send_extra_subject));
intent.putExtra(Intent.EXTRA_TEXT,
getString(R.string.photo_send_extra_text));
startActivity(Intent.createChooser(intent,
getString(R.string.photo_send_chooser_title)));
}
}
And here are the classes of the pingpong ball detection project:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "ObjTrackActivity";
private MenuItem mItemPreviewRGBA;
private MenuItem mItemPreviewTresholded;
public static boolean bShowTresholded = false;
public MainActivity() {
Log.i(TAG, "Instantiated new " + this.getClass());
}
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "onCreate");
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(new ObjTrackViewer(this));
}
public boolean onCreateOptionsMenu(Menu menu){
Log.i(TAG, "onCreateOptionsMenu");
mItemPreviewRGBA = menu.add("Preview RGBA");
mItemPreviewTresholded = menu.add("Preview Thresholded");
return true;
}
public boolean onOptionsItemSelected(MenuItem item){
Log.i(TAG, "Menu Item selected " + item);
if (item == mItemPreviewRGBA)
bShowTresholded = false;
else if (item == mItemPreviewTresholded)
bShowTresholded = true;
return true;
}
}
--
public class ObjTrackViewer extends SampleViewBase {
private int mFrameSize;
private Bitmap mBitmap;
private int[] mRGBA;
public ObjTrackViewer(Context context) {
super(context);
}
#Override
protected void onPreviewStared(int previewWidtd, int previewHeight) {
mFrameSize = previewWidtd * previewHeight;
mRGBA = new int[mFrameSize];
mBitmap = Bitmap.createBitmap(previewWidtd, previewHeight, Bitmap.Config.ARGB_8888);
}
#Override
protected void onPreviewStopped() {
if(mBitmap != null) {
mBitmap.recycle();
mBitmap = null;
}
mRGBA = null;
}
#Override
protected Bitmap processFrame(byte[] data) {
int[] rgba = mRGBA;
CircleObjectTrack(getFrameWidth(), getFrameHeight(), data, rgba, MainActivity.bShowTresholded);
Bitmap bmp = mBitmap;
bmp.setPixels(rgba, 0/* offset */, getFrameWidth() /* stride */, 0, 0, getFrameWidth(), getFrameHeight());
return bmp;
}
public native void CircleObjectTrack(int width, int height, byte yuv[], int[] rgba, boolean debug);
static {
System.loadLibrary("objtrack_opencv_jni");
}
}
--
public abstract class SampleViewBase extends SurfaceView implements SurfaceHolder.Callback, Runnable {
private static final String TAG = "Sample::SurfaceView";
private Camera mCamera;
private SurfaceHolder mHolder;
private int mFrameWidth;
private int mFrameHeight;
private byte[] mFrame;
private boolean mThreadRun;
private byte[] mBuffer;
public SampleViewBase(Context context) {
super(context);
mHolder = getHolder();
mHolder.addCallback(this);
Log.i(TAG, "Instantiated new " + this.getClass());
}
public int getFrameWidth() {
return mFrameWidth;
}
public int getFrameHeight() {
return mFrameHeight;
}
public void setPreview() throws IOException {
//if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
// mCamera.setPreviewTexture( new SurfaceTexture(10) );
//else
mCamera.setPreviewDisplay(null);
}
public void surfaceChanged(SurfaceHolder _holder, int format, int width, int height) {
Log.i(TAG, "surfaceCreated");
if (mCamera != null) {
Camera.Parameters params = mCamera.getParameters();
List<Camera.Size> sizes = params.getSupportedPreviewSizes();
mFrameWidth = width;
mFrameHeight = height;
// selecting optimal camera preview size
{
int minDiff = Integer.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - height) < minDiff) {
mFrameWidth = size.width;
mFrameHeight = size.height;
minDiff = Math.abs(size.height - height);
}
}
}
params.setPreviewSize(getFrameWidth(), getFrameHeight());
List<String> FocusModes = params.getSupportedFocusModes();
if (FocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO))
{
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
}
mCamera.setParameters(params);
/* Now allocate the buffer */
params = mCamera.getParameters();
int size = params.getPreviewSize().width * params.getPreviewSize().height;
size = size * ImageFormat.getBitsPerPixel(params.getPreviewFormat()) / 8;
mBuffer = new byte[size];
/* The buffer where the current frame will be coppied */
mFrame = new byte [size];
mCamera.addCallbackBuffer(mBuffer);
try {
setPreview();
} catch (IOException e) {
Log.e(TAG, "mCamera.setPreviewDisplay/setPreviewTexture fails: " + e);
}
/* Notify that the preview is about to be started and deliver preview size */
onPreviewStared(params.getPreviewSize().width, params.getPreviewSize().height);
/* Now we can start a preview */
mCamera.startPreview();
}
}
public void surfaceCreated(SurfaceHolder holder) {
Log.i(TAG, "surfaceCreated");
mCamera = Camera.open();
mCamera.setPreviewCallbackWithBuffer(new PreviewCallback() {
public void onPreviewFrame(byte[] data, Camera camera) {
synchronized (SampleViewBase.this) {
System.arraycopy(data, 0, mFrame, 0, data.length);
SampleViewBase.this.notify();
}
camera.addCallbackBuffer(mBuffer);
}
});
(new Thread(this)).start();
}
public void surfaceDestroyed(SurfaceHolder holder) {
Log.i(TAG, "surfaceDestroyed");
mThreadRun = false;
if (mCamera != null) {
synchronized (this) {
mCamera.stopPreview();
mCamera.setPreviewCallback(null);
mCamera.release();
mCamera = null;
}
}
onPreviewStopped();
}
/* The bitmap returned by this method shall be owned by the child and released in onPreviewStopped() */
protected abstract Bitmap processFrame(byte[] data);
/**
* This method is called when the preview process is beeing started. It is called before the first frame delivered and processFrame is called
* It is called with the width and height parameters of the preview process. It can be used to prepare the data needed during the frame processing.
* #param previewWidth - the width of the preview frames that will be delivered via processFrame
* #param previewHeight - the height of the preview frames that will be delivered via processFrame
*/
protected abstract void onPreviewStared(int previewWidtd, int previewHeight);
/**
* This method is called when preview is stopped. When this method is called the preview stopped and all the processing of frames already completed.
* If the Bitmap object returned via processFrame is cached - it is a good time to recycle it.
* Any other resourcses used during the preview can be released.
*/
protected abstract void onPreviewStopped();
public void run() {
mThreadRun = true;
Log.i(TAG, "Starting processing thread");
while (mThreadRun) {
Bitmap bmp = null;
synchronized (this) {
try {
this.wait();
bmp = processFrame(mFrame);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (bmp != null) {
Canvas canvas = mHolder.lockCanvas();
if (canvas != null) {
canvas.drawBitmap(bmp, (canvas.getWidth() - getFrameWidth()) / 2, (canvas.getHeight() - getFrameHeight()) / 2, null);
mHolder.unlockCanvasAndPost(canvas);
}
}
}
}
}
I've been trying to figure this out for a while now... I need to place marks over top of a seekBar to show the user places that they bookmarked in the past. The data is stored in xml. The problem is making the little ovals appear over the seekBar... It just doesn't work...
Here's my code:
public class seekMark extends View {
private int seekLength; // in pixels
private int seekLeftPad; // in pixels
private int seekBottomPad; // in pixels
private int trackLength; // in ms
private float pxOverMs; // in px/ms
ShapeDrawable lmark;
private seekMark instance;
public seekMark(Context context){
super(context);
instance = this;
seekLength = progressBar.getWidth();
seekLeftPad = progressBar.getPaddingLeft();
seekBottomPad = progressBar.getBottom();
trackLength = player.getDuration();
pxOverMs = pxPerMs();
lmark = new ShapeDrawable(new OvalShape());
}
private float pxPerMs(){
return ((float) seekLength)/((float) trackLength);
}
private int[] markPxList() throws XmlPullParserException, IOException {
int bmStartTime = 0;
String bmNames[] = bmNameList(xmlPath);
int[] bmPos = new int[bmNames.length];
for(int i=0; i < bmNames.length; i++){
bmStartTime = getBookmark(xmlPath, bmNames[i]);
bmPos[i] = (int) (bmStartTime * pxOverMs);
}
return (bmPos);
}
public void markPlace() throws XmlPullParserException, IOException {
int y = seekBottomPad;
int x = 0;
int bmPos[] = markPxList();
for(int i = 0; i < bmPos.length; i++){
x = bmPos[i] + seekLeftPad;
lmark = new ShapeDrawable();
lmark.getPaint().setColor(0xff74AC23);
lmark.setBounds(x, y, x + 1, y + 1);
instance.invalidate();
}
}
protected void onDraw(Canvas canvas) {
lmark.draw(canvas);
}
}
It's called from onCreate using this code. I call it using in another thread to avoid the problem where the dimensions of progressBar aren't yet set in onCreate.
Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
if (display.getRotation() == 1){ // if landscape
final Runnable runner = new Runnable() {
public void run() {
seekMark seekMarks = new seekMark(context);
try {
seekMarks.markPlace();
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// runs in another thread to avoid the problem with calling
// seekMark directly from onCreate
}
};
handler.postDelayed(runner, 1000);
}
The program crashes whenever I try to call seekMark.markPlace()... I'm trying to draw this over top of my layout main.xml.
im not sure if this is what you are trying to do.
Customize Seekbar
this seems to be similar while the approach is different.