diff --git a/rope_snake/index.html b/rope_snake/index.html
new file mode 100644
index 0000000..e9d4bd7
--- /dev/null
+++ b/rope_snake/index.html
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+ p5.js example
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/rope_snake/intersect.js b/rope_snake/intersect.js
new file mode 100644
index 0000000..85e5067
--- /dev/null
+++ b/rope_snake/intersect.js
@@ -0,0 +1,94 @@
+// Javascript program to check if two given line segments intersect
+
+
+// Given three collinear points p, q, r, the function checks if
+// point q lies on line segment 'pr'
+function onSegment(p, q, r)
+{
+ if (q.x <= Math.max(p.x, r.x) && q.x >= Math.min(p.x, r.x) &&
+ q.y <= Math.max(p.y, r.y) && q.y >= Math.min(p.y, r.y))
+ return true;
+
+ return false;
+}
+
+// To find orientation of ordered triplet (p, q, r).
+// The function returns following values
+// 0 --> p, q and r are collinear
+// 1 --> Clockwise
+// 2 --> Counterclockwise
+function orientation(p, q, r)
+{
+
+ // See https://www.geeksforgeeks.org/orientation-3-ordered-points/
+ // for details of below formula.
+ let val = (q.y - p.y) * (r.x - q.x) -
+ (q.x - p.x) * (r.y - q.y);
+
+ if (val == 0) return 0; // collinear
+
+ return (val > 0)? 1: 2; // clock or counterclock wise
+}
+
+// The main function that returns true if line segment 'p1q1'
+// and 'p2q2' intersect.
+function doIntersect(p1, q1, p2, q2)
+{
+
+ // Find the four orientations needed for general and
+ // special cases
+ let o1 = orientation(p1, q1, p2);
+ let o2 = orientation(p1, q1, q2);
+ let o3 = orientation(p2, q2, p1);
+ let o4 = orientation(p2, q2, q1);
+
+ // General case
+ if (o1 != o2 && o3 != o4)
+ return true;
+
+ // Special Cases
+ // p1, q1 and p2 are collinear and p2 lies on segment p1q1
+ if (o1 == 0 && onSegment(p1, p2, q1)) return true;
+
+ // p1, q1 and q2 are collinear and q2 lies on segment p1q1
+ if (o2 == 0 && onSegment(p1, q2, q1)) return true;
+
+ // p2, q2 and p1 are collinear and p1 lies on segment p2q2
+ if (o3 == 0 && onSegment(p2, p1, q2)) return true;
+
+ // p2, q2 and q1 are collinear and q1 lies on segment p2q2
+ if (o4 == 0 && onSegment(p2, q1, q2)) return true;
+
+ return false; // Doesn't fall in any of the above cases
+}
+
+
+function test_intersect(){
+ // Driver code
+ let p1 = new Vector(1, 1);
+ let q1 = new Vector(10, 1);
+ let p2 = new Vector(1, 2);
+ let q2 = new Vector(10, 2);
+
+ if(doIntersect(p1, q1, p2, q2))
+ console.log("Yes
");
+ else
+ console.log("No
");
+
+ p1 = new Vector(10, 1); q1 = new Vector(0, 10);
+ p2 = new Vector(0, 0); q2 = new Vector(10, 10);
+ if(doIntersect(p1, q1, p2, q2))
+ console.log("Yes
");
+ else
+ console.log("No
");
+
+ p1 = new Vector(-5, -5); q1 = new Vector(0, 0);
+ p2 = new Vector(1, 1); q2 = new Vector(10, 10);;
+ if(doIntersect(p1, q1, p2, q2))
+ console.log("Yes
");
+ else
+ console.log("No
");
+}
+
+// This code is contributed by avanitrachhadiya2155
+
diff --git a/rope_snake/segment.js b/rope_snake/segment.js
new file mode 100644
index 0000000..4493cb5
--- /dev/null
+++ b/rope_snake/segment.js
@@ -0,0 +1,59 @@
+const Vector = p5.Vector;
+
+function Segment(startx, starty, len, heading){
+ this.start = new Vector(startx, starty);
+ this.len = len;
+ this.reference = 0;
+ this.heading = heading;
+ this.child = null;
+ this.parent = null;
+};
+
+Segment.prototype.end = function(){
+ angle = this.heading + this.reference;
+ let x = this.len * cos(angle) + this.start.x;
+ let y = this.len * sin(angle) + this.start.y;
+ return new Vector(x,y);
+};
+
+
+Segment.prototype.update = function(){
+ if(!this.parent) return;
+ this.parent.heading = Vector.sub(this.start, this.parent.start).heading();
+ this.parent.start.add(Vector.sub(this.start, this.parent.end()));
+ this.parent.update();
+};
+
+Segment.prototype.setHeading = function(angle){
+ this.heading = angle;
+ this.update();
+};
+
+Segment.prototype.draw = function(){
+ push();
+ stroke(255);
+ strokeWeight(5);
+ line(
+ this.start.x,
+ this.start.y,
+ this.end().x,
+ this.end().y);
+ pop();
+};
+
+Segment.prototype.expand_parent = function(stx, sty, len, heading){
+ let next = new Segment(stx, sty, len, heading);
+ next.child = this;
+ this.parent = next;
+ return next;
+};
+
+Segment.prototype.eats_parents = function(){
+ let start = this.start;
+ let end = this.end();
+ for(let theSeg = this.parent.parent; theSeg != null; theSeg = theSeg.parent)
+ if(doIntersect(start, end, theSeg.start, theSeg.end()))
+ return true;
+ return false;
+};
+
diff --git a/rope_snake/sketch.js b/rope_snake/sketch.js
new file mode 100644
index 0000000..19c22ff
--- /dev/null
+++ b/rope_snake/sketch.js
@@ -0,0 +1,99 @@
+const START_SEGMENTS = 10;
+const SEG_LEN = 10;
+const SPEED = 4;
+const WIDTH = 300;
+const HEIGHT = 300;
+const APPLE_SIZE = 20;
+const APPLE_R = APPLE_SIZE/2;
+const SPACE_BAR = 32;
+let head;
+let tail;
+let apple;
+let turn = 0;
+let speedup = 0;
+
+const isOutside = (aVec) => (
+ aVec.x > WIDTH ||
+ aVec.x < 0 ||
+ aVec.y > HEIGHT ||
+ aVec.y < 0);
+
+
+function setup() {
+ // put setup code here
+ apple = new Vector(random(APPLE_R,WIDTH-APPLE_R),
+ random(APPLE_R,HEIGHT-APPLE_R));
+ tail = new Segment(WIDTH/2, 0, 10, HALF_PI);
+ head = tail
+ for(let i = 0; i < START_SEGMENTS; i++){
+ let pos = head.end();
+ head.child = new Segment(pos.x, pos.y, 10, HALF_PI);
+ head.child.parent = head;
+ head = head.child;
+ }
+ createCanvas(300,300);
+ frameRate(15);
+}
+
+function draw() {
+ // put drawing code here
+ background(0);
+ for(let current = tail; current !== null; current= current.child){
+ current.draw();
+ }
+ fill(0, 255, 0);
+ noStroke();
+ circle(apple.x, apple.y, APPLE_SIZE);
+ // update
+ head.heading += turn * PI/18;
+ head.start.add(p5.Vector.fromAngle(head.heading, SPEED*(1+speedup)));
+ head.update();
+ head_end = head.end();
+ if(Vector.sub(head_end, apple).mag() < APPLE_SIZE){
+ apple = new Vector(random(APPLE_R,WIDTH-APPLE_R),
+ random(APPLE_R,HEIGHT-APPLE_R));
+ for(let i=1; i<=3; i++){
+ let end = tail.end();
+ let heading = tail.heading;
+ tail = tail.expand_parent(end.x, end.y, SEG_LEN, heading+ PI);
+ }
+ }
+ // Game over
+ if(isOutside(head_end) || head.eats_parents())
+ {
+ background(128);
+ textSize(HEIGHT/10);
+ textAlign(CENTER);
+ text("Game Over! Refresh page to restart.",
+ 0.1*WIDTH, 0.1*HEIGHT,
+ 0.8*WIDTH, 0.8*HEIGHT)
+ noLoop();
+ };
+}
+
+function keyPressed(){
+ switch(keyCode){
+ case LEFT_ARROW:
+ turn = -1;
+ break;
+ case RIGHT_ARROW:
+ turn = +1;
+ break;
+ case SPACE_BAR:
+ speedup = 1;
+ break;
+ }
+}
+
+function keyReleased(){
+ switch(keyCode){
+ case LEFT_ARROW:
+ case RIGHT_ARROW:
+ turn = 0;
+ break;
+ case SPACE_BAR:
+ speedup = 0;
+ break;
+ }
+}
+