Đăng ký
Cộng đồng phát triển game Việt - kết nối đam mê !

Understanding Steering Behaviors: Seek


Để làm cho một nhân vật có thể di chuyển một cách trung thực nhất chúng ta cần thêm vào những hàm xử lý việc di chuyển. Ví dụ như một chiếc xe đang chạy thẳng khi chúng ta đổi hướng của xe thì phải xử lý sao cho chiếc xe di chuyển trông tự nhiên nhất.


Việc di chuyển của các đối tượng được xử lý dựa vào các phép tính trên vector. Nên trước khi bắt đầu vào xử lý việc di chuyển chúng ta nên ôn chút về vector.


I. Tìm hiểu tổng quát về xử lý vector


1.Vector là gì: link


Vector là một đoạn thẳng có hướng . Ví dụ trong mặt phẳng cho hai điểm A, B bất kỳ ta có thể xác định được vector AB. Trong mặt phẳng chỉ có điểm A hoặc B thì ta có thể xác định được vector OA hoặc OB.


 


1
2
3
4
5
6
7
8
9
10
function Vector(x,y)
{
    this.x = x;
    this.y = y;
    this.SetPos = function(x,y)
    {
        this.x = x;
        this.y = y;
    }
}

2.Cộng trừ vector:


Việc cộng 2 vector theo nguyên tắc đuôi vector này nối với đầu vector kia. ví dụ vector AB + BC = AC. Đuôi là B của vector AB và đầu là B của vector BC.



1
2
3
4
5
function PlusVector(VectorA,VectorB)
{
    var result = new Vector(VectorA.x + VectorB.x,VectorA.y+VectorB.y);
    return result;
} 

Từ việc cộng vector ta có thể suy ra trừ 2 vector AC- AB = BC.


1
2
3
4
5
function MinusVector(a,b)
{
    var result = new Vector(a.x - b.x,a.y-b.y);
    return result;
}

3. Nomarlize vector


Normarlize vector được hiểu như là việc chuẩn hoá vector, đưa vector về vector đơn vị mà không làm thay đổi phương và chiều của vector. Với x,y nằm trong khoảng -1 và 1.( - 1 < x, y < 1 ). Việc chuẩn hoá vector như vậy giúp cho việc tính toán trên vector trở nên dễ dàng và tối ưu hơn hơn. 


1
2
3
4
5
function Normalize(VectorA)
{
    var distance = LengthVector(VectorA);
    return new Vector(VectorA.x/distance,VectorA.y/distance);
}

 4. Truncate vector


Truncate chúng ta có hiểu đơn giản là việc cắt cụt không vượt quá độ dài tối đa để di chuyển toạ độ điểm gốc của một vector.


Ví dụ:



Toạ độ điểm đầu A đã di được di chuyển đến một độ dài sau một lần truncate.


