initial commit
This commit is contained in:
commit
e8c3f9862a
193 files changed
+29795
No files matched your search
@@ -0,0 +1,142 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Game\Entities;
|
||||
|
||||
use App\Game\EntityList;
|
||||
use App\Game\Player;
|
||||
use App\Game\Room;
|
||||
use App\Game\Vector2;
|
||||
|
||||
final class MegaWitch extends Witch
|
||||
{
|
||||
private float $novaInterval;
|
||||
|
||||
private int $novaCount;
|
||||
|
||||
private float $novaProjectileSpeed;
|
||||
|
||||
private float $novaTimer;
|
||||
|
||||
private float $novaRotation;
|
||||
|
||||
/** @var array<int, array{0:float, 1:\Closure}> */
|
||||
private array $pendingNova = [];
|
||||
|
||||
public function __construct(
|
||||
float $x,
|
||||
float $y,
|
||||
EntityList $container,
|
||||
Room $room,
|
||||
?Player $initialTarget,
|
||||
array $config = [],
|
||||
?callable $onDeath = null,
|
||||
) {
|
||||
$spawnCount = $config['spawnCount'] ?? 3;
|
||||
$spawnOnDeath = $config['spawnOnDeath'] ?? null;
|
||||
parent::__construct($x, $y, $container, $room, $initialTarget, $config, $onDeath ?? function (Zombie $mega) use ($spawnCount, $spawnOnDeath): void {
|
||||
if ($spawnOnDeath === null) {
|
||||
return;
|
||||
}
|
||||
for ($i = 0; $i < $spawnCount; $i++) {
|
||||
$angle = ($i / $spawnCount) * M_PI * 2.0;
|
||||
$offset = $mega->size + 30.0;
|
||||
$spawnOnDeath(
|
||||
$mega->pos->x + cos($angle) * $offset,
|
||||
$mega->pos->y + sin($angle) * $offset,
|
||||
$mega->container,
|
||||
$mega->room,
|
||||
$mega->target,
|
||||
);
|
||||
}
|
||||
});
|
||||
if ($initialTarget !== null) {
|
||||
$this->target = $initialTarget;
|
||||
}
|
||||
$this->novaInterval = $config['novaInterval'] ?? 5.0;
|
||||
$this->novaCount = $config['novaCount'] ?? 16;
|
||||
$this->novaProjectileSpeed = $config['novaProjectileSpeed'] ?? 250.0;
|
||||
$this->novaTimer = $this->novaInterval * 0.5;
|
||||
$this->novaRotation = $config['novaRotation'] ?? $this->rand01() * M_PI * 2.0;
|
||||
}
|
||||
|
||||
public function kind(): string
|
||||
{
|
||||
return 'megawitch';
|
||||
}
|
||||
|
||||
public function update(float $dt): void
|
||||
{
|
||||
parent::update($dt);
|
||||
|
||||
$target = $this->target;
|
||||
if ($target !== null && $target->dead) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (array_keys($this->pendingNova) as $i) {
|
||||
$this->pendingNova[$i][0] -= $dt;
|
||||
if ($this->pendingNova[$i][0] <= 0.0) {
|
||||
$closure = $this->pendingNova[$i][1];
|
||||
unset($this->pendingNova[$i]);
|
||||
$closure();
|
||||
}
|
||||
}
|
||||
|
||||
$this->novaTimer -= $dt;
|
||||
if ($this->novaTimer <= 0.0) {
|
||||
$this->novaTimer = $this->novaInterval * (0.85 + $this->rand01() * 0.3);
|
||||
$this->nova();
|
||||
}
|
||||
}
|
||||
|
||||
private function nova(): void
|
||||
{
|
||||
$lost = 1.0 - max(0.0, $this->health / max(1, $this->maxHealth));
|
||||
$count = max(6, (int) round($this->novaCount * (0.75 + 0.25 * $lost)));
|
||||
$speed = $this->novaProjectileSpeed * (1.0 + $lost * 0.45);
|
||||
$size = max(8.0, $this->size * 0.3);
|
||||
$color = [1.0, 0.5, 0.3, 1.0];
|
||||
$this->novaRotation += 0.36;
|
||||
|
||||
$fireRing = function (float $offset) use ($count, $speed, $size, $color): void {
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$angle = ($i / $count) * M_PI * 2.0 + $this->novaRotation + $offset;
|
||||
$direction = new Vector2(cos($angle), sin($angle));
|
||||
$this->container->append(new WitchProjectile(
|
||||
$this->pos->x,
|
||||
$this->pos->y,
|
||||
$direction,
|
||||
$this->container,
|
||||
$this->room,
|
||||
$speed,
|
||||
$size,
|
||||
$color,
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
$fireRing(0.0);
|
||||
$this->pendingNova[] = [0.22, function () use ($fireRing, $count): void {
|
||||
$fireRing(M_PI / $count);
|
||||
}];
|
||||
if ($lost > 0.34) {
|
||||
$this->pendingNova[] = [0.44, function () use ($fireRing): void {
|
||||
$fireRing(0.0);
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
public function toSnapshot(): array
|
||||
{
|
||||
$data = parent::toSnapshot();
|
||||
$data['charge'] = 1.0 - max(0.0, $this->novaTimer) / $this->novaInterval;
|
||||
|
||||
if ($data['hp'] < $data['mhp'] && $data['charge'] > 0.72) {
|
||||
$data['nova'] = true;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user