Skip to content

季节系统

四季循环驱动世界视觉变化。一年 365 天,每季 91 天,循环往复。

概述

季节是世界的"心跳"。它控制:

  • 地形 tile 的外观(草地、水面)
  • 树木/植物的状态(茂盛、枯黄、枯萎、开花)
  • 天气概率(春雨多、冬天雪多)
  • 环境粒子(樱花、萤火虫、落叶、飘雪)
  • 建筑色调(秋暖冬冷)

时间模型

一年 = 365 天
每季 = 91 天(365 / 4,余1天归春天)

春:Day 0-90
夏:Day 91-181
秋:Day 182-272
冬:Day 273-364

季节状态机

ts
type Season = 'spring' | 'summer' | 'autumn' | 'winter';

interface SeasonState {
  season: Season;
  dayInSeason: number;        // 0-90
  yearDay: number;            // 0-364
  year: number;               // 第几年
  isTransitioning: boolean;   // 是否在过渡期
  transitionProgress: number; // 0-1,过渡进度
}

function getSeasonState(gameDay: number): SeasonState {
  const year = Math.floor(gameDay / 365);
  const yearDay = gameDay % 365;
  const seasonIndex = Math.floor(yearDay / 91);
  const dayInSeason = yearDay % 91;

  const seasons: Season[] = ['spring', 'summer', 'autumn', 'winter'];
  const TRANSITION_START = 81; // 每季最后10天开始过渡
  const TRANSITION_DAYS = 10;

  const isTransitioning = dayInSeason >= TRANSITION_START;
  const transitionProgress = isTransitioning
    ? (dayInSeason - TRANSITION_START) / TRANSITION_DAYS
    : 0;

  return {
    season: seasons[seasonIndex],
    dayInSeason,
    yearDay,
    year,
    isTransitioning,
    transitionProgress,
  };
}

季节视觉定义

🌸 春 (Day 0-90)

元素视觉
草地嫩绿 #7cba3d#8fd44f
树木新叶,浅绿树冠,部分开花
花卉全部绽放(樱花、野花)
水面清澈,浅蓝
光照暖白,亮度适中
粒子樱花花瓣飘落(粉色,慢速)
天气倾向30% 晴天、40% 阴天、30% 小雨

☀️ 夏 (Day 91-181)

元素视觉
草地深绿 #5a9e2f
树木茂密树冠,深绿
花卉部分凋谢,保留向日葵等夏季花卉
水面深蓝,偶有蜻蜓
光照明亮,偏暖黄
粒子萤火虫(黄色小点,夜间出没)、蜻蜓
天气倾向50% 晴天、20% 阴天、20% 雷阵雨、10% 多云

🍂 秋 (Day 182-272)

元素视觉
草地枯黄 #c9a66b#a68a4a
树木红叶/黄叶,逐渐落叶
花卉大部分凋谢,保留菊花
水面偏灰,反射落叶
光照暖橙,黄昏感
粒子落叶旋转飘落(红/橙/黄,中速)
天气倾向25% 晴天、35% 阴天、25% 小雨、15% 大风

❄️ 冬 (Day 273-364)

元素视觉
草地灰白 #d4d4d4#e8e8e8
树木枯枝,积雪覆盖
花卉全部枯萎,温室除外
水面部分结冰,偏白蓝
光照冷蓝,亮度低
粒子飘雪(白色,慢速)、偶尔暴风雪(密集快速)
天气倾向20% 晴天、30% 阴天、30% 小雪、20% 暴风雪

渐变过渡

季节切换不是突变,而是平滑渐变。

过渡时机

每个季节的 最后 10 天(Day 81-90)为过渡期。

春末 (Day 81-90):春 → 夏  草地嫩绿渐变深绿
夏末 (Day 81-90):夏 → 秋  草地深绿渐变枯黄
秋末 (Day 81-90):秋 → 冬  草地枯黄渐变灰白
冬末 (Day 81-90):冬 → 春  草地灰白渐变嫩绿

