LibGDX - Splash Screen timer isn't working - libgdx

I want a timer that switches screens after a certain amount of time. Here is the code for my splash screen:
private boolean timerIsOn = false;
And here is the render() method code:
if(!timerIsOn) {
timerIsOn = true;
Timer.*schedule*(new Task() {
#Override
public void run() {
*changeScreen*();
}
}, 15);
} else if(Gdx.input.isTouched()) {
// Remove the task so we don't call changeScreen twice:
Timer.instance().clear();
*changeScreen*();
}
}
I'm getting red swiggly lines under the parts of the code that have * and * surrounding them but the suggested action to fix it doesn't help.
Also, if you know of an easier way to make this work or possibly a tutorial that would be great as well.

Related

Pixel Listener (Listener reacting on Pixel changes)

i want to create a program that is reacting on some pixels and is increasing a counter when a selected pixel is changed.
Im using the Robot class for it. cause this:
Boolean dontcount = false;
Robot robot = new Robot();
while (true) {
if(robot.getPixelColor(900, 900).equals(b)){
if(dontcount == false){
counter=counter++;
dontcount = true;
System.out.println(counter);
}
} else {
dontcount = false;
}
}
is killing my pc, i am looking for another way. I guess its possible with listeners. but i got no idea how. any solutions?
Your code does not compile and doesn't seem to make much sense so I rewrote it. In the future, make sure you have a complete example.
The reason the code is killing your PC is because you should be putting a slight wait time in your while loop to let the computer know it has a chance to breathe. 10ms is plenty.
import java.awt.AWTException;
import java.awt.Color;
import java.awt.Robot;
public class Main
{
public static void main(String[] args)
{
Robot robot = null;
try
{
robot = new Robot();
} catch (AWTException e1)
{
e1.printStackTrace();
}
Color lastPixelColor = null;
int counter = 0;
while (true)
{
Color pixelColor = robot.getPixelColor(900, 900);
if (!pixelColor.equals(lastPixelColor))
{
counter++;
System.out.println(counter);
}
lastPixelColor = pixelColor;
try
{
// You need to sleep so you don't murder your CPU
Thread.sleep(10);
} catch (InterruptedException e)
{
}
}
}
}

Elements disappear after pause and resume

Testing my libGDX app in RoboVM, I have encountered a major problem. When I pause my app (by actually going to the Home screen or sending app invites via Facebook) and then return to my app, classes of my games disappear. As if it does not store data properly on the resume() method. First i though it there was a problem of my AssetLoader, but after some debugging I found that the situation is worse. Actual instances of classes and shapes disappear. As if they never existed.
After googling the issue, I found that it might be related to IOSGraphics, but I have not managed to fix the problem.
My IOSLauncher looks something like this, I have erased the Facebook & Google AdMob specific code.
protected IOSApplication createApplication() {
IOSApplicationConfiguration config = new IOSApplicationConfiguration();
config.useAccelerometer = true;
config.useCompass = true;
config.orientationPortrait = true;
config.orientationLandscape = false;
return new IOSApplication(new Game(this), config);
}
#Override
public boolean didFinishLaunching(UIApplication application,
UIApplicationLaunchOptions launchOptions) {
FBSDKApplicationDelegate.getSharedInstance().didFinishLaunching(application, launchOptions);
initialize();
return true;
}
public void initialize() {
//...
}
public static void main(String[] argv) {
NSAutoreleasePool pool = new NSAutoreleasePool();
UIApplication.main(argv, null, IOSLauncher.class);
pool.close();
}
#Override
public void showAds(boolean show) {
//...
}
#Override
public void shareOnFacebook() {
//...
}
#Override
public void inviteFriends() {
//....
}
#Override
public boolean openURL(UIApplication application, NSURL url,
String sourceApplication, NSPropertyList annotation) {
super.openURL(application, url, sourceApplication, annotation);
return FBSDKApplicationDelegate.getSharedInstance().openURL(
application, url, sourceApplication, annotation);
}
#Override
public void didBecomeActive(UIApplication application) {
super.didBecomeActive(application);
FBSDKAppEvents.activateApp();
}
#Override
public void willResignActive(UIApplication application) {
super.willResignActive(application);
}
#Override
public void willTerminate(UIApplication application) {
super.willTerminate(application);
}
}
This sounds similar to a threading bug I once encountered. I fixed it by deferring resize and resume but I'm not sure if it will help in your case. Something like this:
private boolean needResize, needResume;
private void resize (int width, int height){
needResize = true;
}
private void deferredResize ();
if (!needResize) return;
needResize = false;
int width = Gdx.graphics.getWidth();
int height = Gdx.graphics.getHeight();
//move your resize code here
}
private void resume (){
needResume = true;
}
private void deferredResume (){
if (!needResume) return;
needResume = false;
//move your resume code here
}
public void render (){
deferredResize();
deferredResume();
//...
}
I suggest that you start looking for an alternative to RoboVM to avoid more issues in the future, as Robovm was acquired by Microsoft Xamarin (sad but true) and the framework is no longer maintained. License keys (with Libgdx) will continue to work until the 17th of April 2017, there will be no further updates to RoboVM, be it new features or bug fixes.
As far as I know, Libgdx will switch to Multi-OS engine as the default iOS backend for newly created libGDX projects in the next couple of weeks.
After a couple of days filled with headache I found the solution!
LifeCycle methods like pause & resume, hide & show are not always called When they are supposed to be called, therefore data is not stored properly. This issue can completely break your game.
This thing only occurred when testing my game on the iOS platform, mainly when I opened a 3rd party app, Facebook in this case. No such thing found on Android, though.
The only thing I changed on the iOS version was calling the mentioned methods manually to make sure it always pauses and resumes when it has to.

