I am making android- specific game, and would like to use android API's. But I'm wondering, is it possible to have like an android menu, and from there call libGdx? I've tried adapting the manifest in the android part, so android activity (menu) is the LAUNCHER activity and gets called first. Then I thought I could start the ApplicationListener with an intent, but it doesn't work. What am I doing wrong? Is it even possible?
It is pretty simple:
// my call of the loading screen from inside a fragment
Intent intent = new Intent(getActivity(), LoadingScreenActivity.class);
startActivity(intent);
and the LoadingScreenActivity is, guess what, an Activity.
// the onCreate method
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration();
cfg.useGL20 = true;
cfg.useAccelerometer = false;
cfg.useCompass = false;
initialize(new LoadingScreen(), cfg);
}
and LoadingScreen is the the ApplicationListener you already mentioned
public class LoadingScreen implements ApplicationListener {
// create(), resize() and more
}
So basically you need embed libgdx inside an Activity...
Edit:
Here is my complete loading screen activity which uses libgdx. It should work (just remove the CustomApplication stuff that you don't have).
public class LoadingScreenActivity extends AndroidApplication {
private final static String LOG_TAG = LoadingScreenActivity.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration();
cfg.useGL20 = true;
cfg.useAccelerometer = false;
cfg.useCompass = false;
initialize(new LoadingScreen(), cfg);
}
private class LoadingScreen implements ApplicationListener {
private OrthographicCamera mCamera = new OrthographicCamera();
private SpriteBatch mBatch;
private Stage mStage;
private ShapeRenderer mProgressLine;
#Override
public void create() {
AssetManager manager = CustomApplication.getAssetManager();
manager.load("ic_launcher.png", Texture.class);
mStage = new Stage();
mProgressLine = new ShapeRenderer();
mBatch = new SpriteBatch();
mCamera.setToOrtho(false, DesignUtil.getScreenWidth(), DesignUtil.getScreenHeight());
mStage.setCamera(mCamera);
}
#Override
public void resize(int width, int height) {
mStage.setViewport(width, height, true);
}
#Override
public void render() {
if (CustomApplication.getAssetManager().update()) {
IntentUtil.startActivity(LoadingScreenActivity.this, GameActivity.class);
finish();
return;
}
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
// tell the camera to update its matrices.
mCamera.update();
// tell the SpriteBatch to render in the
// coordinate system specified by the camera.
mBatch.setProjectionMatrix(mCamera.combined);
mBatch.begin();
mProgressLine.begin(ShapeRenderer.ShapeType.Rectangle);
mProgressLine.rect(0 + mStage.getWidth() / 5, mStage.getHeight() / 2, mStage.getWidth() - mStage.getWidth() / 2.5f, DesignUtil.percentToPixel(5, mStage.getHeight()));
mProgressLine.setColor(0, 1, 0, 1);
mProgressLine.end();
mProgressLine.begin(ShapeRenderer.ShapeType.FilledRectangle);
mProgressLine.filledRect(0 + mStage.getWidth() / 5, mStage.getHeight() / 2, (mStage.getWidth() - mStage.getWidth() / 2.5f) * CustomApplication.getAssetManager().getProgress(), DesignUtil.percentToPixel(5, mStage.getHeight()));
mProgressLine.setColor(0, 1, 0, 1);
mProgressLine.end();
mBatch.end();
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void dispose() {
mBatch.dispose();
mStage.dispose();
mProgressLine.dispose();
}
}
}
If it helps, you CAN use the Android UI elements from Libgdx. That way, you can get the behavior you want, but not the method you want.
http://code.google.com/p/libgdx-users/wiki/IntegratingAndroidNativeUiElements
http://code.google.com/p/libgdx-users/wiki/IntegratingAndroidNativeUiElements3TierProjectSetup
Related
This is my second game application using LibGdx framework and this is my first time to use a framework in android. I'm trying to understand how to use it.I have already done with the design in the main menu and my problem is the functionality of each button to switch screen. Any link tutorial or sample codes are much appreciated thank you and advance
Here is my code
MainScreen.java
public class MainScreen extends ApplicationAdapter implements Screen {
//Screen Size
private static final int WIDTH= 720;
private static final int HEIGHT= 1280;
Viewport viewport;
private Camera camera;
private Stage stage;
private TextureRegion myTextureRegion;
private TextureRegionDrawable myTexRegionDrawable;
private ImageButton playBtn;
private Texture Background,logo,exit,credits,help,option,play;
SpriteBatch spriteBatch;
Sprite sprite;
MyGdxGame game;
public MainScreen(final MyGdxGame game) {
this.game = game;
stage = new Stage(new ScreenViewport());
Gdx.input.setInputProcessor(stage);
spriteBatch = new SpriteBatch();
camera = new PerspectiveCamera();
viewport = new ScreenViewport(camera);
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
Background = new Texture(Gdx.files.internal("backgroundimage.png")); //background image
//Menu Buttons
exit = new Texture(Gdx.files.internal("menu/exit.png"));
logo = new Texture(Gdx.files.internal("menu/logo.png"));
option = new Texture(Gdx.files.internal("menu/options.png"));
help = new Texture(Gdx.files.internal("menu/help.png"));
credits = new Texture(Gdx.files.internal("menu/credits.png"));
play = new Texture(Gdx.files.internal("menu/play.png"));
sprite = new Sprite(play);
sprite.setPosition(130,360);
sprite.setSize(0,0);
myTextureRegion = new TextureRegion(play);
myTexRegionDrawable = new TextureRegionDrawable(myTextureRegion);
playBtn = new ImageButton(myTexRegionDrawable); //Set the button up
stage.addActor(playBtn); //Add the button to the stage to perform rendering and take input.
Gdx.input.setInputProcessor(stage);
playBtn.addListener(new InputListener(){
#Override
public void touchUp (InputEvent event, float x, float y, int pointer, int button) {
System.out.println("Button Pressed");
game.setScreen(new IngamedayOne());
}
#Override
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
return true;
}
});
stage.addActor(playBtn);
}
#Override
public void create(){
}
#Override
public void show() {
Gdx.input.setInputProcessor(stage); //Start taking input from the ui
}
#Override
public void render(float delta) {
}
#Override
public void resize(int width, int height) {
// viewport.update(width, height);
}
#Override
public void render() {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); // Clear screen
spriteBatch.begin();
spriteBatch.getProjectionMatrix().setToOrtho2D(0, 0, WIDTH, HEIGHT);
spriteBatch.draw(Background,0,0);
spriteBatch.draw(exit,590,1140);
spriteBatch.draw(logo,125,600);
spriteBatch.draw(play,130,360);
spriteBatch.draw(option,170,100);
spriteBatch.draw(help,350,100);
spriteBatch.draw(credits,470,100);
stage.act(Gdx.graphics.getDeltaTime()); //Perform ui logic
spriteBatch.end();
//stage.draw(); //Draw the ui
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
Background.dispose();
logo.dispose();
exit.dispose();
}
}
My Second Screen
public class IngamedayOne extends ApplicationAdapter implements Screen {
// Constant rows and columns of the sprite sheet
private static final int FRAME_COLS = 5, FRAME_ROWS = 1;
private boolean peripheralAvailable;
// Objects used
Animation<TextureRegion> walkAnimation; // Must declare frame type (TextureRegion)
private Texture cat ,left_paw,right_paw,progressbar_background,progressbar_knob,pause,meter;
Texture carpet,desk,plants,square_carpet,shoes;
SpriteBatch spriteBatch;
Sprite sprite;
private Texture Background;
Viewport viewport;
private Camera camera;
private Stage stage;
// A variable for tracking elapsed time for the animation
float stateTime;
//Screen Size
private static final int WIDTH= 720;
private static final int HEIGHT= 1280;
public IngamedayOne() {
}
public IngamedayOne(MyGdxGame game) {
}
#Override
public void create() {
stage = new Stage();
spriteBatch = new SpriteBatch();
// Load the sprite sheet as a texture
cat = new Texture(Gdx.files.internal("cat.png"));
sprite = new Sprite(cat);
sprite.setPosition(0,0);
sprite.setSize(0,0);
peripheralAvailable = Gdx.input.isPeripheralAvailable(Input.Peripheral.Accelerometer);
camera = new PerspectiveCamera();
viewport = new ScreenViewport(camera);
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
//Display Items
carpet = new Texture("equip/carpet2.png");
desk = new Texture("equip/Desk.png");
square_carpet = new Texture("equip/Carpet.png");
plants = new Texture("equip/Plants.png");
shoes = new Texture("equip/Shoes.png");
// Progressbar
progressbar_background = new Texture("progression_map.png");
progressbar_knob = new Texture("cat_head.png");
//pause
pause = new Texture("pause.png");
meter = new Texture("meter.png");
//background
Background = new Texture(Gdx.files.internal("floor.png")); //File from assets folder
//button controller
left_paw = new Texture(Gdx.files.internal("left_paw.png"));
sprite = new Sprite(left_paw);
right_paw = new Texture(Gdx.files.internal("right_paw.png"));
sprite = new Sprite(right_paw);
// Use the split utility method to create a 2D array of TextureRegions. This is
// possible because this sprite sheet contains frames of equal size and they are
// all aligned.
TextureRegion[][] tmp = TextureRegion.split(cat, cat.getWidth() / FRAME_COLS, cat.getHeight()/ FRAME_ROWS);
// Place the regions into a 1D array in the correct order, starting from the top
// left, going across first. The Animation constructor requires a 1D array.
TextureRegion[] walkFrames = new TextureRegion[FRAME_COLS * FRAME_ROWS];
int index = 0;
for (int i = 0; i < FRAME_ROWS; i++) {
for (int j = 0; j < FRAME_COLS; j++) {
walkFrames[index++] = tmp[i][j];
}
}
// Initialize the Animation with the frame interval and array of frames
walkAnimation = new Animation<TextureRegion>(0.200f, walkFrames);
// Instantiate a SpriteBatch for drawing and reset the elapsed animation
// time to 0
spriteBatch = new SpriteBatch();
stateTime = 0f;
}
#Override
public void show() {
}
#Override
public void render(float delta) {
}
#Override
public void resize(int width, int height) {
viewport.update(width, height);
}
#Override
public void render() {
// clear previous frame
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); // Clear screen
stateTime += Gdx.graphics.getDeltaTime(); // Accumulate elapsed animation time
// Get current frame of animation for the current stateTime
TextureRegion currentFrame = walkAnimation.getKeyFrame(stateTime, true);
spriteBatch.begin();
spriteBatch.getProjectionMatrix().setToOrtho2D(0, 0, WIDTH, HEIGHT);
spriteBatch.draw(Background,0,0);
spriteBatch.draw(square_carpet,150,2,408,800);
spriteBatch.draw(carpet,230,980,250,260);
spriteBatch.draw(desk,10,1150,160,260);
spriteBatch.draw(plants,500,700,200,260);
spriteBatch.draw(shoes,300,500,110,110);
spriteBatch.draw(meter,190,990);
spriteBatch.draw(progressbar_background,20,1170);
spriteBatch.draw(progressbar_knob,18,1170);
spriteBatch.draw(pause,580,1150);
spriteBatch.draw(left_paw,10,25);
spriteBatch.draw(right_paw,517,25);
spriteBatch.draw(currentFrame, 260, 120 ); // Draw current frame at (50, 50)
spriteBatch.end();
stage.act(); //acting a stage to calculate positions of actors etc
stage.draw(); //drawing it to render all
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() { // SpriteBatches and Textures must always be disposed
spriteBatch.dispose();
cat.dispose();
left_paw.dispose();
right_paw.dispose();
stage.dispose();
Background.dispose();
progressbar_background.dispose();
progressbar_knob.dispose();
}
}
Your game should possess only one ApplicationListener(called when your application created).
Let's suppose that is your MainScreen which extends ApplicationAdapter(Adapter class of ApplicationListener interface), then not extend your IngamedayOne class again by ApplicationAdapter. You only need to implement with Screen interface.
public class IngamedayOne implements Screen {
}
create() method comes from ApplicationListener interface so migrate your code that in inside create() method to show().
Take a look of this wiki for more clearance.
https://github.com/libgdx/libgdx/wiki/Extending-the-simple-game
You should create actors to add to your stage (in this case buttons, like an ImageButton)
and then use the setScreen() function to change screens on button presses addClickListener()
You can read more about it here:
https://github.com/libgdx/libgdx/wiki/Scene2d
I have a project on libgdx and I'm using a splash screen. The problem is, every time I block my phone on main menu and unlock it again, game shows splash screen again and I'd like it not to "restart" the game but stay where it is
EDIT: to avoid publishing all unnecessary code, I'll explain how I made it:
simple class extending game calls setScreen to splash screen, then after 3 seconds splash screen calls main menu, and I'd like the splash screen not to appear again unless the game is DESTROYED and opened again
code:
public MainMenuScreen(final TowerConquest gam) {
game = gam;
}
#Override
public void show() {
stage = new Stage(new FillViewport(800, 480));
Gdx.input.setInputProcessor(stage);
//((OrthographicCamera)stage.getCamera()).setToOrtho(false, 800, 480);
atlas = new TextureAtlas("skins/userInterface.pack");
skin = new Skin(atlas);
table = new Table(skin);
table.setBounds(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
white = new BitmapFont(Gdx.files.internal("font/white.fnt"), false);
black = new BitmapFont(Gdx.files.internal("font/black.fnt"), false);
TextButtonStyle textButtonStyle = new TextButtonStyle();
textButtonStyle.up = skin.getDrawable("normalbutton");
textButtonStyle.down = skin.getDrawable("pressedbutton");
textButtonStyle.disabled = skin.getDrawable("dissabledbutton");
textButtonStyle.pressedOffsetX = 1;
textButtonStyle.pressedOffsetY = -1;
textButtonStyle.font = black;
buttonPlay = new TextButton("PLAY", textButtonStyle);
buttonPlay.pad(20);
buttonPlay.addListener(new ClickListener(){
#Override
public void clicked(InputEvent event, float x, float y) {
game.setScreen(new testGame(game));
//Gdx.input.vibrate(150);
dispose();
}
});
buttonExit = new TextButton("EXIT", textButtonStyle);
buttonExit.pad(20);
buttonExit.addListener(new ClickListener(){
#Override
public void clicked(InputEvent event, float x, float y) {
dispose();
Gdx.app.exit();
}
});
LabelStyle headingStyle = new LabelStyle(white, Color.WHITE);
heading = new Label("Tower Conquest", headingStyle);
table.add(heading);
table.getCell(heading).padBottom(50);
table.row();
table.add(buttonPlay);
table.getCell(buttonPlay).spaceBottom(15);
table.row();
table.add(buttonExit);
table.debug();
table.setOrigin(table.getWidth()/2, table.getHeight()/2);
table.setFillParent(true);
stage.addActor(table);
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0.2f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act(delta);
stage.draw();
}
#Override
public void resize(int width, int height) {
my resizes...
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
all disposes..
}
I found the answer, add this on manifest file
android:configChanges="keyboard|keyboardHidden|screenSize|orientation">
it is because when the screen gets locked it changes orientation to portrait so it restarts the app, with that option on, it won't restart the application
First of all, I don't speak English, so please forgive me for my terrible grammar.
I try to create Android game, using GLSurfaceView.
I read "Beginning of Android Game" (the link is sample code) in Japanese and imitate its code, so my game almost works fine.
But I have a problem.
When android turns off the screen, onPause of the activity is called as expected.
But sometimes (not always) onResume is called and then onPause() is called again, although the screen is still black.
In onResume I call GLSurfaceView().resume, so onSurfaceCreated() and onSurfaceChanged() are also called.
After this, the game puts out ANR.
[Expected flow]
onPause - (turn on the screen) - onResume - onSurfaceCreated - onSurfaceChanged
[Problematic flow]
onPause - onResume - onPause - onSurfaceCreated - onSurfaceChanged - (turn on the screen) - ANR
Even in the problematic case, GLSurfaceView.onDrawFrame is called normally, and the game is being rendered.
But it doesn't accept any tap.Is there infinite loop?
I found similar questions here and here, for example.
But I think there is no configuration Change.
In Android Manifest,
android:configChanges="keyboard|keyboardHidden|orientation|screenSize
was already declared.
And I can't move my code into Application class because I want to do something (e.g. reload some textures) in onSurfaceCreated method.
So my question is...
Why is the onResume method called?
Why it causes ANR?
And How can I avoid this ANR?
EDIT: the problem was solved.I appreciate it!
Here is my activity.
public abstract class GLGame extends Activity implements Game, Renderer {
enum GLGameState {
Initialized,
Running,
Paused,
Finished,
Idle
}
/////////////////////////////inter-ad
private static class AdHandler extends Handler {
private final WeakReference<GLGame> mActivity;
AdHandler(GLGame activity) {
mActivity = new WeakReference<GLGame>(activity);
}
#Override
public void handleMessage(Message msg) {
GLGame activity = mActivity.get();
switch(msg.what){
case 0:
if (activity != null) {
activity.showInterstitial();
}
break;
case 1:
if (activity != null) {
activity.prepareInterstitial();
}
break;
}
return;
}
};
Handler handler =new AdHandler(this);
/////////////////////////////inter-ad
//ad
static InterstitialAd interstitial;
static AdRequest adRequest;
AdView adView;
//////////////////////////////// //ad
GLSurfaceView glView;
GLGraphics glGraphics;
Audio audio;
Input input;
FileIO fileIO;
Screen screen;
GLGameState state = GLGameState.Initialized;
Object stateChanged = new Object();
long startTime = System.nanoTime();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
/////////////////////////////calculate and normalize the view size
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
float density = displaymetrics.densityDpi/160f;
int adpix = (int)( 50*density);
int navvarpix = (int)( 25*density);
int heightSubAd = displaymetrics.heightPixels -navvarpix-adpix;
int ratioWidth=10;
int ratioHeight=16;
boolean isWidthLong = displaymetrics.widthPixels/(float)heightSubAd > ratioWidth/(float)ratioHeight;
int width = isWidthLong ? heightSubAd * ratioWidth / ratioHeight : displaymetrics.widthPixels;
int height = isWidthLong ? heightSubAd : displaymetrics.widthPixels * ratioHeight/ratioWidth;
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(width, height);
lp.setMargins((displaymetrics.widthPixels-width)/2, 0, 0, (displaymetrics.widthPixels-width)/2);
///////////////////////////// //calc
glView = new GLSurfaceView(this);
glView.setLayoutParams(lp);
glView.setEGLConfigChooser(8 , 8, 8, 8, 16, 0);
glView.setRenderer(this);
adView = new AdView(this, AdSize.BANNER, "MY_NUMBER");
lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, adpix);
lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
lp.addRule(RelativeLayout.CENTER_HORIZONTAL);
adView.setLayoutParams(lp);
RelativeLayout layout = new RelativeLayout(this);
layout.setBackgroundColor(Color.BLACK);
layout.setId(0);
layout.addView(glView);
layout.addView(adView);
adView.loadAd(new AdRequest());
setContentView(layout);
/////////////////////////////////request inter-ad
interstitial = new InterstitialAd(this, "MY_NUMBER");
adRequest = new AdRequest();
adRequest.addTestDevice("MY_NUMBER");
adRequest.addTestDevice("MY_NUMBER");
interstitial.loadAd(adRequest);
/////////////////////////////////inter-ad
glGraphics = new GLGraphics(glView);
fileIO = new AndroidFileIO(getAssets());
audio = new AndroidAudio(this);
input = new AndroidInput(this, glView, 1, 1);
}
public void onResume() {
super.onResume();
glView.onResume();
}
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
glGraphics.setGL(gl);
synchronized(stateChanged) {
if(state == GLGameState.Initialized)
screen = getStartScreen();
state = GLGameState.Running;
screen.resume();
startTime = System.nanoTime();
}
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
}
#Override
public void onDrawFrame(GL10 gl) {
GLGameState state = null;
synchronized(stateChanged) {
state = this.state;
}
if(state == GLGameState.Running) {
float deltaTime = (System.nanoTime()-startTime) / 1000000000.0f;
startTime = System.nanoTime();
screen.update(deltaTime);
screen.present(deltaTime);
}
if(state == GLGameState.Paused) {
screen.pause();
synchronized(stateChanged) {
this.state = GLGameState.Idle;
stateChanged.notifyAll();
}
}
if(state == GLGameState.Finished) {
screen.pause();
screen.dispose();
synchronized(stateChanged) {
this.state = GLGameState.Idle;
stateChanged.notifyAll();
}
}
}
#Override
public void onPause() {
synchronized(stateChanged) {
if(isFinishing())
state = GLGameState.Finished;
else
state = GLGameState.Paused;
while(true) {
try {
stateChanged.wait();
break;
} catch(InterruptedException e) {
}
}
}
glView.onPause();
super.onPause();
}
public GLGraphics getGLGraphics() {
return glGraphics;
}
#Override
public Input getInput() {
return input;
}
#Override
public FileIO getFileIO() {
return fileIO;
}
#Override
public Graphics getGraphics() {
throw new IllegalStateException("We are using OpenGL!");
}
#Override
public Audio getAudio() {
return audio;
}
#Override
public void setScreen(Screen screen) {
if (screen == null)
throw new IllegalArgumentException("Screen must not be null");
this.screen.pause();
this.screen.dispose();
screen.resume();
screen.update(0);
this.screen = screen;
}
#Override
public Screen getCurrentScreen() {
return screen;
}
#Override
public Handler getHandler(){
return handler;
}
private void showInterstitial(){
if(interstitial.isReady()){
interstitial.show();
}
}
private void prepareInterstitial(){
interstitial.loadAd(adRequest);
}
}
thank you for your kindness!
So, this is too hard for me to explain this in short, so the title looks so creepy. Well, I am writing a small android application and i have like three screens: the main-menu one, and two in-game screens. I can switch between the last two ones with a switch button. The problem is, that when i switch back to the last screen I've been to, all its acting stuff starts again from the very beginning. I have also seen a similar question here, but i did not work for me(( So, is there any way to keep the screen rendering, while I am using the other one?
Thank you!
The first screen:
public class InGameScreen implements Screen {
TinyBattles game;
public static OrthographicCamera camera;
public static Button switchButton1;
public InGameScreen(TinyBattles game) {
this.game = game;
}
#Override
public void show() {
camera = new OrthographicCamera(Global.VIEWPORT_WIDTH, Global.VIEWPORT_WIDTH*Global.actualHeight/Global.actualWidth);
camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0);
camera.update();
switchButton1 = new Button();
switchButton1.create(10, 800, 150, 150);
Assets.loadSwitchButton();
}
#Override
public void render(float delta) {
Global.cleanScreen();
touchHandler(camera, Global.touch);
switchButton1.act();
switchButton1.render(Assets.buttonSwitchStateUpSprite, Assets.buttonSwitchStateDownSprite);
Global.debugRender();
localDebugRender();
leaveScreen();
Global.batch.getProjectionMatrix().setToOrtho2D(0, 0, Global.actualWidth, Global.actualHeight);
Global.batch.setProjectionMatrix(camera.combined);
Global.shapeRenderer.setProjectionMatrix(camera.combined);
}
public void localDebugRender(){
switchButton1.debugRender();
}
public void touchHandler(OrthographicCamera camera, Vector3 touch){
if (Gdx.input.isTouched()){
touch.set(Gdx.input.getX(), Gdx.input.getY(), 0);
camera.unproject(touch);
Global.finger.bounds.x = touch.x - 64;
Global.finger.bounds.y = touch.y - 64;
}else{
Global.finger.bounds.x = 10000;
Global.finger.bounds.y = 10000;
}
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
}
public void leaveScreen(){
if (switchButton1.isPressed == true){
game.setScreen(TinyBattles.inGameVirtualScreen);
}
}
}
The second screen:
public class InGameVirtualScreen implements Screen {
TinyBattles game;
public static World world;
public static OrthographicCamera camera;
public static Button switchButton2;
public static Balls balls;
public InGameVirtualScreen(TinyBattles game) {
this.game = game;
}
#Override
public void show() {
world = new World(new Vector2(0, 0), true);
camera = new OrthographicCamera(Global.VIEWPORT_WIDTH, Global.VIEWPORT_WIDTH*Global.actualHeight/Global.actualWidth);
camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0);
camera.update();
switchButton2 = new Button();
switchButton2.create(10, 800, 150, 150);
balls = new Balls();
Assets.loadBallSprites();
balls.create();
balls.setup();
}
#Override
public void render(float delta) {
Global.tweenManager.update(1 / 60f);
Global.cleanScreen();
world.step(1 / 60f, 10, 10);
touchHandler(camera, Global.touch);
switchButton2.act();
balls.act();
renderLayerOne();
renderInterfaceLayer();
renderDebugLayer();
leaveScreen();
Global.batch.getProjectionMatrix().setToOrtho2D(0, 0, Global.actualWidth, Global.actualHeight);
Global.batch.setProjectionMatrix(camera.combined);
Global.shapeRenderer.setProjectionMatrix(camera.combined);
}
public void renderLayerOne(){
balls.render();
}
public void renderInterfaceLayer(){
switchButton2.render(Assets.buttonSwitchStateUpSprite, Assets.buttonSwitchStateDownSprite);
}
public void renderDebugLayer(){
Global.debugRender();
localDebugRender();
}
public void localDebugRender(){
switchButton2.debugRender();
}
public void touchHandler(OrthographicCamera camera, Vector3 touch){
if (Gdx.input.isTouched()){
touch.set(Gdx.input.getX(), Gdx.input.getY(), 0);
camera.unproject(touch);
Global.finger.bounds.x = touch.x - 64;
Global.finger.bounds.y = touch.y - 64;
}else{
Global.finger.bounds.x = 10000;
Global.finger.bounds.y = 10000;
}
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
}
public void leaveScreen(){
if (switchButton2.isPressed){
game.setScreen(TinyBattles.inGameScreen);
}
}
}
There is a leaveScreen() method at the bottom of the each class
You should move all your code in each screen from show() to the constructor. show() is called every time the screen becomes the active screen, so you don't want to do initialization there.
By the way, you should never keep static references to anything that implements Disposable, such as SpriteBatch, or anything that keeps a reference to something that implements Disposable, such as Button or Stage. If you do, when the user backs out of your game activity and reopens it, there will be memory leaks and incorrect textures, etc.
Its been a while since I used libgdx, but it seems you are creating a new screen on each leaveScreen function.
See here for a better approach, where when you create the Game class you create the screens as well:
public class MyGame extends Game {
MainMenuScreen mainMenuScreen;
AnotherScreen anotherScreen;
#Override
public void create() {
mainMenuScreen = new MainMenuScreen(this);
anotherScreen = new AnotherScreen(this);
setScreen(mainMenuScreen);
}
}
Then, you change the screens like this:
public void leaveScreen(){
if (switchButton2.isPressed){
game.setScreen(game.anotherScreen);
}
}
As I said it's been a while, but give it a shot :)
I am using the Libgdx framework along with Spine to do Skeleton animation using Atlas and exported Json file. In the file there are many animations. I am able to load animations from the json file. But there are 2 issues :
Lag when animation starts : there is a lag of 3-4 seconds before the animation starts. I see a black screen and then the animation works.
Delta - i have some issues with the delta time. Only some animations are running from the default delta value, however if i change ( increment or decrease the delta value), different animations give different results.
Cant understand what to do ? I have searched thoroughly in the internet but haven't found the solution.
I am posting my code below:
This is my Main Class
public class AndroidLauncher extends AndroidApplication
{
SpriteBatch batch;
Texture img;
ShapeRenderer renderer;
TextureAtlas atlas;
Skeleton skeleton;
Animation animation;
float time;
Bone root;
float x,y;
View spine_view;
private Screen curScreen; // the current screen
#Override
protected void onCreate (Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
//initialize(new Main(20), config);
spine_view=initializeForView(new ApplicationListener()
{
#Override
public void resume()
{
curScreen.resume();
}
#Override
public void resize(int width, int height)
{
}
#Override
public void render()
{
curScreen.render((Gdx.graphics.getDeltaTime()/(1.5f))); //call the rendermethod with the delta time as parameter
}
#Override
public void pause()
{
curScreen.pause();
}
#Override
public void dispose()
{
curScreen.dispose();
}
#Override
public void create()
{
Gdx.graphics.getWidth();
Gdx.graphics.getHeight();
Firstscreen temp = new Firstscreen();//just an example of the first screen to load up
setScreen(temp);
}
}, config);
LinearLayout l1 = (LinearLayout) findViewById(R.id.container);
l1.addView(spine_view);
}
public void setScreen(Screen s) {
if (curScreen != null) {
curScreen.hide();
curScreen.dispose();
}
curScreen = s;
curScreen.show();
}
}
...............................................
And this is the screen Iam rendering
public class Firstscreen implements Screen
{
SpriteBatch batch;
Texture img;
ShapeRenderer renderer;
TextureAtlas atlas;
Skeleton skeleton;
Animation animation;
float time;
Bone root;
float x,y;
int count =0;
#Override
public void render(float delta)
{
// track
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
time += delta;
animation.apply(skeleton,delta,time, false, null);
SkeletonRenderer render = new SkeletonRenderer();
batch.begin();
render.draw(batch, skeleton);
skeleton.updateWorldTransform();
batch.end();
}
#Override
public void resize(int width, int height)
{
}
#Override
public void show()
{
batch = new SpriteBatch();
renderer = new ShapeRenderer();
atlas = new TextureAtlas(Gdx.files.internal("abc.atlas"));
SkeletonJson json = new SkeletonJson(atlas);
// set the scale of skeleton
json.setScale(0.3f);
SkeletonData skeletonData = json.readSkeletonData(Gdx.files.internal("skeleton.json"));
skeleton = new Skeleton(skeletonData);
skeleton.setToSetupPose();
skeleton.setSkin("Carla");
// set the position of the skeleton to render( here middle)
skeleton.setPosition((Gdx.graphics.getWidth()/2)-(x/2),( Gdx.graphics.getHeight()/2)-(y/2));
//animation = skeletonData.findAnimation("KID-LEVEL 2 - Couch potato");
animation = skeletonData.findAnimation("LEVEL 91- Around a world");
//animation = skeletonData.findAnimation("KID-LEVEL 7 - Super Hero");
}
#Override
public void hide()
{
}
#Override
public void pause()
{
}
#Override
public void resume()
{
}
#Override
public void dispose()
{
batch.dispose();
}
}
That's happens beacuse you are managing a timeline manually.
Use AnimationState instead:
Skeleton skeleton = new Skeleton(skeletonData);
// sctruct for mix animations
AnimationStateData stateData = new AnimationStateData(skeletonData);
// and state
AnimationState state = new AnimationState(stateData);
In some update method (or render, if you prefer update while rendering) call something like this:
state.update(delta);
And in the actual render method:
// apply the state to skeleton
state.apply(skeleton);
// update transformations
skeleton.updateWorldTransform();
// draw then
render.draw(batch, skeleton);
So, AnimationState isn't designed not for managing the delta only, you can play&mix animations using it:
state.setAnimation(0, "LEVEL 91- Around a world", isLoop);
To change animation speed use setTimeScale:
state.setTimeScale(0.5f); // set any time scale you want
Also, you may have some perfomance issues because you calling new SkeletonRenderer() in render method. To fix that, move this code to constructor.