用Swoole來寫個聯機對戰遊戲呀!(五)聯機初始化

寫程式的趙童鞋發表於2019-04-29

聯機邏輯開發進度:□□□□□□□□□□□□

本章結束開發進度:■■□□□□□□□□□□

Swoole開發環境

教程使用Swoole 4.3.0版本開發,但並沒有使用協程等功能,只是使用了WebSocket Server,理論上安裝舊版也是沒問題的。環境需要大家自行安裝,這個也是學習的一個過程。

以下是一些有可能有幫助的資料:

童鞋們也可以像我一樣在Windows使用PHPStorm進行開發,再通過一些方法如共享資料夾WinSCP等工具將專案在CentOS中執行起來。

安裝swoole-ide-helper擴充套件

使用PHPStorm來開發Swoole專案的童鞋,如果不想面向運氣程式設計的話,最好安裝一個swoole-ide-Helper擴充套件來協作開發。

在專案根目錄執行以下命令:

composer require --dev "eaglewu/swoole-ide-helper:dev-master"
複製程式碼

安裝完畢我們就可以愉快地編寫Swoole程式碼了。

服務端基本架構

趙童鞋設想的基本架構需要三個層,他們分別是:

  • 網路層:管理Swoole WebSocket物件,主要負責接收前端訊息,傳遞到邏輯層進行處理。
  • 邏輯層:接收網路層傳遞的訊息,主要負責遊戲房間建立、玩家移動、結束檢測等遊戲邏輯。
  • 資料層:用於管理玩家ID、房間ID、匹配佇列等資料。

管理這三個層分別需要三個類:ServerLogicDataCenter

其中最重要的就是Server類,它的作用就是作為服務端和客戶端的訊息交換中心,我們先來寫一個初始化的Server類,在專案app目錄新建Server.php

  1. 使用物件導向的方式實現一個WebSocket Server類。
  2. 分別繫結startworkerStartopenmessageclose回撥方法
  3. 在類中引入composer自動載入機制。
  4. WebSocket物件設定4個worker程式。

Server類:

<?php
require_once __DIR__ . '/../vendor/autoload.php';

class Server
{
    const HOST = '0.0.0.0';
    const PORT = 8811;
    const CONFIG = [
        'worker_num' => 4,
    ];

    private $ws;

    public function __construct()
    {
        $this->ws = new \Swoole\WebSocket\Server(self::HOST, self::PORT);
        $this->ws->set(self::CONFIG);
        $this->ws->on('start', [$this, 'onStart']);
        $this->ws->on('workerStart', [$this, 'onWorkerStart']);
        $this->ws->on('open', [$this, 'onOpen']);
        $this->ws->on('message', [$this, 'onMessage']);
        $this->ws->on('close', [$this, 'onClose']);
        $this->ws->start();
    }

    public function onStart($server)
    {
        swoole_set_process_name('hide-and-seek');
        echo sprintf("master start (listening on %s:%d)\n",
            self::HOST, self::PORT);
    }

    public function onWorkerStart($server, $workerId)
    {
        echo "server: onWorkStart,worker_id:{$server->worker_id}\n";
    }

    public function onOpen($server, $request)
    {

    }

    public function onClose($server, $fd)
    {

    }

    public function onMessage($server, $request)
    {

    }
}
new Server();
複製程式碼

我們來執行一下Server.php檔案,順便檢驗一下Swoole擴充套件是否執行正常,在專案app目錄下,執行php Server

  • 後面所有啟動Server操作都是基於CentOS環境
[root@localhost app]# php Server.php 
master start (listening on 0.0.0.0:8811)
server: onWorkStart,worker_id:0
server: onWorkStart,worker_id:1
server: onWorkStart,worker_id:2
server: onWorkStart,worker_id:3
複製程式碼

如果輸出以上資訊,就代表Server執行成功。

