made with requirebin
Created
June 27, 2017 21:27
-
-
Save comster/4a5c208dc39d3c3be262abb05fa791a3 to your computer and use it in GitHub Desktop.
requirebin sketch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var SAT = require('sat'); | |
var testCircleCollision = function (a, b) { | |
var circleA = new SAT.Circle(new SAT.Vector(a.x, a.y), a.r); | |
var circleB = new SAT.Circle(new SAT.Vector(b.x, b.y), b.r); | |
var response = new SAT.Response(); | |
var collided = SAT.testCircleCircle(circleA, circleB, response); | |
console.log("did collide?", collided, "details:", response) | |
return { | |
collided: collided, | |
response: response | |
}; | |
}; | |
var reflectBullet = function (bullet, wall, sat_response) { | |
var distVector = new SAT.Vector(bullet.v, 0); | |
var origBulletX = bullet.x; | |
var origBulletY = bullet.y; | |
var currentVector = new SAT.Vector(bullet.x, bullet.y); | |
var bullet_trajectory_radians = Math.atan2(bullet.targetY - bullet.origY, bullet.targetX - bullet.origX); | |
console.log("bullet tragectory radians", bullet_trajectory_radians) | |
distVector.rotate(bullet_trajectory_radians); | |
currentVector.sub(distVector); | |
// move the bullet back from the collision state | |
bullet.x = currentVector.x; | |
bullet.y = currentVector.y; | |
// also set that as our new starting position vector | |
bullet.origY = bullet.y; | |
bullet.origX = bullet.x; | |
var reflectVector = sat_response.overlapN; | |
var targetVector = new SAT.Vector(bullet.origX, bullet.origY); | |
// TODO find the new target direction, via reflection off of the collision point, [origBulletX, origBulletY] | |
// use the tangent line of the cirlce at this point? to determine an axis to pass to .reflect(axis) ? | |
// targetVector.reflect(reflectVector); | |
// set our new target | |
// bullet.targetX = targetVector.x; | |
// bullet.targetY = targetVector.y; | |
console.log("reflected towards target", targetVector); | |
} | |
var a_beam_of_light = { | |
x: 25, | |
y: 40, | |
r: 1, | |
v: 1, | |
origX: 0, | |
origY: 40, | |
targetX: 50, | |
targetY: 40, | |
} | |
var a_curved_mirror = { | |
x: 50, | |
y: 50, | |
r: 25 | |
} | |
var step_world = function() { | |
// step the world forward, moving the bullet towards it's target | |
a_beam_of_light.x = a_beam_of_light.x + a_beam_of_light.v; | |
// console.log(a_beam_of_light, a_curved_mirror) | |
var test_results = testCircleCollision(a_beam_of_light, a_curved_mirror); | |
if(test_results.collided) { | |
reflectBullet(a_beam_of_light, a_curved_mirror, test_results); | |
} | |
} | |
step_world(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
setTimeout(function(){require=function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s}({sat:[function(require,module,exports){(function(root,factory){"use strict";if(typeof define==="function"&&define["amd"]){define(factory)}else if(typeof exports==="object"){module["exports"]=factory()}else{root["SAT"]=factory()}})(this,function(){"use strict";var SAT={};function Vector(x,y){this["x"]=x||0;this["y"]=y||0}SAT["Vector"]=Vector;SAT["V"]=Vector;Vector.prototype["copy"]=Vector.prototype.copy=function(other){this["x"]=other["x"];this["y"]=other["y"];return this};Vector.prototype["clone"]=Vector.prototype.clone=function(){return new Vector(this["x"],this["y"])};Vector.prototype["perp"]=Vector.prototype.perp=function(){var x=this["x"];this["x"]=this["y"];this["y"]=-x;return this};Vector.prototype["rotate"]=Vector.prototype.rotate=function(angle){var x=this["x"];var y=this["y"];this["x"]=x*Math.cos(angle)-y*Math.sin(angle);this["y"]=x*Math.sin(angle)+y*Math.cos(angle);return this};Vector.prototype["reverse"]=Vector.prototype.reverse=function(){this["x"]=-this["x"];this["y"]=-this["y"];return this};Vector.prototype["normalize"]=Vector.prototype.normalize=function(){var d=this.len();if(d>0){this["x"]=this["x"]/d;this["y"]=this["y"]/d}return this};Vector.prototype["add"]=Vector.prototype.add=function(other){this["x"]+=other["x"];this["y"]+=other["y"];return this};Vector.prototype["sub"]=Vector.prototype.sub=function(other){this["x"]-=other["x"];this["y"]-=other["y"];return this};Vector.prototype["scale"]=Vector.prototype.scale=function(x,y){this["x"]*=x;this["y"]*=y||x;return this};Vector.prototype["project"]=Vector.prototype.project=function(other){var amt=this.dot(other)/other.len2();this["x"]=amt*other["x"];this["y"]=amt*other["y"];return this};Vector.prototype["projectN"]=Vector.prototype.projectN=function(other){var amt=this.dot(other);this["x"]=amt*other["x"];this["y"]=amt*other["y"];return this};Vector.prototype["reflect"]=Vector.prototype.reflect=function(axis){var x=this["x"];var y=this["y"];this.project(axis).scale(2);this["x"]-=x;this["y"]-=y;return this};Vector.prototype["reflectN"]=Vector.prototype.reflectN=function(axis){var x=this["x"];var y=this["y"];this.projectN(axis).scale(2);this["x"]-=x;this["y"]-=y;return this};Vector.prototype["dot"]=Vector.prototype.dot=function(other){return this["x"]*other["x"]+this["y"]*other["y"]};Vector.prototype["len2"]=Vector.prototype.len2=function(){return this.dot(this)};Vector.prototype["len"]=Vector.prototype.len=function(){return Math.sqrt(this.len2())};function Circle(pos,r){this["pos"]=pos||new Vector;this["r"]=r||0}SAT["Circle"]=Circle;Circle.prototype["getAABB"]=Circle.prototype.getAABB=function(){var r=this["r"];var corner=this["pos"].clone().sub(new Vector(r,r));return new Box(corner,r*2,r*2).toPolygon()};function Polygon(pos,points){this["pos"]=pos||new Vector;this["angle"]=0;this["offset"]=new Vector;this.setPoints(points||[])}SAT["Polygon"]=Polygon;Polygon.prototype["setPoints"]=Polygon.prototype.setPoints=function(points){var lengthChanged=!this["points"]||this["points"].length!==points.length;if(lengthChanged){var i;var calcPoints=this["calcPoints"]=[];var edges=this["edges"]=[];var normals=this["normals"]=[];for(i=0;i<points.length;i++){calcPoints.push(new Vector);edges.push(new Vector);normals.push(new Vector)}}this["points"]=points;this._recalc();return this};Polygon.prototype["setAngle"]=Polygon.prototype.setAngle=function(angle){this["angle"]=angle;this._recalc();return this};Polygon.prototype["setOffset"]=Polygon.prototype.setOffset=function(offset){this["offset"]=offset;this._recalc();return this};Polygon.prototype["rotate"]=Polygon.prototype.rotate=function(angle){var points=this["points"];var len=points.length;for(var i=0;i<len;i++){points[i].rotate(angle)}this._recalc();return this};Polygon.prototype["translate"]=Polygon.prototype.translate=function(x,y){var points=this["points"];var len=points.length;for(var i=0;i<len;i++){points[i].x+=x;points[i].y+=y}this._recalc();return this};Polygon.prototype._recalc=function(){var calcPoints=this["calcPoints"];var edges=this["edges"];var normals=this["normals"];var points=this["points"];var offset=this["offset"];var angle=this["angle"];var len=points.length;var i;for(i=0;i<len;i++){var calcPoint=calcPoints[i].copy(points[i]);calcPoint.x+=offset.x;calcPoint.y+=offset.y;if(angle!==0){calcPoint.rotate(angle)}}for(i=0;i<len;i++){var p1=calcPoints[i];var p2=i<len-1?calcPoints[i+1]:calcPoints[0];var e=edges[i].copy(p2).sub(p1);normals[i].copy(e).perp().normalize()}return this};Polygon.prototype["getAABB"]=Polygon.prototype.getAABB=function(){var points=this["calcPoints"];var len=points.length;var xMin=points[0]["x"];var yMin=points[0]["y"];var xMax=points[0]["x"];var yMax=points[0]["y"];for(var i=1;i<len;i++){var point=points[i];if(point["x"]<xMin){xMin=point["x"]}else if(point["x"]>xMax){xMax=point["x"]}if(point["y"]<yMin){yMin=point["y"]}else if(point["y"]>yMax){yMax=point["y"]}}return new Box(this["pos"].clone().add(new Vector(xMin,yMin)),xMax-xMin,yMax-yMin).toPolygon()};function Box(pos,w,h){this["pos"]=pos||new Vector;this["w"]=w||0;this["h"]=h||0}SAT["Box"]=Box;Box.prototype["toPolygon"]=Box.prototype.toPolygon=function(){var pos=this["pos"];var w=this["w"];var h=this["h"];return new Polygon(new Vector(pos["x"],pos["y"]),[new Vector,new Vector(w,0),new Vector(w,h),new Vector(0,h)])};function Response(){this["a"]=null;this["b"]=null;this["overlapN"]=new Vector;this["overlapV"]=new Vector;this.clear()}SAT["Response"]=Response;Response.prototype["clear"]=Response.prototype.clear=function(){this["aInB"]=true;this["bInA"]=true;this["overlap"]=Number.MAX_VALUE;return this};var T_VECTORS=[];for(var i=0;i<10;i++){T_VECTORS.push(new Vector)}var T_ARRAYS=[];for(var i=0;i<5;i++){T_ARRAYS.push([])}var T_RESPONSE=new Response;var TEST_POINT=new Box(new Vector,1e-6,1e-6).toPolygon();function flattenPointsOn(points,normal,result){var min=Number.MAX_VALUE;var max=-Number.MAX_VALUE;var len=points.length;for(var i=0;i<len;i++){var dot=points[i].dot(normal);if(dot<min){min=dot}if(dot>max){max=dot}}result[0]=min;result[1]=max}function isSeparatingAxis(aPos,bPos,aPoints,bPoints,axis,response){var rangeA=T_ARRAYS.pop();var rangeB=T_ARRAYS.pop();var offsetV=T_VECTORS.pop().copy(bPos).sub(aPos);var projectedOffset=offsetV.dot(axis);flattenPointsOn(aPoints,axis,rangeA);flattenPointsOn(bPoints,axis,rangeB);rangeB[0]+=projectedOffset;rangeB[1]+=projectedOffset;if(rangeA[0]>rangeB[1]||rangeB[0]>rangeA[1]){T_VECTORS.push(offsetV);T_ARRAYS.push(rangeA);T_ARRAYS.push(rangeB);return true}if(response){var overlap=0;if(rangeA[0]<rangeB[0]){response["aInB"]=false;if(rangeA[1]<rangeB[1]){overlap=rangeA[1]-rangeB[0];response["bInA"]=false}else{var option1=rangeA[1]-rangeB[0];var option2=rangeB[1]-rangeA[0];overlap=option1<option2?option1:-option2}}else{response["bInA"]=false;if(rangeA[1]>rangeB[1]){overlap=rangeA[0]-rangeB[1];response["aInB"]=false}else{var option1=rangeA[1]-rangeB[0];var option2=rangeB[1]-rangeA[0];overlap=option1<option2?option1:-option2}}var absOverlap=Math.abs(overlap);if(absOverlap<response["overlap"]){response["overlap"]=absOverlap;response["overlapN"].copy(axis);if(overlap<0){response["overlapN"].reverse()}}}T_VECTORS.push(offsetV);T_ARRAYS.push(rangeA);T_ARRAYS.push(rangeB);return false}SAT["isSeparatingAxis"]=isSeparatingAxis;function voronoiRegion(line,point){var len2=line.len2();var dp=point.dot(line);if(dp<0){return LEFT_VORONOI_REGION}else if(dp>len2){return RIGHT_VORONOI_REGION}else{return MIDDLE_VORONOI_REGION}}var LEFT_VORONOI_REGION=-1;var MIDDLE_VORONOI_REGION=0;var RIGHT_VORONOI_REGION=1;function pointInCircle(p,c){var differenceV=T_VECTORS.pop().copy(p).sub(c["pos"]);var radiusSq=c["r"]*c["r"];var distanceSq=differenceV.len2();T_VECTORS.push(differenceV);return distanceSq<=radiusSq}SAT["pointInCircle"]=pointInCircle;function pointInPolygon(p,poly){TEST_POINT["pos"].copy(p);T_RESPONSE.clear();var result=testPolygonPolygon(TEST_POINT,poly,T_RESPONSE);if(result){result=T_RESPONSE["aInB"]}return result}SAT["pointInPolygon"]=pointInPolygon;function testCircleCircle(a,b,response){var differenceV=T_VECTORS.pop().copy(b["pos"]).sub(a["pos"]);var totalRadius=a["r"]+b["r"];var totalRadiusSq=totalRadius*totalRadius;var distanceSq=differenceV.len2();if(distanceSq>totalRadiusSq){T_VECTORS.push(differenceV);return false}if(response){var dist=Math.sqrt(distanceSq);response["a"]=a;response["b"]=b;response["overlap"]=totalRadius-dist;response["overlapN"].copy(differenceV.normalize());response["overlapV"].copy(differenceV).scale(response["overlap"]);response["aInB"]=a["r"]<=b["r"]&&dist<=b["r"]-a["r"];response["bInA"]=b["r"]<=a["r"]&&dist<=a["r"]-b["r"]}T_VECTORS.push(differenceV);return true}SAT["testCircleCircle"]=testCircleCircle;function testPolygonCircle(polygon,circle,response){var circlePos=T_VECTORS.pop().copy(circle["pos"]).sub(polygon["pos"]);var radius=circle["r"];var radius2=radius*radius;var points=polygon["calcPoints"];var len=points.length;var edge=T_VECTORS.pop();var point=T_VECTORS.pop();for(var i=0;i<len;i++){var next=i===len-1?0:i+1;var prev=i===0?len-1:i-1;var overlap=0;var overlapN=null;edge.copy(polygon["edges"][i]);point.copy(circlePos).sub(points[i]);if(response&&point.len2()>radius2){response["aInB"]=false}var region=voronoiRegion(edge,point);if(region===LEFT_VORONOI_REGION){edge.copy(polygon["edges"][prev]);var point2=T_VECTORS.pop().copy(circlePos).sub(points[prev]);region=voronoiRegion(edge,point2);if(region===RIGHT_VORONOI_REGION){var dist=point.len();if(dist>radius){T_VECTORS.push(circlePos);T_VECTORS.push(edge);T_VECTORS.push(point);T_VECTORS.push(point2);return false}else if(response){response["bInA"]=false;overlapN=point.normalize();overlap=radius-dist}}T_VECTORS.push(point2)}else if(region===RIGHT_VORONOI_REGION){edge.copy(polygon["edges"][next]);point.copy(circlePos).sub(points[next]);region=voronoiRegion(edge,point);if(region===LEFT_VORONOI_REGION){var dist=point.len();if(dist>radius){T_VECTORS.push(circlePos);T_VECTORS.push(edge);T_VECTORS.push(point);return false}else if(response){response["bInA"]=false;overlapN=point.normalize();overlap=radius-dist}}}else{var normal=edge.perp().normalize();var dist=point.dot(normal);var distAbs=Math.abs(dist);if(dist>0&&distAbs>radius){T_VECTORS.push(circlePos);T_VECTORS.push(normal);T_VECTORS.push(point);return false}else if(response){overlapN=normal;overlap=radius-dist;if(dist>=0||overlap<2*radius){response["bInA"]=false}}}if(overlapN&&response&&Math.abs(overlap)<Math.abs(response["overlap"])){response["overlap"]=overlap;response["overlapN"].copy(overlapN)}}if(response){response["a"]=polygon;response["b"]=circle;response["overlapV"].copy(response["overlapN"]).scale(response["overlap"])}T_VECTORS.push(circlePos);T_VECTORS.push(edge);T_VECTORS.push(point);return true}SAT["testPolygonCircle"]=testPolygonCircle;function testCirclePolygon(circle,polygon,response){var result=testPolygonCircle(polygon,circle,response);if(result&&response){var a=response["a"];var aInB=response["aInB"];response["overlapN"].reverse();response["overlapV"].reverse();response["a"]=response["b"];response["b"]=a;response["aInB"]=response["bInA"];response["bInA"]=aInB}return result}SAT["testCirclePolygon"]=testCirclePolygon;function testPolygonPolygon(a,b,response){var aPoints=a["calcPoints"];var aLen=aPoints.length;var bPoints=b["calcPoints"];var bLen=bPoints.length;for(var i=0;i<aLen;i++){if(isSeparatingAxis(a["pos"],b["pos"],aPoints,bPoints,a["normals"][i],response)){return false}}for(var i=0;i<bLen;i++){if(isSeparatingAxis(a["pos"],b["pos"],aPoints,bPoints,b["normals"][i],response)){return false}}if(response){response["a"]=a;response["b"]=b;response["overlapV"].copy(response["overlapN"]).scale(response["overlap"])}return true}SAT["testPolygonPolygon"]=testPolygonPolygon;return SAT})},{}]},{},[]);var SAT=require("sat");var testCircleCollision=function(a,b){var circleA=new SAT.Circle(new SAT.Vector(a.x,a.y),a.r);var circleB=new SAT.Circle(new SAT.Vector(b.x,b.y),b.r);var response=new SAT.Response;var collided=SAT.testCircleCircle(circleA,circleB,response);console.log("did collide?",collided,"details:",response);return{collided:collided,response:response}};var reflectBullet=function(bullet,wall,sat_response){var distVector=new SAT.Vector(bullet.v,0);var origBulletX=bullet.x;var origBulletY=bullet.y;var currentVector=new SAT.Vector(bullet.x,bullet.y);var bullet_trajectory_radians=Math.atan2(bullet.targetY-bullet.origY,bullet.targetX-bullet.origX);console.log("bullet tragectory radians",bullet_trajectory_radians);distVector.rotate(bullet_trajectory_radians);currentVector.sub(distVector);bullet.x=currentVector.x;bullet.y=currentVector.y;bullet.origY=bullet.y;bullet.origX=bullet.x;var reflectVector=sat_response.overlapN;var targetVector=new SAT.Vector(bullet.origX,bullet.origY);console.log("reflected towards target",targetVector)};var a_beam_of_light={x:25,y:40,r:1,v:1,origX:0,origY:40,targetX:50,targetY:40};var a_curved_mirror={x:50,y:50,r:25};var step_world=function(){a_beam_of_light.x=a_beam_of_light.x+a_beam_of_light.v;var test_results=testCircleCollision(a_beam_of_light,a_curved_mirror);if(test_results.collided){reflectBullet(a_beam_of_light,a_curved_mirror,test_results)}};step_world()},0); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "requirebin-sketch", | |
"version": "1.0.0", | |
"dependencies": { | |
"sat": "0.6.0" | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- contents of this file will be placed inside the <body> --> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- contents of this file will be placed inside the <head> --> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment