MỤC LỤC
MỤC LỤC . 1
LỜI GIỚI THIỆU . . 2
CHƯƠNG I . 3
TỔNG QUAN VỀ THỰC TẠI ẢO VÀ 3D ANIMATION TRONG THỰC
TẠI ẢO . 3
1.1. Tổng quan về thực tại ảo. 3
1.1.1. Sơ lược lịch sử phát triển . 3
1.1.2. Các lĩnh vực ứng dụng của Thực tại ảo. 4
1.2 Hành động của nhân vật (3D Animation) trong thựctại ảo. . 9
1.2.1. Animation trong thực tại ảo là gì? . 10
1.2.2. Hiệu ứng Animation trong thực tại ảo . . 10
1.2.3. Cơ sở mô phỏng 3D Animation . 11
1.2.4. Các vấn đề gặp phải trong quá trình nghiên cứu . . 13
1.2.5. Hướng giải quyết . 14
CHƯƠNG II. 15
KỸ THUẬT MÔ PHỎNG . . . 15
2.1. Đặt vấn đề . 15
2.2. Kỹ thuật mô phỏng . 15
2.2.1 Khởi tạo nhân vật và trang phục. . 15
2.2.2 Điều khiển mô phỏng các trạng thái hành động của nhân vật . 23
2.2.3 Các vấn đề liên quan tới camera và các phím điều khiển. . 39
CHƯƠNG III . . 49
CHƯƠNG TRÌNH MÔ PHỎNG . 49
3.1. Bài toán . 49
3.2. Mục đích và yêu cầu bài toán. . 49
3.3. Phương pháp giải quyết bài toán . 49
3.4 Một số kết quả bài toán. . 50
KẾT LUẬN . 55
HƯỚNG PHÁT TRIỂN ĐỀ TÀI. 56
PHỤ LỤC. . . 57
TÀI LIỆU THAM KHẢO . . . 77
77 trang |
Chia sẻ: netpro | Lượt xem: 1965 | Lượt tải: 5
Bạn đang xem trước 20 trang tài liệu Đồ án Mô phỏng hành động nhân vật trong xây dựng mô hình 3D, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
ng trục X, Y, Z (X_AXIS, Y_AXIS,
Z_AXIS) hoặc có sự kết hợp của các trục khác (ví dụ: scale(1.1,
X_AXIS+Y_AXIS))
void player::scale(double factor, int axis)
{
double scale[3];
Morfit_object_get_scale(m_player_object,scale);
if(axis & X_AXIS)
scale[0]*=factor;
if(axis & Y_AXIS)
scale[1]*=factor;
if(axis & Z_AXIS)
scale[2]*=factor;
Morfit_object_set_scale(m_player_object,scale);
set_parameters_according_to_scale();
}
Ở đây factor là hệ số mà ta có thể tùy chọn theo điều kiện cần, do đó ta sẽ
có được một nhân vật có kích thước phù hợp trong mọi trường hợp.
+ Hàm thiết lập tham số thay đổi theo tỉ lệ kích thước:
void player::set_parameters_according_to_scale()
{
double scale[3];
Morfit_object_get_scale(m_player_object, scale);
m_acceleration = ACCELERATION * scale[2] / 5;
if(m_acceleration < ACCELERATION)
m_acceleration = ACCELERATION;
m_max_speed = MAX_SPEED * scale[2] / 3;
m_min_speed = MIN_SPEED * scale[2] / 3;
//set height
22
double box[2][3];
Morfit_object_get_bounding_box(m_player_object, box);
m_height = box[1][2] - box[0][2];
}
Khi tỉ lệ kích thước thay đổi thì các tham số thuộc tính của nhân vật như
tốc độ, gia tốc, trang phục… cũng sẽ thay đổi theo. Ví dụ một nhân vật khi bị thu
nhỏ lại thì nó sẽ di chuyển chậm hơn nhưng các bước chân sẽ nhanh hơn (ở đây
ta nói tới tốc độ thực hiện một bước chân so với khi chưa thu nhỏ kích thước).
Ở đây gia tốc được đặt giá trị là 4: #define ACCELERATION 4
b. Trang phục của nhân vật
Trang phục là một phần không thể thiếu trong quá trình xây dựng nhân vật
khi mô phỏng, nó quyết định và có tầm quan trọng để tạo lên tính cách, diện
mạo, tính đồng bộ… của nhân vật đối với không gian thế giới. Vì vậy việc tạo
và xây dựng trang phục cho nhân vật cũng là một phần đáng lưu ý của tác giả
trong đề tài này.
Trước tiên ta sẽ khai báo các biến liên quan đến trang phục:
int m_skin_id;
DWORD m_skin_bitmap, m_pain_bitmap;
Biến m_skin_id có giá trị bằng 0 khi nhân vật có trang phục thường và có
giá trị bằng 1 khi nhân vật trong tình trạng bị thương.
m_skin_bitmap, m_pain_bitmap lần lượt là các biến khai báo các ảnh
trang phục của nhân vật ở tình trạng bình thường và tình trạng bị thương.
Việc thay đổi trang phục của nhân vật được hiểu chính là việc thay đổi các
ảnh để có thể làm cho trang phục của nhân vật thay đổi như vậy khi đó nhân vật
sẽ có một trang phục mới và ta có thể dễ dàng chuyển đổi từ trạng thái bình
thường sang trạng thái bị thương và ngược lại mà ta có thể thấy rõ hơn qua đoạn
mã sau:
void player::replace_skin(void)
{
if(m_skin_id==0)
23
{
Morfit_object_set_bitmap(m_player_object, m_pain_bitmap);
m_skin_id=1;
return;
}
Morfit_object_set_bitmap(m_player_object, m_skin_bitmap);
m_skin_id=0;
}
2.2.2 Điều khiển mô phỏng các trạng thái hành động của nhân vật
Điều khiển mô phỏng các trạng thái hành động của nhân vật là phần chính
của đề tài này vì vậy mà tác giả sẽ đi sâu vào các hàm và đoạn mã mô phỏng.
Việc xây dựng các trạng thái hành động của nhân vật phụ thuộc vào nhất
nhiều các yếu tố như lực ma sát, trọng lực, hướng di chuyển, trình tự di
chuyển...do đó dưới đây là các hàm xác định các yếu tố đó.
a. Hàm xác định lực ma sát và trọng lực tác dụng lên nhân vật.
Trước tiên ta phải hiểu rằng lực ma sát luôn luôn có tác dụng làm cản và
làm giảm tốc độ chuyển động của một đối tượng trong môi trường của nó. Với
mỗi môi trường và trọng lượng của đối tượng khác nhau mà lực ma sát tác dụng
sẽ lớn hay nhỏ khác nhau. Ví dụ như một đối tượng chuyển động trên mặt nền
đường nhựa nhẵn (có hệ số ma sát nhỏ) sẽ chuyển động nhanh hơn một đối tượng
chuyển động trên mặt nền cát (có hệ số ma sát lớn).
Như đã nói khối lượng (mà ở đây muốn nói tới chính là trọng lượng của
nhân vật) là thành phần quan trọng trong công thức tính lực ma sát vì nó có liên
quan tới trọng lực. Công thức tính lực trọng lực như sau :
player_mass*earth_gravity*sin(alpha)
Trong đó:
+ player_mass: Khối lượng của nhân vật (kí hiệu là m)
+ earth_gravity: Lực hút của trái đất (kí hiệu là g và thường có giá trị
g=9,18)
+ alpha : Góc nghiêng của nhân vật đối với mặt ngang nền
24
Sau khi đã xác định được trọng lực thì việc tính toán lực ma sát được trở
lên dễ dàng. Sau đây là công thức tính lực ma sát:
gravity_factor * gravity_force
Trong đó:
+ gravity_force : Trọng lực
+ gravity_factor: hệ số ma sát
Sau đây là một hàm được xây dựng để xác định trọng lực và lực ma sát
của nhân vật trong môi trường mô phỏng:
double player::get_friction_and_gravity_factor()
{
double plane[4];
double point_below[3];
DWORD polygon = get_polygon_below(point_below); (3)
if(polygon==NULL)
return(m_friction);
Morfit_polygon_get_plane(polygon, plane); (4)
double gravity_direction[3];
double z_vector[3] = {0,0,1};
// quá trình xác định phương và hướng một véc tơ trọng lực (5)
Morfit_math_cross(plane, z_vector, gravity_direction);
Morfit_math_cross( plane, gravity_direction, gravity_direction);
Morfit_math_normalize_vector(gravity_direction);
if(plane[2] 1)
return(m_friction); //trả về ma sát của môi trường
// tính trọng lực (6)
double cos_alpha = plane[2];
double alpha = acos(cos_alpha);
double gravity_force = sin(alpha); //m*g*sin(alpha) .
// xác định hướng của nhân vật
double direction[3];
25
Morfit_object_get_direction(m_player_object,&direction[0],
&direction[1], &direction[2]);
// xác định hệ số ma sát (7)
double gravity_factor = Morfit_math_product (gravity_direction, direction);
if(m_speed < 0)
gravity_factor = -gravity_factor;
//Nhân vật sẽ ngã khi có một tốc độ quá lớn và chịu trọng lực quá lớn
if((m_sequence_id_num != FALL) && (gravity_factor * gravity_force >
0.3) && (fabs(m_speed) > 0.8 * m_max_speed))
{
m_current_sequence = set_animation_sequence("death",300);
m_sequence_id_num = FALL;
}
// tổng lực tác dụng nhân vật (8)
double result = m_friction+gravity_factor * gravity_force;
if(result < 0)
result = 0;
return(result);
}
Trong đó:
+ m_friction: biến toàn cục khai báo ma sát của môi trường tác động tới
nhân vật
(3) : Xác định một vùng nền bên dưới nơi mà chân của nhân vật sẽ di
chuyển tới.
(4): Xác định một vùng nền trên mặt nghiêng mà ta sẽ dựa vào đây để
xác định.
(5): Quá trình xác định một véc tơ chính của trọng lực
(6): Quá trình tính trọng lực tác dụng lên nhân vật
(7): Xác định hệ số ma sát
(8): Tổng hợp các lực tác dụng lên nhân vật
26
Ghi chú: Khi nhân vật đang đứng trên bề mặt thì lực ma sát và hợp lực sẽ
trả về giá trị m_friction (nhỏ hơn 1). Khi đang đi xuống đồi (một độ nghiêng) nó
sẽ trả về giá trị lớn hơn (lớn hơn 1) vì vậy mà sẽ làm cho nhân vật chuyển động
nhanh hơn. Khi đi lên đồi (một độ nghiêng) thì sẽ trả về một số nhỏ hơn
m_friction vì vậy mà nhân vật sẽ di chuyển chậm lại.
b. Hàm thiết lập trình tự tốc độ cho nhân vật
Trình tự tốc độ nhân vật là trình tự vận tốc của nhân vật thực hiện trong
một quãng đường trong một khoảng thời gian xác định. Ở đây ta sẽ đi thiết lập
trình tự tốc độ trong một quãng đường (một đoạn đường) cụ thể và nó chính là
việc nhân vật đã di chuyển trên một quãng đường thẳng. chính vì vậy mà phải
xây dựng công thức liên kết giữa tốc độ của nhân vật và trình tự tốc độ. Ở đây
chúng ta có thể hiểu là trình tự tốc độ sẽ tuyến tính với tốc độ của nhân vật
theo một phương trình đường thẳng (sequence_speed=F(player_speed)) có
dạng y = ax + b.
Trong đề tài này tác giả sẽ xây dựng công thức tính khi tốc độ của nhân
vật là 1 thì trình tự tốc độ sẽ là 0.7 và khi tốc độ của nhân vật là m_max_speed
thì trình tự tốc độ sẽ là 0.25. Vì vậy mà khi thực hiên thay đổi các tùy chọn thì sẽ
nhìn thấy sự thay đổi về hiệu ứng trạng thái hành động trong không gian của
trình tự tốc độ như thế nào.
Sự thay đổi của chính trình tự tốc độ sẽ làm cho một vài tham gia số
của tỉ lệ kích thước nhân vật thay đổi. Như vậy việc thường xuyên cập nhật
các tham số về tỉ lệ kích thước sẽ làm tăng thêm vẻ đẹp bề ngoài sự uyển
chuyển của nhân vật.
Morfit_3D_sequence_set_speed(m_current_sequence, sequence_speed);
Là hàm được gọi để thiết lập cho trình tự nhân vật.
Sau đây là đoạn chương trình thực hiện các mô tả thuật toán ở trên với
việc thiết lập trình tự tốc độ cho nhân vật:
void player::set_sequence_speed()
{
double sequence_speed=1;
27
if(m_sequence_id_num==FALL ||
m_sequence_id_num==ATTACK || m_sequence_id_num==PAIN)
return;
if(m_sequence_id_num==STAND)
sequence_speed=get_standing_sequence_speed();
else
{
double abs_speed=m_speed;
if(abs_speed<0)
abs_speed=-abs_speed;
m_effort++; // tăng nhịp thở
double seq_speed1=0.7; //trình tự khi nhân vật có tốc độ là 1.
double seq_speed_max=0.35; // trình tự khi nhân vật có tốc độ là
m_max_speed.
//cập nhật tham số tỉ lệ kích thước nhân vật
double scale[3];
Morfit_object_get_scale(m_player_object, scale);
seq_speed1*=(1+scale[2]/200);
seq_speed_max*=(1+scale[2]/200);
//liên hệ giữa trình tự tốc độ và tốc độ theo pt đường thẳng
if((m_max_speed-1) <=0)
return; //trở lại khi chia cho 0
double a=(seq_speed_max-seq_speed1)/(m_max_speed -1);
double b=seq_speed1-a;
sequence_speed=a*abs_speed+b;
if(sequence_speed<seq_speed_max)
sequence_speed=seq_speed_max;
}
28
Morfit_3D_sequence_set_speed(m_current_sequence,
sequence_speed);
}
c. Hàm tạo trình tự tốc độ khi nhân vật đang đứng
Trình tự tốc độ khi nhân vật đang ở trạng thái đứng yên chính là việc mô
phỏng nhịp thở của nhân vật. Ở đây thiết lập các giá trị sao cho nhịp độ âm thở
(tempo) phù hợp với tần suất (effort). Việc tăng giảm tần suất của nhịp thở cũng
kéo theo sự tăng giảm của âm độ nhịp thở. Trong trường hợp này sẽ đưa ra công
thức như sau: tempo có giá trị là 0.1 (tempo==0.1) khi effort có giá trị 0
(effort=0) và tempo cũng đạt 0.1 khi effort==400.
Sau đây là đoạn mã mô phỏng:
double player::get_standing_sequence_speed()
{
double tempo=-(double)m_effort/400+0.8;
if(tempo<0.1)
tempo=0.1;
m_effort=m_effort-1;
if(m_effort<0)
m_effort=0;
if(m_effort>500)
m_effort=500;
return(tempo);
}
d. Hàm thiết lập trình tự trạng thái hành động
Thiết lập trình tự trạng thái hành động cho nhân vật chính là việc lấy các
tên trình tự đã được thiết lập để gán vào từng quá trình hành động của nhân vật.
Có nghĩa là ta sẽ lấy mỗi hành động của nhân vật trong không gian thế giới và
gán cho nó một cái tên tương ứng với đúng trình tự hành động của nó. Để hiểu rõ
hơn có thể xem đoạn mã sau:
29
WORD player::set_animation_sequence(char *sequence_name, int
transition_duration)
{
DWORD anim3d = Morfit_object_get_3D_animation(m_player_object);
DWORD sequence = Morfit_3D_sequence_get_using_name(anim3d,
sequence_name);
if(sequence == NULL)
return(NULL);
Morfit_object_set_3D_sequence(m_player_object, sequence,
transition_duration);
return(sequence);
}
e. Hàm lựa chọn trình tự cho nhân vật
Việc lựa chọn trình tự cho nhân vật được thực hiện khi ta thiết lập các
trình tự đã có như trình tự đi bộ, trình tự tấn công bị thương, trình tự đứng,…Với
mỗi trình tự sẽ được gắn một số id (m_sequence_id_num) vì vậy mà sẽ rất dễ
dàng cho việc lựa chọn, quản lý các trình tự.
Ở đây chúng ta sẽ cố gắng giữ m_sequence_id_num được cập nhập nhưng
trong một số trường hợp thì không thể. Ví dụ nếu trình tự hiện tại
(m_current_sequence) là trình tự tấn công (m_attack_sequence) và sẽ được phép
làm như sau:
Morfit_object_set_3D_sequence(m_player_object, m_attack_sequence, 0);
Morfit_object_replace_3D_sequence_when_finished(m_player_object,
m_stand_sequence,300);
Trong trường hợp không biết chính xác thì trình đứng sẽ trở thành trình tự
hiện tại. Vì vậy mà ở đây sẽ truy vấn tới trình tự hiện tại và sẽ cập nhập
m_sequence_id_num và m_current_sequence phù hợp. Để hiểu rõ ý này xem
đoạn mã sau:
30
DWORD sequence = Morfit_object_get_3D_sequence(m_player_object);
if(sequence == m_stand_sequence)
{
m_sequence_id_num = STAND;
m_current_sequence = m_stand_sequence;
}
else
{
if(sequence == m_walk_sequence)
m_sequence_id_num = WALK;
m_current_sequence = m_walk_sequence;
}
Chú ý điều quan trọng là khi chúng ta thiết lập một trình tự riêng biệt
(specific sequence) thì đầu tiên sẽ thiết lập một trạng thái trình tự hành động
và chỉ sau khi trình tự trạng thái hành động kết thúc thì nó sẽ tự động thiết lập
trình tự muốn có. Có nghĩa là nếu muốn tạo trình tự đi bộ (walk_sequence) ta
sẽ gọi hàm
Morfit_object_set_3D_sequence(m_player_object,walk_sequence);
Và ngay sau đó gọi hàm :
sequence=Morfit_object_get_3D_sequence(m_player_object);
thì kết quả trình tự trả về sẽ nhận được không phải là trình tự đi bộ
(sequence!=walk_sequence !!!). Chỉ sau khi trình tự trạng thái hành động kết
thúc thì trình tự walk_sequence mới được sử dụng.
Sau đây là đoạn mã của quá trình lựa chọn một trình tự:
void player::select_sequence()
{
DWORD sequence =
Morfit_object_get_3D_sequence(m_player_object);
if(sequence == m_stand_sequence)
{
31
m_sequence_id_num = STAND;
m_current_sequence = m_stand_sequence;
}
else
{
if(sequence == m_walk_sequence)
m_sequence_id_num = WALK;
m_current_sequence = m_walk_sequence;
}
if( (sequence == m_walk_sequence) && (m_speed < m_min_speed
&& m_speed > -m_min_speed))
{
m_current_sequence =
set_animation_sequence("stand",100);
m_sequence_id_num = STAND;
}
else if((sequence == m_stand_sequence) && (m_speed >=
m_min_speed || m_speed <= -m_min_speed))
{
m_current_sequence =
set_animation_sequence("walk",100);
m_sequence_id_num = WALK;
}
else if((sequence == m_fall_sequence) && (m_speed <
m_min_speed && m_speed > -m_min_speed))
{
//kiểm tra trình tự ngã (fall_sequence) đã kết thúc hay chưa
DWORD anim3d = Morfit_object_get_3D_animation(m_player_object);
32
DWORD fall_sequence = Morfit_3D_sequence_get_using_name(anim3d,
"death");
int num_of_frames =
Morfit_3D_sequence_get_number_of_frames(fall_sequence);
double current_position =
Morfit_3D_sequence_get_current_frame(fall_sequence);
if(current_position >= num_of_frames - 2)
{
m_current_sequence =
set_animation_sequence("stand",1000);
m_sequence_id_num = STAND;
}
}
if(m_sequence_id_num!=FALL)
{
//thiết lập một trình tự đúng
if(m_speed<0 )
{
Morfit_3D_sequence_backwards_play(m_current_sequence,YES);
}
else
{
Morfit_3D_sequence_backwards_play(m_current_sequence,NO);
}
}
set_sequence_speed();
}
33
f. Hàm di chuyển trạng thái hành động của nhân vật
Di chuyển trạng thái hành động của nhân vật là việc thực hiện các thao tác
điều khiển cho nhân vật thực hiện một hành động để chuyển từ vị trí này sang vị
trí khác như tiến lên trước, lùi về phía sau, sang phải, sang trái…
Để thực hiện việc di chuyển cho nhân vật trước tiên phải xác định vị trí
mà nhân vật cần đi tới. Việc này được thực hiện một cách dễ dàng qua hàm :
Morfit_object_get_location(m_player_object,&save_location[0],
&save_location[1], &save_location[2]);
Sau đó sẽ tạo một trình tự cho nhân vật qua hàm:
DWORD sequence = Morfit_object_get_3D_sequence(m_player_object);
Có nghĩa là giả sử m_sequence_id_num==WALK là một trình tự đi bộ
hoặc là một vài trình tự vận chuyển ban đầu của trình tự đi bộ, nếu ta có thể thay
thế sequence==m_walk_sequence thì nó sẽ không thể bắt kịp sự chuyển vận từ
trạng thái đứng sang trạng thái đi bộ được. Nên nhớ rằng trình tự vận chuyển đã
được phát sinh một cách tự động bởi các engine vì vậy mà việc chuyển đổi từ
một trình tự này sang một trình tự khác được thực hiện một cách mềm mại và
nhịp nhàng. Nếu không muốn trình tự vận chuyển phát sinh một cách tự động thì
đơn giản có thể gọi hàm sau :
Morfit_object_set_3D_sequence( ,0);
Trong đó với 0 là khoảng thời gian tồn tại cho sự vận chuyển.
Cũng như vậy trong quá trình di chuyển phải xác định lực đã sử dụng hay
chính xác hơn chính là lực tác dụng vào nhân vật, vì vậy mà biến int
muscle_force_used = NO; được khai báo có ý nghĩa ban đầu là chưa có lực nào
tác dụng. Như đã nói ở trên thì tốc độ của nhân vật phụ thuộc vào các thành phần
lực vì vậy mà dựa vào đó mà có thể thấy rõ sự nhanh hay chậm của nhân vật
trong từng trình tự trạng thái chuyển động.
Sau đây là một đoạn chương trình mô phỏng việc dịch chuyển tiến phía
trước, lùi phía sau, sang trái, sang phải của nhân vật:
void player::move(void)
{
34
int muscle_force_used = NO; // ko có lực tác dụng
double save_location[3];
//Xác định vị trí nhân vật cần di chuyển tới
Morfit_object_get_location(m_player_object, &save_location[0],
&save_location[1], &save_location[2]);
DWORD sequence = Morfit_object_get_3D_sequence(m_player_object);
if(m_sequence_id_num == WALK || sequence == m_stand_sequence)
{
//tiến phía trước
if(GetAsyncKeyState(VK_UP) < 0)
{
m_speed += m_acceleration;
muscle_force_used = YES;
}
//lùi phía sau
if(GetAsyncKeyState(VK_DOWN) < 0)
{
muscle_force_used = YES;
m_speed -= m_acceleration;
}
}
if(m_sequence_id_num == WALK || sequence ==
m_stand_sequence || sequence == m_attack_sequence || sequence ==
m_pain_sequence)
{
//sang trái
if(GetAsyncKeyState(VK_LEFT) < 0)
{
Morfit_object_rotate_z(m_player_object, 6, WORLD_SPACE);
}
35
//sang phải
if(GetAsyncKeyState(VK_RIGHT) < 0)
{
Morfit_object_rotate_z(m_player_object, -6, WORLD_SPACE);
}
}
// xác định vận tốc và lực đã sử dụng
double gravity_and_friction_factor = get_friction_and_gravity_factor();
if(muscle_force_used == NO || fabs(m_speed) > m_min_speed)
{
m_speed *= gravity_and_friction_factor;
if(muscle_force_used == YES)
if(fabs(m_speed) < fabs(m_min_speed))
m_speed = m_min_speed * m_speed / fabs(m_speed);
}
if(m_speed > m_max_speed)
m_speed = m_max_speed;
if(m_speed < -m_max_speed)
m_speed = -m_max_speed;
Morfit_object_move(m_player_object,OBJECT_SPACE, -m_speed,0,0);
// Lựa chọn trình tự đúng
select_sequence();
// Xác địn vùng nền dưới
double point_below[3];
get_polygon_below(point_below);
// Xác định một trạng thái mới
if(new_altitude > save_location[2] + m_height / 3)
{
36
Morfit_object_set_location(m_player_object,save_location[0],
save_location[1], save_location[2]);
m_speed = -m_speed * 0.5;
}
else
{
double location[3];
Morfit_object_get_location(m_player_object, &location[0],
&location[1], &location[2]);
Morfit_object_set_location(m_player_object, location[0],
location[1], new_altitude);
}
}
g. Một số trạng thái chuyển động của nhân vật
* Trạng thái tấn công (Attack)
Ở đây sẽ mô phỏng nhân vật trong tư thế dùng vũ khí tấn công một đối
tượng khác. Một trình tự tấn công thực tế được xây dựng từ rất nhiều các trình tự
tấn công khác. Như tấn công với súng, phóng đạn, bắn trúng mục tiêu với cùng
một điều khiển…Trong game thì nó rất dễ dàng có được các trạng thái riêng biệt
đối với các trình tự khác nhau. Có thể tham khảo đoạn mã sau để hiểu rõ hơn về
một trình tự trạng thái tấn công:
void player::attack(void)
{
if(m_attack_sequence==NULL)
return;
Morfit_object_set_3D_sequence(m_player_object,
m_attack_sequence, 0);
Morfit_object_replace_3D_sequence_when_finished(m_player_obj
ect, m_stand_sequence,300);
m_current_sequence=m_attack_sequence;
37
m_sequence_id_num=ATTACK;
}
* Trạng thái bị thương
Cũng giống như trạng thái tấn công thì trạng thái bị thương sẽ mô phỏng
khi nhân vật bị trúng đạn và nó cũng được tạo lên bằng hàng loạt các trình tự bị
thương khác như sẽ giảm tốc độ, có thể khụy xuống và hiện chỗ thương trúng
đạn tại vị trí đó. Và sau đây là đoạn mã mô phỏng trạng thái bị thương:
void player::pain(void)
{
if(m_pain_sequence==NULL)
return;
Morfit_object_set_3D_sequence(m_player_object,
m_pain_sequence, 0);
Morfit_object_replace_3D_sequence_when_finished(m_player_obj
ect, m_stand_sequence,400);
m_current_sequence=m_pain_sequence;
m_sequence_id_num=PAIN;
}
* Cập nhập theo một trạng thái hành động mới
Như đã nói khi một trạng thái được thay đổi thì các tham số hành động
một hành động của nhân vật sẽ thay đổi theo sao cho phù hợp với từng trình tự
mô phỏng hành động đó. Ở đây có thể “load” chúng khi mà cần tới những ảnh
mô phỏng đó trong khi các “engine” sẽ không đủ nhanh để “load” những ảnh đã
có sẵn trong bộ nhớ. Có thể theo dõi đoạn mã sau để thấy được sự thay đổi giữa
các trạng thái:
int player::update_according_to_new_animation(void)
{
char buff[MAX_PATH];
strcpy(buff,m_bitmap_path);
38
strcat(buff,"\\skin.bmp");
m_skin_bitmap = Morfit_bitmap_load(buff,-1);
strcpy(buff,m_bitmap_path);
strcat(buff,"\\pain.bmp");
m_pain_bitmap = Morfit_bitmap_load(buff,-1);
//Thiết lập trang phục
Morfit_object_set_bitmap(m_player_object, m_skin_bitmap);
// Thiết lập tham số theo tỉ lệ kích thước
set_parameters_according_to_scale();
m_current_sequence = set_animation_sequence("stand", 0);
m_sequence_id_num = STAND;
m_stand_sequence = m_current_sequence;
DWORD anim3d = Morfit_object_get_3D_animation(m_player_object);
m_fall_sequence = Morfit_3D_sequence_get_using_name(anim3d, "death");
if(m_fall_sequence != NULL)
{
int num_of_frames =
Morfit_3D_sequence_get_number_of_frames(m_fall_sequence);
//Dừng quá trình đang ngã trong một trạng thái riêng.
Morfit_3D_sequence_set_frame_duration(m_fall_sequence,
num_of_frames-2, 1000000);
Morfit_3D_sequence_set_speed(m_fall_sequence,0.5);
}
m_walk_sequence = Morfit_3D_sequence_get_using_name(anim3d, "walk");
if(m_walk_sequence == NULL)
return(VR_ERROR);
m_attack_sequence =
Morfit_3D_sequence_get_using_name(anim3d, "attak");
m_pain_sequence = Morfit_3D_sequence_get_using_name(anim3d, "pain");
return(OK);
}
39
2.2.3 Các vấn đề liên quan tới camera và các phím điều khiển.
a. Các vấn đề liên quan tới camera.
Camera là thành phần vô cùng quan trọng trong kĩ thuật mô phỏng vì nó
quyết định tới góc nhìn, khoảng cách nhìn, không gian nhìn đối với các đối tượng
trong không gian thới giới ảo. Việc liên kết giữa camera và đối tượng sẽ làm cho
quá trình mô phỏng sẽ được linh động hơn, mềm mại và chân thật hơn đối với
người quan sát. Với mỗi chế độ camera khác nhau ta cũng có các hiệu ứng khác
nhau vì vậy mà sau đây là một số chế độ camera và hiệu ứng cơ bản về camera
đã sử dụng để mô phỏng nhân vật trong đề tài này:
* Thiết lập camera ở chế độ chase_flexible
Ở chế độ này camera sẽ di chuyển mềm mại, uyển chuyển theo đối tượng
mà nó bám theo. Chúng ta có thể thiết lập kiểu theo cho đối tượng bằng hàm:
STATE_object_set_chase_type(Handle,chase_type)
Với kiểu theo là flexible, ta có thể thiết lập độ mềm dẻo của đường rẽ
bằng hàm STATE_object_set_chase_softness(object_handle,softness) và tương
tự có hàm lấy sự mềm dẻo hiện tại của đối tượng theo là:
STATE_object_get_chase_softness(object_handle). Giá trị softness nằm trong
khoảng [0-1].
Khoảng cách theo (chase offset): Chase offset xác định khoảng cách từ
đối tượng theo đến đối tượng bị theo. Ví dụ: char offset là [0,0,10] có nghĩa là
đối tượng theo sẽ theo đối tượng nhưng nó sẽ ở bên trên đối tượng cách đối
tượng 10 đơn vị.
Ta có thể thiết lập char offset bằng hàm sau:
STATE_object_set_chase_offset(object_handle,offset[3]).
Ta cũng có thể lấy char offset hiện tại của đối tượng bằng hàm sau:
STATE_object_get_chase_offset(object_handle,offset[3]).
Sau đây là đoạn mã mô phỏng thiết lập camera ở chế độ chase_flexible:
void camera::set_ chase_flexible_mode(void)
{
40
Morfit_camera_set_chase_type(m_camera_handle,
CHASE_FLEXIBLE);
double chase_offset[3] = {0,0,0};
Morfit_camera_set_chase_offset(m_camera_handle, chase_offset);
update_chase_params();
}
* Thiết lập camera ở chế độ chase_location
Cũng giống như ở chế độ chase_flexible nó cũng có nhiệm vụ bám theo
đối tượng và tính khoảng cách tới đối tượng xong có sự khác biệt ở đây là camera
sẽ không quay khi đối tượng bị theo quay. Sau đây là đoạn mã mô phỏng thiết
lập camera ở chế độ chase_location:
void camera::set_chase_location_mode(void)
{
Morfit_camera_set_chase_type(m_camera_handle,
CHASE_LOCATION);
double box[2][3];
Morfit_object_get_bounding_box(m_object_to_chase, box);
double height = box[1][2] - box[0][2];
double distance = height * 1.5 + 40;
// double scale[3];
// Morfit_object_get_scale(m_camera_handle, scale);
// double distance=scale[2]*100+100;
double direction[3];
Morfit_object_get_direction(m_object_to_chase,&direction[0],
&direction[1], &direction[2]);
Double chase_off
Các file đính kèm theo tài liệu này:
- Mô phỏng hành động nhân vật trong xây dựng mô hình 3d.pdf