x = $x; $this->y = $y; $this->width = self::WIDTH; $this->height = self::HEIGHT; $this->facing = $facing; $this->state = 'growing'; } public function update(float $dt): void { $this->age += $dt; if ($this->state === 'growing' && $this->age >= self::GROW_TIME) { $this->state = 'solid'; } if ($this->state === 'falling') { $this->vy += self::GRAVITY * $dt; $this->y += $this->vy * $dt; } elseif ($this->age >= self::LIFETIME) { $this->kill(); } } public function isGrowing(): bool { return $this->state === 'growing'; } public function isFalling(): bool { return $this->state === 'falling'; } /** Bub landed on it from a jump (or a falling rainbow hit it). */ public function breakDown(): void { if ($this->state !== 'falling') { $this->state = 'falling'; $this->vy = 0; } } /** * The walkable height (world y) of the arc at world column $x, null where there is nothing to stand on. * Its two feet are ramps so Bub can walk up from the ground. */ public function surfaceAt(float $x): ?float { if ($this->state === 'falling') { return null; } $local = (int)floor($x - $this->x); if ($local < 0 || $local >= self::WIDTH) { return null; } // while it grows, only the part already drawn holds (Bub walking on climbs it as it appears) if ($this->state === 'growing') { $grown = $this->age / self::GROW_TIME * self::WIDTH; if ($this->facing === 'right' ? $local >= $grown : $local < self::WIDTH - $grown) { return null; } } $ramp = 8; $edge = min($local, self::WIDTH - 1 - $local); if ($edge < $ramp) { $bottom = self::HEIGHT - 1; return $this->y + $bottom - ($bottom - $this->profile[$ramp]) * $edge / $ramp; } return $this->y + $this->profile[$local]; } public function render(Renderer $r, float $camX = 0, float $camY = 0): void { } public function draw(Renderer $r, Artwork $artwork, int $island, float $camY): void { $left = self::LIFETIME - $this->age; if ($this->state !== 'falling' && $left < self::BLINK_TIME && fmod($left, 0.2) < 0.08) { return; } // while it grows, the arc appears column by column from Bub's side $columns = $this->state === 'growing' ? (int)ceil($this->age / self::GROW_TIME * 6) : 6; foreach ($this->tiles as $row => $line) { foreach ($line as $column => $tile) { $shown = $this->facing === 'right' ? $column < $columns : $column >= 6 - $columns; if ($tile && $shown) { $artwork->drawOverlayTile($r, $island, $tile, $this->x + $column * Round::TILE, $this->y - $camY + $row * Round::TILE); } } } } }