1
2
3
4
5
6
7
8
9
10
11
function TruncateVector(vector, maxLength)
{
    var s;
    s = maxLength/LengthVector(vector);
     // console.log(s);
    if(s
    s=1;
    vector.x *= s;
    vector.y *= s;
    return vector;
}

II. Di chuyển vật thể không xử dụng việc bẻ lái (steering) của nhân vật:

Trước tiên chúng ta cách di chuyển đơn giản nhất đó chính là khi một vật đang di chuyển mà ta đổi hướng di chuyển của đối tượng đó thì đối tượng đó sẽ lập tức đổi hướng mà không cần xử lý bất kỳ sự kiện bẻ lái nào cả.


Ví dụ để di chuyển vật thể đang nằm ở toạ độ A di chuyển theo vector AB thì chúng ta có công thức OA + AB = OB => AB = OB - OA 


Vì thế để có thể di chuyển theo hướng vector AB chúng ta chỉ cần lấy vector B - Vector A. Nghĩa là lấy vector đích trừ cho vector của vật thể


Ta gọi vector AB là vector vận tốc vì A sẽ di chuyển theo hướng vector đó.


1
2
velocityVector = Normalize(TruVector(destVector,object.pos));
velocityVector = MultiVector(velocityVector,max_velocity);

Sau khi đã có vector Vận tốc thì việc cuối cùng là ta lấy toạ độ nhân vật cộng với vector vận tốc để nhân vật di chuyển theo hướng của vector đó

1
object.pos = PlusVector(object.pos,velocityVector);

Demo: ( Click chuột trái để di điều khiển )


III. Xử lý việc bẻ lái của nhân vật:


Ví dụ trên chưa xử lý việc bẻ lái nên đối tượng di chuyển không tự nhiên khi thay đổi vị trí đích. Để làm cho nhân vật di chuyển tự nhiên hơn ta sẽ thêm vào một vector vận tốc tại vị trí mới và giữ vị trí vector vị trí cũ. Bằng cách này chúng ta chỉ cần thay đổi từ từ vector vận tốc hiện tại để nhân vật có thể di chuyển đúng hướng với điểm đích cần đến.


Steering forces.


Nhân vật đang di chuyển theo vector currentVelocity để di chuyển theo hướng vector mới là desiredVelocity thì chúng ta phải xử lý để vector currentVelocity di chuyển theo hướng vector Steering. vector steering = desiredVeclocity - currentVelocity.


1
2
desire_velority = MultiVector(Normalize(TruVector(desiredVelocity,object.pos)),max_velocity);
steering = MinusVector(desire_velority,velocityVector);

Sau khi đã có vector steering thì việc còn lại là cho vector currentVelocity di chuyển theo hướng mới hướng về target. Vì thế nhân vật sẽ di chuyển vừa theo hướng currentVelocity và steering nên nhân vật sẽ di chuyển theo dạng hình cung.

Seek path.

1
2
3
4
5
6
steering = TruncateVector(steering,max_force);
steering = DevideVector(steering,mass);  
 
velocityVector = TruncateVector(PlusVector(velocityVector,steering),max_speed);
 
object.pos = PlusVector(object.pos,velocityVector);

Demo: ( Click chuột trái để di điều khiển )


Kết luận:


Việc thêm vào xử lý bẻ lái khiến cho nhân vật có thể di chuyển một cách thật hơn. Việc xử lý tính toán có vẻ đơn giản nhưng cho một kết quả rất tốt. Bài tutorial này hướng dẫn một trong những hành vi bẻ lái di chuyển của nhân vật đơn giản nhất. Qua những bài viết tiếp theo chúng ta sẽ học thêm những cách di chuyển khác phức tạp hơn như là né vật cản, hoặc chạy trốn một đối tượng như là enemy, hoặc thậm chí khiến cho nhân vật di chuyển vòng vòng một cách tự nhiên, mong các bạn đón xem .


Trong bài viết nếu có chổ nào sai sót mong mọi người góp ý  !!!.

Tuấn Trần
Không cần điều kiện s==1 đâu bạn. Bạn có thể coi link tham khảo về các cách tính TruncateVector nè : http://blog.signalsondisplay.com/?p=336
  • tháng 7 9, 2013
  • ·
  • Thích
  • ·
Mr Phêu
Bác nào gợi ý cho e về vụ này cái, e hơi bị mù mờ về vụ vecto này. Đề bài ở link ảnh
http://i.upanh.com/vpdcoh
e muốn tìm toạ độ điểm E và F sao cho luôn vuông góc với vecto AB ạ...và điểm B luôn luôn di chuyển, A thì cố định...
cảm ơn các bác trước ạ...
  • tháng 7 23, 2013
  • ·
  • Thích
  • ·
Lân
thank so much, bài viết rất chi tiết, có cả hàm code để minh họa,
  • tháng 7 29, 2013
  • ·
  • Thích
  • ·
Tuấn Trần
@Mr Phiêu: Muốn tìm toạ độ điểm điểm E F thì ta chỉ cần tìm vector BE thôi là điểm F chỉ cần reverse là kiếm được. Vậy giờ điều duy nhất chúng ta cần tìm là tìm vector BE. Để có được vector BE chúng ta cần tìm góc EBC, khi có được góc EBC thì vector BE được tính như sau: vector.X = Math.Cos(angle); ...
  • tháng 7 30, 2013
  • ·
  • Thích
  • ·
Jack Steve
cho mình hỏi tí, sao lại lấy vecto trừ cho điểm, trả ra kết quả Vecto,
desire_velority = MultiVector(Normalize(TruVector(desiredVelocity,object.pos)),max_velocity);
  • tháng 10 22, 2013
  • ·
  • Thích
  • ·
Nguyễn Bảo Toàn
điểm ở đây là lấy điểm đó với điểm gốc tọa độ tạo thành vector đó bạn
  • tháng 3 24, 2014
  • ·
  • Thích
  • ·
Xuyen Nguyen
các giá trị max_force , mass ở trong bài này thì lấy giá trị như thế nào vậy nhỉ
  • tháng 4 15, 2014
  • ·
  • Thích
  • ·
OKYO
http://gamedevelopment.tutsplus.com/tutorials/unde...

bạn đọc bài gốc ở đây nhé
  • tháng 12 11, 2014
  • ·
  • Thích
  • ·
OKYO
Bài viết này có một số chỗ sai trong công thức thì phải, ngoài ra tác giả nên ghi chú các biến dùng trong công thức, mình nghĩ bài gốc ở đây:

http://gamedevelopment.tutsplus.com/tutorials/unde...
  • tháng 12 11, 2014
  • ·
  • Thích
  • ·
OKYO
sao phấn steering em làm nó ko đi được vòng vòng thế kia nhỉ ?
Nguyễn Tài Hải
@namtran
  • tháng 12 11, 2014
  • ·
  • Thích
  • ·
Phạm Anh Đại
velocityVector = Normalize(TruVector(destVector,object.pos));
velocityVector = MultiVector(velocityVector,max_velocity);
mình k hiểu hàm multivector là hàm gì?
  • tháng 1 3, 2015
  • ·
  • Thích
  • ·
OKYO
Hàm nhân vector đó mà, multi là nhân
  • tháng 1 3, 2015
  • ·
  • Thích
  • ·
dudu
rat hieu qua
  • tháng 5 12, 2015
  • ·
  • Thích
  • ·
Captcha Challenge