/**
* PlayerView
* プレイヤーの描画責務を担うビュー
* Pixi Spriteの生成と座標反映を行う
*/
import { Assets, Sprite, Texture } from "pixi.js";
import { config } from "@repo/shared";
export class PlayerView {
public readonly displayObject: Sprite;
constructor(teamId: number, isLocal: boolean) {
const { PLAYER_RADIUS_PX } = config.GAME_CONFIG;
// 🌟 1. チームIDと画像ファイル名の紐づけ(すべて .svg に変更しました!)
const characterImages = [
"/red.svg", // teamId: 0 のときの画像
"/blue.svg", // teamId: 1 のときの画像
"/green.svg", // teamId: 2 のときの画像
"/yellow.svg", // teamId: 3 のときの画像
];
// 配列から対応する画像ファイル名を取得(デフォルトは red.svg)
const imageFileName = (characterImages[teamId] || "/red.svg").replace(
/^\//,
"",
);
// 🌟 2. スプライト(画像)の生成(初期は1x1テクスチャ)
this.displayObject = new Sprite(Texture.WHITE);
// 🌟 3. 画像の基準点を「中心」にする(ズレ防止)
this.displayObject.anchor.set(0.5);
// 🌟 4. 画像サイズを当たり判定(半径×2)に合わせる
this.displayObject.width = PLAYER_RADIUS_PX * 2;
this.displayObject.height = PLAYER_RADIUS_PX * 2;
// ローカルプレイヤーだけ少し視認性を上げる(未使用引数対策を兼ねる)
this.displayObject.alpha = isLocal ? 1 : 0.95;
// 非同期で画像テクスチャを読み込んで差し替える
void this.applyTexture(imageFileName);
}
/** BASE_URL対応のURLで画像を読み込み、スプライトに反映する */
private async applyTexture(imageFileName: string): Promise<void> {
try {
const imageUrl = `${import.meta.env.BASE_URL}${imageFileName}`;
const texture = await Assets.load(imageUrl);
this.displayObject.texture = texture;
const { PLAYER_RADIUS_PX } = config.GAME_CONFIG;
// 当たり判定の本来のサイズ
const targetSize = PLAYER_RADIUS_PX * 2;
// 画像の元サイズから、当たり判定のサイズに合わせるための「倍率」を計算
const baseScale = targetSize / Math.max(texture.width, texture.height);
// 💡 ここがポイント!余白がある分、少し大きめに表示してあげる(1.5倍〜2倍など調整してください)
const visualScale = 1.5;
// 縦横比を崩さずにスケール(倍率)を設定
this.displayObject.scale.set(baseScale * visualScale);
} catch (error) {
console.error(
`[PlayerView] 画像の読み込みに失敗: ${imageFileName}`,
error,
);
}
}
/** グリッド座標を描画座標へ反映する */
public syncPosition(gridX: number, gridY: number): void {
const { GRID_CELL_SIZE } = config.GAME_CONFIG;
// マスの中心に配置されるように調整
this.displayObject.x = gridX * GRID_CELL_SIZE + GRID_CELL_SIZE / 2;
this.displayObject.y = gridY * GRID_CELL_SIZE + GRID_CELL_SIZE / 2;
}
/** 描画リソースを破棄する */
public destroy(): void {
this.displayObject.destroy();
}
}