GameDev – Va chạm giữa nhiều đường tròn

HTML5 - Canvas - Multiple Balls Collisions(Kích thước quả cầu tương ứng với khối lượng của nó và được hiển thị bởi con số bên trong)

Xem Demo.  

Để xác định hướng di chuyển của hai quả cầu có khối lượng khác nhau sau khi va chạm, ta sử dụng công thức của định luật bảo toàn động lượng trong một hệ cô lập.

Xét trường hợp va chạm trong không gian một chiều (1D – các vật di chuyển trên một đường thẳng), ta gọi m là khối lượng và vận tốc của quả cầu C, u là vận tốc trước khi va chạm và v là vận tốc sau khi va chạm. Tại thời điểm hai quả cầu C1 và C2 va chạm nhau, ta có công thức:

m1u1 + m2u2 = m1v1 + m2v2

Suy ra:

v1 = (u1*(m1-m2) + 2*m2*u2)/(m1+m2)

v2 = (u2*(m2-m1) + 2*m1*u1)/(m1+m2)

Ta có thể áp dụng công thức này trong không gian hai chiều (2D) để tính vận tốc theo một phương xác định.

Bằng cách chia vector vận tốc thành hai vector thành phần, một vector ux1 nằm trên đường thẳng chứa hai tâm C1 và C2 (phương ngang), vector uy1 còn lại vuông góc với vx1 (phương dọc).ta chuyển không gian 2 chiều thành 1 chiều theo phương chứa đoạn thẳng nối hai tâm đường tròn.

Two Balls collision

var angle1 = Math.atan2(u1.y, u1.x);
var ux1 = u1.length * Math.cos(angle1-angle);
var uy1 = u1.length * Math.sin(angle1-angle);

Áp dụng công thức bên trên, ta tính được vector vận tốc mới theo phương ngang là vx1. Do đây là không gian 1D nên vận tốc uy1 sẽ không ảnh hưởng.

var vx1 = ((ball1.mass-ball2.mass)*ux1+(ball2.mass+ball2.mass)*ux2)/(ball1.mass+ball2.mass);
var vy1 = uy1;

Đã có hai vector thành phần là vx1 và vy1, ta cần chuyển lại các vector mới này sang không gian 2D và hợp thành vector vector chuyển động mới là v1. Do vector vx1 vuông góc với vy1 nên ta cần cộng với angle một góc 90 độ hay PI/2. Ở đây, angle là góc tạo bởi đoạn thẳng nối hai tâm đường tròn.

var v1 = {};
v1.x = Math.cos(angle)*vx1+Math.cos(angle+Math.PI/2)*vy1;
v1.y = Math.sin(angle)*vx1+Math.sin(angle+Math.PI/2)*vy1;

Xử lý va chạm của nhiều đường tròn

Cách đơn giản nhất và có độ phức tạp tương đối nhỏ (số lần lặp là n(n-1)/2) trong việc kiểm tra và xử lý va chạm cho nhiều đối tượng là sử dụng hai vòng lặp lồng nhau theo dạng sau:

for(var i=0;i<_balls.length;i++)
{
	for(var j=i+1;j<_balls.length;j++)
		checkCollision(_balls[i],_balls[j]);
}

Mã nguồn

Download.

Hàm checkCollision:

function checkCollision(ball1,ball2){

	var dx = ball1.cx - ball2.cx;
	var dy = ball1.cy - ball2.cy;

	// check collision between two balls
	var distance =  Math.sqrt(dx*dx+dy*dy);
	if(distance > ball1.radius + ball2.radius)
		return;

	var angle = Math.atan2(dy,dx);

	var u1 = ball1.getVelocity();
	var u2 = ball2.getVelocity();

	var angle1 = Math.atan2(u1.y, u1.x);
	var angle2 = Math.atan2(u2.y, u2.x);
	var ux1 = u1.length * Math.cos(angle1-angle);
	var uy1 = u1.length * Math.sin(angle1-angle);
	var ux2 = u2.length * Math.cos(angle2-angle);
	var uy2 = u2.length * Math.sin(angle2-angle);

	var vx1 = ((ball1.mass-ball2.mass)*ux1+(ball2.mass+ball2.mass)*ux2)/(ball1.mass+ball2.mass);
	var vx2 = ((ball1.mass+ball1.mass)*ux1+(ball2.mass-ball1.mass)*ux2)/(ball1.mass+ball2.mass);
	var vy1 = uy1;
	var vy2 = uy2;

	// now we transform the 1D coordinate back to 2D
	var v1 = {}, v2 = {};
	v1.x = Math.cos(angle)*vx1+Math.cos(angle+Math.PI/2)*vy1;
	v1.y = Math.sin(angle)*vx1+Math.sin(angle+Math.PI/2)*vy1;

	v2.x = Math.cos(angle)*vx2+Math.cos(angle+Math.PI/2)*vy2;
	v2.y = Math.sin(angle)*vx2+Math.sin(angle+Math.PI/2)*vy2;

	ball1.velocity = v1;
	ball2.velocity = v2;
}

YinYang’s Blog

Advertisements

3 thoughts on “GameDev – Va chạm giữa nhiều đường tròn

Trả lời

Mời bạn điền thông tin vào ô dưới đây hoặc kích vào một biểu tượng để đăng nhập:

WordPress.com Logo

Bạn đang bình luận bằng tài khoản WordPress.com Log Out / Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Log Out / Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Log Out / Thay đổi )

Google+ photo

Bạn đang bình luận bằng tài khoản Google+ Log Out / Thay đổi )

Connecting to %s