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


 Tiếp tục của phần 2 là việc thêm hiệu ứng rớt và dịch chuyển qua lại của những viên kim cương. Nếu ai chưa coi phần 1 thì có thể vào đây Clone game Bejeweled


Demo:



 


Để thực hiện các hiệu ứng chuyển động đó trước tiên chúng ta phải xem xét nó có bao nhiêu trạng thái khi ta chọn ăn 2 viên kim cương.


Theo như phân tích của mình thì nó có các trạng thái sau


1
2
3
4
5
var STATE_IDEL = 0; //Khi chưa tác động đến kim cương
var STATE_SWAP = 1; //Khi 2 viên kim cương dịch chuyển qua nhau để ăn
var STATE_RESWAP = 2;//Nếu không ăn được thì dịch chuyển trở về
var STATE_REMOVE = 3;//Nếu có thể ăn được thì loại bỏ các viên kim cương
var STATE_GENERATE = 4;//Sau khi ăn xong sẽ tạo ra kim cương mới và rớt xuống

Tạo thêm object cho viên kim cương


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var GEM_NONE = 0;
var GEM_DESTROY = 1;
var GEM_SWAP = 2;
var GEM_DROP = 3;
 
function Gem(type, x, y)
{
    this.type = type;
    this.state = GEM_NONE;
    this.x = x;
    this.y = y;
    this.desx = x;
    this.desy = y;
    this.lasX = x;
    this.lasY = y;
}

 Vậy thì từng trạng thái nó sẽ xử lý ra sao


Trước tiên là trạng thái Idel khi không có tác động gì


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
case STATE_IDEL:
            if(item_selected[0] != -1 && item_selected[1] != -1 && item_selected[2] != -1 && item_selected[3] != -1)
            {
                s_timeState = (new Date()).getTime();
                s_gemState = STATE_SWAP;
                initSubState = false;
            }
             
            if(this.checkClearItems())
            {
                s_timeState = (new Date()).getTime();
                s_gemState = STATE_REMOVE;
                initSubState = false;
            }
            this.updateTouch();

 ở trạng thái này mục đích chính là kiểm tra xem người chơi có chọn 2 viên kim cương chưa nếu chọn rồi thì sẽ qua trạng thái swap ngoài ra thì có thêm vòng lặp luôn kiểm tra kim cương có thể ăn hay không. Chổ này có vẻ tốn thời gian xử lý dư thừa tạm thời xài đở như vậy có thời gian sẽ xử lý sau.


