Bạn có thể xây dựng trò chơi bằng php không?

Tôi là nhà phát triển chính của 2 trò chơi trình duyệt thành công vừa phải cách đây vài năm và dự định sẽ sớm làm việc trên một trò chơi mới. Vào thời điểm đó, tôi đã viết chúng bằng PHP thuần túy [không có công cụ mẫu hoặc bất kỳ thứ gì tương tự]

Tôi muốn bắt đầu làm một trò chơi mới, nhưng đã rời khỏi thế giới phát triển web một thời gian. Đọc xung quanh, tôi nghe rất nhiều điều hay về Rails, Django, Node. js, v.v. , mà tôi không có kinh nghiệm [mặc dù tôi biết khá rõ về Python, Javascript và những thứ khác]

Vì vậy, câu hỏi của tôi là như sau - nếu tôi đi theo con đường cũ của mình và tiếp tục với PHP, liệu tôi có đang tự làm khó mình không?

Ngoài ra, có ai có bất kỳ gợi ý nào liên quan đến việc phát triển cụ thể các trò chơi trình duyệt bằng các công cụ hiện đại hơn này không?

Trước khi tôi chỉ cho bạn cách làm, tôi muốn cho bạn thấy kết quả. Không được đánh bóng, vì vậy hãy hạ thấp kỳ vọng của bạn ngay bây giờ. Tôi chỉ muốn một POC đủ tốt để được hiển thị ở đây 😬

Bạn có thể xem cách chơi trên video dưới đây

Tuyệt, phải. ?

Tôi sẽ chỉ cho bạn mã trông như thế nào và tôi đã sử dụng công cụ nào. Hy vọng rằng nó sẽ thu hút sự chú ý của bạn đủ để thấy tiện ích mở rộng này có được lực kéo

Trước bất cứ điều gì, hãy để tôi nói với bạn một chút về bản thân raylib

raylib

Được viết bằng ngôn ngữ C, Raylib được định nghĩa là "một thư viện đơn giản và dễ sử dụng để thưởng thức lập trình trò chơi điện tử"

Nó cung cấp các chức năng rất đơn giản để thao tác với video, âm thanh, đầu vào đọc như bàn phím, chuột hoặc gamepad. Nó cũng hỗ trợ kết xuất 2d và 3d. Là một thư viện khá đầy đủ

Dưới đây là tổng quan về kiến ​​trúc của Raylib. Nó hy vọng rằng bạn sẽ viết trò chơi, công cụ hoặc công cụ của mình trên các mô-đun của Raylib. Các mô-đun cung cấp các tính năng để xử lý những thứ như máy ảnh, kết cấu, văn bản, hình dạng, mô hình, âm thanh, toán học…

[email protected]:joseph-montanez/raylib-php.git $ cd raylib-php/ $ phpize $ ./configure $ make

Nó chỉ được biên dịch tốt với PHP 7. 4 cho tôi. Vì vậy, hãy chắc chắn rằng bạn có phiên bản php phù hợp

Tiện ích mở rộng này nhằm mục đích cung cấp các ràng buộc cho thư viện C để chúng tôi có thể viết các trò chơi tương tự bằng PHP

Tất nhiên vì thư viện C sẽ không cung cấp các tính năng dành riêng cho trò chơi như vật lý và các tính năng khác. Vì vậy, những thứ như vậy sẽ phải được phát triển ở phía PHP

Phần mở rộng này chưa hoàn thành. Bạn có thể kiểm tra MAPPING. md từ kho lưu trữ chính thức để hiểu những gì đã hoàn thành

Mặc dù nó chưa hoàn chỉnh nhưng tôi đã quyết định chơi một chút với nó và theo những gì tôi thấy thì nó đã hoạt động khá tốt

Một trò chơi rắn đơn giản

Mặc dù "Snake" là một trò chơi đơn giản nhưng tôi đã quyết định không triển khai nó hoàn toàn. Mục tiêu chính của tôi ở đây là có một công cụ chạy đủ tốt để kiểm tra một số tính năng cơ bản từ tiện ích mở rộng

Tôi đã chọn sau đó một vài yêu cầu để thực hiện

  • Con rắn phải liên tục di chuyển, nhưng có thể thay đổi hướng
  • Sẽ có một quả được đặt ở một vị trí ngẫu nhiên trên màn hình
  • Khi đầu rắn chạm vào trái cây, năm điều phải xảy ra. trái cây phải bị phá hủy, cơ thể của con rắn phải phát triển, trái cây khác phải được tạo ra, bộ đếm điểm số phải tăng lên một và tốc độ của Rắn cũng tăng lên
  • Khi Snake chạm vào một cạnh cửa sổ, nó sẽ cong sang cạnh đối diện

