Thứ Năm, 2 tháng 6, 2011

Những lỗi “nhỏ nhặt” trong lập trình Flash

Khi chạy chương trình đã viết, thử bấm chuột để lật vài hình, rất có thể bạn thấy có hiện tượng lạ: bấm một phát nhưng lật được cả hai hình lân cận! Đó là sự “tiện lợi” không mong đợi. Điều ngày nghĩa là hình “được thêm” cũng cảm thấy cú bấm chuột trúng vào nó!
Để kiểm tra xem tại sao như vậy, bạn mở bảng Library (gõ phím F11) nếu bảng Library chưa mở, bấm kép vào nhân vật Tile0 để chuyển qua chế độ chỉnh sửa nhân vật Tile0 (hình 1).

Có thể bạn sẽ thấy hình vẽ ở lớp Layer 2 của nhân vật Tile0 nằm trong khung bao (bounding box) lớn hơn hình vuông làm nền ở lớp Layer 1. Đó chính là nguyên nhân của hiện tượng “bấm một, được hai” khi bạn thử nghiệm chương trình. Khi bạn bấm chuột vào thể hiện của nhân vật Tile0 trên sân khấu, mọi điểm nằm trong phạm vi khung bao đều “cảm thấy” cú bấm chuột của bạn. Vì khung bao lấn sang hình vuông nằm kế bên, hình vuông ấy cũng “cảm thấy” mình được bấm trúng.

image0021 Những lỗi nhỏ nhặt trong lập trình Flash

Để khắc phục lỗi đang xét, ta có thể sửa trong chương trình thay vì sửa khung bao bên trong mỗi nhân vật. Bạn hãy bấm vào Scene 1 để thoát khỏi chế độ chỉnh sửa nhân vật, trở lại bảng Actions – Frame và viết thêm vào câu lệnh gọi hàm hitTest() như sau:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
this.onMouseUp = function() {
for(i = 0; i < 4; i++) {
for(j = 0; j < 4; j++) {
if(tiles[i][j].hitTest(_root._xmouse, _root._ymouse, true)) {
backs[i][j]._visible = false;
}
}
}
}
...

Ta ghi thêm trị true vào câu lệnh gọi hàm hitTest() của nhân vật với tư cách là đối mục thứ ba của hàm, sau _root._xmouse và _root._ymouse. Khi nhận được đối mục thứ ba như vậy, hàm hitTest() chỉ xem xét cú bấm chuột dựa vào hình ảnh thực sự được hiển thị, chứ không dựa vào khung bao. Nhờ vậy việc xem xét cú bấm chuột sẽ chính xác hơn. Điều này đặc biệt quan trọng khi nhân vật của bạn không có dạng hình khung, khi đó bạn cần nhận diện một cách tinh tế điểm nào thực sự thuộc về “cơ thể” của nhân vật, điểm nào thuộc về “thế giới bên ngoài”.
Chạy lại chương trình, bạn sẽ thấy hiện tượng “bấm một, được hai” không còn nữa.
Khi thử nghiệm chương trình nhiều lần, bạn sẽ nhận ra một hiện tượng khác: hàng thứ tư (ứng với chỉ số hàng là 3) và cột thứ tư (ứng với chỉ số cột là 3) không chịu thay đổi ngẫu nhiên như ta dự định (hình 2). Chúng không đổi trong những lần chạy chương trình khác nhau.

image006 Những lỗi nhỏ nhặt trong lập trình FlashĐể tìm hiểu xem tại sao như vậy, bạn ghi thêm hai câu lệnh theo dõi diễn biến bên trong hàm shuffleTiles() như sau:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
function shuffleTiles() {
for(i = 0; i < 200; i++) {
r1 = getRandom(0, 3);
c1 = getRandom(0, 3);
r2 = getRandom(0, 3);
c2 = getRandom(0, 3);
trace("r1:" + r1 + ", c1:" + c1);
trace("r2:" + r2 + ", c2:" + c2);
tx = tiles[r1][c1]._x;
ty = tiles[r1][c1]._y;
...

Hai câu lệnh vừa thêm nhằm in ra bảng Output chỉ số ngẫu nhiên của hàng và cột do hàm getRamdom() sinh ra. Chạy lại chương trình, bạn thấy các chỉ số ngẫu nhiên đó trong bảng Output đại khái như sau:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
...
r1:0, c1:2
r2:1, c2:0
r1:1, c1:2
r2:1, c2:0
r1:1, c1:1
r2:1, c2:2
...

Theo dõi những chỉ số ngẫu nhiên do hàm getRandom() sinh ra, bạn thấy không hề có chỉ số 3. Dường như không có lúc nào chỉ số 3 được xuất hiện một cách ngẫu nhiên. Câu lệnh getRandom(0, 3); chỉ cho trị ngẫu nhiên tối đa là 2.
Bạn có thể sửa lại định nghĩa hàm getRandom() một chút, không dùng hàm Math.floor() để làm tròn kết quả trả về:

1
2
3
4
5
6
7
8
9
10
11
...
function getRandom(min, max) {
//return Math.floor(Math.random()*(max - min) + min);
return Math.random()*(max - min) + min;
}
...

Chạy tại chương trình và quan sát bảng Output, bạn thấy có trị ngẫu nhiên lớn hơn 2 (ở dạng thập phân) nhưng không hề có trị 3. Khi chỉ số hàng hoặc cột là 2.5 chẳng hạn, Flash tự động xem là 2. Hàm Math.random() cho trị ngẫu nhiên từ 0 đến gần 1, không cho trị ngẫu nhiên nào là 1.
Để có trị ngẫu nhiên từ 0 đến 3, ta có thể viết getRandom(0, 4) thay cho getRandom(0, 3). Giải pháp tốt hơn là sửa một chút trong định nghĩa hàm getRandom() để đối mục thứ hai (max) của hàm được tự động cộng thêm 1:

1
2
3
4
5
6
7
8
9
...
function getRandom(min, max) {
return Math.floor(Math.random()*(max + 1 - min) + min);
}
...

Chạy tại chương trình và quan sát bảng Output, bạn thấy ta có được chỉ số 3 trong những chỉ số ngẫu nhiên:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
...
r1:3, c1:2
r2:3, c2:3
r1:0, c1:1
r2:3, c2:2
r1:2, c1:1
r2:1, c2:2
r1:2, c1:3
...

Nhờ vậy, hàng thứ tư và cột thứ tư được thay đổi ngẫu nhiên, không còn “bất khả xâm phạm” như trước nữa.

Theo echip

0 nhận xét:

Đăng nhận xét

Twitter Delicious Facebook Digg Stumbleupon Favorites More

 
Design by Free WordPress Themes | Bloggerized by Lasantha - Premium Blogger Themes | 100 Web Hosting