核心要點
我從決定嘗試使用PHP和React構建遊戲的那一刻起,就開始思考這個問題。 “我想製作一個多人經濟類游戲,類似於《星露穀物語》,但沒有交友方面的內容,並且擁有玩家驅動的經濟系統。” 問題是,我對多人遊戲的動態性,或者如何思考和實現基於玩家的經濟系統一無所知。
我甚至不確定自己是否了解足夠的React知識來證明使用它的合理性。我的意思是,我最初的界面——我非常關注服務器和遊戲的經濟方面——非常適合React。但是當我開始製作耕作/互動方面的內容時呢?我喜歡圍繞經濟系統構建等距界面的想法。
我曾經觀看過dead_lugosi的演講,她描述了用PHP構建中世紀遊戲的過程。 Margaret激勵了我,那次演講是我寫一本關於JS遊戲開發書籍的原因之一。我決心要寫下我的經驗。也許其他人也可以從我的錯誤中學習。
(本部分的代碼可在以下地址找到:github.com/assertchris-tutorials/sitepoint-making-games/tree/part-1。我已經在PHP 7.1和最新版本的Google Chrome中對其進行了測試。)
後端設置
我首先搜索的是關於構建多人經濟系統的指導。我找到一個優秀的Stack Overflow帖子,其中人們解釋了需要考慮的各種事情。在我意識到我可能從錯誤的地方開始之前,我已經看了一半了。 “首先:我需要一個PHP服務器。我將有一堆React客戶端,所以我想要一個能夠處理高並發(甚至可能是WebSockets)的東西。它需要是持久性的:即使玩家不在線,事情也必須發生。”
我開始設置一個異步PHP服務器——來處理高並發並支持WebSockets。我添加了我最近使用PHP預處理器的工作,使事情更清晰,並創建了前幾個端點。
來自config.pre
:
$host = new Aerys\Host(); $host->expose("*", 8080); $host->use($router = Aerys\router()); $host->use($root = Aerys\root(.."/public")); $web = process .."/routes/web.pre"; $web($router); $api = process .."/routes/api.pre"; $api($router);
我決定對應用程序的HTTP和WebSocket部分使用Aerys。這段代碼與Aerys文檔看起來非常不同,但這是因為我對所需內容有很好的了解。
運行Aerys應用程序的通常過程是使用類似這樣的命令:
vendor/bin/aerys -d -c config.php
有很多代碼需要重複,而且它沒有處理我想使用PHP預處理的事實。我創建了一個加載器文件。
來自loader.php
:
return Pre\processAndRequire(__DIR__ . "/config.pre");
然後我安裝了我的依賴項。這是來自composer.json
:
"require": { "amphp/aerys": "dev-amp_v2", "amphp/parallel": "dev-master", "league/container": "^2.2", "league/plates": "^3.3", "pre/short-closures": "^0.4.0" }, "require-dev": { "phpunit/phpunit": "^6.0" },
我想使用amphp/parallel
將阻塞代碼從異步服務器中移出,但它無法與amphp/aerys
的穩定標籤一起安裝。這就是我使用dev-amp_v2
分支的原因。
我認為包含某種模板引擎和服務定位器是個好主意。我選擇了PHP League的每個版本。最後,我添加了pre/short-closures
,既用於處理config.pre
中的自定義語法,也用於我之後計劃使用的短閉包……
然後我開始創建路由文件。來自routes/web.pre
:
use Aerys\Router; use App\Action\HomeAction; return (Router $router) => { $router->route( "GET", "/", new HomeAction ); };
以及來自routes/api.pre
:
use Aerys\Router; use App\Action\Api\HomeAction; return (Router $router) => { $router->route( "GET", "/api", new HomeAction ); };
雖然是簡單的路由,但這有助於我測試config.pre
中的代碼。我決定讓這些路由文件返回閉包,這樣我就可以向它們傳遞一個類型化的$router
,它們可以向其中添加自己的路由。最後,我創建了兩個(類似的)操作。
來自app/Actions/HomeAction.pre
:
namespace App\Action; use Aerys\Request; use Aerys\Response; class HomeAction { public function __invoke(Request $request, Response $response) { $response->end("hello world"); } }
最後的潤色是添加快捷腳本,以啟動Aerys服務器的開發和生產版本。
來自composer.json
:
"scripts": { "dev": "vendor/bin/aerys -d -c loader.php", "prod": "vendor/bin/aerys -c loader.php" }, "config": { "process-timeout": 0 },
完成所有這些後,我可以啟動一個新的服務器,只需鍵入以下命令即可訪問http://127.0.0.1:8080:
composer dev
前端設置
“好的,既然我已經讓PHP方面的事情相對穩定了;我該如何構建ReactJS文件呢?也許我可以使用Laravel Mix……?”
我不太想創建一個全新的構建鏈,而且Mix也已被重建為可在非Laravel項目中良好工作。雖然配置和擴展相對容易,但它默認情況下更偏向VueJS。
我首先要做的是安裝一些NPM依賴項。來自package.json
:
"devDependencies": { "babel-preset-react": "^6.23.0", "bootstrap-sass": "^3.3.7", "jquery": "^3.1.1", "laravel-mix": "^0.7.5", "react": "^15.4.2", "react-dom": "^15.4.2", "webpack": "^2.2.1" },
Mix使用Webpack來預處理和捆綁JS和CSS文件。我還需要安裝React和相關的Babel庫來構建jsx文件。最後,我添加了Bootstrap文件,以獲得一些默認樣式。
Mix自動加載自定義配置文件,所以我添加了以下內容。來自webpack.mix.js
:
let mix = require("laravel-mix") // load babel presets for jsx files mix.webpackConfig({ "module": { "rules": [ { "test": /jsx$/, "exclude": /(node_modules)/, "loader": "babel-loader" + mix.config.babelConfig(), "query": { "presets": [ "react", "es2015", ], }, }, ], }, }) // set up front-end assets mix.setPublicPath("public") mix.js("assets/js/app.jsx", "public/js/app.js") mix.sass("assets/scss/app.scss", "public/css/app.css") mix.version()
我需要告訴Mix如何處理jsx文件,所以我添加了與通常放在.babelrc
中的配置相同的配置。我計劃讓單個JS和CSS入口點進入應用程序的各個部分。
注意:未來版本的Mix將內置支持構建ReactJS資產。屆時,可以刪除mix.webpackConfig
代碼。
再一次,我創建了一些快捷腳本,以節省大量的打字工作。來自package.json
:
$host = new Aerys\Host(); $host->expose("*", 8080); $host->use($router = Aerys\router()); $host->use($root = Aerys\root(.."/public")); $web = process .."/routes/web.pre"; $web($router); $api = process .."/routes/api.pre"; $api($router);
所有三個腳本都使用了Webpack變量命令,但它們在除此之外的操作方面有所不同。 dev
構建了JS和CSS文件的調試版本。 -w
開關啟動了Webpack監視器(以便可以部分重建捆綁包)。 -p
開關啟用了精簡的生產版本的捆綁包。
由於我使用了捆綁版本控制,所以我需要一種方法來引用類似/js/app.60795d5b3951178abba1.js
的文件,而無需知道哈希值。我注意到Mix喜歡創建清單文件,所以我製作了一個輔助函數來查詢它。來自helpers.pre
:
vendor/bin/aerys -d -c config.php
Aerys知道如何在它們以$val = yield $promise
的形式出現時處理promise,所以我使用了Amp的Promise實現。讀取並解碼文件後,我可以查找匹配的文件路徑。我調整了HomeAction
。來自app/Actions/HomeAction.pre
:
return Pre\processAndRequire(__DIR__ . "/config.pre");
我意識到我可以繼續創建返回promise的函數,並以這種方式使用它們來保持代碼的異步性。這是我的JS代碼,來自assets/js/component.jsx
:
"require": { "amphp/aerys": "dev-amp_v2", "amphp/parallel": "dev-master", "league/container": "^2.2", "league/plates": "^3.3", "pre/short-closures": "^0.4.0" }, "require-dev": { "phpunit/phpunit": "^6.0" },
……以及來自assets/js/app.jsx
:
use Aerys\Router; use App\Action\HomeAction; return (Router $router) => { $router->route( "GET", "/", new HomeAction ); };
畢竟,我只是想看看Mix是否會編譯我的jsx文件,以及我是否可以使用異步mix
函數再次找到它們。事實證明它有效!
注意:每次都使用mix
函數是很昂貴的,特別是如果我們正在加載相同的文件。相反,我們可以在服務器引導階段加載所有模板,並在需要時從操作內部引用它們。我們啟動Aerys的配置文件可以返回一個promise(例如Amp\all
給我們的那種),因此我們可以在服務器啟動之前解析所有模板。
使用WebSockets連接
我幾乎已經設置好了。最後要做的是通過WebSockets連接後端和前端。我發現這相對簡單,使用一個新類。來自app/Socket/GameSocket.pre
:
use Aerys\Router; use App\Action\Api\HomeAction; return (Router $router) => { $router->route( "GET", "/api", new HomeAction ); };
……以及對web路由的輕微修改(來自routes/web.pre
):
namespace App\Action; use Aerys\Request; use Aerys\Response; class HomeAction { public function __invoke(Request $request, Response $response) { $response->end("hello world"); } }
現在,我可以更改JS以連接到此WebSocket,並將消息發送到連接到它的每個人。來自assets/js/component.jsx
:
"scripts": { "dev": "vendor/bin/aerys -d -c loader.php", "prod": "vendor/bin/aerys -c loader.php" }, "config": { "process-timeout": 0 },
當我創建一個新的Component
對象時,它將連接到WebSocket服務器,並為新消息添加一個事件監聽器。我添加了一些調試代碼——以確保它能夠正確連接,並發送新的消息。
我們稍後會詳細介紹PHP和WebSockets,別擔心。
總結
在本部分中,我們研究瞭如何設置一個簡單的異步PHP Web服務器,如何在非Laravel項目中使用Laravel Mix,甚至如何使用WebSockets將後端和前端連接在一起。
哇!涵蓋了很多內容,而且我們還沒有編寫一行遊戲代碼。加入我在第二部分,我們將開始構建遊戲邏輯和React界面。
(本文由Niklas Keller同行評審。感謝所有SitePoint的同行評審者,使SitePoint的內容達到最佳狀態!)
使用ReactJS和PHP進行遊戲開發的常見問題解答(FAQ)
ReactJS和PHP在遊戲開發中具有高度的兼容性。 ReactJS是一個JavaScript庫,非常適合構建用戶界面,尤其適用於單頁應用程序。它允許快速、響應迅速的網頁設計。另一方面,PHP是一種服務器端腳本語言,非常適合後端開發。它可以處理數據庫、用戶身份驗證和服務器端邏輯。當一起使用時,ReactJS可以處理前端,創建動態且交互式用戶界面,而PHP則管理後端。
是的,你可以在ReactJS遊戲中使用PHP進行遊戲邏輯。雖然ReactJS處理用戶界面,但PHP可以在服務器端管理遊戲邏輯。這包括處理數據、管理用戶會話和控制遊戲規則。這種關注點分離允許更井然有序且高效的開發過程。
ReactJS為遊戲開發提供了許多好處。它的虛擬DOM允許高效的更新和渲染,使遊戲運行更流暢。它還支持可重用的組件,這可以大大加快開發時間。此外,ReactJS擁有龐大的社區和豐富的資源,使查找問題的解決方案或學習新技術更容易。
PHP在遊戲開發中具有多項優勢。它是一種服務器端語言,這意味著它可以處理數據管理、用戶身份驗證和服務器端遊戲邏輯。 PHP也很容易學習,語法簡單,並且擁有龐大的開發者社區。它也具有高度的可擴展性,使其適合可能需要處理大量用戶的遊戲。
要開始使用ReactJS和PHP開發遊戲,你首先需要學習這兩種語言的基礎知識。有很多在線資源和教程可用。一旦你熟悉了這些語言,你可以從構建簡單的遊戲開始。這可以是一個基本的文本遊戲或一個簡單的益智遊戲。隨著你獲得更多經驗,你可以開始構建更複雜的遊戲。
是的,有幾個資源和庫可以幫助使用ReactJS和PHP進行遊戲開發。對於ReactJS,像React Game Kit和React Game Engine這樣的庫非常有用。對於PHP,你可能會發現像PHP-SDL或Wyvern這樣的庫很有用。此外,在線還有很多教程、指南和論壇,你可以在那裡學習更多知識並獲得幫助。
是的,你可以使用ReactJS和PHP構建多人遊戲。 ReactJS可以處理用戶界面,而PHP可以管理服務器端邏輯,包括管理玩家會話和跨多個客戶端同步遊戲狀態。
使用ReactJS和PHP,你可以構建各種各樣的遊戲。這包括簡單的文本遊戲、益智遊戲、平台遊戲、角色扮演遊戲,甚至是多人在線遊戲。可能性是巨大的,限制實際上是你的想像力和技能水平。
在一個使用ReactJS和PHP開發的遊戲中,可以使用服務器端的PHP處理數據。這可以包括玩家數據、遊戲狀態、分數等等。這些數據可以存儲在數據庫中,並且可以使用PHP與這個數據庫進行交互,根據需要檢索和更新數據。
在一個使用ReactJS開發的遊戲中,可以使用React的事件處理系統處理用戶輸入。這可以包括鼠標點擊、鍵盤按鍵和触摸事件。 React的事件處理系統功能強大且靈活,允許你輕鬆控制遊戲如何響應用戶輸入。
以上是與React和PHP的遊戲開發:它們的兼容性如何?的詳細內容。更多資訊請關注PHP中文網其他相關文章!