Scale meteor impacts by size

This commit is contained in:
2026-05-26 18:26:34 +09:00
parent 9df4f3dcde
commit 2c013247a9
6 changed files with 81 additions and 11 deletions
+4 -1
View File
@@ -132,11 +132,14 @@ export const PROJECTILE = {
export const WORLD_EFFECT = {
INTERVAL: 4000,
AREA_TILES: 15,
SIZE_SCALE_VARIANCE: 3,
FRAMES: 7,
FRAME_RATE: 14,
FALL_DURATION: 920,
FALL_TRAVEL_TILES: 8,
VISUAL_SCALE: 50,
METEOR_SHAKE_DURATION_MS: 150,
METEOR_SHAKE_INTENSITY: 0.004,
// 0 keeps target selection proportional to living units.
// 1 adds pressure when a team's living share exceeds its paid spawn share.
DOMINANCE_TARGETING_MULTIPLIER: 0.5,
@@ -144,7 +147,7 @@ export const WORLD_EFFECT = {
FROST_DAMAGE: 45,
FROST_STUN_DURATION: 2000,
FROST_STUN_TINT: 0x82e9ff,
FROST_DURATION: 20000,
FROST_DURATION: 2000,
FROST_SPEED_MULTIPLIER: 0.55,
SUDDEN_DEATH: {
ENABLED: false,
+47 -6
View File
@@ -125,7 +125,7 @@ function triggerWorldEffect(scene) {
}
const target = chooseWorldEffectTarget(livingFighters);
const zone = createEffectZone(target);
const zone = createEffectZone(target, resolveWorldEffectSizeScale());
// Sudden Death 상태이고 냉기 고정 설정이 되어있으면 무조건 냉기 메테오
if ((scene.isSuddenDeath && WORLD_EFFECT.SUDDEN_DEATH.FORCE_FROST) || Phaser.Math.Between(0, 1) === 0) {
@@ -218,7 +218,7 @@ function spawnMeteor(scene, zone) {
onImpact: () => {
scene.tweens.killTweensOf(marker);
marker.setAlpha(1);
scene.cameras.main.shake(150, 0.004);
applyMeteorImpactShake(scene, zone);
resolveImpactDamage(scene, zone, WORLD_EFFECT.METEOR_DAMAGE);
},
onAnimationComplete: () => {
@@ -239,6 +239,7 @@ function spawnFrostZone(scene, zone) {
disposeCombatObject(scene, marker);
},
onImpact: () => {
applyMeteorImpactShake(scene, zone);
resolveImpactDamage(scene, zone, WORLD_EFFECT.FROST_DAMAGE, (fighter) => {
applyFrostStun(scene, fighter);
});
@@ -261,7 +262,7 @@ function dropWorldEffectSprite(
const sprite = scene.add
.sprite(trajectory.startX, trajectory.startY, effectKey, 0)
.setDepth(3)
.setScale(WORLD_EFFECT.VISUAL_SCALE)
.setScale(resolveWorldEffectVisualScale(zone))
.setFlipX(trajectory.flipX)
.setAngle(trajectory.angle)
.setAlpha(0.9);
@@ -300,6 +301,40 @@ function worldEffectAnimationKey(effectKey) {
return `${effectKey}-anim`;
}
function resolveWorldEffectSizeScale() {
const variance = Math.max(0, Number(WORLD_EFFECT.SIZE_SCALE_VARIANCE) || 0);
if (variance === 0) {
return 1;
}
const minScale = Math.max(0.1, 1 - variance);
const maxScale = 1 + variance;
return Phaser.Math.FloatBetween(minScale, maxScale);
}
function resolveWorldEffectVisualScale(zone) {
const baseScale = Math.max(0.01, Number(WORLD_EFFECT.VISUAL_SCALE) || 1);
return baseScale * Math.max(0.1, Number(zone?.sizeScale) || 1);
}
function applyMeteorImpactShake(scene, zone) {
const sizeScale = Math.max(0.1, Number(zone?.sizeScale) || 1);
const duration = Math.round(
Math.max(0, Number(WORLD_EFFECT.METEOR_SHAKE_DURATION_MS) || 0)
* Math.sqrt(sizeScale),
);
const intensity =
Math.max(0, Number(WORLD_EFFECT.METEOR_SHAKE_INTENSITY) || 0) * sizeScale;
if (duration <= 0 || intensity <= 0) {
return;
}
scene.cameras.main.shake(duration, intensity);
}
function createFallTrajectory(zone) {
const distance = ARENA.TILE_SIZE * WORLD_EFFECT.FALL_TRAVEL_TILES;
const isLeftHalf = zone.centerX < ARENA.SIZE / 2;
@@ -313,16 +348,22 @@ function createFallTrajectory(zone) {
};
}
function createEffectZone(target) {
const size = ARENA.TILE_SIZE * WORLD_EFFECT.AREA_TILES;
function createEffectZone(target, sizeScale = 1) {
const areaTiles = Math.max(
1,
(Number(WORLD_EFFECT.AREA_TILES) || 1) * Math.max(0.1, Number(sizeScale) || 1),
);
const size = ARENA.TILE_SIZE * areaTiles;
const centerX = target.body?.center.x ?? target.x;
const centerY = target.body?.center.y ?? target.y;
return {
areaTiles,
bounds: new Phaser.Geom.Rectangle(centerX - size / 2, centerY - size / 2, size, size),
centerX,
centerY,
marker: null,
sizeScale,
};
}
@@ -336,7 +377,7 @@ function createZoneMarker(scene, zone, color) {
marker.strokeRect(x, y, width, height);
marker.lineStyle(1, color, 0.34);
for (let index = 1; index < WORLD_EFFECT.AREA_TILES; index += 1) {
for (let index = 1; index < zone.areaTiles; index += 1) {
const offset = index * ARENA.TILE_SIZE;
marker.lineBetween(x + offset, y, x + offset, y + height);
marker.lineBetween(x, y + offset, x + width, y + offset);