Transition gives flicker when splash screen calls "finish()" after startActivity(intent, options.toBundle());

I am creating an android app (lollipop version). App shows large logo in middle of splash screen. Login screen contains a small sized logo at top. I use ActivityOptions.makeSceneTransitionAnimation() to set animation from large logo of splash screen to small logo of login screen.
Splash screen launches to launch app. After delay of few milisec , splash screen creates intent for login screen. Also set transition. Then it starts login activity. It begins transition animation of logo. And shows login screen successfully. Everything is working well and animation is smooth up to this point.
Then I added "finish();" in splash screen so that back button on login screen do not loads splash screen. Now transition was giving flicker.
I tried following approach but still flicker is there.
used "finishAfterTransition();" instead of "finish();"
added FLAG_ACTIVITY_CLEAR_TOP and FLAG_ACTIVITY_NEW_TASK flags to intent (this leads to even wired behavior)
Override onBackPressed() in login screen. and added
finish();
android.os.Process.killProcess(android.os.Process.myPid()); - This terminates app but restarts it again.
Here, I'm pasting the code of splashScreen. This code is working but gives flicker while transition. gotoLoginScreen() method at the end of class is the place which loads login activity. The login screen is basic activity template from android studio. Using com.android.support:appcompat-v7:21.0.2 library to support lower devices.
public class SplashActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment())
.commit();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_splash, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
ImageView imageView_logo;
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_splash, container, false);
imageView_logo = (ImageView) rootView.findViewById(R.id.imageview_logo);
imageView_logo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startTimer();
}
});
startTimer();
return rootView;
}
private void startTimer() {
new CountDownTimer(1000, 1000) {
#Override
public void onTick(long l) {
}
public void onFinish() {
launchNextActivity();
}
}.start();
}
/**
* base on session continuity the next activity will be decided and
* launches next activity
*/
private void launchNextActivity() {
if (isSessionContinue()) {
goToHomeScreen();
} else {
goToLoginScreen();
}
}
/**
* checks current user ID, null indicate terminated session
*
* #return true if session is continued and false of session is terminated
*/
private boolean isSessionContinue() {
return false;
}
/**
* directly leads to home screen
*/
private void goToHomeScreen() {
//code to start home screen by skipping login
}
/**
* leads to login screen.
*/
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
**private void goToLoginScreen() {
Intent loginIntent = new Intent(getActivity(), LoginActivity.class);
if (android.os.Build.VERSION.SDK_INT >= 21) {
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(getActivity(), imageView_logo, getString(R.string.transition_logo));
getActivity().startActivity(loginIntent, options.toBundle());
getActivity().finishAfterTransition();
} else {
startActivity(loginIntent);
getActivity().finish();
}
}**
}
}
Is there any way to avoid flicker? It is a stain on beauty.
add this to your activity:
private boolean shouldFinish = false;
#Override
public void onStop() {
super.onStop();
if (shouldFinish) {
getActivity().finish();
}
}
and change this:
private void goToLoginScreen() {
shouldFinish = true;
Intent loginIntent = new Intent(getActivity(), LoginActivity.class);
if (android.os.Build.VERSION.SDK_INT >= 21) {
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(getActivity(), imageView_logo, getString(R.string.transition_logo));
getActivity().startActivity(loginIntent, options.toBundle());
} else {
startActivity(loginIntent);
}
}

libgdx: Dispose Screen on Demand

