Search…

STML5 CF - Game Loop

Trần Thị Thu HiềnTrần Thị Thu Hiền
24/09/20204 min read
Một khi đã đặt chân vào lĩnh vực phát triển game, bạn chắc chắn sẽ gặp một thuật ngữ cho dù game bạn có nhỏ hay lớn thế nào đi chăng nữa. Đó là Game Loop. Trong bài viết này, tôi sẽ giới thiệu cho các bạn thuật ngữ này và cách hiện thực Game Loop sử dụng STML5 CF.

Khi đặt chân vào lĩnh vực phát triển game, dù game lớn hay nhỏ, bạn chắc chắn sẽ gặp một thuật ngữ đó là Game Loop. Trong bài viết này, tôi sẽ giới thiệu về Game Loop và cách hiện thực Game Loop bằng STML5 CF.

Bài viết này dành cho những bạn đang muốn tìm hiểu HTML5, STML5 CF và những bạn muốn tự phát triển Framework HTML5 riêng cho những sản phẩm của mình.

Game Loop là gì

Game Loop (vòng lặp game) là trái tim của tất cả các game hiện nay. Tất cả những phần liên quan đến xử lý sự kiện, cập nhật trạng thái game (như vị trí của nhân vật, trí thông minh của các con quái, cảnh chơi ... ) đều nằm trong Game Loop. Game Loop gồm có 3 thành phần cơ bản là handleEvents (để xử lý những sự kiện do hệ thống sinh ra), update (cập nhật trạng thái game) và render (vẽ game).

Tùy cách nhìn nhận khác nhau, tôi thường thêm 2 thành phần nữa vào Game Loop là init (khởi tạo trạng thái ban đầu của game) và release (giải phóng tài nguyên game đã sử dụng). Lúc này tôi gọi nó là Game Loop mở rộng.

Game Loop của tôi trong game sẽ có dạng như sau:

init();
while(isGameRunning)
{
    handleEvents();
    update();
    render();   
}
release();

Hiện thực Game Loop sử dụng STML5 CF

Chương trình chính của tôi đơn giản chỉ là file html nhúng thư viện STML5 CF và những file tôi viết để demo cho bài viết này. Tất cả những phần ma thuật tôi sẽ viết trong stml5Game.js.

<!DOCTYPE html>
<html>
<head>
<!-- Include STML5CF -->
<script src="../stml5cf/Graphics.js"></script>
<script src="../stml5cf/TextureCache.js"></script>

<!-- Demo Sources -->
<script src="./src/Resources.js"></script>
<script src="./src/stml5Game.js"></script>
</head>
<body onload="startGameLoop()">
</body>
</html>

Sau khi trang Web của tôi load xong, tôi sẽ gọi hàm startGameLoop để kích hoạt game của mình.

Game Loop

Game Loop của tôi bắt đầu ngay sau khi TextureCache của tôi load xong

this.textureCache.startLoading(function() {
    game.init();
    gameLoop();
}); 

Với đoạn code trên, bạn đã thấy một phần trong Game Loop mở rộng là init rồi phải không. Ở phần dưới đây bạn sẽ thấy những phần còn lại.

function gameLoop() {
    window.requestAnimationFrame(gameLoop);

    game.update();
    game.render();
}

Hai thành phần update và render xuất hiện không có gì lạ. Mấu chốt ở đâu là cách sử dụng hàm window.requestAnimationFrame. Hàm window.requestAnimationFrame thông báo cho browser biết hàm gameLoop của bạn chính là một vòng lặp. Khi gọi hàm này, browser của bạn sẽ gọi lại hàm gameLoop ở lần vẽ tiếp theo. Điều đó giúp bạn tạo một vòng lặp game hoàn chỉnh.

Ví dụ minh họa

Trong ví dụ minh họa, tôi sẽ vẽ logo của Stdio ở giữa màn hình và cho logo này di chuyển theo đường chéo. Khi gặp các cạnh của Canvas, logo sẽ đổi hướng theo góc phản xạ.

Hiện thực hàm init

this.init = function() {
    this.screenWidth = 800;
    this.screenHeight = 480;

    initSTML5CF(this.screenWidth, this.screenHeight);

    this.x = 400;
    this.y = 240;

    this.vx = 2;
    this.vy = 3;

    this.stdioImage = this.textureCache.getImage(s_stdioLogo);
};

Trong phần init này, tôi đã khởi tạo STML5CF thông qua hàm initSTML5CF và các trạng thái game như vị trí, vận tốc di chuyển của logo. Ngoài ra tôi khai báo thêm 1 biến thành viên stdioImage để sử dụng cho việc vẽ trong hàm render.

Hiện thực hàm update

this.update = function() {
    var dt = 1; //THIS IS A CHEAT
    this.x += this.vx*dt;
    this.y += this.vy*dt;

    if(this.x < 0 || this.x > this.screenWidth - getImageWidth(this.stdioImage)) {
        this.vx = -this.vx;
    }

    if(this.y < 0 || this.y > this.screenHeight - getImageHeight(this.stdioImage)) {
        this.vy = -this.vy;
    }
}

Logic phần update tương đối đơn giản. Vị trí của logo được tôi tăng tùy thuộc vào thời gian giữa 2 frame liên tiếp nhau dt. Trong ví dụ này, tôi cho dt có giá trị cố định nhưng trong thực tế, bạn phải tính toán con số này thật CHÍNH XÁC. Phần còn lại là phần tôi dùng để thay đổi chiều chuyển động của logo.

Lưu ý: Hàm getImageWidthgetImageHeight là 2 hàm dùng để lấy chiều rộng và chiều cao của hình ảnh. Các hàm này nằm trong STML5 CF.

Hiện thực hàm render

this.render = function() {
    clearScreen();

    drawImage(this.stdioImage, this.x, this.y);
}

Trong game, hàm render luôn luôn bắt đầu bằng một phép gọi hàm để xóa sạch màn hình game. Trong ví dụ này cũng vậy, tôi gọi clearScreen() để xóa sạch Canvas. Sau đó tôi dùng hàm drawImage để vẽ logo tại vị trí tôi đã khai báo ở trên.

Mã nguồn

Bạn có thể tải toàn bộ mã nguồn của bài viết này tại STML5CF_GameLoop.

Bài chung series

IO Stream

IO Stream Co., Ltd

developer@iostream.co
383/1 Quang Trung, ward 10, Go Vap district, Ho Chi Minh city
Business license number: 0311563559 issued by the Department of Planning and Investment of Ho Chi Minh City on February 23, 2012

©IO Stream, 2013 - 2025