Core points
I started thinking about this from the moment I decided to try building a game with PHP and React. "I want to make a multiplayer economic game, similar to Stardew Valley, but without dating content and have a player-driven economic system." The question is, my dynamics of multiplayer games, or how Thinking about and implementing a player-based economic system is ignorant.
I'm not even sure I know enough React knowledge to justify using it. I mean, my initial interface—I was very focused on the economics of servers and games—is perfect for React. But what when I start making the farming/interactive aspect of things? I like the idea of building isometric interfaces around economic systems.
I have watched a speech by dead_lugosi, who described the process of building a medieval game with PHP. Margaret inspired me, and that speech was one of the reasons why I wrote a book about JS game development. I am determined to write down my experience. Maybe others can learn from my mistakes, too.
(The code for this part can be found at: github.com/assertchris-tutorials/sitepoint-making-games/tree/part-1. I have matched it in PHP 7.1 and the latest version of Google Chrome It was tested. )
Back-end settings
I first searched for guidance on building a multi-person economic system. I found an excellent Stack Overflow post where people explain various things to consider. I've been halfway through before I realize I might have started in the wrong place. "First: I need a PHP server. I'll have a bunch of React clients, so I want something that can handle high concurrency (and maybe even WebSockets). It needs to be persistent: things have to be even if the player is not online. Occurs. ”
I started setting up an asynchronous PHP server - to handle high concurrency and support WebSockets. I added my recent work with PHP preprocessor to make things clearer and created the first few endpoints.
Fromconfig.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);
I decided to use Aerys for the HTTP and WebSocket parts of the application. This code looks very different from the Aerys documentation, but that's because I have a good understanding of what I need.
The usual process of running an Aerys application is to use a command like this:
vendor/bin/aerys -d -c config.php
There is a lot of code to be repeated, and it doesn't handle the fact that I want to preprocess using PHP. I created a loader file.
Fromloader.php
:
return Pre\processAndRequire(__DIR__ . "/config.pre");
Then I installed my dependencies. This is from 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" },
I want to use amphp/parallel
to move the blocking code out of the asynchronous server, but it cannot be installed with the stable tag of amphp/aerys
. This is why I use the dev-amp_v2
branch.
I think it's a good idea to include some kind of template engine and service locator. I chose each version of PHP League. Finally, I added pre/short-closures
, which is used both to handle the custom syntax in config.pre
, and also to the short closures I plan to use later...
Then I started creating the routing file. From routes/web.pre
:
use Aerys\Router; use App\Action\HomeAction; return (Router $router) => { $router->route( "GET", "/", new HomeAction ); };
and from routes/api.pre
:
use Aerys\Router; use App\Action\Api\HomeAction; return (Router $router) => { $router->route( "GET", "/api", new HomeAction ); };
Although it is a simple route, this helps me test the code in config.pre
. I decided to have these routing files return to closures so I could pass them a typed $router
to which they can add their own routes. Finally, I created two (similar) operations.
Fromapp/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"); } }
The final touch is to add shortcut scripts to start the development and production version of the Aerys server.
Fromcomposer.json
:
"scripts": { "dev": "vendor/bin/aerys -d -c loader.php", "prod": "vendor/bin/aerys -c loader.php" }, "config": { "process-timeout": 0 },
After all this I can start a new server and access http://127.0.0.1:8080 by typing the following command:
composer dev
Front-end settings
"Okay, now that I've made things relatively stable on the PHP side; how do I build a ReactJS file? Maybe I can use Laravel Mix…?"
I don't really want to create a brand new build chain, and Mix has also been rebuilt to work well in non-Laravel projects. While configuration and extensions are relatively easy, it is more VueJS-oriented by default.
The first thing I have to do is install some NPM dependencies. From 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 uses Webpack to preprocess and bundle JS and CSS files. I also need to install React and related Babel libraries to build jsx files. Finally, I added the Bootstrap file to get some default styles.
Mix automatically loads custom configuration files, so I added the following. From 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()
I need to tell Mix how to handle jsx files, so I added the same configuration as the ones that are usually placed in .babelrc
. I plan to get a single JS and CSS entry point into various parts of the application.
Note: Future versions of Mix will have built-in support for building ReactJS assets. At that time, the mix.webpackConfig
code can be deleted.
Once again, I created some shortcut scripts to save a lot of typing work. From 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);
All three scripts use Webpack variable commands, but they differ in their operations other than that. dev
Build debug versions of JS and CSS files. The -w
switch starts the Webpack monitor (so that the bundle can be partially rebuilt). The -p
switch enables a streamlined production version of the bundle.
Since I use bundled version control, I need a way to reference a file like /js/app.60795d5b3951178abba1.js
without knowing the hash value. I noticed that Mix likes to create manifest files, so I made a helper function to query it. From helpers.pre
:
vendor/bin/aerys -d -c config.php
Aerys knows how to handle promises when they appear in the form of $val = yield $promise
, so I used Amp's Promise implementation. After reading and decoding the file, I can find the matching file path. I adjusted HomeAction
. From app/Actions/HomeAction.pre
:
return Pre\processAndRequire(__DIR__ . "/config.pre");
I realized that I could continue to create functions that return promises and use them in this way to keep the code asynchronous. This is my JS code from 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" },
…and from assets/js/app.jsx
:
use Aerys\Router; use App\Action\HomeAction; return (Router $router) => { $router->route( "GET", "/", new HomeAction ); };
After all, I just want to see if Mix will compile my jsx files and if I can find them again using the async mix
function. It turns out to work!
Note: Using the mix
function every time is expensive, especially if we are loading the same file. Instead, we can load all templates during the server boot phase and reference them from inside the operation if needed. The configuration file we start Aerys can return a promise (such as the one given to us by Amp\all
), so we can parse all templates before the server starts.
Connect using WebSockets
I've almost set it up. The last thing to do is to connect the backend and frontend through WebSockets. I found this relatively simple, using a new class. From app/Socket/GameSocket.pre
:
use Aerys\Router; use App\Action\Api\HomeAction; return (Router $router) => { $router->route( "GET", "/api", new HomeAction ); };
…and minor modifications to web routing (from 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"); } }
Now I can change the JS to connect to this WebSocket and send the message to everyone connected to it. From assets/js/component.jsx
:
"scripts": { "dev": "vendor/bin/aerys -d -c loader.php", "prod": "vendor/bin/aerys -c loader.php" }, "config": { "process-timeout": 0 },
When I create a new Component
object, it connects to the WebSocket server and adds an event listener for the new message. I added some debugging code - to make sure it connects correctly and sends new messages.
We will go into more detail on PHP and WebSockets later, don't worry.
Summary
In this section, we looked at how to set up a simple asynchronous PHP web server, how to use Laravel Mix in non-Laravel projects, and even how to connect the backend and frontend together using WebSockets.
Wow! It covers a lot of content and we haven't written a line of game code yet. Join me in the second part and we will start building the game logic and React interface.
(This article was peer reviewed by Niklas Keller. Thanks to all the peer reviewers of SitePoint to get the content of SitePoint to its best!)
FAQ for Game Development with ReactJS and PHP
ReactJS and PHP are highly compatible in game development. ReactJS is a JavaScript library that is ideal for building user interfaces, especially for single-page applications. It allows for fast and responsive web design. On the other hand, PHP is a server-side scripting language that is very suitable for back-end development. It can handle database, user authentication, and server-side logic. When used together, ReactJS can handle the front-end, create dynamic and interactive user interfaces, while PHP manages the back-end.
Yes, you can use PHP for game logic in ReactJS games. Although ReactJS handles the user interface, PHP can manage game logic on the server side. This includes processing data, managing user sessions, and controlling game rules. This separation of concerns allows for a more orderly and efficient development process.
ReactJS provides many benefits for game development. Its virtual DOM allows efficient updates and rendering, making the game run smoother. It also supports reusable components, which can greatly speed up development time. Additionally, ReactJS has a huge community and rich resources to make it easier to find solutions to problems or learn new technologies.
PHP has many advantages in game development. It is a server-side language, which means it can handle data management, user authentication, and server-side game logic. PHP is also easy to learn, has simple syntax, and has a huge developer community. It is also highly scalable, making it suitable for games that may require handling a large number of users.
To start developing games with ReactJS and PHP, you first need to learn the basics of both languages. There are many online resources and tutorials available. Once you are familiar with these languages, you can start by building a simple game. This can be a basic text game or a simple puzzle game. As you gain more experience, you can start building more complex games.
Yes, there are several resources and libraries that can help with game development using ReactJS and PHP. For ReactJS, libraries like React Game Kit and React Game Engine are very useful. For PHP, you may find libraries like PHP-SDL or Wyvern useful. In addition, there are many tutorials, guides and forums online where you can learn more and get help.
Yes, you can build multiplayer games using ReactJS and PHP. ReactJS can handle user interfaces, while PHP can manage server-side logic, including managing player sessions and synchronizing game state across multiple clients.
With ReactJS and PHP, you can build a wide variety of games. This includes simple text games, puzzle games, platform games, role-playing games, and even multiplayer online games. The possibilities are huge, and the limit is actually your imagination and skill level.
In a game developed using ReactJS and PHP, server-side PHP can be used to process data. This can include player data, game status, scores, and so on. This data can be stored in a database and can be interacted with this database using PHP to retrieve and update the data as needed.
In a game developed using ReactJS, the user input can be processed using React's event processing system. This can include mouse clicks, keyboard keys, and touch events. React's event processing system is powerful and flexible, allowing you to easily control how the game responds to user input.
The above is the detailed content of Game Development with React and PHP: How Compatible Are They?. For more information, please follow other related articles on the PHP Chinese website!