RU
games/combat-sprite-simulator / src / Geo / AircraftShadow.php · commit efee358
<?phpnamespace App\Geo;use JumPHP\Renderer\Sdl;/** Extract the player's actual alpha silhouette and tint it as a ground shadow. */final class AircraftShadow{    /**     * Central atlas frame: middle bank (row 1), middle propeller state (col 1).     * Works with both the original and the Blender-refined Hurricane atlas.     */    public static function create(        Sdl $sdl,        string $atlasPath,        int $frameSize = 256,        int $size = 64,        string $textureName = 'css-flight-shadow',        int $column = 1,        int $row = 1,        ?int $frameHeight = null,    )    {        $frameHeight ??= $frameSize;        $atlas = @imagecreatefrompng($atlasPath);        if (!$atlas) {            return null;        }        $sample = imagecreatetruecolor($size, $size);        imagealphablending($sample, false);        imagesavealpha($sample, true);        imagecopyresampled($sample, $atlas, 0, 0, $column * $frameSize, $row * $frameHeight,            $size, $size, $frameSize, $frameHeight);        imagedestroy($atlas);        $shadow = imagecreatetruecolor($size, $size);        imagealphablending($shadow, false);        imagesavealpha($shadow, true);        imagefill($shadow, 0, 0, imagecolorallocatealpha($shadow, 0, 0, 0, 127));        for ($y = 0; $y < $size; ++$y) {            for ($x = 0; $x < $size; ++$x) {                $alpha = (imagecolorat($sample, $x, $y) >> 24) & 0x7F;                if ($alpha >= 125) {                    continue;                }                // A visible but translucent dark silhouette; preserve source antialiasing.                $tint = min(127, 68 + (int) round($alpha * 0.46));                imagesetpixel($shadow, $x, $y, imagecolorallocatealpha($shadow, 9, 22, 19, $tint));            }        }        imagedestroy($sample);        $texture = $sdl->createTextureFromGd($textureName, $shadow)[0]['texture'];        imagedestroy($shadow);        return $texture;    }}