Phải rõ ràng, nhưng cũng bắt buộc người chơi phải thay đổi hướng của Snake bằng thiết bị đầu vào, chẳng hạn như bàn phím

Hai yêu cầu cực kỳ quan trọng mà tôi chọn không thực hiện là 1] Rắn không được cắn mình. Có nghĩa là nếu vì bất kỳ lý do gì Rắn đánh vào cơ thể của chính nó, trò chơi sẽ kết thúc. Và 2] Con rắn đó không thể thay đổi ngay lập tức theo hướng ngược lại của nó. Vì vậy, khi bạn đang đi về bên phải, chuyển sang hướng bên trái, trước tiên bạn phải đi lên hoặc đi xuống

Hai yêu cầu đó không được thực hiện vì chúng hoàn toàn là thuật toán và sẽ không bổ sung nhiều vào thử nghiệm của chính tiện ích mở rộng

Thực hiện

Việc thực hiện trò chơi này có hai thành phần. Vòng lặp trò chơi và Trạng thái trò chơi

Vòng lặp trò chơi chịu trách nhiệm cập nhật trạng thái trò chơi dựa trên đầu vào và tính toán của người dùng, sau đó vẽ trạng thái này trên màn hình. Đối với điều này, tôi đã tạo một lớp có tên "GameLoop"

Trạng thái trò chơi giữ ảnh chụp nhanh của trò chơi. Nó chứa những thứ như điểm số của người chơi, tọa độ x, y của trái cây, tọa độ x, y từ Snake và tất cả các ô vuông tạo thành cơ thể của nó. Đối với cái này, một lớp “GameState” đã được tạo

Đây là cách họ trông giống như

Vòng lặp trò chơi

Lớp GameLoop khởi tạo hệ thống và tạo một vòng lặp thực hiện hai bước trên mỗi lần lặp. cập nhật trạng thái và vẽ trạng thái

Vì vậy, trong hàm tạo, tôi chỉ khởi tạo chiều rộng và chiều cao của canvas và khởi tạo GameState

Là tham số cho GameState, tôi đã chuyển chiều rộng và chiều cao chia cho kích thước ô mong muốn [trong trường hợp của tôi là 30 pixel]. Các giá trị như vậy đại diện cho tọa độ X và Y tối đa mà GameState có thể hoạt động với. Chúng tôi sẽ kiểm tra chúng sau

// GameLoop.php
final class GameLoop
{
  // ...
  public function __construct[
    int $width,
    int $height
  ] {
    $this->width = $width;
    $this->height = $height;

    // 30
    $s = self::CELL_SIZE;
    $this->state = new GameState[
      [int] [$this->width / $s],
      [int] [$this->height / $s]
    ];
  }
  // ...
}

