You are on page 1of 5

GameLoop.

php
final class GameLoop
{
// ...
public function __construct(
int $width,
int $height
){
$this->width = $width;
$this->height = $height;

// 30
$s = self::CELL_SIZE;
$this->state = new GameState(
(int) ($this->width / $s),
(int) ($this->height / $s)
);
}
// ...
}
// ...
public function start(): void
{
Window::init(
$this->width,
$this->height,
'PHP Snake'
);
Timming::setTargetFPS(60);

while (
$this->shouldStop ||
!Window::shouldClose()
){
$this->update();
$this->draw();
}
}
// …
private function update(): void
{
$head = $this->state->snake[0];
$recSnake = new Rectangle(
(float) $head['x'],
(float) $head['y'],
1,
1,
);
$fruit = $this->state->fruit;
$recFruit = new Rectangle(
(float) $fruit['x'],
(float) $fruit['y'],
1,
1,
);

// Snake bites fruit


if (
Collision::checkRecs(
$recSnake,
$recFruit
)
){
$this->state->score();
}

// Controls step speed


$now = microtime(true);
if (
$now - $this->lastStep
> (1 / $this->state->score)
){
$this->state->step();
$this->lastStep = $now;
}

// Update direction if necessary


if (Key::isPressed(Key::W)) {
$this->state->direction = GameState::DIRECTION_UP;
} else if (Key::isPressed(Key::D)) {
$this->state->direction = GameState::DIRECTION_RIGHT;
} else if (Key::isPressed(Key::S)) {
$this->state->direction = GameState::DIRECTION_DOWN;
} else if (Key::isPressed(Key::A)) {
$this->state->direction = GameState::DIRECTION_LEFT;
}
}
private function draw(): void
{
Draw::begin();

// Clear screen
Draw::clearBackground(
new Color(255, 255, 255, 255)
);
// Draw fruit
$x = $this->state->fruit['x'];
$y = $this->state->fruit['y'];
Draw::rectangle(
$x * self::CELL_SIZE,
$y * self::CELL_SIZE,
self::CELL_SIZE,
self::CELL_SIZE,
new Color(200, 110, 0, 255)
);

// Draw snake's body


foreach (
$this->state->snake as $coords
){
$x = $coords['x'];
$y = $coords['y'];
Draw::rectangle(
$x * self::CELL_SIZE,
$y * self::CELL_SIZE,
self::CELL_SIZE,
self::CELL_SIZE,
new Color(0,255, 0, 255)
);
}

// Draw score
$score = "Score: {$this->state->score}";
Text::draw(
$score,
$this->width - Text::measure($score, 12) - 10,
10,
12,
new Color(0, 255, 0, 255)
);

Draw::end();
}
GameState.php
final class GameState
{
public function __construct(
int $maxX,
int $maxY
){
$this->maxX = $maxX;
$this->maxY = $maxY;
$this->snake = [
$this->craftRandomCoords(),
];

$this->fruit = $this->craftRandomCoords();
}
}
private function incrementBody(): void
{
$newHead = $this->snake[0];

// Adjusts head direction


switch ($this->direction) {
case self::DIRECTION_UP:
$newHead['y']--;
break;
case self::DIRECTION_DOWN:
$newHead['y']++;
break;
case self::DIRECTION_RIGHT:
$newHead['x']++;
break;
case self::DIRECTION_LEFT:
$newHead['x']--;
break;
}

// Adds new head, in front


// of the whole the body
$this->snake = array_merge(
[$newHead],
$this->snake
);
}
public function score(): void
{
$this->score++;
$this->incrementBody();
$this->fruit = $this->craftRandomCoords();
}
public function step(): void
{
$this->incrementBody();

// Remove last element


array_pop($this->snake);
// Warp body if necessary
foreach ($this->snake as &$coords) {
if ($coords['x'] > $this->maxX - 1) {
$coords['x'] = 0;
} else if ($coords['x'] < 0) {
$coords['x'] = $this->maxX - 1;
}

if ($coords['y'] > $this->maxY - 1) {


$coords['y'] = 0;
} else if ($coords['y'] < 0) {
$coords['y'] = $this->maxY - 1;
}
}
}

You might also like