MultiTouch is multi tough! Need some help...

edited June 2017 in Android Mode

I have been messing with this for a few days now, and I have something that is working very close to what I want. I know the code could be structured better, but I am just trying to get the hang of the Multi touch workflow. If you run the sketch you will see that you can use as many fingers as you want and drag out multiple lines... that part works fine... I THOUGHT that would be the hard part of this. If you look at the code you will see 2 commented out sections, this is what adds the balls to the sketch. For some reason this part of the code is causing the sketch to crash randomly. It may work for a little while, but after repeated fast shots it will eventually crash (and I need it to be solid). I am testing this on a galaxy s7... if anyone could take a look at the code and test it that would be great. I cant figure out what is making it crash... its made my head hurt for the past 2 days.

 import android.view.MotionEvent;
HashMap<Integer, Line> lh;
ArrayList<Ball> balls;
void setup() {
  fullScreen(P2D);
  lh = new HashMap<Integer, Line>(10);
  balls = new ArrayList<Ball>() ;
}   
void draw() {
  background(255);
  for (int i = 0; i <lh.size(); i++) {
    Line l = lh.get(i);
    if ( l != null) {
      l.show();
    }
  }
  for (int i = balls.size()-1; i>=0; i--) {
    Ball tempb = balls.get(i);
    if (tempb.pos.x > width || tempb.pos.x <0 ||  tempb.pos.y  > height || tempb.pos.y< 0) {
      balls.remove(i);
    }
  }
  for (Ball b : balls) {
    b.show();
  }
}
public boolean surfaceTouchEvent(MotionEvent ev) {
  int maskedAction = ev.getActionMasked();
  switch (maskedAction) {
  case MotionEvent.ACTION_DOWN: 
    {
      Line templ = new Line((int)ev.getX(), (int)ev.getY()); 
      lh.put(ev.getPointerId(0), templ);
      break;
    }
  case MotionEvent.ACTION_POINTER_DOWN: 
    {
      int pointerIndex =   ev.getActionIndex();
      int pointerId = ev.getPointerId(pointerIndex);
      Line templ = new Line((int)ev.getX(pointerIndex), (int)ev.getY(pointerIndex)); 
      lh.put(pointerId, templ);
      break;
    }
  case MotionEvent.ACTION_MOVE: 
    {
      for ( int i = 0; i < ev.getPointerCount(); i ++) {
        int id = ev.getPointerId(i);
        Line templ = lh.get(id);
        if (templ!=null) {
          templ.mx = (int)ev.getX(i);
          templ.my = (int)ev.getY(i);
        }
      }
      break;
    }
  case MotionEvent.ACTION_UP:
    {
      int pointerIndex = ev.getActionIndex();
      int j = ev.getPointerId(pointerIndex);
      //Line l = lh.get(j);
      //PVector p = new PVector(ev.getX(pointerIndex), ev.getY(pointerIndex));
      //PVector op = new PVector (l.sx, l.sy);
      //PVector v = PVector.sub(op, p);
      //v.normalize();
      //v.setMag(20);
      //balls.add(new Ball(p, v));
      lh.put(j, null);
      break;
    }
  case MotionEvent.ACTION_POINTER_UP: 
    {
      int pointerIndex = ev.getActionIndex();
      int j = ev.getPointerId(pointerIndex);
      //Line l = lh.get(j);
      //PVector p = new PVector(ev.getX(pointerIndex), ev.getY(pointerIndex));
      //PVector op = new PVector (l.sx, l.sy);
      //PVector v = PVector.sub(op, p);
      //v.normalize();
      //v.setMag(20);
      //balls.add(new Ball(p, v));
      lh.put(j, null);
      break;
    }
  }
  return super.surfaceTouchEvent(ev);
}
class Ball {
  PVector pos;
  PVector vel;
  Ball(PVector _pos, PVector _vel) {
    pos = _pos.get();
    vel = _vel.get();
  }
  void show () {
    fill(20);
    noStroke();
    pos.add(vel);
    ellipse(pos.x, pos.y, 50, 50);
  }
}
class Line {
  int sx, sy, mx, my;
  Line(int _x, int _y) {
    sx=_x;
    sy=_y;
    mx=_x;
    my=_y;
  }
  void show( ) {
    stroke(0);
    strokeWeight(10);    
    line( sx, sy, mx, my);
  }
}

Answers

  • it will eventually crash

    Any error messages?

  • You don't check that l is not null before using it on line 62 (etc).

    You also appear to have a hash map keyed on the numbers from 1 to 10. An array would be more obvious.

  • Sure is :)...

    android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1562) android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1262)

  • I will switch to array and see if that helps... I started with arraylist, and switched to hashmap because it was easier switch. I checked to see if l was null and it still crashes. It should not be null at that point anyway... as the value for that id is already filled with a line when that touch id went down.

  • For reference, see also past discussions of multitouch -- https://forum.processing.org/two/search?Search=MultiTouch

  • Thought I would post this... I didnt fix it yet, but after getting new system and reinstalling processing/ android I got much better error message. I kinda suspected that this was the case. Separate threads modifying the same arraylist. Still open to suggestions to fix it... I have a few hacky thoughts of ways to get around it, but what is the proper way to handle this type of thing?

    FATAL EXCEPTION: GLThread 53033
    Process: processing.test.multitouch_5_forum, PID: 25116
    java.util.ConcurrentModificationException
        at java.util.ArrayList$Itr.next(ArrayList.java:831)
        at processing.test.multitouch_5_forum.multitouch_5_forum.draw(multitouch_5_forum.java:43)
        at processing.core.PApplet.handleDraw(Unknown Source)
        at processing.opengl.PGLES$AndroidRenderer.onDrawFrame(Unknown Source)
        at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1562)
        at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1262)
    
Sign In or Register to comment.