Hướng dẫn sử dụng Macromedia Flash mx


Bài 34: Những lỗi "nhỏ nhặt"



tải về 0.86 Mb.
trang19/27
Chuyển đổi dữ liệu02.09.2017
Kích0.86 Mb.
#32845
1   ...   15   16   17   18   19   20   21   22   ...   27

Bài 34: Những lỗi "nhỏ nhặt"



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.



Để 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:

...

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.

Để 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:

...

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:

...


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ề:



...

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:

...


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:

...


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.

Bài 35: Tìm hình giống nhau



Trong trò chơi lật hình, sau khi người chơi lật hai hình (bấm vào một hình rồi bấm thêm một hình nữa), nếu hai hình không giống nhau, chúng bị "úp" trở lại. Nếu hai hình giống nhau, chúng giữ nguyên trạng thái. Ta xem đó là hai hình đã "hoàn thành nhiệm vụ". Người chơi tiếp tục lật các hình khác và cố gắng ghi nhớ vị trí của các hình để có thể lật liên tiếp hai hình giống nhau. Khi không còn hình nào bị "úp", trò chơi kết thúc.

Hiện tại, trong chương trình của ta, hàm xử lý tình huống bấm chuột không kiểm tra gì cả, chỉ giữ nguyên trạng thái của hình được lật. Để có thể thực hiện việc kiểm tra như vừa nêu, mỗi hình cần có một biến cho biết nó là loại hình gì, có thể đặt tên là type. Hình cũng cần chứa biến gọi là solved chẳng hạn, có thể nhận trị true hoặc false để cho biết nó đã "hoàn thành nhiệm vụ" hay chưa. Ngoài ra, ta cũng cần một biến để ghi nhận lần bấm chuột đang xét là lần thứ mấy, có thể đặt tên là count. Phải có đủ thông tin như vậy, chương trình mới có thể "suy xét" và hành động thích hợp mỗi khi người dùng bấm chuột. Biến type cần có trị ra sao? Nhìn lại phần đầu chương trình, bạn thấy rằng ta đã dùng biểu thức n % 8 để thu được các trị số từ 0 đến 7 (các nhân vật được đánh số từ 0 đến 7). Hai thể hiện giống nhau là hai thể hiện ứng với cùng số thứ tự, nghĩa là cùng được tạo ra từ một nhân vật. Ta gọi đó là hai thể hiện cùng loại. Bạn hiểu ngay: biến type cần có trị từ 0 đến 7. Ta cần lấy trị của biểu thức n % 8 để gán cho biến type của từng hình được xem xét trong vòng lặp ở phần đầu chương trình. Bạn viết thêm vào phần đầu chương trình như sau:

tiles = new Array();

backs = new Array();

n = 0;

type = 0;



count = 0;

for(i = 0; i < 4; i++) {

  tiles[i] = new Array();

  backs[i] = new Array();

  for(j = 0; j < 4; j++) {

    type = n%8;

    attachMovie("Tile" + type, "tile" + i + j, n);

    attachMovie("Back", "back" + i + j, n + 100);

    n++;

    tiles[i][j] = this["tile" + i + j];

    tiles[i][j]._x = 20 + 120 * j;

    tiles[i][j]._y = 20 + 120 * i;

    tiles[i][j].type = type;

    tiles[i][j].solved = false;

    backs[i][j] = this["back" + i + j];

    backs[i][j]._x = 20 + 120 * j;

    backs[i][j]._y = 20 + 120 * i;

  }


}

...


Ta lưu trị số của biểu thức n % 8 vào biến type dùng chung và gán trị của biến type dùng chung ấy vào biến type bên trong mỗi hình bằng câu lệnh tiles[i][j].type = type. Câu lệnh tiles[i][j].solved = false; nhằm tạo ra biến solved bên trong mỗi hình và gán ngay cho nó trị ban đầu là false (chưa "hoàn thành nhiệm vụ"). Nếu bạn từng có kinh nghiệm về ngôn ngữ lập trình khác, có thể bạn thấy "phong cách" của ngôn ngữ lập trình ActionScript trong Flash hơi lạ lùng: khi cần biến mới, ta chỉ đơn giản dùng biến đó, không cần khai báo trước. Khi dùng một biến chưa từng có, bạn đã tạo ra biến mới. Tuy nhiên, thói quen viết ra các biến cần dùng ở đầu chương trình và gán trị ban đầu cho nó (xem như một cách khai báo các biến sẽ dùng trong chương trình, giống như trong ngôn ngữ lập trình Pascal) là thói quen tốt, giúp chương trình rõ ràng, dễ hiểu hơn. Không hiếm trường hợp người lập trình đọc lại những đoạn mã từng do chính mình viết và... không hiểu lúc trước mình viết cái gì! Nhờ lưu giữ thông tin quan trọng khi tạo ra các hình cho trò chơi, bạn có cơ sở để thực hiện những điều cần làm mỗi khi người dùng bấm chuột. Trong hàm xử lý tình huống bấm chuột, bạn viết thêm như sau:

...


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;

        if(!tiles[i][j].solved) {

 

        }



        return;

      }


    }

  }


}

