HTML5+Javascript 小球碰撞

初次用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();
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值