Search code examples
processingcollision-detection

Processing: collisions with trails


Dealing with collisions in Processing is straightforward. However, how do I identify collisions with trails?

Example: imagine the light cycles in Tron, if you wish, with the alteration that trails of derezzed light cycles do not disappear. In Tron, if a cycle intersects any point another cycle, itself included, has ever been, it 'dies'. How do I efficiently find this event in Processing?


Solution

  • One hacky workaround is to draw the line into a PImage and check if the colour at a location is the same as the background or not (e.g. a pre-existing line, hence a collision).

    Here's a rough (and slightly inefficient (due to get()/set() calls) proof of concept:

    PImage buffer;
    
    //how mutch we scale down = how pixely this will look
    int multiplier = 8;
    //scaled down width/height
    int w,h;
    //cursor position
    int px,py;
    //cursor velocity;
    int vx,vy;
    
    
    void setup(){
      size(400,400);
      noSmooth();
    
      w = width / multiplier;
      h = height / multiplier;
    
      buffer = createImage(w,h,RGB);
      clear();
    }
    void clear(){
      java.util.Arrays.fill(buffer.pixels,color(0));
      buffer.updatePixels();
    }
    void draw(){
      //update cursor
      px += vx;
      py += vy;
      //check edges
      if(px < 0){
        px = w-1;
      }
      if(px > w){
        px = 0;
      }
      if(py < 0){
        py = h-1;
      }
      if(py > h){
        py = 0;
      }
      //check collision
      if(keyPressed){
        if(keyCode == UP || keyCode == DOWN || keyCode == LEFT || keyCode == RIGHT){
          checkSelfIntersection();
        }
      }
      //paint cursor
      buffer.set(px,py,color(0,192,0));
    
      //render on screen
      image(buffer,0,0,width,height);
    }
    void checkSelfIntersection(){
      //if the pixel ahead is not the same colour as the background
      if(buffer.get(px+vx,py+vy) > color(0)){
        clear();  
        println("Cycle go BOOM!");
      }
    }
    void keyPressed(){
      if(keyCode == UP){
        vy = -1;
      }
      if(keyCode == DOWN){
        vy = +1;
      }
      if(keyCode == LEFT){
        vx = -1;
      }
      if(keyCode == RIGHT){
        vx = +1;
      }
    }
    void keyReleased(){
      vx = vy = 0;
    }
    

    A similar concept can be done be keeping track of points in a list and checking if a new point is already part of this list (collision) or not:

    ArrayList<PVector> path = new ArrayList<PVector>();
    
    
    //cursor position
    int px,py;
    //cursor velocity;
    int vx,vy;
    
    void setup(){
      size(400,400);
      noFill();
      strokeWeight(10);
    }
    void draw(){
      //update cursor
      px += vx;
      py += vy;
      //check edges
      if(px < 0){
        px = 0;
      }
      if(px > width){
        px = width;
      }
      if(py < 0){
        py = 0;
      }
      if(py > height){
        py = height;
      }
      //check collision
      if(keyPressed){
        if(keyCode == UP || keyCode == DOWN || keyCode == LEFT || keyCode == RIGHT){
          checkSelfIntersection();
        }
      }
    
      background(255);
      beginShape();
      for(int i = 0 ; i < path.size(); i++){
        PVector p = path.get(i);
        vertex(p.x,p.y);
      }
      endShape();
    }
    void checkSelfIntersection(){
      PVector cursor = new PVector(px,py);
      if(path.contains(cursor)){
        path.clear();
        println("Cycle go BOOM!");
      }else{
        path.add(cursor);
      }
    }
    void keyPressed(){
      if(keyCode == UP){
        vy = -5;
      }
      if(keyCode == DOWN){
        vy = +5;
      }
      if(keyCode == LEFT){
        vx = -5;
      }
      if(keyCode == RIGHT){
        vx = +5;
      }
    }
    void keyReleased(){
      vx = vy = 0;
    }
    

    The concept isn't that different from how games like Snake/Volfied/etc. check for self intersections.

    Note I'm cheating a bit by updating a "cursor" on keys with a small velocity: this avoid gaps in the lines. If you try to replace with the mouse, you'll notice the collision check may fail if the mouse moves fast as it checks one point against a list of recorded points. An alternative might be to split the list of points into pairs of lines and check if the new point intersects any of them.

    You might want to also check this similar question