Bài toán va chạm là một
nỗi ám ảnh và lo sợ của những lập trình viên trong việc phát triễn game, thông
thường họ thường chọn cho mình phương án sử dụng các API sẵn có để giải quyết
bài toán. Đa số các lập trình viên đều sử dụng phương pháp tính bao hình (AABB)
là phương án cho bài toán va chạm, tuy nhiên phương pháp này khi nâng cấp lên
các thuật toán nâng cao hơn như SAT và GJK lại gặp rất nhiều khó khăn. Swept
AABB là một giải thuật trung gián, nó ứng dụng tư tưởng của giải thuật bao AABB
thông thường nhưng là chuyển tiếp đến các giải thuật nâng cao khác, giúp lập
trình viên dễ dàng tiếp cận và sử dụng.
Ghi
chú: Bài viết này sẽ giúp bạn đọc tìm hiểu thuật toán
AABB, thuật toán lấy căn bản là toán vector, tuy nhiên sẽ không quá phức tạp để
có thể hiểu và ứng dụng vào bài toán thực tế. Các ví dụ được biểu diễn trên nền
C/C++ và hoàn toàn có thể chuyển đối sang bất kì ngôn ngữ khác như: C#, Java,...
SWEPT
LÀ GÌ?
AABB được diễn tả gồm 3
vấn đề cơ bản, mà hiếm khi chúng được nhìn nhận ngay lần đầu tiếp cận. 3 vấn đề
đó bao gồm:
Trường hợp 1: trường hợp
căn bản của AABB. Hình vuông màu xanh là trạng thái của đối tượng trước khi diễn
ra va chạm, hình xanh lá cây là trạng thái của đối tượng sau khi di chuyển,
hình AABB là trạng thái của đối tượng sau khi di chuyển và được xử lý thông qua
thuật giải AABB. Hình chử nhật màu xám là đối tượng tỉnh không di chuyển. Kết
quả của trường hợp thứ nhất: sau khi hình vuông xanh xảy ra va chạm với hình
xám thì sẽ được chuyển về vị trí cạnh điểm va chạm và không bị va chạm với hình
xám.
Trường hợp 3: khi kết
quả của quá trình di chuyển là đối tượng đích cách quá xa với vật cản và không
hề diễn ra va chạm với vật cản, điều đó 2 đối tượng sẽ dường như không có va chạm
diễn ra.
Vậy vấn đề là đâu? Và tại sao ta lại cần swept?
Vấn đề nảy sinh khi đối tượng di chuyển quá nhanh,
và dường như sau 1 frame di chuyển hoàn toàn không thể kiểm tra được các đối tượng
có va chạm hay không vì toàn bộ đều rơi vào trường hợp thứ 3. Để giải quyết vấn
đề đó, ta cần biết được khoảng di chuyển của đối tượng qua thời gian, từ đó kiểm
tra chính xác các va chạm, đó gọi là swept!.
HIỆN
THỰC SWEPT AABB
Trong phần tiếp theo của bài viết, đối tượng va chạm
được xác định bởi tọa độ góc trái trên và chiều rộng, chiều dài của chúng. Một
yếu tố khóa của swept trong tính toán mà không thể bỏ qua là vận tốc của đối tượng.
Ghi
chú: Vận tốc của đối tượng là giá trị cho biết bước di
chuyển của đối tượng sau mỗi 1 giấy. Nếu chúng ta nhân vận tốc với một khoảng
thời gian, thì chúng ta sẽ thu được vùng di chuyển của đối tượng trong khoảng
thời gian đó.
c ấu trúc của một đối tượng va chạm được định dạng
trong một box như sau:
Phương thức kiểm tra SweptAABB được mô tả như sau:
Trong đó:
-
Box1: là đối tượng di chuyển.
-
Box2: là đối tượng tĩnh xét va chạm.
-
Normalx, Normaly là giá trị để xác định
kết quả phản ứng sau quá trình va chạm.
Ghi
chú: thông thường
sau những va chạm, đối tượng sẽ chuyển hướng 90 độ so với góc di chuyển ban đầu.
Giá trị trả về của phương thức sweptAABB nằm trong
khoảng 0 đến 1, trong đó chỉ định trạng thái va chạm đang diễn ra. Nếu giá trị
là 0 cho biết đang bắt đầu di chuyển, giá trị là 1 cho biết kết thúc di chuyển
(không xảy ra va chạm nữa), giá trị 0.5 cho biết đối tượng đang va chạm ở đoạn
giữa.
Và bây giờ chúng ta sẽ chính thức đi vào quá trình
tính toán của swept, trước tiên, thuật toán sẽ tính toán những khoảng cách, thời
gian cần thiết trên mỗi trục x, y để xác định thời điểm va chạm.
Trong đó các giá trị: InvEntry là khoảng cách gần nhất
của 2 cạnh bất kỳ của 2 đối tượng, InvExit là khoảng cách xa nhất của 2 cạnh bất
kỳ của 2 đuối tượng. Ở đây chúng ta vạch sẵn đường đi của đối tượng để dự đoán
thời gian có thể xãy ra va chạm của 2 đối tượng.
Tiếp theo, chúng ta sẽ căn cứ vào vận tốc của đối tượng
và các chỉ số khoảng cách để tính toán khả năng va chạm của 2 đối tượng.
Và câu hỏi được đặt ra ở đây là: tại sao chúng ta phải
tính toán xEntry, xExit, yEntry, yExit bằng phép toán chia vận tốc.
Trả lời: trong mỗi đơn vị thời gian di chuyển, đối
tượng sẽ di chuyển đúng một khoảng cách bằng vận tốc, như vậy, phép toán chia
xác định xảy ra va chạm khi giá trị phép tính từ 0 đến 1.
Như vậy, cơ bản ta xác định được thêm 1 điều kiện
không diễn ra va chạm là thời gian kết thúc va chạm sớm hơn thời gian bắt đầu
va chạm.
Với giá trị trả về là 1 cho biết không có khả năng xảy
ra va chạm.
Tiếp theo, khi va chạm được xác nhận diễn ra, vận tốc
sẽ được biến đổi để thể hiện được phản ứng của đối tượng với va chạm.
Vì mỗi đối tượng chỉ có 4 điểm vị trí, nên sẽ có tối
đa 4 trường hợp tương tác va chạm diễn ra. Với cách tính đơn giản như trên, đã
chỉ ra được giá trị kết quả của va chạm và thời gian va chạm.
Trên đây là toàn bộ code hướng dẫn kỹ thuật Swept
AABB, nhưng sẽ không đúng trong một số trường hợp, vì trên thực tế, đối tượng
không chỉ thay đổi về vận tốc mà còn các thuộc tính như: hướng, cách di chuyển,
vv.. Và đó chính là nội dung của phần tiếp theo.
Không có nhận xét nào:
Đăng nhận xét