Làm HTML canvas game bằng Create JS
Trong bài viết nay tôi sẽ hướng dẫn mọi người làm một game nhỏ nhỏ dùng CreateJS – một thư viện Javascript vô cùng thú vị.
Mọi người có thể thử chơi game tại http://heasygame.com/beezaro.html. Chắc hẳn ai ai cũng biết trò chơi cờ caro, ai xếp được 5 quân của mình thẳng hàng với nhau là thắng. Trò này cũng vậy, tuy nhiên thay vì bàn cờ ô vuông 8 hướng thì tôi làm bàn cơ hình tổ ong 6 hướng, và tôi gọi trò chơi của mình là Beezaro .
Create JS là gì?
Bạn có thể tìm thấy tất cả những thứ có liên quan đến Create JS từ trang chủ của nó http://www.createjs.com/.
Nói ngắn gọn nhất theo lời quảng cáo trên trang chủ, Create JS là một bộ thư viện Javascript bao gồm nhiều thư viện độc lập, nhưng có thể hoạt động cùng nhau để làm ra những ứng dụng HTML5 tuyệt vời.
4 thư viện hiện tại của Create JS là:
- Easel JS: Một thư viện cho phép chúng ta thao tác trên HTML5 Canvas rất dễ dàng. Hình dung cái này là để vẽ hình rồi thiết lập các event trên các hình đó. Beezaro được viết hoàn toàn dùng Easel JS.
- TweenJS: Cho phép tạo ra các ảnh động hay hoạt hình trên canvas.
- SoundJS: Làm việc với âm thanh dễ dàng hơn rất nhiều.
- PreloadJS: Quản lý và điều khiển việc loading của các assets.
Demo thì các bạn có thể xem tại đây. Các bạn cũng có thể tìm thấy một số lượng không giới hạn các bài hướng dẫn từ cơ bản đến nâng cao trên chính trang chủ của Create JS. Cộng đồng sử dụng Create JS cũng khá lớn, gần như cần cái gì là có thể tìm ngay ra câu trả lời ?
Với một số mục đích bí mật, tôi có nhu cầu làm một HTML5 game, tiện thể thì viết luôn hướng dẫn. Hi vọng nó sẽ có ích với các bạn quan tâm.
Beezaro
Các bạn có thể tham khảo source code đầy đủ trên repo github của tôi https://github.com/bs90/bs90.github.io
Chuẩn bị
Tất cả những gì bạn cần làm là include 2 thư viện jquery và craete js vào header của file HTML.
1
2
3
4
|
<script src = "https://code.jquery.com/jquery-2.2.1.min.js" > </script>
<script src = "https://code.createjs.com/createjs-2015.11.26.min.js" > </script>
|
Do game trong bài này chỉ dùng Easel JS nên các bạn chỉ cần include mỗi nó thôi cũng được. Link CDN của các thư viện thì các bạn hãy dành 5 giây google nhé.
Tạo HTML canvas
Nội dung body chỉ vẻn vẹn như sau
1
2
3
4
5
|
< div style = "text-align: center;" >
< canvas style = "background-color: white; border-bottom: 10px solid #209900; border-top: 10px solid #209900" id = "gameCanvas" width = "950" height = "550" > < / canvas >
< / div >
|
(Hãy tha thứ cho việc tôi viết inline CSS)
Canvas có id là gameCanvas sẽ chính là nơi chúng ta dùng thư viện để vẽ vời lên.
Vẽ bàn thi đấu
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
|
$ ( function ( ) {
init ( ) ; // Hàm init được gọi sau khi load xong trang
} ) ;
function init ( ) {
stage = new createjs . Stage ( "gameCanvas" ) ; // Khởi tạo một stage của Create JS trên canvas có id là gameCanvas
draw_game_table ( stage ) ; // Vẽ bàn thi đấu
. . .
}
function polygon_maker ( x , y , size , color ) {
// Đây là hàm vẽ một hình lục giác đều với vị trí, kích cỡ, màu sắc tuỳ ý
var polygon = new createjs . Shape ( ) ;
polygon . graphics . beginFill ( color ) . drawPolyStar ( x , y , size , 6 , 0 , 30 ) ;
return polygon ;
}
function draw_game_table ( stage ) {
// Đây là hàm vẽ 160 hình lục giác theo đúng thứ tự
var polygon ;
for ( j = 0 ; j <= 5 ; j ++ ) {
for ( i = 1 ; i <= 15 ; i ++ ) {
polygon = polygon_maker ( 40 + 54 * i , 35 + j * 96 , 30 , "#209900" ) ;
. . .
stage . addChild ( polygon ) ;
}
if ( j != 5 ) {
for ( i = 1 ; i <= 14 ; i ++ ) {
polygon = polygon_maker ( 67 + 54 * i , 83 + j * 96 , 30 , "#209900" ) ;
. . .
stage . addChild ( polygon ) ;
}
}
}
stage . update ( ) ; // Update lại stage, lúc này các hình lục giác mới chính thức xuất hiện trên canvas
}
|
Và đây là kết quả:
Khởi tạo mạng để lưu trạng thái của game
Phần này tôi tự cho mình là khá tinh tế, hay nói các khách là khôn vặt. Thay vì dùng mảng hai chiều 15×11 để lưu thì tôi dùng mảng 23×19 để lưu. Vì sau thì hồi sau sẽ rõ. Giá trị mặc định của các phần từ là 0, tức là trạng thái không có gì, 1 nếu có nước đi của người chơi số 1, 2 nếu có nước đi của người chơi số 2 ở ô tương ứng.
1
2
3
4
5
6
7
8
9
10
|
function init_game_array ( ) {
for ( j = 0 ; j <= 18 ; j ++ ) {
game_state [ j ] = new Array ( ) ;
for ( i = 0 ; i <= 22 ; i ++ ) {
game_state [ j ] [ i ] = 0 ;
}
}
}
|
Gán event cho các hình lục giác khi ấn chuột vào
Ở phần code phía trên, các bạn có thể thấy có vài phần vẫn để …. Sau khi sinh ra mỗi hình lục giác, trước khi add chúng vào stage, chúng ta cần add hành động cho chú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
|
. . .
polygon = polygon_maker ( 40 + 54 * i , 35 + j * 96 , 30 , "#209900" ) ;
polygon . addEventListener ( "click" , move_click ( j* 2 , i - 1 ) ) ;
stage . addChild ( polygon ) ;
. . .
function move_click ( j , i ) {
return function ( event ) {
if ( game_log . indexOf ( j + " " + i ) != - 1 ) {
return
} else {
game_log . push ( j + " " + i ) ;
}
place_move ( current_player , j , i ) ;
current_player = current_player == 1 ? 2 : 1 ;
check_game_over ( ) ;
}
}
function place_move ( player , x , y ) {
game_state [ x + 4 ] [ y + 4 ] = player ;
draw_game_state ( ) ;
}
|
Các bạn hãy dành thời gian xem code trên repo github của tôi để hiểu rõ hơn nhé. Cơ bản là đây là khi click vào một ô chưa có nước đi nào, sẽ gán nước đi tiếp theo vào ô đó ?
Kiểm tra trạng thái kết thúc của game và vẽ đường thẳng chiến thắng
Phần nay vận dụng cái "tinh tế" phía trên tôi nói. Để kiểm tra game kết thúc hay chưa tất nhiên phải kiểm tra xem đã có 5 nước đi nào của cùng 1 user thẳng 1 hàng hay chưa. Và để không phãi nghĩ đến trường hợp biên, tôi cộng vào một chiều 4 đơn vị nữa (thế mới thành 23×19) để khi cộng hay trừ đi 1 2 3 4 thì không bị lỗi . Việc còn lại đơn giản như sau:
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
59
60
61
|
( function ( ) {
Array . prototype . check_same = function ( ) {
for ( var i = 1 ; i < this . length ; i ++ ) {
if ( this [ 0 ] == 0 || this [ i ] != this [ 0 ] ) return false ;
}
return true ;
}
} ) ( ) ;
function check_game_over ( ) {
var win_line = new createjs . Shape ( ) ;
win_line . name = "win_line" ;
win_line . graphics . setStrokeStyle ( 3 ) ;
win_line . graphics . beginStroke ( "#e74c3c" ) ;
for ( j = 4 ; j <= 14 ; j ++ ) {
for ( i = 4 ; i <= 18 ; i ++ ) {
if ( [ game_state [ j ] [ i - 4 ] , game_state [ j ] [ i - 3 ] , game_state [ j ] [ i - 2 ] , game_state [ j ] [ i - 1 ] , game_state [ j ] [ i ] ] . check_same ( )
|| [ game_state [ j ] [ i + 1 ] , game_state [ j ] [ i - 3 ] , game_state [ j ] [ i - 2 ] , game_state [ j ] [ i - 1 ] , game_state [ j ] [ i ] ] . check_same ( )
|| [ game_state [ j ] [ i + 1 ] , game_state [ j ] [ i + 2 ] , game_state [ j ] [ i - 2 ] , game_state [ j ] [ i - 1 ] , game_state [ j ] [ i ] ] . check_same ( )
|| [ game_state [ j ] [ i + 1 ] , game_state [ j ] [ i + 2 ] , game_state [ j ] [ i + 3 ] , game_state [ j ] [ i - 1 ] , game_state [ j ] [ i ] ] . check_same ( )
|| [ game_state [ j ] [ i + 1 ] , game_state [ j ] [ i + 2 ] , game_state [ j ] [ i + 3 ] , game_state [ j ] [ i + 4 ] , game_state [ j ] [ i ] ] . check_same ( ) ) {
if ( j % 2 == 0 ) {
win_line . graphics . moveTo ( 40 + 54 * ( i - 3 ) - 30 , 35 + ( j - 4 ) / 2 * 96 ) . lineTo ( 40 + 54 * ( i - 3 ) + 30 , 35 + ( j - 4 ) / 2 * 96 ) ;
} else {
win_line . graphics . moveTo ( 67 + 54 * ( i - 3 ) - 30 , 83 + ( j - 5 ) / 2 * 96 ) . lineTo ( 67 + 54 * ( i - 3 ) + 30 , 83 + ( j - 5 ) / 2 * 96 ) ;
}
// console.log("["+(j-4)+","+(i-4)+"]");
}
var ya = j % 2 == 0 ? [ i - 2 , i - 2 , i - 1 , i - 1 , i , i + 1 , i + 1 , i + 2 ] : [ i - 2 , i - 1 , i - 1 , i , i + 1 , i + 1 , i + 2 , i + 2 ] ;
if ( [ game_state [ j - 4 ] [ ya [ 0 ] ] , game_state [ j - 3 ] [ ya [ 1 ] ] , game_state [ j - 2 ] [ ya [ 2 ] ] , game_state [ j - 1 ] [ ya [ 3 ] ] , game_state [ j ] [ i ] ] . check_same ( )
|| [ game_state [ j + 1 ] [ ya [ 4 ] ] , game_state [ j - 3 ] [ ya [ 1 ] ] , game_state [ j - 2 ] [ ya [ 2 ] ] , game_state [ j - 1 ] [ ya [ 3 ] ] , game_state [ j ] [ i ] ] . check_same ( )
|| [ game_state [ j + 1 ] [ ya [ 4 ] ] , game_state [ j + 2 ] [ ya [ 5 ] ] , game_state [ j - 2 ] [ ya [ 2 ] ] , game_state [ j - 1 ] [ ya [ 3 ] ] , game_state [ j ] [ i ] ] . check_same ( )
|| [ game_state [ j + 1 ] [ ya [ 4 ] ] , game_state [ j + 2 ] [ ya [ 5 ] ] , game_state [ j + 3 ] [ ya [ 6 ] ] , game_state [ j - 1 ] [ ya [ 3 ] ] , game_state [ j ] [ i ] ] . check_same ( )
|| [ game_state [ j + 1 ] [ ya [ 4 ] ] , game_state [ j + 2 ] [ ya [ 5 ] ] , game_state [ j + 3 ] [ ya [ 6 ] ] , game_state [ j + 4 ] [ ya [ 7 ] ] , game_state [ j ] [ i ] ] . check_same ( ) ) {
if ( j % 2 == 0 ) {
win_line . graphics . moveTo ( 40 + 54 * ( i - 3 ) - 17 , 35 + ( j - 4 ) / 2 * 96 - 30 ) . lineTo ( 40 + 54 * ( i - 3 ) + 17 , 35 + ( j - 4 ) / 2 * 96 + 30 ) ;
} else {
win_line . graphics . moveTo ( 67 + 54 * ( i - 3 ) - 17 , 83 + ( j - 5 ) / 2 * 96 - 30 ) . lineTo ( 67 + 54 * ( i - 3 ) + 17 , 83 + ( j - 5 ) / 2 * 96 + 30 ) ;
}
// console.log("["+(j-4)+","+(i-4)+"]");
}
ya = j % 2 == 0 ? [ i + 2 , i + 1 , i + 1 , i , i - 1 , i - 1 , i - 2 , i - 2 ] : [ i + 2 , i + 2 , i + 1 , i + 1 , i , i - 1 , i - 1 , i - 2 ] ;
if ( [ game_state [ j - 4 ] [ ya [ 0 ] ] , game_state [ j - 3 ] [ ya [ 1 ] ] , game_state [ j - 2 ] [ ya [ 2 ] ] , game_state [ j - 1 ] [ ya [ 3 ] ] , game_state [ j ] [ i ] ] . check_same ( )
|| [ game_state [ j + 1 ] [ ya [ 4 ] ] , game_state [ j - 3 ] [ ya [ 1 ] ] , game_state [ j - 2 ] [ ya [ 2 ] ] , game_state [ j - 1 ] [ ya [ 3 ] ] , game_state [ j ] [ i ] ] . check_same ( )
|| [ game_state [ j + 1 ] [ ya [ 4 ] ] , game_state [ j + 2 ] [ ya [ 5 ] ] , game_state [ j - 2 ] [ ya [ 2 ] ] , game_state [ j - 1 ] [ ya [ 3 ] ] , game_state [ j ] [ i ] ] . check_same ( )
|| [ game_state [ j + 1 ] [ ya [ 4 ] ] , game_state [ j + 2 ] [ ya [ 5 ] ] , game_state [ j + 3 ] [ ya [ 6 ] ] , game_state [ j - 1 ] [ ya [ 3 ] ] , game_state [ j ] [ i ] ] . check_same ( )
|| [ game_state [ j + 1 ] [ ya [ 4 ] ] , game_state [ j + 2 ] [ ya [ 5 ] ] , game_state [ j + 3 ] [ ya [ 6 ] ] , game_state [ j + 4 ] [ ya [ 7 ] ] , game_state [ j ] [ i ] ] . check_same ( ) ) {
if ( j % 2 == 0 ) {
win_line . graphics . moveTo ( 40 + 54 * ( i - 3 ) + 17 , 35 + ( j - 4 ) / 2 * 96 - 30 ) . lineTo ( 40 + 54 * ( i - 3 ) - 17 , 35 + ( j - 4 ) / 2 * 96 + 30 ) ;
} else {
win_line . graphics . moveTo ( 67 + 54 * ( i - 3 ) + 17 , 83 + ( j - 5 ) / 2 * 96 - 30 ) . lineTo ( 67 + 54 * ( i - 3 ) - 17 , 83 + ( j - 5 ) / 2 * 96 + 30 ) ;
}
// console.log("["+(j-4)+","+(i-4)+"]");
}
}
}
stage . addChild ( win_line ) ;
stage . update ( ) ;
}
|
Dù trông hơi vô học nhưng mà thực sự là nó vẫn chạy (tin tôi đi !). Nếu bạn có cách check nào hay hơn hãy chỉ cho tôi với
Hết rồi (tl;dr)! Chúc bạn có những giờ phút vui vẻ với Create JS!
- Chụp ảnh màn hình điện thoại Android không cần cài app
- Tài liệu và mã nguồn hệ thống groupon, bán deal, mua hàng theo nhóm
- Tôi code vì tiền
- Tặng mã nguồn và dữ liệu thật của forum nông nghiệp, nông sản hữu cơ
- Kỹ năng viết và sử dụng email vô cùng đơn giản nhưng không phải ai cũng biết
- Hiện trạng triển khai hệ thống giao thông thông minh tại Việt Nam
- Ứng dụng mô hình phần mềm SaaS trong môi trường mobility
- Danh sách 6.500 website mua bán rao vặt, tốt để quảng cáo, SEO và tạo backlink
- Cải tiến qui trình phần mềm?
- Java đang giãy chết?
- BYOD là gì ?
- Cấu hình scheduled tasks Mautic - marketing automation software trên Windows
DVMS chuyên:
- Tư vấn, xây dựng, chuyển giao công nghệ Blockchain, mạng xã hội,...
- Tư vấn ứng dụng cho smartphone và máy tính bảng, tư vấn ứng dụng vận tải thông minh, thực tế ảo, game mobile,...
- Tư vấn các hệ thống theo mô hình kinh tế chia sẻ như Uber, Grab, ứng dụng giúp việc,...
- Xây dựng các giải pháp quản lý vận tải, quản lý xe công vụ, quản lý xe doanh nghiệp, phần mềm và ứng dụng logistics, kho vận, vé xe điện tử,...
- Tư vấn và xây dựng mạng xã hội, tư vấn giải pháp CNTT cho doanh nghiệp, startup,...
Vì sao chọn DVMS?
- DVMS nắm vững nhiều công nghệ phần mềm, mạng và viễn thông. Như Payment gateway, SMS gateway, GIS, VOIP, iOS, Android, Blackberry, Windows Phone, cloud computing,…
- DVMS có kinh nghiệm triển khai các hệ thống trên các nền tảng điện toán đám mây nổi tiếng như Google, Amazon, Microsoft,…
- DVMS có kinh nghiệm thực tế tư vấn, xây dựng, triển khai, chuyển giao, gia công các giải pháp phần mềm cho khách hàng Việt Nam, USA, Singapore, Germany, France, các tập đoàn của nước ngoài tại Việt Nam,…
Quý khách xem Hồ sơ năng lực của DVMS tại đây >>
Quý khách gửi yêu cầu tư vấn và báo giá tại đây >>