Say I have a splash screen. This screen is loaded only at the beginning of the game, and afterwards I don't use it.
Is it possible to dispose this screen on demand?
I tried to dispose it right after setting the screen after the splash, and also tried to call dispose() on the hide() method.
Both of the tries rendered in an exception.
How can I dispose this screen on demand? I have there pretty heavy textures, and wanted to free the memory as soon as possible.
Example:
// SplashScreen class
class SplashScreen implements Screen {
private boolean renderingEnabled = true;
private Object lock = new Object();
#Override
public void render(float delta) {
synchronized(lock) {
if (!renderingEnabled) {
return;
}
spriteBatch.begin();
// here render the animations
spriteBatch.end();
}
}
#Override
public void dispose() {
synchronized(lock) {
renderingEnabled = false;
// here come the disposing of SpriteBatch and TextureAtlas
atlas.dispose();
atlas = null;
spriteBatch.dispose();
spriteBatch = null;
}
}
}
// The usage
game.setScreen(splashScreen);
...
// now when the splash screen animation is finished, I am calling the following from the controller:
splashScreen.dispose();
game.setScreen(mainMenuScreen);
I get the following exception:
FATAL EXCEPTION: GLThread 398
java.lang.NullPointerException
at mypackage.SplashScreen.render(SplashScreen.java:85)
at com.badlogic.gdx.Game.render(Game.java:46)
at mypackage.Game.render(MyGame.java:33)
at com.badlogic.gdx.backends.android.AndroidGraphics.onDrawFrame(AndroidGraphics.java:414)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1522)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)
And when I have the following dispose pattern (disposing after showing the mainMenuScreen)
// The usage
game.setScreen(splashScreen);
...
// now when the splash screen animation is finished, I am calling the following from the controller:
game.setScreen(mainMenuScreen);
splashScreen.dispose();
I get the same exception.
The exception is on spriteBatch.end() row inside the render method. The spriteBatch member turns to be null. Really confusing, since I have mutual exclusive lock on the render and the dispose methods.
What I figured out, is that LibGDX works in one thread.
What happens is the following. When the game.setScreen(mainMenuScreen) is called, and the program is in the middle of the render method of the splash screen, the thread is interrupted, and the code for setting the mainMenuScreen is executed (in the Game class), and then going back to continue the render method of the splash screen. Weird, right? After setting the new screen still to render the old screen?
Anyways, what I did is the following:
As part of the Game.setScreen(Screen screen) method, the Screen.hide() method is called on the old screen.
So what I did, I introduced a flag, hideCalled and set it to true in the hide() event inside the splash screen.
Inside the render method of the splash screen I check this flag at the beginning and at the end of the method. If the flag is true - I dispose the screen.
I was just thinking about AssetManager, maybe it would help you with this problem in a cleaner way.
Take a look here.
I see it loads assets asynchronously so maybe this problem that you described would not be happening again.
And just for some knowledge sharing, I changed screens with another approach:
I used actions attached to an image, and these actions are executed in the order they are added. First i created an action which loads the images, then, when this first action was finished, i added another action which switches the screen.
Here is my code:
#Override
public void show() {
stage.addActor(splashImage);
splashImage.addAction(Actions.sequence(Actions.alpha(0), Actions.run(new Runnable() {
#Override
public void run() {
Assets.load();
}
}), Actions.fadeIn(0.5f), Actions.delay(1), Actions.fadeOut(0.5f), Actions.run(new Runnable() {
#Override
public void run() {
Utils.changeGameScreen(new GameScreen());
// ((Game) Gdx.app.getApplicationListener()).setScreen(new
// GameScreen());
}
})));
}

Reduce lifecycle validation calls in resizeable Flex LabelItemRenderer

I've subclassed the LabelItemRenderer class to create an expandable renderer for a spark list in my mobile app.
When the user selects an item, the renderer's size increases, additional data is shown. The renderer basically looks like this (I've removed the parts that don't matter here, so this is basically pseudo code).
public class PositionsGridRenderer extends LabelItemRenderer
{
public function PositionsGridRenderer() {
super();
addEventListener(MouseEvent.CLICK, expandHandler);
}
protected override function createChildren():void {
super.createChildren();
_dg = new DataGroup();
_dg.visible = false;
addChild(_dg);
}
private function expandHandler(event:Event):void {
if(_gridVisible) {
if(!_detailClicked) {
_dg.visible = false;
_gridVisible = false;
}
_detailClicked = false;
} else {
_dg.visible = true;
_gridVisible = true;
}
}
public override function set data(value:Object):void {
if(!value) return;
super.data = value;
var pos:Position = data as Position;
label = pos.positionName;
_dg.dataProvider = pos.positionSymbols;
}
protected override function measure():void {
!_gridVisible ? measuredHeight = 30 : measuredHeight = 30 + getElementPreferredHeight(_dg);
this.height = measuredHeight;
}
protected override function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void {
setElementSize(labelDisplay, unscaledWidth, 30);
setElementPosition(labelDisplay, 10,10);
if(_gridVisible) {
setElementSize(_dg, unscaledWidth, getElementPreferredHeight(_dg));
setElementPosition(_dg, 0, 30);
} else {
setElementSize(_dg, unscaledWidth, 0);
}
invalidateSize();
}
}
}
Works as expected, I'm just wondering if there's a way to reduce the amount of validation calls this renderer does when I expand it.
If it is clicked to be expanded the layoutContents and measure functions are both called three times in the following order: layoutcontents -> measure, layoutcontens -> measure, layoutcontents -> measure.
I'd understand them being called once because I invalidate the size, but three times seems odd.
Does anyone know why this is happening, or maybe even how to prevent this from happening?
The real question was why is the component going through three full renderer cycles? After some disussion, this is what we came across:
The first time the invalidate cycle is triggered is when a mouse down, or possibly a touch begin event occurs. This puts the component into the hover state; which causes a visual change in the component.
The second time the invalidate cycle is triggered is when the item is selected. This puts the renderer in the down state; causing a different visual indicator to be drawn.
The third invalidate cycle is caused by the component's own code; when layoutContents() calls invalidatesize()