Build mini game bằng HTML/CSS/JS trong 15 phút

Xây một mini game bằng HTML/CSS/JS không hề phức tạp như nhiều người nghĩ. Chỉ với một thẻ div, vài dòng CSS và một ít JavaScript, bạn đã có thể tạo ra trò chơi nhỏ để minh họa kiến thức, luyện phản xạ hoặc tăng tương tác trên bài viết. Trong bài này, chúng ta sẽ làm một game đơn giản: nhấn chuột nhanh nhất khi màu chuyển, có thống kê kết quả và điểm tốt nhất, chạy gọn trong một thẻ uk-card.

Build mini game bằng HTML/CSS/JS trong 15 phút

Demo: mini game phản xạ với màu sắc

Trò chơi hoạt động như sau: bạn nhấn nút Bắt đầu, chờ vòng tròn đổi màu. Khi vòng tròn chuyển sang xanh, hãy nhấp nhanh nhất có thể. Hệ thống sẽ đo thời gian phản xạ, lưu lại lần gần nhất, tốt nhất và trung bình.

Mini game: nhấn khi màu chuyển

Nhấn Bắt đầu, chờ vòng tròn chuyển sang màu xanh rồi click nhanh nhất có thể.

Nhấn Bắt đầu để chơi.
Sẵn sàng

Kết quả

  • Lần gần nhất: ms
  • Tốt nhất: ms
  • Trung bình: ms
  • Số lần chơi: 0

Thử nhiều lần để xem phản xạ của bạn ổn định đến đâu.

1. Ý tưởng mini game: đơn giản nhưng có số đo

Thay vì làm một game phức tạp, bài viết này chọn một ý tưởng rất gọn: đo thời gian phản xạ. Người chơi chỉ cần chờ màu xanh xuất hiện rồi click. Đổi lại, bạn có thể:

  • Minh họa trực quan cách kết hợp HTML, CSS, JS.
  • Hiển thị được số liệu rõ ràng: thời gian phản xạ, tốt nhất, trung bình.
  • Dễ mở rộng: bảng xếp hạng, lưu kết quả bằng localStorage, giới hạn số lượt.

Cấu trúc chung của game gồm ba phần: giao diện chính, khu vực thống kêlogic điều khiển bằng JavaScript.

2. Cấu trúc HTML: chỉ cần một thẻ uk-card và vài phần tử

Phiên bản tối giản của khung game trông như sau:

<div class="uk-card uk-card-default uk-card-body reaction-game-card">
  <div class="reaction-game-status">Nhấn Bắt đầu để chơi.</div>

  <div class="reaction-game-circle">Sẵn sàng</div>

  <button type="button" class="uk-button uk-button-primary">
    Bắt đầu
  </button>
</div>

Trong bài viết này, ta bổ sung thêm phần thống kê ở bên cạnh và phân chia bố cục bằng Flexbox để nhìn rõ hơn: một cột điều khiển, một cột hiển thị kết quả. Tất cả đều nằm trong một uk-card để đồng bộ với UIkit.

3. CSS: tạo vòng tròn phản hồi rõ ràng

Điểm quan trọng nhất về mặt giao diện là vòng tròn phản ứng theo trạng thái. Ta dùng thêm các class như .is-waiting, .is-ready để thay đổi màu sắc, con trỏ và hiệu ứng.

.reaction-game-circle {
  width: 130px;
  height: 130px;
  border-radius: 50%;
  background: #d4d4d4;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background-color 0.18s ease;
}

.reaction-game-circle.is-waiting {
  background: #f0506e;
  color: #fff;
}

.reaction-game-circle.is-ready {
  background: #32d296;
  color: #fff;
  cursor: pointer;
}

Ngoài ra, phần còn lại của CSS chủ yếu phục vụ bố cục và dark mode. Bạn có thể tinh chỉnh thêm để đồng bộ với hệ thống thiết kế của dự án hiện tại.

