i'm new of libgdx and this is my first app, but i have the problem with screen switch.
i have set main class like this:
public class MyClass extends Game {
MenuClass menuClass;
ActionGame actionGame;
#Override
public void create() {
menuClass = new MenuClass(this);
actionGame = new ActionGame(this);
setScreen(actionGame);
}
}
and method of ActionGame class like this:
....
#Override
public void pause() {
game.setScreen(game.menuClass);
}
#Override
public void resume() {
this.show();
this.render(Gdx.graphics.getDeltaTime());
}
....
and method of menuClass.java like this, when touch Play button:
....
#Override
public void resume() {
game.actionGame.resume();
}
....
When i touch play button i wish that actionGame class return in action render, but the render don't start.
I have try with setScreen, but this restart my screen, this not good.
Help
Thanks
You're using resume incorrectly. It is something that is always called when your app is brought back to screen. You should never call resume() on any of your classes yourself. It is called by Libgdx when your app is brought back to the foreground.
It is correct that you should switch to the menu screen in the pause method, because gamers expect the game to automatically go to a menu or pause screen when the app goes off screen. But you do not want to be automatically switching back to the game when the app comes back on screen.
The resume method would only be used for reloading stuff that you unloaded in pause (which you probably don't need to do), or to restart music, or something like that.
Your Play button definitely should not be calling resume. It should be calling setScreen(actionGame);. And there should be nothing in any of your resume methods as you have currently designed it.
Related
I am created a Stopwatch app with using Chronometer and ViewModel the app is working well until the configuration change. when the rotation of the screen the Stopwatch is reset into 00:00.
this is part of StopwatchTabFrag.java.
stopwatchTabViewModel.buttonIcon.observe(getViewLifecycleOwner(), new Observer<Integer>() {
#Override
public void onChanged(Integer imgId) {
switch (imgId){
//when the icon is changed to pause (or) when user clicks play icon then Stopwatch is start.
case R.drawable.ic_round_pause_circle_filled_24:
binding.stop.setVisibility(View.VISIBLE);
binding.startPause.setImageResource(imgId);
stopwatchTabViewModel.startStopwatch(stopwatchChronometer);
break;
//when the icon is changed to start (or) when user clicks pause icon then Stopwatch is pause.
case R.drawable.ic_round_play_arrow_24:
binding.startPause.setImageResource(imgId);
stopwatchTabViewModel.pauseStopwatch(stopwatchChronometer);
break;
case R.drawable.ic_round_stop_24:
binding.stop.setVisibility(View.GONE);
stopwatchTabViewModel.stopStopwatch(stopwatchChronometer);
}
}
});
I am using Observer to whenever changing the particular button icon it was execute this particular task.
this is part of StopwatchTabViewModel.java.
public void startStopwatch(Chronometer chronometer){
if (!isRunning.getValue()){
chronometer.setBase(SystemClock.elapsedRealtime()-pauseOfset.getValue());
chronometer.start();
_isRunning.setValue(true);
}
}
public void pauseStopwatch(Chronometer chronometer){
if (isRunning.getValue()){
chronometer.stop();
_pauseOfset.setValue(SystemClock.elapsedRealtime()-chronometer.getBase());
_isRunning.setValue(false);
}
}
public void stopStopwatch(Chronometer chronometer){
chronometer.setBase(SystemClock.elapsedRealtime());
_pauseOfset.setValue(0L);
chronometer.stop();
//Reset the icon to Start
_buttonIcon.setValue(R.drawable.ic_round_play_arrow_24);
}
I implemented the Stopwatch task methods in ViewModel class. I don't know if this is correct or wrong.
I am waiting for your answers.
add this line to your Activitys declaration in manifest:
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
it will prevent Activity destroy on rotation (thus also your chrono), you have to handle rotation in onConfigurationChanged method call by yourself (you probably won't need to do anything in your case)
HERE you have some info about configuration changing.
I am currently working on a Game in Android Studio that combines Java and Android.
My problem: When I close the App, wait for a few seconds and return to the App, it still runs in the background.
This causes Game Objects to continue moving which always results in Game Over obviously.
I implemented a "Pause" Function / Method in my Game, that can be accessed via a Pause Button, but also should get called when I close the app.
This should pause the game when I close the app and be paused when I return to my app.
I also implemented a "Resume" Function / Method to get out of the pause screen, that should also be called when I re-enter my app.
Both methods "public void pause()" and "public void resume()" get called correctly when my activity provokes the onStop() and onRestart() methods but they do not do what they normally do when called via the pause button.
I tested this with a simple System.out.println("");
This showed me that my pause() and resume() methods get called when I close or re-enter my app. But they don't actually do the logic behind them (pause the game)
My MainActivity Class
public class MainActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
scene = new GameplayScene();
#Override
protected void onStop() {
super.onStop();
scene.pause(); //
System.out.println("stopped"); //testing purposes
}
#Override
protected void onRestart() {
super.onRestart();
scene.resume();
System.out.println("restarted"); //testing purposes
}
}
And my GamePlayScene Class
public void pause() {
System.out.println("Pause Method Called");//works
paused = true;
timeScale = 0; //this freeze all movement (game pause)
pauseImg = bf.decodeResource(Constants.CURRENT_CONTEXT.getResources(), R.drawable.resumesymbol);
}
public void resume() {
System.out.println("Resume Method Called");
paused = false;
timeScale = 1; //this unlocks every movement again (game resume)
touchable = true;
pauseImg = bf.decodeResource(Constants.CURRENT_CONTEXT.getResources(), R.drawable.pausesymbol);
}
As I said: Every method necessary gets called correctly.
I/System.out: Pause Method Called
I/System.out: stopped
I/System.out: Resume Method Called
I/System.out: restarted
Why does it not actually pause the Game but instead keeps moving the objects?
EDIT:
My Button is just a Rect, 100x100 pixels that floats in the top right corner.
The Button is displayed via a Bitmap of a pausebutton.png and I check if the Button has been pressed by the following:
public void pause(float touchX, float touchY) {
if (pauseRect.contains((int)touchX,(int) touchY)) {
paused = true;
timeScale = 0;
pauseImg = bf.decodeResource(Constants.CURRENT_CONTEXT.getResources(), R.drawable.resumesymbol);
}
}
This is the pause method for the button.
This method gets called by the user on the physical button - the other pause method you see above should get called by closing the app (which works perfectly fine, but at the moment it's getting closed it does not do the other stuff inside the method)
What the method does in detail:
sets the boolean paused = true;
sets int timeScale = 0
The gameloop always calls update() on every frame for my player class, where in this update() method it sets the speed * timeScale resulting in a stop of motion when timeScale = 0.
This all works fine with my pause button but not with onRestart()
I would create an app for get the double tap also if the app is in background.
I create this code:
public class MainActivity extends Activity implements
GestureDetector.OnGestureListener,
GestureDetector.OnDoubleTapListener
{
private static final String DEBUG_TAG = "Gestures";
private GestureDetectorCompat mDetector;
private int counter = 0;
// Called when the activity is first created.
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDetector = new GestureDetectorCompat(this,this);
mDetector.setOnDoubleTapListener(this);
}
#Override
public boolean onDoubleTap(MotionEvent event)
{
counter++;
Log.d(DEBUG_TAG, String.valueOf(counter));
return true;
}
//..........................
}
if the app is open in the log i see the number of count of double tap increase, if the app work in background the number is blocked.
There is a way for fix it? or i have to create a services? i need a grafic app and service, there is a way for create just one with both things?
Thanks
There isn't an easy answer to this. Normally it is NOT possibile because an App cannot interact with other pieces of Android interface that is OUTSIDE the App itselfs. But if the device has Root Permissions it's possibile to directly read the Touchscreen and intercept all touch events.
An alternative method that not requires Root exists but I discurage to use it: place a fullscreen View that acts as a transparent layer and that intercepts all the events. However this method has few disadvantages: slows down graphic performance of WHOLE device (expecially while running games), could interfere with user experience while touching interactive areas (buttons, checkboxes, etc...) and however could not work well by loosing some touching events.
I'm making a little game and in it I have to check if a value is zero every second. When it is zero the game should stop and show a dialog instead.
As from now the game never ever shoud work until the app is reinstalled.
So, I have an timer with an timertask which executes a runOnUiThread.
Timer:
private void update(){
Timer timer = new Timer();
timer.schedule(new TimerTask(){
#Override
public void run() {
onChange();
}
},0,(1000* getResources().getInteger(R.integer.remove_speed_inSecond)));
}
runOnUiThread: (with try/catch to catch the exeption at this point but i want to fix and not just ignore it.)
private void onChange(){
runOnUiThread(new Runnable() {
#Override
public void run() {
try{
checkupifexpire();
}
catch (Exception ex) {
}
}
});
}
The Method where i show the dialog:
private void checkupifexpire() {
if(eat == 0 || drink == 0 || wash == 0 || care == 0){
dialog = new Dialog(this, android.R.style.Theme_Black_NoTitleBar_Fullscreen);
dialog.setOnCancelListener(new DialogInterface.OnCancelListener()
{
#Override
public void onCancel(DialogInterface dialog)
{
GameEngine.this.finish();
}
});
dialog.setContentView(R.layout.activity_rip);
dialog.show();
}
}
Always when I press the back button or just the home button then the App crashes.
Any Idea how to fix this?
So, the logcat tells us that is crashes on line 306 of GameEngine.java, in the method checkupifexpire, which looks like it is the dialog.show() line.
I'm not 100% sure, but from what you've said, it would seem to me that when back or home is pressed, the app will lose its UI thread. This means that checkuponexpire cannot do what it does.
To solve your crash problem, there are three obvious options:
You could use onPause in your main activity to catch when the app loses the screen. At this point you need to either stop the timer, or switch it to using Toast to communicate information.
Only use Toast in checkuponexpire
Decide that when the back or home is pressed the game is over anyway and cancel the Timer.
To Actually get the dialog, it may also be helpful to change the context you use to create the dialog with. Although it should be used sparingly, it may be that getApplicationContext() is what you need here (possibly this.getApplicationContext()).
Thanks to Neil Townsend and WELLCZECH. :)
My problem was the Lifecycles.
Mostly i had the App running in the onCreat() and had no onStart() method.
Just didn't know that thies methods were as much important as they are.
Also i didn't need a dialog shown. Instead i just have to start a new activity and cancel the old one.
The example is pretty straightforward: i want to let the user know about what the app is doing by just showing a text (canvas.drawText()). Then, my first message appears, but not the other ones. I mean, i have a "setText" method but it doesn't updates.
onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(splash); // splash is the view class
loadResources();
splash.setText("this");
boundWebService();
splash.setText("that"):
etc();
splash.setText("so on");
}
The view's text drawing works by doing just a drawText in onDraw();, so setText changes the text but doesn't show it.
Someone recommended me replacing the view with a SurfaceView, but it would be alot of trouble for just a couple of updates, SO... how the heck can i update the view dinamically at runtime?
It should be quite simple, just showing a text for say 2 seconds and then the main thread doing his stuff and then updating the text...
Thanks!
Update:
I tried implementing handler.onPost(), but is the same story all over again. Let me put you the code:
public class ThreadViewTestActivity extends Activity {
Thread t;
Splash splash;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
splash = new Splash(this);
t = new Thread(splash);
t.start();
splash.setTextow("OA");
try { Thread.sleep(4000); } catch (InterruptedException e) { }
splash.setTextow("LALA");
}
}
And:
public class Splash implements Runnable {
Activity activity;
final Handler myHandler = new Handler();
public Splash(Activity activity) {
this.activity=activity;
}
#Override
public void run() {
// TODO Auto-generated method stub
}
public synchronized void setTextow(final String textow) {
// Wrap DownloadTask into another Runnable to track the statistics
myHandler.post(new Runnable() {
#Override
public void run() {
TextView t = (TextView)activity.findViewById(R.id.testo);
t.setText(textow);
t.invalidate();
}
});
}
}
Although splash is in other thread, i put a sleep on the main thread, i use the handler to manage UI and everything, it doesn't changes a thing, it only shows the last update.
I haven't hit this yet, but I think the usual pattern is to do lengthy initialization in a background thread, and use Handler.post() to update the UI. See http://developer.android.com/reference/android/widget/ProgressBar.html for a different, but possibly related, example.
Also see this answer, especially the first paragraph:
The problem is most likely that you
are running the splash screen (some
sort of Dialog such as ProgressDialog
I assume) in the same thread as all
the work being done. This will keep
the view of the splash screen from
being updated, which can keep it from
even getting displayed to the screen.
You need to display the splash screen,
kick off an instance of AsyncTask to
go download all your data, then hide
the splash screen once the task is
complete.
Update (based on your update and your comment): You are not supposed to update the UI in any thread except the one where your Activity is created. Why is it impossible for you to load your resources in a background thread?
First: onCreate is executed on main UI thread of application so no UI updates until you leave it. Basically you need one thread to execute long running tasks and some mechanism to push updates into the UI.
Most usual approach is to extend AsyncTask see this link for further info
i suppose that your view is an extended view and you call onDraw for drawing the view, so, maybe the view isnĀ“t 'refresh' their state, so try this
onCreate(Bundle bundle) {
setContentView(splash); // splash is the view class
loadResources();
splash.setText("this");
splash.invalidate();
boundWebService();
splash.setText("that"):
splash.invalidate();
etc();
splash.setText("so on");
splash.invalidate();
}