Skip to content

An Asteroids-like game, running in a terminal, written in PHP

License

Notifications You must be signed in to change notification settings

NoiseByNorthwest/term-asteroids

Repository files navigation

TermAsteroids

An Asteroids-like game, running in a terminal, written in PHP.

Showcase

TermAsteroid is a horizontal scrolling Asteroids-like game which has the following particularities:

  • it runs in a terminal emulator.
  • it is fully implemented in PHP (except for the alternative and optional rendering backend described below).
  • it features 2 rendering backends (and can switch between the 2 at runtime):
    • one implemented in PHP.
    • one implemented in C and called through FFI.
  • it highlights:
    • the benefit of using FFI in order to reimplement a tight loop, as long as it significantly outweighs the PHP / FFI communication overhead. This is the case here since the main data movement is between the renderer and PHP's output buffer.
    • PHP's JIT benefits for such (CPU-bound) application and especially how it boosts the PHP rendering backend, making it 2 times faster and reducing the frame time by 40%.
    • PHP's cycle collector fairness for such application. Back in PHP 5 or even early PHP 7 versions, it was still a big issue for long-running processes with high load of object creations & destructions.
  • it renders early 90s style 2D graphics featuring:
    • 300x144 true color (24bpp) screen reaching 2+ million of pixel changes per second.
    • tens of animated medium/large sprites rendered per frame.
    • transparency, distortion and persistence effects.
    • procedural bitmap / animation generation via Perlin noise.
    • pre-rendered sprite rotations.
    • adaptive performance in order to preserve a minimal framerate of 35 FPS.

Requirements

  • GNU/Linux distro
  • Docker
  • A fast terminal emulator with unicode & true color support and an adjusted font size so that a maximized window will render at least 300 columns x 77 rows
    • xterm meets these requirements and is embedded in the Docker image

Getting started

git clone https://github.com/NoiseByNorthwest/term-asteroids.git
cd term-asteroids
make run

The first make run execution will take some time (building the Docker image, warming up some caches...) before starting the game, but the next executions will start instantly.

Controls

  • UP arrow: move the spaceship up
  • DOWN arrow: move the spaceship down
  • LEFT arrow: move the spaceship left
  • RIGHT arrow: move the spaceship right
  • Esc or q: quit
  • s: reset

Goals

Survive as long as possible:

  • use the arrow keys to move the spaceship
  • avoid collision with the asteroids
  • collide with bonuses, they give one third of your health and improve one of your 3 weapons

Other running mode

Game modes

Default mode (native renderer + JIT)

make run

Run it without JIT

make run.nojit

Run it with PHP renderer

make run.full_php

Run it with PHP renderer and without JIT

make run.full_php.no_jit

Dev mode

The dev mode gives nearly infinite health and more controls (see below). The difficulty level also increases faster.

make run.dev

Additional controls:

  • r: toggle renderer
  • a: toggle adaptive performance
  • w: show bounding and hit boxes
  • d: increase blue laser's level
  • c: decrease blue laser's level
  • f: increase plasma ball's level
  • v: decrease plasma ball's level
  • g: increase energy beam's level
  • b: decrease energy beam's level

Benchmark

This game comes with a benchmark mode which allows to highlight the performance differences between the four optimization levels (PHP/native renderer combined with JIT on/off).

Running it

To run all benchmark and generate the Markdown report:

make run.benchmark.all

Results

PHP version: 8.2.6

CPU: Intel(R) Core(TM) i7-9850H CPU @ 2.60GHz

Native Renderer + JIT Native Renderer PHP Renderer + JIT PHP Renderer
Execution time 20.7s 20.9s 20.7s 20.9s
Rendered frames 909 746 609 369
Average frame time 22.7ms 28.0ms 33.9ms 56.7ms
Average framerate 44.0 FPS 35.7 FPS 29.5 FPS 17.6 FPS
Average gameplay+physic time 7.0ms 11.0ms 7.8ms 13.5ms
Average rendering time 15.8ms 17.0ms 26.1ms 43.2ms
Average drawing time 1.7ms 1.9ms 7.6ms 20.7ms
Average update time 1.1ms 1.2ms 5.4ms 11.1ms
Average flushing time 13.0ms 13.9ms 13.1ms 11.4ms

Time breakdown explanation:

  • frame time: the elapsed time between 2 frames (i.e. the inverse of frame rate). It is compound of gameplay+physic and rendering times.
  • gameplay+physic time: this the time spent doing anything other than rendering the new frame, it mainly includes the gameplay & physic (moves, collisions) management.
  • rendering time: this is the time spent for the new frame rendering, it is compound of drawing, update and flushing times.
  • drawing time: the time spent drawing something (mainly bitmaps) to the frame buffer.
  • update time: the time spent generating the stream of characters to the buffered output in order to update the terminal based screen.
  • flushing time: the time spent flushing the output buffer. It may counterintuitively increase with a faster rendering loop since a faster rendering loop means a higher character changes throughput and thus more work for the terminal (and consequently a higher output blocking time).

About

An Asteroids-like game, running in a terminal, written in PHP

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published