Skip to content

Instantly share code, notes, and snippets.

@philipnorton42
Created March 8, 2021 21:41
Show Gist options
  • Save philipnorton42/64aaca02200f048a7d07b1f2c8bf0c89 to your computer and use it in GitHub Desktop.
Save philipnorton42/64aaca02200f048a7d07b1f2c8bf0c89 to your computer and use it in GitHub Desktop.
Creating A Game With PHP Part 4: Side Scrolling Shooter (see https://www.hashbangcode.com/article/creating-game-php-part-4-side-scrolling-shooter)
<?php
class Entity {
public $positionX = 0;
public $positionY = 0;
public function __construct($x, $y) {
$this->positionX = $x;
$this->positionY = $y;
}
}
class Spaceship extends Entity {
public $movementX = 0;
public $movementY = 0;
public $fire = FALSE;
}
class Enemy extends Entity {}
class Bullet extends entity {}
class Scene {
public $height;
public $width;
public $ship;
public $enemies = [];
public $bullets = [];
public $score = 0;
public function __construct($width, $height) {
$this->width = $width;
$this->height = $height;
$this->ship = new Spaceship(2, round($this->height / 2));
}
public function renderGame() {
$output = '';
for ($i = 0; $i < $this->height; $i++) {
for ($j = 0; $j < $this->width; $j++) {
if ($this->ship->positionX == $i && $this->ship->positionY == $j) {
$cell = '>';
}
else {
$cell = ' ';
}
foreach ($this->enemies as $enemy) {
if ($enemy->positionX == $i && $enemy->positionY == $j) {
$cell = 'X';
}
}
foreach ($this->bullets as $bullet) {
if ($bullet->positionX == $i && $bullet->positionY == $j) {
$cell = '-';
}
}
$output .= $cell;
}
$output .= PHP_EOL;
}
$output .= PHP_EOL;
$output .= 'Score:' . $this->score . PHP_EOL;
return $output;
}
public function moveEnemies() {
foreach ($this->enemies as $enemyId => $enemy) {
$enemy->positionY--;
if ($enemy->positionY == 0) {
// Remove the enemy if it goes beyond the left hand side of the scene.
unset($this->enemies[$enemyId]);
continue;
}
foreach ($this->bullets as $bulletId => $bullet) {
if ($bullet->positionX == $enemy->positionX && ($bullet->positionY == $enemy->positionY || $bullet->positionY == $enemy->positionY - 1)) {
unset($this->enemies[$enemyId]);
unset($this->bullets[$bulletId]);
$this->score++;
}
}
}
}
public function moveBullets() {
foreach ($this->bullets as $bullet) {
$bullet->positionY++;
}
}
public function shoot() {
if ($this->ship->fire == TRUE) {
$this->bullets[] = new Bullet($this->ship->positionX, $this->ship->positionY + 1);
$this->ship->fire = FALSE;
}
}
public function spawnEnemies() {
if (count($this->enemies) < 15) {
$y = rand($this->width, $this->width * 2);
$x = rand(0, $this->height - 1);
$this->enemies[] = new Enemy($x, $y);
}
}
public function gameOver() {
foreach ($this->enemies as $enemy) {
if ($this->ship->positionX == $enemy->positionX && $this->ship->positionY == $enemy->positionY) {
die('dead :(');
}
}
}
public function moveShip() {
$this->ship->positionX += $this->ship->movementX;
$this->ship->positionY += $this->ship->movementY;
$this->ship->movementX = 0;
$this->ship->movementY = 0;
if ($this->ship->positionX < 0) {
$this->ship->positionX = 0;
}
if ($this->ship->positionX >= $this->height) {
$this->ship->positionX = $this->height - 1;
}
if ($this->ship->positionY < 0) {
$this->ship->positionY = 0;
}
if ($this->ship->positionY > $this->width / 4) {
$this->ship->positionY = $this->width / 4;
}
}
public function action($stdin) {
// Listen to the button being pressed.
$key = fgets($stdin);
if ($key) {
$key = $this->translateKeypress($key);
switch ($key) {
case "UP":
$this->ship->movementX = -1;
$this->ship->movementY = 0;
break;
case "DOWN":
$this->ship->movementX = 1;
$this->ship->movementY = 0;
break;
case "RIGHT":
$this->ship->movementX = 0;
$this->ship->movementY = 1;
break;
case "LEFT":
$this->ship->movementX = 0;
$this->ship->movementY = -1;
break;
case "ENTER":
case "SPACE":
$this->ship->fire = TRUE;
break;
case "ESC":
die();
}
}
}
private function translateKeypress($string) {
switch ($string) {
case "\033[A":
return "UP";
case "\033[B":
return "DOWN";
case "\033[C":
return "RIGHT";
case "\033[D":
return "LEFT";
case "\n":
return "ENTER";
case " ":
return "SPACE";
case "\e":
return "ESC";
}
return $string;
}
}
$seed = 1;
srand($seed);
$scene = new Scene(50, 10);
system('stty cbreak -echo');
$stdin = fopen('php://stdin', 'r');
stream_set_blocking($stdin, 0);
while (1) {
system('clear');
$scene->action($stdin);
$scene->moveShip();
$scene->shoot();
$scene->moveBullets();
$scene->moveEnemies();
echo $scene->renderGame();
$scene->gameOver();
$scene->spawnEnemies();
usleep(100000);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment