Point-Line Collision

by makurell

HTML

<canvas id="c"></canvas>

CSS

* { margin:0; padding:0; }
html, body { width:100%; height:100%; }
canvas { display:block; }

JavaScript

var c = document.getElementById('c'),
cx = c.getContext('2d');

var t = 0; //gametime
var speed = 1; //gamespeed
var fps = 120;//max is 1000
var f = 1000.0/fps*speed;

var balls=[];//list of ball objects
var lines=[];

function newBall(x,y,vx=0,vy=0){
  return {
    x:x,
    y:y,
    m:20,//mass
    r:20,
    vx:vx,
    vy:vy,
    w:1,//width
  }
}
function newLine(x1,y1,x2,y2){
  return {
    x1:x1,
    y1:y1,
    x2:x2,
    y2:y2,
    w:1,//width
  }
}

function init(){
	lines.push(newLine(300,30,400,550));
  lines.push(newLine(30,650,400,550));

  balls.push(newBall(30,30,0.7,0.3));
}

function update(){
	for(var i=0; i<balls.length; i++){
  	var ball=balls[i];
    
    //collision with line
    for(var j=0; j<lines.length; j++){
    	var line=lines[j];
      if(distPS(ball.x+ball.vx*f,ball.y+ball.vy*f,line.x1,line.y1,line.x2,line.y2)<ball.r){
        //collided
        //store ball vel magnitude
        var mag=Math.sqrt(Math.pow(ball.vx,2)+Math.pow(ball.vy,2));
        
        //compute n
        var d = dist(line.x1,line.y1,line.x2,line.y2);
        var nx = (line.y1-line.y2)/d;
        var ny = (line.x2-line.x1)/d;
        //console.log({nx,ny});
        
        //split ball vel into components:
        var ux=(ball.vx*nx+ball.vy*ny/nx*nx+ny*ny)/nx;
        var uy=(ball.vx*nx+ball.vy*ny/nx*nx+ny*ny)/ny;
        var wx=ball.vx-ux;
        var wy=ball.vy-uy;
        
        //compute resultant vel
        rx=(wx-ux);
        ry=(wy-uy);

        //compute k (constant to result in same mag)
        var k = (mag*Math.sqrt(Math.pow(rx,2)+Math.pow(ry,2)))/(Math.pow(rx,2)+Math.pow(ry,2));
        
        //apply vel
        ball.vx=k*rx;
        ball.vy=k*ry;
      }
    }
    
    //updt vels
    ball.x=ball.x+ball.vx*f;
    ball.y=ball.y+ball.vy*f;
  }
}

function draw(){
	for(var i=0; i<lines.length;i++){
  	drawLine(lines[i]);
  }
  for(var i=0; i<balls.length;i++){
  	drawBall(balls[i]);
  }
}
function drawLine(line){
  cx.beginPath();
 ...