Nếu đã chọn 2 kim cương thì sẽ chuyển qua trạng thái dịch chuyển 2 viên kim cương


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
case STATE_SWAP:
                                     //Chuyển tọa độ cột dòng của mảng 2 chiều thành 1 chiều
                var index1 = convertArray(item_selected[0],item_selected[1],NUM_COL);
                var index2 = convertArray(item_selected[2],item_selected[3],NUM_COL);  
               
                //Yêu cầu kim cương sẽ di chuyển đến đâu
                if(!initSubState)
                {
                    ITEMS[index1].state = GEM_SWAP;
                    ITEMS[index1].desx = ITEMS[index2].x;
                    ITEMS[index1].desy = ITEMS[index2].y;
                     
                    ITEMS[index2].state = GEM_SWAP;
                    ITEMS[index2].desx = ITEMS[index1].x;
                    ITEMS[index2].desy = ITEMS[index1].y;
                    initSubState = true;
                }
                                     //Xử lý việc dịch chuyển của kim cương, dịch chuyển kim cương đến tọa độ swap với kim cương còn lại
                else
                {
                    var direction, vX, vY;
                    direction = unitVector(ITEMS[index1].x, ITEMS[index1].y, ITEMS[index1].desx, ITEMS[index1].desy);
                    vX = GEM_SPEED*direction[0];
                    vY = GEM_SPEED*direction[1];
                    ITEMS[index1].x += vX;
                    ITEMS[index1].y += vY;
                     
                    direction = unitVector(ITEMS[index2].x, ITEMS[index2].y, ITEMS[index2].desx, ITEMS[index2].desy);
                    vX = GEM_SPEED*direction[0];
                    vY = GEM_SPEED*direction[1];
                    ITEMS[index2].x += vX;
                    ITEMS[index2].y += vY;
                     //Khi kim cương đã dịch chuyển xong thì khai báo lại tọa độ của kim cương và kiểm tra xem có thể ăn được không
                    if(ITEMS[index2].x == ITEMS[index2].desx && ITEMS[index2].y == ITEMS[index2].desy && ITEMS[index1].x == ITEMS[index1].desx && ITEMS[index1].y == ITEMS[index1].desy)
                    {
                        var temp;
                        temp = ITEMS[index2].type;
                        ITEMS[index1].x = ITEMS[index1].lasX;
                        ITEMS[index1].y = ITEMS[index1].lasY;
                        ITEMS[index2].x = ITEMS[index2].lasX;
                        ITEMS[index2].y = ITEMS[index2].lasY;
                         
                        ITEMS[index2].type = ITEMS[index1].type;
                        ITEMS[index1].type = temp;
                                                        //Nếu sau khi dịch chuyển có thể ăn được kim cương thì chuyển qua trạng thại hủy kim cương
                        if(this.checkCanEat(index1) || this.checkCanEat(index2))
                        {
                            s_timeState = (new Date()).getTime();
                            s_gemState = STATE_REMOVE;
                            initSubState = false;
                        }
                                                        //Nếu không có ăn được thì chuyển qua trạng thại reswap 2 viên kim cương về vị trí cũ
                        else
                        {
                            s_timeState = (new Date()).getTime();
                            s_gemState = STATE_RESWAP;
                            initSubState = false;
                             
                        }
                        isItemSelected = false;
                        Game.md = false;
                    }
                }
            break;

Thế là chúng ta đã xử lý xong việc dịch chuyển qua lại khi chọn 2 viên kim cương. Nếu không ăn được thì xử lý trạng thái chuyển kim cương về vị trí cũ


Công đoạn xử lý của reswap với swap giống nhau như chỉ khác nhau ở việc xử lý sau khi swap mà thôi.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
case STATE_RESWAP:
            var index1 = convertArray(item_selected[0],item_selected[1],NUM_COL);
            var index2 = convertArray(item_selected[2],item_selected[3],NUM_COL);  
            if(!initSubState)
            {
                ITEMS[index1].state = GEM_SWAP;
                ITEMS[index1].desx = ITEMS[index2].x;
                ITEMS[index1].desy = ITEMS[index2].y;
                 
                ITEMS[index2].state = GEM_SWAP;
                ITEMS[index2].desx = ITEMS[index1].x;
                ITEMS[index2].desy = ITEMS[index1].y;
                initSubState = true;
            }
            else
            {
                var direction, vX, vY;
                direction = unitVector(ITEMS[index1].x, ITEMS[index1].y, ITEMS[index1].desx, ITEMS[index1].desy);
                vX = GEM_SPEED*direction[0];
                vY = GEM_SPEED*direction[1];
                ITEMS[index1].x += vX;
                ITEMS[index1].y += vY;
                 
                direction = unitVector(ITEMS[index2].x, ITEMS[index2].y, ITEMS[index2].desx, ITEMS[index2].desy);
                vX = GEM_SPEED*direction[0];
                vY = GEM_SPEED*direction[1];
                ITEMS[index2].x += vX;
                ITEMS[index2].y += vY;
            }
            if(ITEMS[index2].x == ITEMS[index2].desx && ITEMS[index2].y == ITEMS[index2].desy && ITEMS[index1].x == ITEMS[index1].desx && ITEMS[index1].y == ITEMS[index1].desy)
            {      
                var temp;
                temp = ITEMS[index2].type;
                ITEMS[index2].type = ITEMS[index1].type;
                ITEMS[index1].type = temp;
 
                ITEMS[index1].x = ITEMS[index1].lasX;
                ITEMS[index1].y = ITEMS[index1].lasY;
                ITEMS[index2].x = ITEMS[index2].lasX;
                ITEMS[index2].y = ITEMS[index2].lasY;
 
                s_gemState = STATE_IDEL;
                item_selected[0] = item_selected[1] = item_selected[2] = item_selected[3] = -1;
            }
            break;

