A very simple Flappy Bird-like game written in PHP, built on PHP-GLFW and the VISU framework.
Make sure the php-glfw extension is installed and enabled.
If you havent done so already follow the instructions for your operating system here:
Then you can simply clone the project and install the dependencies with composer.
git clone https://github.com/phpgl/flappyphpant.git
cd flappyphpant
composer install
bash bin/play
- Press
space
to jump. - Press
R
to reset. - Press
F1
to disable the profiler and the debug overlay. Note: the profiler takes a huge toll on performance as it forces the GPU to sync with the CPU after each render pass.
I really suck at this game, so if you surpass my score, please refrain from tweeting at me and making me feel ashamed.
s.mp4
A lot of this is complete overkill for a simple Flappy Bird game, but I see this as an example project to demonstrate how you could build a 2D game with PHP-GLFW and VISU.
Also, for time's sake, I cut a few corners, so the code is not as clean as I would like it to be.
-
Decoupled Simulation from Rendering
The
render
andupdate
functions are decoupled. This means the game simulation (akaupdate()
) runs at a fixed rate, while the rendering (akarender()
) runs as fast as possible. (Or, when vsync is enabled, at the refresh rate of the monitor.) The player movement is interpolated between the last and the current simulation step, allowing smooth movement even when the simulation is running significantly slower than the rendering.FlappyPHPant specifically has a tick rate of
60ups
but can render at about3000fps
with a resolution of2560x1440
on an M1 MacBook Pro.I was honestly really surprised at how good the frametimes are, considering the entire framework is written in PHP.
-
Proper 2D Camera
The camera, unlike the real Flappy Bird, is not fixed to a vertical resolution. The window can be resized to any resolution and aspect ratio you want, and the game should scale properly.
- Support for High DPI displays means that on retina displays, the game will be rendered at a higher internal resolution.
- The number of pipes rendered is based on the viewport and automatically adjusts to the window size.
Vertical Horizontal -
Abstracted Input Handling
Input handling can get messy quickly; this example utilizes Input and Action maps to abstract the input handling and, theoretically, allow for easy remapping of the controls.
// apply jump if ($this->inputContext->actions->didButtonPress('jump')) { $playerComponent->velocity = $playerComponent->jumpForce; }
(I do understand how silly this is in a game where you basically just press one button.)
-
Entity Component System
This example uses an Entity Component System to manage the game objects and share state between the different systems.
$playerEntity = $entities->create(); $entities->attach($playerEntity, new SpriteComponent('visuphpant2.png')); $entities->attach($playerEntity, new PlayerComponent()); $entities->attach($playerEntity, new Transform());
This kind of game is unfortunately not the best example for an ECS.
-
Simple Sprite Renderer
This project showcases a simple sprite renderer that can render individual sprites from a sprite sheet. This is used to render the animated player elephant as well as the pipes. It's nothing complex but should give you a starting point if you want to build a 2D game with VISU.
-
Very Basic AABB Collision Detection
The collision detection is very basic and only checks for collisions between the player AABB and the pipe AABBs. It can be infuriating at times, as the elephant will collide with the pipes even if it looks like it should not.
-
Text Rendering
Showcasing a simple example of how to render text labels. I know this might sound underwhelming, but text handling can be pretty darn annoying.