Improve level-up animation and unit audio assets

This commit is contained in:
2026-06-24 15:23:26 +09:00
parent 44c017ab6c
commit 384ce7725c
8 changed files with 308 additions and 54 deletions

View File

@@ -48,7 +48,7 @@ const unitSheetRows: Record<UnitDirection, number> = {
west: 3
};
const unitSheets = [
const sourceUnitSheets = [
{ key: 'unit-liu-bei', url: liuBeiUnitSheetUrl, actionKey: 'unit-liu-bei-actions', actionUrl: liuBeiActionSheetUrl },
{ key: 'unit-guan-yu', url: guanYuUnitSheetUrl, actionKey: 'unit-guan-yu-actions', actionUrl: guanYuActionSheetUrl },
{ key: 'unit-zhang-fei', url: zhangFeiUnitSheetUrl, actionKey: 'unit-zhang-fei-actions', actionUrl: zhangFeiActionSheetUrl },
@@ -58,6 +58,30 @@ const unitSheets = [
{ key: 'unit-rebel-leader', url: rebelLeaderUnitSheetUrl, actionKey: 'unit-rebel-leader-actions', actionUrl: rebelLeaderActionSheetUrl }
];
const generatedUnitSheets = [
{ key: 'unit-shu-infantry', sourceKey: 'unit-guan-yu', actionKey: 'unit-shu-infantry-actions', sourceActionKey: 'unit-guan-yu-actions', tint: 0x2f7fba, alpha: 0.32 },
{ key: 'unit-shu-spearman', sourceKey: 'unit-zhang-fei', actionKey: 'unit-shu-spearman-actions', sourceActionKey: 'unit-zhang-fei-actions', tint: 0x4aa878, alpha: 0.3 },
{ key: 'unit-shu-archer', sourceKey: 'unit-rebel-archer', actionKey: 'unit-shu-archer-actions', sourceActionKey: 'unit-rebel-archer-actions', tint: 0x4b9bd5, alpha: 0.36 },
{ key: 'unit-shu-cavalry', sourceKey: 'unit-rebel-cavalry', actionKey: 'unit-shu-cavalry-actions', sourceActionKey: 'unit-rebel-cavalry-actions', tint: 0x488fc4, alpha: 0.36 },
{ key: 'unit-shu-strategist', sourceKey: 'unit-liu-bei', actionKey: 'unit-shu-strategist-actions', sourceActionKey: 'unit-liu-bei-actions', tint: 0x75b7d8, alpha: 0.28 },
{ key: 'unit-shu-officer', sourceKey: 'unit-guan-yu', actionKey: 'unit-shu-officer-actions', sourceActionKey: 'unit-guan-yu-actions', tint: 0x3f91c8, alpha: 0.36 },
{ key: 'unit-wei-infantry', sourceKey: 'unit-rebel', actionKey: 'unit-wei-infantry-actions', sourceActionKey: 'unit-rebel-actions', tint: 0x8b3030, alpha: 0.42 },
{ key: 'unit-wei-archer', sourceKey: 'unit-rebel-archer', actionKey: 'unit-wei-archer-actions', sourceActionKey: 'unit-rebel-archer-actions', tint: 0x9d3c3c, alpha: 0.4 },
{ key: 'unit-wei-cavalry', sourceKey: 'unit-rebel-cavalry', actionKey: 'unit-wei-cavalry-actions', sourceActionKey: 'unit-rebel-cavalry-actions', tint: 0x7a3540, alpha: 0.44 },
{ key: 'unit-wei-strategist', sourceKey: 'unit-rebel-archer', actionKey: 'unit-wei-strategist-actions', sourceActionKey: 'unit-rebel-archer-actions', tint: 0x7f5a8e, alpha: 0.38 },
{ key: 'unit-wei-officer', sourceKey: 'unit-rebel-leader', actionKey: 'unit-wei-officer-actions', sourceActionKey: 'unit-rebel-leader-actions', tint: 0x8f3940, alpha: 0.44 },
{ key: 'unit-wu-infantry', sourceKey: 'unit-rebel', actionKey: 'unit-wu-infantry-actions', sourceActionKey: 'unit-rebel-actions', tint: 0x0b8b86, alpha: 0.42 },
{ key: 'unit-wu-archer', sourceKey: 'unit-rebel-archer', actionKey: 'unit-wu-archer-actions', sourceActionKey: 'unit-rebel-archer-actions', tint: 0x169b91, alpha: 0.4 },
{ key: 'unit-wu-cavalry', sourceKey: 'unit-rebel-cavalry', actionKey: 'unit-wu-cavalry-actions', sourceActionKey: 'unit-rebel-cavalry-actions', tint: 0x087b86, alpha: 0.44 },
{ key: 'unit-wu-strategist', sourceKey: 'unit-rebel-archer', actionKey: 'unit-wu-strategist-actions', sourceActionKey: 'unit-rebel-archer-actions', tint: 0x3aa57e, alpha: 0.38 },
{ key: 'unit-wu-officer', sourceKey: 'unit-rebel-leader', actionKey: 'unit-wu-officer-actions', sourceActionKey: 'unit-rebel-leader-actions', tint: 0x168f83, alpha: 0.44 },
{ key: 'unit-nanman-infantry', sourceKey: 'unit-rebel', actionKey: 'unit-nanman-infantry-actions', sourceActionKey: 'unit-rebel-actions', tint: 0x8b6c2f, alpha: 0.42 },
{ key: 'unit-nanman-shaman', sourceKey: 'unit-rebel-archer', actionKey: 'unit-nanman-shaman-actions', sourceActionKey: 'unit-rebel-archer-actions', tint: 0x6e8a3a, alpha: 0.42 },
{ key: 'unit-nanman-officer', sourceKey: 'unit-rebel-leader', actionKey: 'unit-nanman-officer-actions', sourceActionKey: 'unit-rebel-leader-actions', tint: 0x9a6a2e, alpha: 0.46 }
];
const animatedUnitSheets = [...sourceUnitSheets, ...generatedUnitSheets].map(({ key }) => ({ key }));
export class BootScene extends Phaser.Scene {
constructor() {
super('BootScene');
@@ -90,7 +114,7 @@ export class BootScene extends Phaser.Scene {
this.load.image(key, url);
});
unitSheets.forEach(({ key, url, actionKey, actionUrl }) => {
sourceUnitSheets.forEach(({ key, url, actionKey, actionUrl }) => {
this.load.spritesheet(key, url, {
frameWidth: unitSheetFrameSize,
frameHeight: unitSheetFrameSize
@@ -105,6 +129,7 @@ export class BootScene extends Phaser.Scene {
create() {
this.createPetalTexture();
this.createEquipmentIconTextures();
this.createGeneratedUnitSheets();
this.createUnitAnimations();
this.scene.start('TitleScene');
}
@@ -369,8 +394,42 @@ export class BootScene extends Phaser.Scene {
graphics.strokePath();
}
private createGeneratedUnitSheets() {
generatedUnitSheets.forEach((sheet) => {
this.createTintedUnitSheet(sheet.key, sheet.sourceKey, sheet.tint, sheet.alpha);
this.createTintedUnitSheet(sheet.actionKey, sheet.sourceActionKey, sheet.tint, sheet.alpha);
});
}
private createTintedUnitSheet(targetKey: string, sourceKey: string, tint: number, alpha: number) {
if (this.textures.exists(targetKey) || !this.textures.exists(sourceKey)) {
return;
}
const sourceImage = this.textures.get(sourceKey).getSourceImage() as CanvasImageSource & { width: number; height: number };
const canvas = document.createElement('canvas');
canvas.width = sourceImage.width;
canvas.height = sourceImage.height;
const context = canvas.getContext('2d');
if (!context) {
return;
}
context.drawImage(sourceImage, 0, 0);
context.globalCompositeOperation = 'source-atop';
context.globalAlpha = alpha;
context.fillStyle = `#${tint.toString(16).padStart(6, '0')}`;
context.fillRect(0, 0, canvas.width, canvas.height);
context.globalCompositeOperation = 'source-over';
context.globalAlpha = 1;
this.textures.addSpriteSheet(targetKey, canvas as unknown as HTMLImageElement, {
frameWidth: unitSheetFrameSize,
frameHeight: unitSheetFrameSize
});
}
private createUnitAnimations() {
unitSheets.forEach(({ key }) => {
animatedUnitSheets.forEach(({ key }) => {
(['south', 'east', 'north', 'west'] as UnitDirection[]).forEach((direction) => {
const frames = Array.from({ length: unitWalkFrameCount }, (_, frameIndex) => ({
key,