Làm game 2D với Javascript thuần (phần 1)
Bài viết này được dịch dựa trên nguồn sau đây. DEMO : https://jsfiddle.net/erajpypL/ PHẦN HTML Trước hết, chúng ta sẽ xây dựng khung HTML để có thể render game này. <!DOCTYPE html> < html > < head > < meta charset = " utf-8 " /> ...
Bài viết này được dịch dựa trên nguồn sau đây.
DEMO : https://jsfiddle.net/erajpypL/
PHẦN HTML
Trước hết, chúng ta sẽ xây dựng khung HTML để có thể render game này.
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>DUONG-GAME STUDIO</title> <style> * { padding: 0; margin: 0; } canvas { background: #eee; display: block; margin: 0 auto; } </style> </head> <body> <canvas id="myCanvas" awidth="480" height="320"></canvas> <script> // Code JavaScript </script> </body> </html>
Khá đơn giản phải ko? Nguyên nhân là game sẽ được render toàn bộ vào thẻ <canvas>.
CANVAS CƠ BẢN
Trước hết, bàn cần phải lấy được thẻ <canvas> trong body của html bằng Javascript. Hãy làm theo bước sau :
var canvas = document.getElementById("myCanvas"); var ctx = canvas.getContext("2d");
Biến ctx được tạo để lưu lại nội dung render 2D.
Dưới đây là 1 ví dụ cơ bản về việc vẽ 1 hình vuông bằng canvas.
ctx.beginPath(); ctx.rect(20, 40, 50, 50); ctx.fillStyle = "#FF0000"; ctx.fill(); ctx.closePath();
Tất cả mọi hướng dẫn sẽ nằm trong 2 methods beginPath() và closePath(). Chúng ta đang định nghĩa một hình vuông sử dụng rect() : 2 giá trị đầu tiên cho thấy tọa độ của góc trên cùng bên trái của hình vuông đó, trong khi 2 giá trị tiếp theo thì định nghĩa chiều rộng và cao của hình vuông. Thuộc tính fillStyle định nghĩa màu sẽ đc sử dụng trong phương thức fill() tiếp theo để vẽ hình vuông này.
Tất nhiên ko chỉ giới hạn ở hình vuông hay chữ nhật. Chúng ta còn có thể vẽ cả hình tròn màu xanh với đoạn code dưới đây.
ctx.beginPath(); ctx.arc(240, 160, 20, 0, Math.PI*2, false); ctx.fillStyle = "green"; ctx.fill(); ctx.closePath();
Bạn cũng có thê sử dụng stroke() thay vì fill(). Hàm này sẽ cho phép bạn tô màu mỗi phần viền của hình thay vì tô màu hết cả hình đó.
ctx.beginPath(); ctx.rect(160, 10, 100, 40); ctx.strokeStyle = "rgba(0, 0, 255, 0.5)"; ctx.stroke(); ctx.closePath();
ĐỊNH NGHĨA MỘT DRAWING LOOP
Vậy là bạn đã biết cách vẽ 1 quả bóng và những hình vuông rồi. Nào tiếp tục là hãy làm cho chúng có thể di chuyển được. Về mặt kĩ thuật, chúng ta sẽ vẽ quả bóng trên màn hình, xóa nó và vẽ nó lại lần nữa trong một vị trí gần gần với vị trí vừa rồi cho mỗi frame khác nhau. Việc này sẽ khiến cho bạn cảm giác sự di chuyển của nó. Đại ý là nó giống kiểu làm film ấy.
Để có thể update canvas vẽ trên mỗi frame, chúng ta cần định nghĩa một function chạy đi chạy lại. Rất may mắn là Javascript cung cấp cho bạn loại hàm này setInterval() và requestAnimationFrame().
Cho đoạn code sau vào phần thẻ <script>. Hàm draw() sẽ được thực thi mỗi 10 mili giây.
function draw() { // drawing code } setInterval(draw, 10);
Nào trước hết bạn hãy vẽ thử một quả bóng. Chú ý xóa hết mấy cái hình ở mục bên trên trước đi nhé.
ctx.beginPath(); ctx.arc(50, 50, 10, 0, Math.PI*2); ctx.fillStyle = "#0095DD"; ctx.fill(); ctx.closePath();
MAKE IT MOVEEEE
Bạn sẽ thấy rằng ở trên bạn đang hard code vị trí của quả bóng là (50, 50) và cho dù frame đó đc vẽ đi vẽ lại liên tục mỗi 10 mili giây thì bạn cung sẽ ko thấy nó di chuyển. Hãy suy nghĩ cách định nghĩa vị trí khác. (x, y) này là tọa độ của tâm quẩ bóng nhé.
var x = canvas.awidth/2; var y = canvas.height-30;
Tiếp, mình định nghĩa 2 giá trị dx và dy thể hiện cho sự thay đổi giá trị x và y khi quả bóng di chuyển. Việc này giống ngày xưa các bạn học về đạo hàm này nọ hổi cấp 3 ấy.
var dx = 2; var dy = -2;
Cuối cũng, viết lại hàm draw() như sau. Chú ý giá trị x và y sẽ được update mỗi lần frame thay đổi.
function draw() { ctx.beginPath(); ctx.arc(x, y, 10, 0, Math.PI*2); ctx.fillStyle = "#0095DD"; ctx.fill(); ctx.closePath(); x += dx; y += dy; }
Xóa canvas trước khi vẽ frame mới
Bạn sẽ thấy ở trên bạn có 1 vệt ảnh dài tạo thành đường thẳng, nguyên nhân mình vẫn chưa xóa các nội dung canvas được vẽ trước đó. Hãy dùng hàm clearRect(). Add hàm này vào hàm draw() như sau.
function draw() { ctx.clearRect(0, 0, canvas.awidth, canvas.height); ctx.beginPath(); ctx.arc(x, y, 10, 0, Math.PI*2); ctx.fillStyle = "#0095DD"; ctx.fill(); ctx.closePath(); x += dx; y += dy; }
CLEAN CODE
Chú ý đoạn code ở trên cần viết lại theo hướng đẹp hơn nhé. Nếu ko bạn sẽ bị các reviewer comment đấy