TẠO 1 GAME ĐƠN GIẢN VỚI CANVAS TRONG HTML5

1.Giới thiệu chung về canvas: HTML5 là phiên bản mới cao nhất của ngôn ngữ đánh dấu siêu văn bản. Trong phiên bản này đã cũng cấp cho người dùng một số APIs hỗ trợ việc vẽ các đối tượng 1 cách đơn giản dễ dàng như: Canvas, SVG và WebGL. Canvas có thể hiểu nó là cái khung có khả năng vẽ các đối tượng đồ hoạ một cách dễ dàng với các thuộc tính của Canvas được xử lý bởi JavaScript. Ví dụ về việc vẽ 1 đoạn thẳng có màu với 2 đầu mút cho trước.

<html>
    <head>
        <style>
            #doanthang{border: 2px solid orange;}
        </style>
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
        <script>
            $(document).ready(function(){
            var canvas = document.getElementById("doanthang");
            var context = canvas.getContext("2d");
            context.beginPath();
            context.moveTo(50, 50);
            context.lineTo(200, 50);
            context.lineWidth = 10;
            context.strokeStyle = '#0000FF';
            context.lineCap = 'round';
            context.stroke();
            });
        </script>
    </head>
    <body>
        <canvas id = "doanthang" width = "300" height = "300"></canvas>
    </body>
</html>

Ngoài ra Canvas còn hỗ trợ việc thao tác với các đối tượng ảnh, hỗ trợ hiệu ứng di chuyển, va chạm giữa các đối tượng. Đây là điều quan trọng nhất dẫn đến việc chúng ta hoàn toàn có thể sử dụng canvas để có thể phát triển game trên nền tảng web.

2.Tạo game rắn săn mồi đơn giản với canvas:

  • Bước 1: tạo 1 khung canvas với các chiều dài chiều rộng tưởng ứng.
<canvas id = "myCanvas" width = "600" height = "600">
  • Bước 2: Viết phần Javascript để tạo canvas trong thẻ <script> trên phần head của ứng dụng
var myCanvas = $("#myCanvas")[0];
var context = myCanvas.getContext("2d");
var width = $("#myCanvas").width();
var height = $("#myCanvas").height();
  • Bước 3: khởi tạo các biến cần sử dụng
var widthUnit = 15;
var huongDi;
var food;
var score;
var ran;

Hàm start để bắt đầu game với các giá trị khởi tạo ban đầu gồm 1 mảng ran để lưu các các cell là các phần của con rắn và phương thức tạo thức ăn cho con rắn và điểm khởi tạo ban đầu là 0.

function start(){
    huongDi = "right";
    createSnake();
    createFood();
    score = 0;
}

Để di chuyển con rắn ta cần dùng 1 vòng lặp sẽ gọi hàm vẽ lại con rắn paintSnake sau mỗi thời gian cho trước (có thể hiểu như hàm update()) mà các game developer đã quen thuộc trong các game engine khác.

if(typeof game_loop != "undefined") clearInterval(game_loop);
game_loop = setInterval(paintSnake, 70);
  • Bước 4: hàm khởi tạo con rắn là hàm khởi tạo 1 mảng rỗng với độ dài cho trước sau đó ta thêm các phần tử vào mảng đến khi đủ độ dài của khởi tạo của con rắn
function createSnake(){
    var snakeSize = 5;
    ran = [];
    for (var i = 0; i < snakeSize - 1; i++){
        ran.push({x: 0, y:20});
    }
}
  • Bước 5: hàm tạo mồi cho rắn là hàm tạo ra các ô với các toạ độ random nằm trong toạ độ của canvas nên giá trị x/y luôn nằm trong khoảng nguyên lần thương của chiều dài hay chiều rộng chia cho kích thước của 1 ô rồi từ đi 1
function createFood(){
    food = {
        x:Math.round(Math.random() * (width - widthUnit) / widthUnit),
        y:Math.round(Math.random() * (height - widthUnit) / widthUnit),
    };
}
  • Bước 6: Tạo hàm vẽ rắn ra màn hình ở mỗi frame của game
function paintSnake()

chúng ta sẽ tô màu vào khung canvas

context.fillStyle = "#c0f0aa";
context.fillRect(0, 0, width, height);
context.strokeStyle = "#0000ff";
context.strokeRect(0, 0, width, height);

tiếp theo là cần xác định đầu con rắn để có thể điều khiển được con rắn, như vậy sẽ cần 2 biến để xác định toạ độ x, y của con rắn.

var headX = ran[0].x;
var headY = ran[0].y;

ta thay đổi vị trí của đầu rắn ở mỗi trường hợp khi rắn di chuyển bằng cách tăng giảm chỉ số x, y phù hợp với hướng di chuyển của rắn

if(huongDi == "right") headX++;
else if(huongDi == "left") headX--;
else if(huongDi == "down") headY++;
else if(huongDi == "up") headY--;

Kiểm tra việc con rắn va chạm vào tường hoặc đầu con rắn chạm vào mình con rắn thì restart game

if(headX == -1 || headX == width / widthUnit || headY == -1 ||
headY == height / widthUnit || checkCollision(headX, headY,ran)){
    start();
    return;
}

tiếp theo là khi đầu con rắn chạm vào thức ăn thì ta sẽ thêm 1 ô vào con rắn và gán lại các giá trị headX, headY

if(headX == food.x && headY == food.y) {
var snakeTemp = {x: headX, y: headY};
score++;
createFood();
} else {
var snakeTemp = ran.pop();
snakeTemp.x = headX;
snakeTemp.y = headY;
}
ran.unshift(snakeTemp);
Tô màu cho các đối tượng trong game
for (var i = 0; i <ran.lengt; i++) {
var k = ran[i];
paintCell(k.x, k.y);
}
paintCell(food.x, food.y);
var scoreText = "Score :"+ score;
context.fillText(scoreText, width - 50, 20);
  • Bước 7: định nghĩa phương thức paintCell(x, y)
function paintCell(x, y){
context.fillStyle = "orange";
context.fillRect(x * widthUnit, y * widthUnit, widthUnit, widthUnit);
context.strokeStyle = "red";
context.strokeRect(x * widthUnit, y * widthUnit, widthUnit, widthUnit);
}
  • Bước 8: định nghĩa phương thức checkCollision
function checkCollision(x, y, array) {
for (var i = 0; i < array.length; i++) {
if(array[i].x == x && array[i].y == y) return true;
}
return false;
}
  • Bước 9: Các phím nhấn điều khiển con rắn
$(document).keydown(function(e){
var keyInput = e.which;
if(keyInput == "40" && huongDi != "up") huongDi = "down";
else if(keyInput == "39" && huongDi != "left") huongDi = "right";
else if(keyInput == "38" && huongDi != "down") huongDi = "up";
else if(keyInput == "39" && huongDi != "right") huongDi = "left";
})

Như vậy ta đã hoàn thành 1 game rắn săn mồi đơn giản với canvas. Việc sử dụng canvas để phát triển các game trên nền tảng web sẽ giúp cho game nhẹ hơn load nhanh hơn về máy client không gây khó chịu cho người chơi phải chờ game load lâu, tốt hơn, đơn giản hơn việc sử dụng các engine lớn để build đa nền tảng. Toàn bộ source của bài viết đã được up lên github với link để các bạn có thể tham khảo https://github.com/bacph178/snake