4. JavaScript: trạng thái trò chơi và đo thời gian phản xạ

Phần JavaScript chịu trách nhiệm:

  • Quản lý trạng thái: idle, waiting, ready.
  • Đặt timeout ngẫu nhiên để đổi màu vòng tròn.
  • Xử lý tình huống click quá sớm hoặc click đúng lúc.
  • Tính toán và cập nhật thống kê.

Đoạn mã cốt lõi để đo thời gian phản xạ:

var gameState = 'idle';
var timerId = null;
var startTime = 0;

function startGame() {
  gameState = 'waiting';
  var delay = 1500 + Math.random() * 2500;

  timerId = setTimeout(function () {
    gameState = 'ready';
    startTime = performance.now();
    // đổi màu vòng tròn sang xanh
  }, delay);
}

function onCircleClick() {
  if (gameState === 'waiting') {
    // click quá sớm
  } else if (gameState === 'ready') {
    var endTime = performance.now();
    var reactionTime = endTime - startTime;
    // hiển thị reactionTime
  }
}

Thay vì dùng Date.now(), bài viết sử dụng performance.now() để có độ phân giải tốt hơn. Với một mini game đo thời gian, cảm giác chênh lệch vài chục mili giây cũng tạo được động lực cho người chơi thử lại.

5. Thống kê: lần gần nhất, tốt nhất, trung bình

Để game bớt “một lần đo rồi thôi”, ta giữ lại một vài chỉ số:

  • Lần gần nhất: giúp người chơi thấy ngay kết quả mới.
  • Tốt nhất: tạo cảm giác muốn phá kỷ lục cá nhân.
  • Trung bình: phản ánh độ ổn định của phản xạ.

Việc cập nhật thống kê khá đơn giản:

attempts += 1;
totalTime += reactionTime;
if (bestTime === null || reactionTime < bestTime) {
  bestTime = reactionTime;
}

lastEl.textContent = reactionTime.toFixed(0);
bestEl.textContent = bestTime.toFixed(0);
avgEl.textContent = (totalTime / attempts).toFixed(0);

Nếu muốn nâng cấp thêm, bạn có thể dùng localStorage để lưu kỷ lục giữa các lần tải trang, hoặc gửi dữ liệu lên server để làm bảng xếp hạng.

6. Gợi ý mở rộng mini game

Từ cấu trúc hiện tại, bạn có thể dễ dàng phát triển ra nhiều biến thể:

  • Đổi từ vòng tròn sang nhiều ô, chỉ có một ô đổi màu và người chơi phải chọn đúng ô.
  • Thêm giới hạn thời gian, nếu phản xạ chậm hơn ngưỡng nào đó sẽ tính là thua.
  • Đếm điểm combo: phản xạ liên tiếp dưới 300 ms sẽ cộng chuỗi.
  • Kết hợp phím tắt: thay vì click vào vòng tròn, người chơi phải bấm phím tương ứng.

Điểm chung là bạn vẫn giữ được khung logic: chờ sự kiện xảy ra, đo thời gian phản ứngcập nhật trạng thái giao diện.

7. Kết luận

Một mini game nhỏ như trò phản xạ với màu sắc là ví dụ rất tốt để luyện kết hợp HTML, CSS, JavaScript trong một khối độc lập. Bạn có giao diện rõ ràng, trạng thái cụ thể, logic xử lý sự kiện đơn giản nhưng đủ sinh động để người đọc muốn tương tác ngay trong bài viết. Từ nền tảng này, bạn có thể tiếp tục xây dựng thêm nhiều trò chơi khác, hoặc biến mini game thành công cụ đo lường, khảo sát và tương tác cho sản phẩm của mình.

Bình luận


  • Không có bình luận.

Công cụ trực tuyến

Nhấn Ctrl + \ trên máy tính, hoặc vuốt sang trái ở bất kỳ đâu trên mobile.

Đăng nhập





Đang tải...