Bạn cần xóa đi câu lệnh backs[i][j]._visible = false; vì bây giờ ta không chỉ đơn giản phơi ra hình được bấm, mà phải cân nhắc cẩn thận. Khi xem xét hình được bấm, trước tiên bạn cần biết nó đã "hoàn thành nhiệm vụ" hay chưa bằng cách dùng câu lệnh if(!tiles[i][j].solved). Nếu biến solved bên trong hình đang xét có trị false (chưa "hoàn thành nhiệm vụ"), ta mới cần tiếp tục xem xét. Nếu biến solved bên trong hình đang xét có trị là true (hình đang xét đã "hoàn thành nhiệm vụ") thì không cần làm gì hết. Câu lệnh return; thể hiện điều đó. Khi hình được bấm chưa "hoàn thành nhiệm vụ", ta cần nhận biết lần bấm chuột đang xét là lần thứ mấy, từ đó mới quyết định cần làm gì cho thích hợp. Trong cặp dấu gộp { } theo sau câu lệnh if(!tiles[i][j].solved), bạn diễn đạt suy nghĩ của mình như sau:

...

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;

        if(!tiles[i][j].solved) {

          if(count == 0) {

            backs[i][j]._visible = false;

            count = 1;

 

          }



          else if(count == 1) {

            backs[i][j]._visible = false;

 

          }



        }

        return;

      }

    }


  }

}

Nếu lần bấm chuột đang xét là lần thứ nhất (trị của biến count là 0), ta gán trị 1 cho biến count. Nhờ vậy, khi xem xét một lần bấm chuột, nếu thấy biến count có trị là 1, ta biết rằng đó là lần bấm chuột thứ hai. Trong cả hai lần bấm chuột, điều đầu tiên cần làm là phơi ra hình được bấm bằng câu lệnh backs[i][j]._visible = false; (cho hình "mặt sau" biến đi). Trong lần bấm chuột thứ hai, ta cần so sánh hình đang xét với hình được bấm của lần trước. Như vậy, cần phải có thêm hai biến để ghi nhớ chỉ số hàng và cột của lần bấm chuột thứ nhất. Bạn tiếp tục viết thêm:



...

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;

        if(!tiles[i][j].solved) {

          if(count == 0) {

            backs[i][j]._visible = false;

            count = 1;

            r = i;

            c = j;

          }

          else if(count == 1) {

            backs[i][j]._visible = false;

            if(r == i && c == j)

              return;

            if(tiles[r][c].type == tiles[i][j].type) {

              tiles[i][j].solved = true;

              tiles[r][c].solved = true;

              count = 0;

            }

            else {

              backs[i][j]._visible = true;

              backs[r][c]._visible = true;

              count = 0;

            }

          }

        }

        return;

      }

    }


  }

}

Trong lần bấm chuột thứ nhất, ta dùng hai biến r và c để ghi nhớ chỉ số hàng và cột của hình được bấm. Trong lần bấm chuột thứ hai, nếu hình được bấm chính là hình trước thì không cần làm gì hết. Điều này thể hiện bằng câu lệnh điều kiện:



if(r == i && c == j)

  return;

Nếu hình được bấm đang xét khác với hình được bấm lần trước, ta cần so sánh biến type bên trong hai hình, xem có giống nhau không. Nếu giống, ta gán trị true cho biến solved trong mỗi hình để "đánh dấu", cho biết chúng đã "hoàn thành nhiệm vụ". Nếu không giống, cả hai hình đang xét đều được "úp" trở lại. Dù giống hay không giống, ta cho biến count trở về trị 0, kết thúc một đợt kiểm tra. Bạn chạy thử chương trình xem sao nhé.


Каталог: files -> 2012
files -> PHỤ LỤC 2 TỔng hợp danh mục tài liệu tham khảO
files -> BÁo cáo quy hoạch vùng sản xuất vải an toàn tỉnh bắc giang đẾn năM 2020 (Thuộc dự án nâng cao chất lượng, an toàn sản phẩm nông nghiệp và phát triển chương trình khí sinh học ) Cơ quan chủ trì
files -> BỘ TÀi nguyên và MÔi trưỜng
files -> 1. Mục tiêu đào tạo: Mục tiêu chung
2012 -> Số Hồ sơ: 50 / /cs-bhyt cộng hòa xã HỘi chủ nghĩa việt nam
2012 -> HÌnh ảnh thao tác dữ liệu máy toàN ĐẠc nts 310 CỦa hãng south
2012 -> Khóa học 2010 -2012 (TT10C/1) (Ban hành theo quyết định số /QĐ-bgh ngày …tháng…năm của Hiệu trưởng trường Đại học Hoa Sen)
2012 -> Thông báo về việc xét thông qua đề tài luận văn và người hướng dẫn cho hvch k56

tải về 0.86 Mb.

Chia sẻ với bạn bè của bạn:
1   ...   15   16   17   18   19   20   21   22   ...   27




Cơ sở dữ liệu được bảo vệ bởi bản quyền ©hocday.com 2024
được sử dụng cho việc quản lý

    Quê hương