初次用HTML5的canvas和javascript,实现了一个多个小球匀速运动的动画,主要有边界反弹和碰撞
/**
*
*/
var cvs;
var ctx;
var cvs_width;
var cvs_height;
var shape_vec = new Array();
var velocity_vec = new Array();
var num_shapes = 20;
var Shape = function(x, y, r)
{
this.m_x = x;
this.m_y = y;
this.m_r = r;
};
var Velocity = function(x, y)
{
this.m_x = x;
this.m_y = y;
};
function get_len(x, y)
{
var len = Math.sqrt(x*x + y*y);
return len;
}
function get_cos(x1, y1, x2, y2)
{
var product = x1*x2 + y1*y2;
var len1 = get_len(x1, y1);
var len2 = get_len(x2, y2);
var cos = product/Math.sqrt(len1 * len2);
return cos;
}
function initCanvas()
{
$(document).ready(function()
{});
cvs = $('#ID_CVS');
ctx = cvs.get(0).getContext('2d');
// jquery methods
cvs.attr("width", $(window).get(0).innerWidth - 20);
cvs.attr("height", $(window).get(0).innerHeight - 20);
cvs_width = cvs.width();
cvs_height = cvs.height();
}
function initShapes()
{
for(var i=0; i<num_shapes; i++)
{
var x = 20+i*10;
var y = 20+i*10;
//var r = 5+Math.random()*5;
var r = 6;
shape_vec[i] = new Shape(x, y, r);
};
}
function initVelocity()
{
for(var i=0; i<num_shapes; i++)
{
var x = 2 + Math.random()*5;
var y = 2 + Math.random()*5;
velocity_vec[i] = new Velocity(x, y);
};
}
function boundary_check_and_bounce()
{
var pixel_delta = 2;
for(var i=0; i<num_shapes; i++)
{
var tmpShape = shape_vec[i];
var tmpVelocity = velocity_vec[i];
var delta_x_0 = tmpShape.m_x - tmpShape.m_r - pixel_delta;
var delta_x_w = tmpShape.m_x + tmpShape.m_r + pixel_delta - cvs_width;
if(delta_x_0 < 0)
{
tmpVelocity.m_x *= -1;
tmpShape.m_x -= delta_x_0;
}
else if(delta_x_w > 0)
{
tmpVelocity.m_x *= -1;
tmpShape.m_x -= delta_x_w;
};
var delta_y_0 = tmpShape.m_y - tmpShape.m_r - pixel_delta;
var delta_y_h = tmpShape.m_y + tmpShape.m_r + pixel_delta - cvs_height;
if(delta_y_0 < 0)
{
tmpVelocity.m_y *= -1;
tmpShape.m_y -= delta_y_0;
}
else if(delta_y_h > 0)
{
tmpVelocity.m_y *= -1;
tmpShape.m_y -= delta_y_h;
};
};
}
// coordinates transform, pretty cool
function collision_check_and_bounce_instruct()
{
for(var i=0; i<num_shapes; i++)
{
for(var j=i+1; j<num_shapes; j++)
{
var shapeA = shape_vec[i];
var shapeB = shape_vec[j];
var vA = velocity_vec[i];
var vB = velocity_vec[j];
var dx = (shapeB.m_x - shapeA.m_x);
var dy = (shapeB.m_y - shapeA.m_y);
var distance = Math.sqrt(dx*dx + dy*dy);
var angle = Math.atan2(dy, dx);
var sine = Math.sin(angle);
var cosine = Math.cos(angle);
if(shapeA.m_r + shapeB.m_r > distance)
{
var x = 0;
var y = 0;
var xB = dx*cosine + dy*sine;
// assert yB == 0
var yB = dy*cosine - dx*sine;
var vA_x = vA.m_x *cosine + vA.m_y*sine;
var vA_y = vA.m_y*cosine - vA.m_x*sine;
var vB_x = vB.m_x * cosine + vB.m_y * sine;
var vB_y = vB.m_y * cosine - vB.m_x * sine;
var tmp = vA_x;
vA_x = vB_x;
vB_x = tmp;
xB = x + shapeA.m_r + shapeB.m_r + 0.5;
shapeA.m_x = shapeA.m_x + (x*cosine - y*sine);
shapeA.m_y = shapeA.m_y + (y*cosine - x*sine);
shapeB.m_x = shapeA.m_x + (xB*cosine - yB*sine);
shapeB.m_y = shapeA.m_y + (yB*cosine + xB*sine);
vA.m_x = vA_x*cosine - vA_y*sine;
vA.m_y = vA_y*cosine + vA_x*sine;
vB.m_x = vB_x*cosine - vB_y*sine;
vB.m_y = vB_y*cosine + vB_x*sine;
};
};
};
}
function animate()
{
ctx.clearRect(0, 0, cvs_width, cvs_height);
boundary_check_and_bounce();
// collision_check_and_bounce();
collision_check_and_bounce_instruct();
for(var i=0; i<num_shapes; i++)
{
var tmpShape = shape_vec[i];
var tmpVelocity = velocity_vec[i];
ctx.beginPath();
ctx.arc(tmpShape.m_x, tmpShape.m_y, tmpShape.m_r, 0, Math.PI*2, false);
ctx.closePath();
ctx.fill();
tmpShape.m_x += tmpVelocity.m_x;
tmpShape.m_y += tmpVelocity.m_y;
};
setTimeout(animate, 30);
}
function main()
{
initCanvas();
ctx.fillRect(300, 300, 50, 30);
initShapes();
initVelocity();
animate();
}