0

I´m having the following problem in my game:

let´s say I have 5 screens on the lvl 3. Each screen has a class for itself. so i have 5 classes named lvl 3_1_0, 3_2_0 .... .... 3_5_0. I also have a gesture listener so when you swipe right it will go to the screen on the right. When playing normally it all works fine but if the user starts swiping right like crazy for example and he does it like a lot of times per second, the game crashes off course.

I thought about adding a "Thread.sleep" but I cant make it work when I put the Thread sleep the game crashes when loading the class. I think I´m putting it in the wrong place, or places.... the best would be if the gesture listener wait´s a second to be active. I also have a gesture filter class. I don´t know if I should put the thread.sleep in the gesture filter class or in the gesture listener that is in every class.

here is the code of the on create and the gesture listener...

public class lvl3_5_0 extends Activity implements View.OnTouchListener ,  SimpleGestureListener {


public static final String PREFS_NAME = "MyPrefsFile";
  static SharedPreferences settings;
  SharedPreferences.Editor editor;


private SimpleGestureFilter detector; 
static final int MIN_DISTANCE = 100;




   @Override
    public void onCreate(Bundle savedInstanceState) {
       overridePendingTransition(R.anim.fadein, R.anim.fadeout);

        detector = new SimpleGestureFilter(this,this);

        super.onCreate(savedInstanceState);
        setContentView(R.layout.lvl3_5_0);



                ImageView iv = (ImageView) findViewById (R.id.image);
                if (iv != null) {
                   iv.setOnTouchListener (this);
                }



setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    }


   //-----------------------------     

   // Gesture detection



        @Override 
        public boolean dispatchTouchEvent(MotionEvent me){ 
          this.detector.onTouchEvent(me);
         return super.dispatchTouchEvent(me); 

        }
        @Override
         public void onSwipe(int direction) {

          switch (direction) {

          case SimpleGestureFilter.SWIPE_RIGHT : {
              { Intent game = new Intent(lvl3_5_0.this, lvl3_4_0.class); 

                  game.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);  game.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                  mHandler.removeCallbacks(dismissPopup);
                    this.finish(); startActivity(game);   
          }break;}



          case SimpleGestureFilter.SWIPE_LEFT :{

              { Intent game = new Intent(lvl3_5_0.this, lvl3_1_0.class); 

                      game.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);  game.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                      mHandler.removeCallbacks(dismissPopup);
                        this.finish(); startActivity(game);   
              }break;}


          case SimpleGestureFilter.SWIPE_DOWN : {


              break;}





          case SimpleGestureFilter.SWIPE_UP :{

              openOptionsMenu(); ;
          }


                                                         break;

          } 
         }

And here is my Gesture Filter Class

public class SimpleGestureFilter extends SimpleOnGestureListener{

 public final static int SWIPE_UP    = 1;
 public final static int SWIPE_DOWN  = 2;
 public final static int SWIPE_LEFT  = 3;
 public final static int SWIPE_RIGHT = 4;

 public final static int MODE_TRANSPARENT = 0;
 public final static int MODE_SOLID       = 1;
 public final static int MODE_DYNAMIC     = 2;

 private final static int ACTION_FAKE = -13; //just an unlikely number
 private int swipe_Min_Distance = 65;
 private int swipe_Max_Distance = 1111100;
 private int swipe_Min_Velocity = 60;

 private int mode      = MODE_DYNAMIC;
 private boolean running = true;
 private boolean tapIndicator = false;

 private Activity context;
 private GestureDetector detector;
 private SimpleGestureListener listener;


 public SimpleGestureFilter(Activity context,SimpleGestureListener sgl) {

  this.context = context;
  this.detector = new GestureDetector(context, this);
  this.listener = sgl; 
 }

 public void onTouchEvent(MotionEvent event){

   if(!this.running)
  return;  

   boolean result = this.detector.onTouchEvent(event); 

   if(this.mode == MODE_SOLID)
    event.setAction(MotionEvent.ACTION_CANCEL);
   else if (this.mode == MODE_DYNAMIC) {

     if(event.getAction() == ACTION_FAKE) 
       event.setAction(MotionEvent.ACTION_UP);
     else if (result)
       event.setAction(MotionEvent.ACTION_CANCEL); 
     else if(this.tapIndicator){
      event.setAction(MotionEvent.ACTION_DOWN);
      this.tapIndicator = false;
     }

   }

   //else just do nothing, it's Transparent
 }

