Nếu bạn chưa từng chơi trò chơi Rắn săn mồi nổi tiếng, hãy giơ tay!
Tôi nói vậy, nhưng tôi cho rằng ngày nay, thế hệ mới có thể chưa bao giờ nghe nói đến trò chơi này, trò chơi này có vẻ hơi lỗi thời so với những khả năng mà máy tính và Web ngày nay mang lại.
Chưa hết, đã có lúc trò chơi Rắn săn mồi là một trò chơi mà tất cả những người sở hữu điện thoại di động đều dành một lượng thời gian chơi quá lớn. Đúng vậy, hồi đó chúng ta không nói về điện thoại thông minh mà chỉ nói về điện thoại.
Người ta thường nói đó là thời điểm thuận lợi và Nokia đã phổ biến trò chơi này thông qua các thiết bị di động của mình, đây cũng là một chuẩn mực. Ngày nay, sự thống trị của Nokia trong thế giới di động và trò chơi Snake không còn nhiều nữa.
Đối với những người hoài niệm về trò chơi này – và tôi phải thừa nhận là một trong số họ – hướng dẫn này sẽ hướng dẫn bạn cách tạo lại nó cho Web. Để làm như vậy, tôi sẽ sử dụng API Canvas và JavaScript của HTML5.
Đây cũng là cơ hội để tìm hiểu cách sử dụng các lớp trong Javascript và tạo vòng lặp trò chơi hiệu quả cho các trò chơi trên Web.
Để bắt đầu, chúng ta sẽ tạo trang Web cho phép chúng ta chơi trò chơi Rắn săn mồi mà chúng ta sẽ phát triển trong hướng dẫn này. Bạn sẽ sớm thấy rằng trang Web này không gặp bất kỳ khó khăn gì. Hai div, một cho tiêu đề trang và một cho hiển thị khu vực mà con rắn sẽ di chuyển.
Để làm điều này, tôi sẽ thêm một chút CSS để căn giữa các div này bằng cách áp dụng chiều rộng cố định cho chúng:
Như tôi đã giải thích trong phần giới thiệu hướng dẫn này, tôi sẽ sử dụng lớp Snake chuyên dụng để lập mô hình trò chơi. Điều này cũng sẽ cho phép bạn khám phá cách thao tác các lớp trong JavaScript.
Con rắn của chúng ta sẽ có các thuộc tính sau:
Ở cuối hàm tạo, một phương thức init được gọi để khởi tạo con rắn khi bắt đầu trò chơi. Khi một trò chơi mới được bắt đầu, chỉ cần gọi lại phương thức init này.
Điều này cung cấp cho chúng tôi đoạn mã sau cho lớp Snake của chúng tôi:
Trong phương thức init, bạn có thể xác định các thuộc tính khác của con rắn, chẳng hạn như con trỏ tới đầu và con trỏ tới đuôi. Mảng phần tử sẽ lưu trữ tất cả các phần tử của con rắn tại một thời điểm nhất định. Thuộc tính điểm được sử dụng để lưu trữ điểm cho trò chơi hiện tại, trong khi thuộc tính cấp độ được sử dụng để xác định số điểm được tích lũy để tăng khung hình/giây của trò chơi. Số fps càng cao thì con rắn sẽ di chuyển càng nhanh.
Vì thuộc tính fps biểu thị số khung hình trên giây nên chúng ta cần có thuộc tính fpsinterval có giá trị bằng kết quả chia 1 giây (hoặc 1.000 mili giây) cho số khung hình/giây mong muốn.
Nguyên tắc của trò chơi Rắn săn mồi rất đơn giản: bạn phải hướng dẫn con rắn sử dụng bốn mũi tên chỉ hướng để nó ăn được số lượng táo tối đa xuất hiện trên bảng. Mỗi lần bạn ăn một quả táo, con rắn sẽ tăng thêm một yếu tố. Khi con rắn lớn lên, bạn sẽ khó tránh khỏi việc chạm vào đuôi của nó. Nếu không, bạn sẽ thua và điểm số sẽ bắt đầu lại từ con số 0. Tất nhiên, mỗi khi bạn ăn một quả táo, bạn sẽ ghi được một điểm.
Cần chỉ ra rằng phiên bản Snake mà chúng tôi sắp triển khai là phiên bản mà việc chạm vào các cạnh của bàn cờ không khiến bạn thua cuộc. Nó chỉ khiến bạn nghiêng sang phía đối diện. Phiên bản thứ hai của trò chơi Snake đã được Nokia triển khai theo cách này.
Vì con rắn phải ăn một quả táo nên chúng ta cần hiển thị quả táo này lên bảng một cách ngẫu nhiên, chú ý không tạo ra quả táo trực tiếp trên một phần tử của con rắn.
Điều này cung cấp cho chúng ta phương thức generatefood sau cho lớp Snake của chúng ta:
Lớp Rắn của chúng tôi đang tiến triển và bây giờ chúng tôi cần tạo một phương thức để hiển thị con rắn trên màn hình. Chúng tôi cũng cần hiển thị số điểm của người chơi tại một thời điểm nhất định và cuối cùng, hiển thị quả táo sẽ ăn. Vị trí của quả táo được lưu trữ trong thuộc tính thực phẩm của lớp Rắn.
Để hiển thị Rắn trên màn hình, tôi đang sử dụng API Canvas của HTML5.
Tôi sẽ sử dụng các bản vẽ nguyên thủy của API này để vẽ các hình chữ nhật thể hiện các thành phần khác nhau của con rắn cũng như quả táo để ăn. Tôi sẽ tô màu khác cho quả táo và con rắn để người chơi có thể phân biệt giữa chúng.
Điều này cung cấp đoạn mã sau cho phương thức vẽ của lớp Snake của chúng tôi:
Bây giờ chúng ta có một con rắn mà chúng ta có thể hiển thị trên màn hình. Tất cả điều này đều rất tốt, nhưng chúng ta cần thêm sự hỗ trợ cho chuyển động của con rắn. Như đã giải thích ở trên, con rắn di chuyển dọc theo vectơ tọa độ (dirx, diry). Vì vậy, mỗi lần chúng ta gọi phương thức di chuyển mà tôi định xác định ở đây, con rắn sẽ di chuyển một lượng như nhau.
Trong phương pháp di chuyển này, chúng tôi kiểm tra xem tọa độ của đầu con rắn có tương ứng với tọa độ của quả táo được ăn hay không. Nếu vậy thì con rắn vừa ăn quả táo. Người chơi ghi được một điểm, nhưng quan trọng hơn, chúng ta cần thực hiện bốn hành động:
Tuy nhiên, trong phương thức di chuyển, chúng ta cần kiểm tra xem người chơi có mắc lỗi khi chạm đầu vào một phần tử của con rắn hay không. Nếu đúng như vậy, trò chơi sẽ thua và chúng ta sẽ bắt đầu lại từ đầu! Để làm điều này, chúng ta gọi phương thức init của lớp Snake được trình bày ở trên.
Bây giờ, chúng ta cần hoàn thành phương pháp di chuyển bằng cách di chuyển con rắn. Để làm điều này, chúng ta thêm dirx và diry vào tọa độ đầu con rắn. Điều này cho chúng ta một cái đầu mới để thêm vào. Bạn cũng sẽ nhận thấy rằng việc di chuyển con rắn được thực hiện một cách thông minh bằng cách loại bỏ đuôi mỗi lần và thêm một đầu mới. Điều này tránh phải cập nhật vị trí của tất cả các phần tử của con rắn.
Kết thúc bằng cách nhớ cập nhật phần đầu mới. Ngẫu nhiên, bạn cũng sẽ nhận thấy rằng khi đầu con rắn vượt qua ranh giới của bảng, chúng ta sẽ làm cho nó di chuyển sang phía đối diện của bảng. Điều này áp dụng cho cả chiều rộng và chiều dài.
Điều này cung cấp cho chúng tôi đoạn mã sau cho phương thức di chuyển:
Con rắn của chúng tôi có thể được hiển thị trên màn hình. Con rắn của chúng ta có thể được di chuyển bằng cách gọi phương thức di chuyển của nó. Chúng ta đang thiếu gì?
Chúng tôi đang thiếu việc triển khai GameLoop của trò chơi!
Nếu không có GameLoop này, nó sẽ gọi các phương thức di chuyển và vẽ đều đặn, Rắn sẽ không thể di chuyển. Trong phần tiếp theo, chúng tôi sẽ chỉ cho bạn cách triển khai GameLoop đúng cách trong JavaScript, để trình duyệt gọi nó khi thấy phù hợp để không chặn luồng hiển thị của trang web trò chơi.
Để thực hiện việc này, chúng ta sẽ sử dụng phương thức requestAnimationFrame của cửa sổ đối tượng JavaScript tiêu chuẩn. Sau đó, trình duyệt sẽ điều chỉnh tốc độ khung hình/giây tối đa mà nó có thể hỗ trợ cho phù hợp với máy tính hoặc điện thoại thông minh nơi trang web sẽ được sử dụng.
Trong phương pháp vòng lặp trò chơi của chúng tôi, sau đó chúng tôi sẽ loại bỏ mối tương quan giữa số khung hình/giây được trình duyệt hỗ trợ với số khung hình/giây mà chúng tôi muốn di chuyển con rắn của mình. Chúng ta sẽ chỉ gọi các phương thức di chuyển và vẽ khi chúng ta ở trong phạm vi khung hình/giây được xác định trước đó.
Điều quan trọng là phải cập nhật tọa độ của vectơ chuyển động của con rắn theo trạng thái của bốn phím định hướng: lên, xuống, trái và phải.
Cuối cùng, chúng tôi gọi GameLoop, giao cho trình duyệt nhiệm vụ chọn thời điểm tốt nhất để thực hiện điều đó. Điều này cung cấp cho chúng tôi đoạn mã sau cho GameLoop:
Để cho phép Rắn di chuyển theo các phím định hướng mà người chơi nhấn, chúng tôi sử dụng các sự kiện keydown và keyup. Đối với mỗi sự kiện này, chúng ta sẽ gọi một phương thức của lớp Snake. Về mặt logic, đây sẽ là nút nhấn cho sự kiện nhấn phím và nhấn nút cho sự kiện nhấn phím.
Chúng tôi cập nhật giá trị của các thuộc tính lớp Snake được liên kết tùy theo những gì người chơi thực hiện với các khóa này. Như bạn có thể thấy, chúng tôi không chặn trò chơi bằng cách cập nhật trực tiếp vị trí của con rắn. Thay vào đó, chúng tôi cập nhật trạng thái trong phương thức gameloop, được gọi đều đặn.
Để hoàn thành trò chơi Rắn săn mồi này, chúng ta cần tập hợp các yếu tố khác nhau. Chúng tôi truy xuất đối tượng Canvas thông qua ID của nó. Sau đó, chúng tôi thu được bối cảnh 2D được liên kết với Canvas này. Áp dụng các kích thước mong muốn. Chúng tôi tạo một đối tượng Snake, chuyển các giá trị mong đợi khác nhau dưới dạng tham số, bao gồm số lượng ô trên bảng.
Thêm trình xử lý sự kiện cho các sự kiện keydown và keyup.
Cuối cùng, tất cả những gì còn lại cần làm là gọi vòng lặp trò chơi Snake của chúng tôi một lần để bắt đầu trò chơi. Điều này cung cấp cho chúng tôi mã hoàn chỉnh sau đây cho trò chơi Snake nổi tiếng được tạo bằng API Canvas và cặp đôi Web HTML5/JavaScript cực kỳ nguy hiểm:
Snake của chúng ta đã hoàn tất, đã đến lúc thử nghiệm nó trên trình duyệt Web để xem liệu phép thuật Snake có hoạt động trở lại hay không, giống như khi Nokia thống trị thế giới di động một cách ngoạn mục:
Từ trò chơi Snake này, bạn có thể hình dung ra một số cải tiến có thể có. Ví dụ: bạn có thể thêm âm thanh mỗi khi con rắn ăn quả táo. Bạn có thể sử dụng API lưu trữ web của HTML5 để lưu trữ điểm cao cục bộ của người chơi. Bằng cách này, khi người chơi đạt điểm cao, bạn có thể hiển thị thông báo chúc mừng. Khả năng là vô tận và giới hạn duy nhất của bạn, như mọi khi trong lập trình, là trí tưởng tượng của bạn.
Hướng dẫn này cũng có thể được xem trên YouTube trên kênh SSaurel:
Cũng được xuất bản ở đây .