Tiếp theo là việc xử lý ăn kim cương, hiển thị kim cương nổ


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
case STATE_REMOVE:
           //Xóa đi các kim cương đã ăn
            if(!initSubState)
            {
                this.checkClearItems();
                item_selected[0] = item_selected[1] = item_selected[2] = item_selected[3] = -1;
                initSubState = true;
            }
           //Chuyển qua trạng thái tạo kim cương mới
            else
            {
                s_gemState = STATE_GENERATE;
                initSubState = false;
                s_timeState = (new Date()).getTime();
            }

Sau khi đã ăn xong thì công đoạn cuối cùng là xử lý việc tạo kim cương mới và di chuyển kim cương xuống


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
case STATE_GENERATE:
            if(!initSubState)
            {
                                     //Khởi tạo lại trạng thái của các kim cương
                for(var i=0;i
                {
                    ITEMS[i].state = GEM_NONE;
                    ITEMS[i].x = ITEMS[i].lasX;
                    ITEMS[i].y = ITEMS[i].lasY;
                    ITEMS[i].desx = ITEMS[i].lasX;
                    ITEMS[i].desy = ITEMS[i].lasY;
                }
                                     //Chuyển trạng thái kim cương thành đã ăn và tạo kim cương mới
                this.eatItems();
                this.generateNewItems();
                initSubState = true;
            }
            else
            {
                 // Tất cả kim cương đã di chuyển xong
                if(this.isAllGemNone())
                {
                    s_gemState = STATE_IDEL;   
                    for(var i=0;i
                    {
                        ITEMS[i].x = ITEMS[i].lasX;
                        ITEMS[i].y = ITEMS[i].lasY;
                    }
                }
                else
                {
                    for(var i=0;i
                    {
                        if(ITEMS[i].state == GEM_DROP)
                        {
                                                                  //Dịch chuyển kim cương rớt xuống.
                            var direction, vX, vY;
                            direction = unitVector(ITEMS[i].x, ITEMS[i].y, ITEMS[i].desx, ITEMS[i].desy);
                            vX = GEM_SPEED_DOWN*direction[0];
                            vY = GEM_SPEED_DOWN*direction[1];
                            ITEMS[i].x += vX;
                            ITEMS[i].y += vY;
                            if(ITEMS[i].y == ITEMS[i].desy && ITEMS[i].x == ITEMS[i].desx)
                            ITEMS[i].state = GEM_NONE;
                        }
                    }
                }
            }
            break;

 


Tóm tắt:


Để thêm hiệu ứng swap và rớt xuống chúng ta chỉ chú ý các vấn đề sau:


- Mỗi viên kim cương sẽ có vị trí ban đầu và vị trí sẽ dịch chuyển đến, khi swap hay khi kim cương rớt xuống chúng ta chỉ cần khai báo vị trị hiện tại ở 1 vị trí khác để nó dịch chuyển đến


- Chúng ta chỉ cần xử lý dịch chuyển kim cương lúc swap và rớt xuống thôi.


Mọi người coi có bug hay không hiểu gì hoặc có góp ý gì cứ comment nha. Code còn chưa sạch mong mọi người thông cảm. Để xem source full thì F12 nha


 


Cảm ơn mọi người.


 

Nguyễn Tài Hải
5 stars.
  • tháng 1 25, 2013
  • ·
  • Thích
  • ·
Đinh Cẩm Phong
Quá hay!!!!
  • tháng 1 26, 2013
  • ·
  • Thích
  • ·
Nguyễn Quang Vinh
Tuyệt vời, coi như xong game Diamond roài
  • tháng 1 26, 2013
  • ·
  • Thích
  • ·
Tony Tran
Xong thể lọai "Match 3" mới đúng chứ lão V ^^
  • tháng 1 26, 2013
  • ·
  • Thích
  • ·
Ngọc Tuấn
phần 3 gắn thêm time nữa
  • tháng 1 27, 2013
  • ·
  • Thích
  • ·
Lâm Nhật Tú
10 stars,
  • tháng 1 27, 2013
  • ·
  • Thích
  • ·
Captcha Challenge