 public void setMode(int m){
  this.mode = m;
 }

 public int getMode(){
  return this.mode;
 }

 public void setEnabled(boolean status){
  this.running = status;
 }

 public void setSwipeMaxDistance(int distance){
  this.swipe_Max_Distance = distance;
 }

 public void setSwipeMinDistance(int distance){
  this.swipe_Min_Distance = distance;
 }

 public void setSwipeMinVelocity(int distance){
  this.swipe_Min_Velocity = distance;
 }

 public int getSwipeMaxDistance(){
  return this.swipe_Max_Distance;
 }

 public int getSwipeMinDistance(){
  return this.swipe_Min_Distance;
 }

 public int getSwipeMinVelocity(){
  return this.swipe_Min_Velocity;
 }


 @Override
 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
   float velocityY) {

  final float xDistance = Math.abs(e1.getX() - e2.getX());
  final float yDistance = Math.abs(e1.getY() - e2.getY());

  if(xDistance > this.swipe_Max_Distance || yDistance > this.swipe_Max_Distance)
   return false;

  velocityX = Math.abs(velocityX);
  velocityY = Math.abs(velocityY);
        boolean result = false;

  if(velocityX > this.swipe_Min_Velocity && xDistance > this.swipe_Min_Distance){
   if(e1.getX() > e2.getX()) // right to left
    this.listener.onSwipe(SWIPE_LEFT);
   else
    this.listener.onSwipe(SWIPE_RIGHT);

   result = true;
  }
  else if(velocityY > this.swipe_Min_Velocity && yDistance > this.swipe_Min_Distance){
   if(e1.getY() > e2.getY()) // bottom to up 
    this.listener.onSwipe(SWIPE_UP);
   else
    this.listener.onSwipe(SWIPE_DOWN);

   result = true;
  }

   return result;
 }

 @Override
 public boolean onSingleTapUp(MotionEvent e) {
  this.tapIndicator = true;
  return false;
 }



 @Override
 public boolean onSingleTapConfirmed(MotionEvent arg0) {

  if(this.mode == MODE_DYNAMIC){        // we owe an ACTION_UP, so we fake an       
     arg0.setAction(ACTION_FAKE);      //action which will be converted to an ACTION_UP later.                                    
     this.context.dispatchTouchEvent(arg0);  
  }   

  return false;
 }


    static interface SimpleGestureListener{
     void onSwipe(int direction);
 }

}

So the questions would be: Where should I put the "Thread.sleep(1000);" surrounded by try/catch? ( if that´s what I have to use )

I tried a lot and I´m stuck

----------------------------Solved--------------------------------------

here is the code fixed

public class lvl3_3_0 extends Activity implements View.OnTouchListener ,  SimpleGestureListener {


   boolean finished = false;   // This was added ( no need to explain XD )

private SimpleGestureFilter detector; 
static final int MIN_DISTANCE = 100;

// Handler and runnable reference

        private PopupWindow popupWindow;
        private Handler mHandler = new Handler();
        private Runnable dismissPopup = new Runnable() {
                public void run() {
                    if (popupWindow.isShowing())
                        popupWindow.dismiss();
                }
            };




   @Override
    public void onCreate(Bundle savedInstanceState) {{
       overridePendingTransition(R.anim.fadein, R.anim.fadeout);


        detector = new SimpleGestureFilter(this,this);


        settings = getSharedPreferences(PREFS_NAME, 0);
        editor = settings.edit();
          editor.putString("currentscreen", "com.appsimple.roomdroid.lvl3_3_0");
          editor.commit();


        super.onCreate(savedInstanceState);
        setContentView(R.layout.lvl3_3_0);





                ImageView iv = (ImageView) findViewById (R.id.image);
                if (iv != null) {
                   iv.setOnTouchListener (this);
                }



setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    }
   finished = true;      // This will make true the boolean after finishing the loading of the activity

    }




   //-----------------------------     

   // Gesture detection





