Thông thường các đối tượng trong game sẽ được xác định va chạm bằng cách đưa chúng về một dạng hình học cơ bản như hình chữ nhật, hình trịn. Bài viết này sẽ giúp bạn cách tính tốn để kiểm tra va chạm giữa hai loại hình học này.
1. Giữa hai hình chữ nhật
Phương pháp: kiểm tra từng đỉnh của hình này có nằm bên trong hình kia khơng.
Rect.prototype.collideWidthRect = function(rect) { return this.contains(rect.left,rect.top) || this.contains(rect.right,rect.top) || this.contains(rect.right,rect.bottom) || this.contains(rect.left,rect.bottom); }
Cách trên không phải cách nhanh nhất, vì vậy bạn có thể dùng cách sau, đơn giản và hiệu quả hơn:
Rect.prototype.collideWidthRect = function(rect) { return !(this.left > rect.right ||
48 | P a g e this.right < rect.left || this.top > rect.bottom || this.bottom < rect.top); } 2. Giữa hai hình trịn
Phương pháp: Bởi vì mọi điểm nằm trên đường tròn cách đều tâm, nên việc kiểm tra va chạm giữa hai hình trịn sẽ được xác định dựa vào khoảng cách tâm giữa chúng. Để xác định khoảng cách giữa hai điểm, ta dựa vào định lý Pythagoras (Pythagorean theorem) . Ta coi khoảng cách giữa hai điểm là đường chéo của một tam giác vuông. Vậy độ lớn của đường chéo này là:
c² = a² + b²
=> c = sqrt(a² + b²)
Circle.prototype.collideWithCircle = function(circle){ var dx = this.cx - circle.cx;
var dy = this.cy - circle.cy;
return Math.sqrt(dx*dx + dy*dy) <= this.radius+circle.radius; }
Trong minh họa dưới đây, hai hình trịn có màu mặc định là xanh lá, khi va chạm nhau, chúng sẽ chuyển sang màu đỏ.
3. Giữa hình trịn và hình chữ nhật
Phương pháp: Gọi C là tâm và R là bán kính hình trịn. Ta sẽ tìm cách xác định điểm A là điểm gần nhất thuộc hình chữ nhật đến tâm C. Sau đó so sánh độ lớn của CA với R.
49 | P a g e Khoảng cách giữa tâm C hình trịn và điểm A của hình chữ nhật được minh họa như hình dưới đây. Khi tâm hình trịn nằm bên trong hình chữ nhật, thì điểm C và A sẽ trùng nhau.
Gọi rect là hình chữ nhật cần xác định va chạm. Ta có thuật toán để xác định điểm A như sau: - B1: Gán A bằng với C.
- B2: Nếu C.X < rect.Left, đặt A.X = rect.Left. Ngược lại nếu C.X > rect.Right, đặt A.X =
rect.Right.
- B3: Nếu C.Y < rect.Top, đặt A.Y = rect.Top. Ngược lại nếu C.Y > rect.Bottom, đặt A.Y = rect.Bottom.
Khi đã có điểm A, ta lại dùng công thức Pythagoras để so sánh với bán kính của hình trịn.
Circle.prototype.collideWithRect = function(rect){ var px = this.cx;
var py = this.cy;
if(px < rect.left) px = rect.left; else if(px > rect.right)
px = rect.right;
if(py < rect.top) py = rect.top; else if(py > rect.bottom)
py = rect.bottom;
var dx = this.cx - px; var dy = this.cy - py;
return (dx*dx + dy*dy) <= this.radius*this.radius; }
50 | P a g e