maze

back at it again with the lines

// made by alex
// iamalexbaker@gmail.corm

int num_lines = 8;
int shape = 3; // 3 = triangle, 4 = square, 5 = pentagon, etc
float gap = 15;
float pad = 10;
float offset_angle;
color bg = color(220);
float colourSpread = 80;
color lineColour;
boolean start_cross = false; // it sets randomly in setup() - comment it if you want it stable

boolean do_draw;
PVector origin;
ArrayList<ray> rays = new ArrayList<ray>();
ArrayList<boundary> lines = new ArrayList<boundary>();
float shape_angle;
int active_rays;
int rotation_dir;

class boundary {
  boolean wall;
  PVector a, b;

  boundary(float x1, float y1, float x2, float y2, boolean w) {
    a = new PVector(x1, y1); 
    b = new PVector(x2, y2); 
    wall = w;
  }

  void show() {
    stroke(lineColour, 255);
    line(a.x, a.y, b.x, b.y);
  }
}

class ray {
  PVector pos, dir;
  color colour;
  float angle;
  boolean active;
  ArrayList<boundary> bb;
  int _step = 1;
  int id;

  ray(PVector p, float a, color c, ArrayList<boundary> b) {
    active = true; 
    pos = new PVector(p.x, p.y); 
    colour = c; 
    angle = a; 
    dir = PVector.fromAngle(a); 
    bb = b; 
    id = int(random(1000));
  }

  PVector cast(boundary b) {
    // https://en.wikipedia.org/wiki/Line–line_intersection
    float x1, x2, x3, x4, y1, y2, y3, y4, d, t, u, hx, hy;
    x1 = b.a.x;
    y1 = b.a.y;
    x2 = b.b.x;
    y2 = b.b.y;
    x3 = pos.x;
    y3 = pos.y;
    x4 = pos.x + dir.x;
    y4 = pos.y + dir.y;
    //line(pos.x, pos.y, pos.x + dir.x*150, pos.y + dir.y*150);
    //ellipse(pos.x + dir.x*150, pos.y + dir.y*150, 10,8);
    //text(_step, pos.x + dir.x*150, pos.y + dir.y*150);

    d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
    if (d==0) return null;

    t = ((x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4)) / d;
    u = - ((x1 - x2) * (y1 - y3) - (y1 - y2) * (x1 - x3)) / d;

    if (t > 0 && t < 1 && u > 0) {
      hx = x1 + t * (x2-x1);
      hy = y1 + t * (y2-y1);
      return new PVector(hx, hy);
    } else return null;
  }

  hit multicast(ArrayList<boundary> walls)
  {
    float record = Float.POSITIVE_INFINITY;
    PVector h;
    float d;
    PVector pt = new PVector(0, 0);
    boundary b = walls.get(1);
    // find nearest boundary, so ray doesn't hit multiple walls
    for (boundary wall : walls) {
      h = cast(wall);
      boolean cond = start_cross ? (h != null && (wall.wall || _step > 1)) : h != null;
      if (cond) {
        //noStroke();
        //ellipse(h.x, h.y, 20,20);
        d = pos.dist(h);
        if (d < record) {
          record = d;
          pt = h;
          b = wall;
        }
      }
    }
    if (record < Float.POSITIVE_INFINITY) {
      return new hit(pt, b);
    } else return null;
  }

  void step() {
    println(" --- step --- "+_step+" id "+id);
    boolean valid = false;
    float distance = 0;
    hit h = null;
    float o_angle = angle;
    float rot_dir = (rotation_dir==0) ? int(random(2))*2 - 1 : rotation_dir; // pick - 1 or 1 if dir is 0
    for (int i = 0; i < shape; i ++) {
      angle = (angle + rot_dir * shape_angle) % TWO_PI;
      if ((angle + PI) % TWO_PI == o_angle) { 
        println("OH"); 
        continue;
      }
      dir = PVector.fromAngle(angle);
      h = multicast(bb);
      distance = pos.dist(h.p);
      if (distance > gap + pad)
      {
        valid = true;
        break;
      }
    }

    if (!valid) {
      stroke(0, 255, 0);
      //line(pos.x,pos.y,h.p.x,h.p.y);
      //ellipse(h.p.x, h.p.y, 5, 5);
      println("deactivate on step "+_step+" "+h.b.wall+", pos: "+pos+", h.p: "+h.p);
      //ellipse(h.p.x,h.p.y,10,10);
      active = false;
      active_rays--;
    } else {
      color cc = color(random(255), random(255), random(255));
      stroke(cc);
      fill(cc);
      pushMatrix();
      translate(pos.x, pos.y);
      rotate(angle-PI/2);
      translate(0, distance - gap);
      PVector v = getMatrix().mult(new PVector(0, 0), null);
      popMatrix();
      println("num boundaries: "+lines.size());
      lines.add(new boundary(pos.x, pos.y, v.x, v.y, false));
      pos.x = v.x;
      pos.y = v.y;
      println("v "+v);
      println("angle: "+angle+", dir: "+dir);
      pushMatrix();
      translate(width/2, height/2);
      //line(0,0,dir.x*30,dir.y*30);
      popMatrix();
      _step++;
    }
  }
}

class hit {
  PVector p;
  boundary b;

  hit(PVector pp, boundary bb) {
    p = pp; 
    b = bb;
  }
}

void setup() {
  size(800, 800);
  background(bg);
  strokeWeight(1);
  do_draw = true;
  shape_angle = TWO_PI/shape;
  offset_angle = random(TWO_PI);
  start_cross = parseBoolean(int(random(2)));
  println("shape_angle: "+shape_angle);
  rays.clear();
  lines.clear();

  origin = new PVector(random(width), random(height));
  rotation_dir = int(random(3))- 1;
  lineColour = dullColour(colourSpread);

  // boundaries of screen
  lines.add(new boundary(0, 0, width, 0, true));
  lines.add(new boundary(0, 0, 0, height, true));
  lines.add(new boundary(0, height, width, height, true));
  lines.add(new boundary(width, 0, width, height, true));

  active_rays = num_lines;

  for (int i = 0; i < num_lines; i++)
  {
    pushMatrix();
    translate(width/2, height/2);
    rotate(shape_angle*i - PI/2);
    stroke(100*(i+1), 0, 0);
    //line(0,0,0,200);
    popMatrix();
    rays.add(new ray(new PVector(random(width), random(height)), shape_angle*i + offset_angle, lineColour, lines));
  }
  println(lines.size());
}

void draw() {
  do {
    for (ray r : rays) {
      //println("ray "+r.pos);
      if (r.active) {
        r.step();
      }
    }
  } while (active_rays > 0);
  if (do_draw) {
    for (boundary l : lines) {
      println("line: "+l.a+" - "+l.b);
      if (!l.wall) {
        l.show();
      }
    }
    do_draw = false;
  }
}

void keyPressed()
{
  if (keyCode==32) {
    saveFrame("maze-"+hour()+"-"+minute()+"-"+second()+".png");
  }
  if (keyCode==10) {
    setup();
  }
}

color dullColour(float spread)
{
  color col;
  float x = random(255);
  col = color(constrain(x + random(spread) - spread/2, 0, 255), constrain(x + random(spread) - spread/2, 0, 255), constrain(x + random(spread) - spread/2, 0, 255));
  return col;
}

Leave a comment