Sau đó, một phương thức công khai có tên start[] sau đó sẽ sinh ra một Cửa sổ, đặt tốc độ khung hình và tạo một vòng lặp vô hạn - vâng, một loại while [true] - trước tiên sẽ kích hoạt một phương thức riêng tư update[] và sau đó là một phương thức draw[

// ...
public function start[]: void
{
  Window::init[
    $this->width,
    $this->height,
    'PHP Snake'
  ];
  Timming::setTargetFPS[60];

  while [
    $this->shouldStop ||
    !Window::shouldClose[]
  ] {
    $this->update[];
    $this->draw[];
  }
}
// ...

Phương thức update[] sẽ chịu trách nhiệm cập nhật thể hiện trạng thái trò chơi. Nó thực hiện điều này bằng cách đọc đầu vào của người dùng [nhấn phím] và thực hiện những việc như kiểm tra va chạm, v.v.

Dựa trên các tính toán được thực hiện trong phương thức update[], nó sẽ kích hoạt các thay đổi trạng thái trên phiên bản GameState

private function update[]: void
{
  $head = $this->state->snake[0];
  $recSnake = new Rectangle[
    [float] $head['x'],
    [float] $head['y'],
    1,
    1,
  ];

  $fruit = $this->state->fruit;
  $recFruit = new Rectangle[
    [float] $fruit['x'],
    [float] $fruit['y'],
    1,
    1,
  ];

  // Snake bites fruit
  if [
    Collision::checkRecs[
      $recSnake,
      $recFruit
    ]
  ] {
    $this->state->score[];
  }

  // Controls step speed
  $now = microtime[true];
  if [
    $now - $this->lastStep
      > [1 / $this->state->score]
  ] {
    $this->state->step[];
    $this->lastStep = $now;
  }

  // Update direction if necessary
  if [Key::isPressed[Key::W]] {
    $this->state->direction = GameState::DIRECTION_UP;
  } else if [Key::isPressed[Key::D]] {
    $this->state->direction = GameState::DIRECTION_RIGHT;
  } else if [Key::isPressed[Key::S]] {
    $this->state->direction = GameState::DIRECTION_DOWN;
  } else if [Key::isPressed[Key::A]] {
    $this->state->direction = GameState::DIRECTION_LEFT;
  }
}

Cuối cùng là phương thức draw[]. Nó sẽ đọc các thuộc tính trên GameState và chỉ cần in chúng. Áp dụng tất cả các tỷ lệ và quy mô

Theo cách tôi đã xây dựng điều này, hy vọng rằng tọa độ X sẽ nằm trong khoảng từ 0 đến [chiều rộng chia cho kích thước ô] và tọa độ Y sẽ nằm trong khoảng từ 0 đến [chiều cao chia cho kích thước ô]. Bằng cách nhân từng tọa độ với "kích thước ô", chúng ta có được một bản vẽ được chia tỷ lệ đủ tốt mà không trộn lẫn thao tác và bản vẽ trạng thái của chúng ta

Khá đơn giản. Hình như sau

private function draw[]: void
{
  Draw::begin[];

  // Clear screen
  Draw::clearBackground[
    new Color[255, 255, 255, 255]
  ];

  // Draw fruit
  $x = $this->state->fruit['x'];
  $y = $this->state->fruit['y'];
  Draw::rectangle[
    $x * self::CELL_SIZE,
    $y * self::CELL_SIZE,
    self::CELL_SIZE,
    self::CELL_SIZE,
    new Color[200, 110, 0, 255]
  ];

  // Draw snake's body
  foreach [
    $this->state->snake as $coords
  ] {
    $x = $coords['x'];
    $y = $coords['y'];
    Draw::rectangle[
      $x * self::CELL_SIZE,
      $y * self::CELL_SIZE,
      self::CELL_SIZE,
      self::CELL_SIZE,
      new Color[0,255, 0, 255]
    ];
  }

  // Draw score
  $score = "Score: {$this->state->score}";
  Text::draw[
    $score,
    $this->width - Text::measure[$score, 12] - 10,
    10,
    12,
    new Color[0, 255, 0, 255]
  ];

  Draw::end[];
}

Có một số thứ khác tôi đã thêm vào để gỡ lỗi nhưng tôi muốn bỏ chúng ra khỏi bài viết này

Sau đó là quản lý nhà nước. Đây là trách nhiệm của GameState. Kiểm tra nó ra

Trạng thái trò chơi

GameState đại diện cho mọi thứ tồn tại trong trò chơi. Điểm số, đối tượng như người chơi và các loại trái cây

Điều này có nghĩa là bất cứ khi nào người chơi phải di chuyển hoặc phải ăn trái cây, điều này sẽ xảy ra bên trong GameState.

Đối với cơ thể của Rắn, tôi quyết định có một mảng có tọa độ [x, y] bên trong. Và tôi coi phần tử đầu tiên của mảng [chỉ số 0] là đầu rắn. Việc thêm nhiều phần tử [x, y] vào mảng này sẽ làm tăng kích thước cơ thể của Rắn

Tuy nhiên, trái cây là một cặp tọa độ [x, y] duy nhất. Như tôi mong đợi mỗi lần chỉ có một quả trên màn hình

Hàm tạo của lớp GameState sẽ khởi tạo các đối tượng như vậy với tọa độ ngẫu nhiên. Nó trông như thế này

// GameState.php
final class GameState
{
  public function __construct[
    int $maxX,
    int $maxY
  ] {
    $this->maxX = $maxX;
    $this->maxY = $maxY;

    $this->snake = [
        $this->craftRandomCoords[],
    ];

    $this->fruit = $this->craftRandomCoords[];
  }
}

Để tăng kích thước cơ thể của Rắn, tôi đã tạo một phương thức riêng có tên là incrementBody[] để thêm một cái đầu mới vào cơ thể của Rắn. Cái đầu mới này sẽ xem xét hướng hiện tại mà Rắn đang hướng tới. [trái, phải, lên hoặc xuống]

Để thêm một cái đầu mới, tôi chỉ cần sao chép cái đầu hiện tại, cập nhật tọa độ của nó dựa trên hướng hiện tại và hợp nhất nó với cơ thể Snake chiếm chỉ số bằng không

private function incrementBody[]: void
{
  $newHead = $this->snake[0];

  // Adjusts head direction
  switch [$this->direction] {
    case self::DIRECTION_UP:
      $newHead['y']--;
      break;
    case self::DIRECTION_DOWN:
      $newHead['y']++;
      break;
    case self::DIRECTION_RIGHT:
      $newHead['x']++;
      break;
    case self::DIRECTION_LEFT:
      $newHead['x']--;
      break;
  }

  // Adds new head, in front
  // of the whole the body
  $this->snake = array_merge[
    [$newHead],
    $this->snake
  ];
}

Có sẵn phương thức incrementBody[] giúp việc triển khai phương thức score[] trở nên rất đơn giản, phương thức này chỉ tăng bộ đếm điểm và cơ thể của con rắn. Ngoài ra điểm[] sẽ đặt một loại trái cây mới trong một tọa độ ngẫu nhiên

public function score[]: void
{
  $this->score++;
  $this->incrementBody[];
  $this->fruit = $this->craftRandomCoords[];
}

Điều thú vị là phương thức step[] chịu trách nhiệm di chuyển con rắn

Nếu bạn nhớ kỹ, cách di chuyển của Rắn là đầu của nó sẽ liên tục hướng về một hướng và cơ thể sau đó sẽ chậm lại theo hướng đó. Vì vậy, nếu con rắn có kích thước cơ thể là 3 khối và đang di chuyển xuống dưới, thì phải mất ba bước để nó quay mặt hoàn toàn sang bên trái

Cách tôi đã làm điều này về cơ bản là tăng cơ thể của Rắn một lần nữa [thêm phần đầu mới theo hướng mới] và loại bỏ phần tử cuối cùng khỏi cơ thể rắn. Bằng cách này, kích thước vẫn giữ nguyên, đầu có hướng mới và trên mỗi bước, tọa độ cũ sẽ bị xóa

Tôi cũng đã thêm một số logic để làm cong từ cạnh này sang cạnh khác của màn hình, bạn có thể đọc nó [tôi hy vọng]

________số 8_______

Dán mọi thứ lại với nhau và khởi tạo mọi thứ. Chúng tôi đã sẵn sàng để chơi

Phát triển trò chơi bằng PHP có khả thi không?

Chắc chắn là khả thi hơn trước. Hy vọng ít hơn ngày mai

Tiện ích mở rộng cung cấp liên kết thực sự thú vị nhưng vẫn chưa hoàn thành. Nếu bạn biết một chút mã C, bạn có thể biến tương lai thành một nơi tốt hơn để phát triển trò chơi bằng PHP bằng cách đóng góp cho nó. Đây là danh sách nơi bạn có thể tìm thấy các chức năng vẫn cần triển khai

PHP vẫn bị chặn theo mặc định, vì vậy I/O nặng nên được xử lý thông minh. Có thể sử dụng thư viện này cùng với Vòng lặp sự kiện hoặc sử dụng các luồng từ tiện ích mở rộng Parallel. Có lẽ bạn sẽ phải tự mình phát triển thứ gì đó để đạt được điều này

Điều làm tôi khó chịu nhất cho đến nay là các trò chơi di động được viết bằng php có thể như thế nào. Không có cách nào đơn giản để đóng gói các trò chơi như vậy thành các chương trình nhị phân. Vì vậy, người chơi sẽ phải cài đặt PHP và biên dịch tiện ích mở rộng Raylib để chơi

Nhưng như tôi đã đề cập, những bước đầu tiên đã được thực hiện. Vì vậy, về mặt kỹ thuật, việc đạt được điều này đã dễ dàng hơn trước đây

Xin chân thành cảm ơn Joseph Montanez. Tiện ích mở rộng của bạn thực sự đã truyền cảm hứng cho tôi và tôi hy vọng bài đăng này sẽ tiếp cận và kích hoạt nhiều nhà phát triển hơn để hỗ trợ sự phát triển của nó

Tôi có thể xây dựng gì bằng PHP?

PHP có thể làm gì? .
PHP có thể tạo nội dung trang động
PHP có thể tạo, mở, đọc, ghi, xóa và đóng tệp trên máy chủ
PHP có thể thu thập dữ liệu biểu mẫu
PHP có thể gửi và nhận cookie
PHP có thể thêm, xóa, sửa đổi dữ liệu trong cơ sở dữ liệu của bạn
PHP có thể được sử dụng để kiểm soát quyền truy cập của người dùng
PHP có thể mã hóa dữ liệu

Làm cách nào để tạo trò chơi rắn trong PHP?

Để tạo một thể hiện mới của đối tượng Snake, chúng ta chỉ cần chuyển vào chiều rộng và chiều cao của bàn trò chơi. $width = 20; . To render the snake game we pass the snake object to a rendering function.

Bạn có thể sử dụng C ++ để tạo trò chơi không?

Một trong những ngôn ngữ phổ biến nhất để viết công cụ trò chơi là C++ . Ngôn ngữ lập trình C++ kết hợp tốc độ với khả năng sử dụng lập trình hướng đối tượng [OOP] và các mô hình lập trình khác giúp các nhà phát triển tổ chức và thiết kế các dự án phần mềm lớn.

Bạn có thể tạo trò chơi trong Scala không?

Nếu bạn có thể viết Scala, bạn có thể tạo trò chơi . Indigo được cung cấp bởi Scala. js và xây dựng với sbt & Mill.

Chủ Đề