过渡实现

地形 Tile — 交叉淡入淡出

ts
function renderTerrainWithTransition(state: SeasonState) {
  const currentSeasonSprite = getSeasonSprite(state.season);
  const nextSeasonSprite = getNextSeasonSprite(state.season);

  if (state.isTransitioning) {
    const t = easeInOutCubic(state.transitionProgress);
    currentSeasonSprite.alpha = 1 - t;
    nextSeasonSprite.alpha = t;
  } else {
    currentSeasonSprite.alpha = 1;
    nextSeasonSprite.alpha = 0;
  }
}

function easeInOutCubic(t: number): number {
  return t < 0.5
    ? 4 * t * t * t
    : 1 - Math.pow(-2 * t + 2, 3) / 2;
}

建筑 — 色调渐变

ts
function applySeasonTint(building: Sprite, state: SeasonState) {
  const tints: Record<Season, number> = {
    spring: 0xFFFFFF,  // 正常
    summer: 0xFFFAE6,  // 微暖
    autumn: 0xFFE0B2,  // 暖橙
    winter: 0xD4E5F7,  // 冷蓝
  };

  if (state.isTransitioning) {
    const from = tints[state.season];
    const to = tints[getNextSeason(state.season)];
    building.tint = lerpColor(from, to, easeInOutCubic(state.transitionProgress));
  } else {
    building.tint = tints[state.season];
  }
}

雪顶叠加层

ts
function updateSnowOverlay(building: Container, state: SeasonState) {
  const snowOverlay = building.getChildByName('snow_overlay');
  if (!snowOverlay) return;

  if (state.season === 'winter') {
    if (state.isTransitioning) {
      // 冬末 → 春:雪融化
      snowOverlay.alpha = 1 - easeInOutCubic(state.transitionProgress);
    } else {
      snowOverlay.alpha = 1;
    }
  } else if (state.season === 'autumn' && state.isTransitioning) {
    // 秋末 → 冬:积雪开始
    snowOverlay.alpha = easeInOutCubic(state.transitionProgress);
  } else {
    snowOverlay.alpha = 0;
  }
}

季节对世界模拟的影响

季节NPC 行为倾向经济影响
户外活动增多、播种农产品价格低
工作效率高、夜生活活跃旅游旺季
收获忙碌、储备物资农产品价格高
室内活动多、社交频繁燃料/食物需求高

渲染层级(含季节)

1. 地形层(季节化 tile)
2. 道路层
3. 水域层(季节化水面 + 结冰叠加)
4. 建筑底层(阴影)
5. 自然装饰层(季节化树木/花卉/灌木)
6. 建筑主体层(色调滤镜 + 雪顶叠加)
7. 道具层(围栏、路灯等)
8. 角色层
9. 建筑顶层(遮挡角色的屋顶部分)
10. 自然装饰顶层(遮挡角色的树冠)
11. 天气粒子层
12. 天气遮罩层(雾气/色调偏移)
13. UI 层

配置参考

ts
// src/config/seasonConfig.ts
export const SEASON_CONFIG = {
  DAYS_PER_YEAR: 365,
  DAYS_PER_SEASON: 91,
  TRANSITION_DAYS: 10,
  TRANSITION_START_DAY: 81,
} as const;

export const SEASON_COLORS = {
  spring: { grass: '#7cba3d', accent: '#ff9ec4', light: '#fff8f0' },
  summer: { grass: '#5a9e2f', accent: '#ffd700', light: '#fffff0' },
  autumn: { grass: '#c9a66b', accent: '#ff6b35', light: '#fff0e0' },
  winter: { grass: '#d4d4d4', accent: '#87ceeb', light: '#e8f0ff' },
} as const;

📐 天气系统见 天气系统 📐 地图设计见 地图设计 🎨 美术规范见 Art Bible

Released under the MIT License.