174 lines
4.3 KiB
PHP
174 lines
4.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Game\Entities;
|
|
|
|
use App\Game\EntityList;
|
|
use App\Game\GameObject;
|
|
use App\Game\Player;
|
|
use App\Game\Room;
|
|
use App\Game\Vector2;
|
|
|
|
class Zombie extends GameObject
|
|
{
|
|
public ?Player $target = null;
|
|
|
|
protected EntityList $container;
|
|
|
|
protected Room $room;
|
|
|
|
public float $speed;
|
|
|
|
public float $size;
|
|
|
|
/** @var array<float> */
|
|
public array $baseColor;
|
|
|
|
public int $health;
|
|
|
|
public int $maxHealth;
|
|
|
|
public float $knockback;
|
|
|
|
public float $knockbackDamping;
|
|
|
|
public int $scoreValue;
|
|
|
|
/** @var null|callable(Zombie):void */
|
|
public $onDeath;
|
|
|
|
protected Vector2 $hitKnockback;
|
|
|
|
protected float $flash = 0.0;
|
|
|
|
protected float $time = 0.0;
|
|
|
|
public float $broken;
|
|
|
|
protected float $emergeTotal;
|
|
|
|
protected float $emerge;
|
|
|
|
public function __construct(
|
|
float $x,
|
|
float $y,
|
|
EntityList $container,
|
|
Room $room,
|
|
array $config = [],
|
|
?callable $onDeath = null,
|
|
) {
|
|
parent::__construct($x, $y);
|
|
$this->container = $container;
|
|
$this->room = $room;
|
|
$this->speed = $config['speed'] ?? 110.0;
|
|
$this->size = $config['size'] ?? 24.0;
|
|
$this->baseColor = $config['color'] ?? [0.15, 0.65, 0.2, 1.0];
|
|
$this->health = $config['health'] ?? 1;
|
|
$this->maxHealth = $this->health;
|
|
$this->knockback = $config['knockback'] ?? 260.0;
|
|
$this->knockbackDamping = $config['knockbackDamping'] ?? 10.0;
|
|
$this->scoreValue = $config['scoreValue'] ?? 1;
|
|
$emergeTime = $config['emergeTime'] ?? 0.0;
|
|
$this->emergeTotal = $emergeTime;
|
|
$this->emerge = $emergeTime;
|
|
$this->onDeath = $onDeath;
|
|
$this->broken = rand(0, 100000) / 100000.0 * M_PI * 2.0;
|
|
$this->hitKnockback = Vector2::zero();
|
|
$this->width = $this->size;
|
|
$this->height = $this->size;
|
|
}
|
|
|
|
public function kind(): string
|
|
{
|
|
return 'zombie';
|
|
}
|
|
|
|
public function die(): void
|
|
{
|
|
if ($this->onDeath !== null) {
|
|
($this->onDeath)($this);
|
|
}
|
|
$this->removeAllReferences();
|
|
$this->container->remove($this);
|
|
}
|
|
|
|
protected function removeAllReferences(): void {}
|
|
|
|
public function hit(Vector2 $impulse, int $damage = 1): bool
|
|
{
|
|
$this->health -= $damage;
|
|
if ($this->health < 0) {
|
|
$this->health = 0;
|
|
}
|
|
$this->hitKnockback = $impulse->mulS($this->knockback);
|
|
$this->flash = 0.08;
|
|
|
|
return $this->health <= 0;
|
|
}
|
|
|
|
public function update(float $dt): void
|
|
{
|
|
$this->time += $dt;
|
|
if ($this->updateEmerge($dt)) {
|
|
return;
|
|
}
|
|
if ($this->target === null) {
|
|
return;
|
|
}
|
|
$delta = $this->target->pos->subV($this->pos);
|
|
$distance = $delta->length();
|
|
$chaseVelocity = Vector2::zero();
|
|
if ($distance > 1.0) {
|
|
$chaseVelocity = $delta->divS($distance)->mulS($this->speed);
|
|
}
|
|
|
|
$this->velocity = $chaseVelocity->addV($this->hitKnockback);
|
|
parent::update($dt);
|
|
|
|
$this->hitKnockback = $this->hitKnockback->mulS(max(0.0, 1 - $dt * $this->knockbackDamping));
|
|
$this->flash = max(0.0, $this->flash - $dt);
|
|
}
|
|
|
|
public function updateEmerge(float $dt): bool
|
|
{
|
|
if ($this->emerge <= 0.0) {
|
|
return false;
|
|
}
|
|
$this->emerge -= $dt;
|
|
if ($this->emerge <= 0.0) {
|
|
$this->emerge = 0.0;
|
|
$this->onEmergeComplete();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
protected function onEmergeComplete(): void {}
|
|
|
|
protected function rand01(): float
|
|
{
|
|
return random_int(0, 1000000) / 1000000.0;
|
|
}
|
|
|
|
public function toSnapshot(): array
|
|
{
|
|
$snapshot = [
|
|
'eid' => $this->eid,
|
|
'd' => $this->kind(),
|
|
'x' => round($this->pos->x, 1),
|
|
'y' => round($this->pos->y, 1),
|
|
's' => $this->size,
|
|
'hp' => $this->health,
|
|
'mhp' => $this->maxHealth,
|
|
'c' => array_slice($this->baseColor, 0, 3),
|
|
];
|
|
if ($this->emergeTotal > 0.0) {
|
|
$snapshot['et'] = round($this->emergeTotal, 2);
|
|
$snapshot['er'] = round($this->emerge, 2);
|
|
}
|
|
|
|
return $snapshot;
|
|
}
|
|
}
|