Logic類和DataCenter類屬於遊戲管理類,在Manager資料夾下新建Logic.phpDataCenter.php檔案,並在Datacenter類中增加一個格式化輸出日誌的log()方法。

Logic類:

<?php
namespace App\Manager;

class Logic
{
}
複製程式碼

DataCenter類:

<?php
namespace App\Manager;

class DataCenter
{
    public static function log($info, $context = [], $level = 'INFO')
    {
        if ($context) {
            echo sprintf("[%s][%s]: %s %s\n", date('Y-m-d H:i:s'), $level, $info,
            		json_encode($context, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
        } else {
            echo sprintf("[%s][%s]: %s\n", date('Y-m-d H:i:s'), $level, $info);
        }
    }
}
複製程式碼

前端初始化

前端我們將會使用Vue框架來開發,專案只使用到了v-ifv-for<template>WebSocket技術。如果沒有接觸過前端框架的童鞋,可以嘗試閱讀官方文件。

在專案根目錄建立frontend資料夾,並在其中建立index.html檔案,進行前端初始化。

  1. 使用CDN的形式引入Vue框架。
  2. 根據Vue官方文件,編寫一個HelloWorld頁面。

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>HideAndSeek</title>
    <script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
    <link rel="icon" href="data:;base64,=">
</head>
<body>

<div id="app">
    {{ message }}
</div>

<script>
    var app = new Vue({
        el: '#app',
        data: {
            message: 'Hello Vue!'
        }
    })
</script>
</body>
</html>
複製程式碼

前端的HelloWorld頁面我們也有了,但是我們要怎麼通過HTTP請求獲取到這個頁面呢?這時候就需要使用SwooleStatic Handler功能。

  1. 根據官方文件新增Swoole Static Handler配置。
  2. Server新增一個監聽埠8812,用於處理HTTP請求。

Server類:

const FRONT_PORT = 8812;
const CONFIG = [
    ...
    'enable_static_handler' => true,
    'document_root' =>
        '/mnt/htdocs/HideAndSeek_teach/frontend',
];

public function __construct()
{
    ...
    $this->ws->listen(self::HOST, self::FRONT_PORT, SWOOLE_SOCK_TCP);
    ...
}
複製程式碼

記得將程式碼中的document_root改為自己專案的前端目錄哦。

新增完以上程式碼後,在虛擬機器中執行Server,並嘗試通過瀏覽器訪問http://虛擬機器ip:8812/index.html瀏覽前端頁面。

用Swoole來寫個聯機對戰遊戲呀!(五)聯機初始化
看到以上畫面就代表訪問成功。

WebSocket初始化

現在專案的服務端有了,前端頁面有了,就差一個橋樑把他們連線起來,這個橋樑就是WebSocket通訊機制,專案使用到了簡單的websock.onmessagewebsock.onopenwebsock.onerrorwebsock.onclose

以下是一些有可能有幫助的資料。

  1. Vue例項新增data屬性websock,在Vue例項建立完畢後,初始化WebSocket連線服務端並繫結上述四個方法。
  2. WebSocket物件建立連線後,立刻傳送訊息到服務端。
  3. 服務端接收到客戶端傳送的訊息後,通過客戶端的fd返回一條訊息。
  4. 服務端增加客戶端連線日誌輸出。
  5. 在頁面關閉時,斷開WebSocket連線。

本章專案初始化就到這裡啦,請童鞋們儘量完成自己的Homework後,再進入下一章的學習。

當前專案結構:

HideAndSeek
├── app
│   ├── Manager
│   │   ├── DataCenter.php
│   │   ├── Game.php
│   │   └── Logic.php
│   ├── Model
│   │   ├── Map.php
│   │   └── Player.php
│   └── Server.php
├── composer.json
├── composer.lock
├── frontend
│   └── index.html
├── test.php
└── vendor
    ├── autoload.php
    └── composer

複製程式碼

用Swoole來寫個聯機對戰遊戲呀!(五)聯機初始化

相關文章