        @Override 
        public boolean dispatchTouchEvent(MotionEvent me){ 
            if (!finished){}                 // This was added to make the gesturelistener not to listen if the activity has not finished loading.
            else {
          this.detector.onTouchEvent(me);
         return super.dispatchTouchEvent(me); }
            return false;
        }
        @Override
         public void onSwipe(int direction) {
                    if (!finished){}
            else {
          switch (direction) {

          case SimpleGestureFilter.SWIPE_RIGHT : {
              finished = false;      // this wass added after doing the swipe to avoid the gesture listener to have a que of events.
              { Intent game = new Intent(lvl3_3_0.this, lvl3_2_0.class); 

                  game.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);  game.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                  mHandler.removeCallbacks(dismissPopup);
                    this.finish(); startActivity(game);   
          }break;}



          case SimpleGestureFilter.SWIPE_LEFT :{


              { finished = false; Intent game = new Intent(lvl3_3_0.this, lvl3_4_0.class); 

                      game.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);  game.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                      mHandler.removeCallbacks(dismissPopup);
                        this.finish(); startActivity(game);   
              }break;}


          case SimpleGestureFilter.SWIPE_DOWN : {


              break;}





          case SimpleGestureFilter.SWIPE_UP :{

              openOptionsMenu(); ;
          }


                                                         break;

          } }}

Hope this helps ! Thaks AndroidPenguin for the help :)

the other solution i was thinking about was a bit laggi and not this good was making a Runnable in the gesture filter class to work as a timer every time the timer got to for example 1 sec it would return the "isoktodotheswipe" boolean and every time a wipe was made the "isoktodotheswipe" boolean would become false...

  • Holy, that's a lot of code and a very broad problem. Why not just record the time of class creation with `System.currentTimeMillis()`, then check if `System.currentTimeMillis() - creationTime > 1000L` on each gesture? (Or even better, use a `boolean`, but that's optional and for performance.) – Cat Dec 15 '12 at 02:57
  • Is it that you want the gesturelistener to wait until the rest of the activity has loaded before beginning to respond? – AndroidPenguin Dec 15 '12 at 03:16
  • Eric: I´m trying your idea, I hadn´t tought in a boolean ( that´s what happens if a musician makes an android game :P ) Android Penguin: yes, that´s the idea :) – Rodrigofantino Dec 15 '12 at 03:18
  • check out below :) Also no insulting musicians :P – AndroidPenguin Dec 15 '12 at 03:23

1 Answers1

1

Set up a boolean

e.g.

boolean finished = false;

Then in your gesture/dispatch listeners, add the following to the very top of your code:

if(!finished){
return;}

Once your class has finished setting up. Set finished to true. That's how I solved the same problem I had.

AndroidPenguin
  • 3,445
  • 2
  • 21
  • 42
  • I found a solution based on a boolean applied to the gesture filter but I wan´t to try your solution as well because it seams It would be better to do that I´ll try it and tell what I ended up doing XD – Rodrigofantino Dec 15 '12 at 03:26
  • Awesome :) If your other solution works out better, please do post it up here? Would like to consider using it myself then :P – AndroidPenguin Dec 15 '12 at 03:38
  • What you posted definitively works in a way but it seams I´m still storing a callback ( don´t know if that´s the word) of all the swipes... because it´s all fine when I swipe a fre times it wont change lot´s of screens but it still crashes sometimes... I´ll try to make it better let´s try stuffs :P jajaja – Rodrigofantino Dec 15 '12 at 03:48
  • Simple question, If I put the finished = true; at the end of the "on create" It will become true after loading everything? – Rodrigofantino Dec 15 '12 at 03:56
  • Yup. Of course you can prove it using logs (logging when your oncreate finishes and constantly logging finished), but 100% works for me. – AndroidPenguin Dec 15 '12 at 03:59
  • You will get a callback each time swipe is called through your swipe or through your dispatch, but return means it ends there. Naturally if a return boolean is needed return false (so that the dispatch knows the events been consumed i.e. you're done with it and bring on the next one) – AndroidPenguin Dec 15 '12 at 04:04
  • It has to work I have a feeling this is what I´m dooing. "public boolean finished = false;" after defining the class then "finished = true" at the end of the "onCreate" and finally And in the gesture listener Before the switch i added: "if(!finished) { return; } Else do the switch" – Rodrigofantino Dec 15 '12 at 04:08
  • Don't need the else part because return terminates the method and literally returns it back. Also try putting it in your dispatchtouchevent method, that'll make all touches unresponsive until your class has loaded. – AndroidPenguin Dec 15 '12 at 04:10
  • greate, It works almost fine, now I only have to remove the callbacks for the gesture listener because it keeps changing screens for a wile if i swipe a lot. Thanks for everything !. Once i finisht fixing it I will upload the code below the question. – Rodrigofantino Dec 15 '12 at 04:51
  • 1
    Set finished back to false until you finish changing the screen? – AndroidPenguin Dec 15 '12 at 05:05