Day night cycle

This commit is contained in:
2026-09-26 11:03:07 -03:00
parent 8f32a59bd6
commit 8b549162c4
16 changed files with 244 additions and 6 deletions
+67
View File
@@ -0,0 +1,67 @@
// the day and night cycle. world time counts ticks since 06:00 of day 1, it never wraps around
import { TICKS_PER_SECOND } from "./constants.ts";
// 30 minutes of day, 06:00 to 18:00
export const DAY_TICKS = 30 * 60 * TICKS_PER_SECOND;
// 10 minutes of night, 18:00 to 06:00
export const NIGHT_TICKS = 10 * 60 * TICKS_PER_SECOND;
export const CYCLE_TICKS = DAY_TICKS + NIGHT_TICKS;
// dusk right after sunset and dawn right before sunrise, so the whole day is bright
export const TWILIGHT_TICKS = 60 * TICKS_PER_SECOND;
// in game hours are longer during the day than at night, since both halves are 12 hours
const DAY_TICKS_PER_HOUR = DAY_TICKS / 12;
const NIGHT_TICKS_PER_HOUR = NIGHT_TICKS / 12;
// from midnight to 06:00, to count days from midnight
const TICKS_BEFORE_SIX = 6 * NIGHT_TICKS_PER_HOUR;
// named times of day, as ticks into the cycle
export const TIMES_OF_DAY: Record<string, number> = {
day: 0,
noon: 6 * DAY_TICKS_PER_HOUR,
sunset: DAY_TICKS,
night: DAY_TICKS + TWILIGHT_TICKS,
midnight: DAY_TICKS + 6 * NIGHT_TICKS_PER_HOUR,
};
// ticks into the current cycle, 0 is 06:00
export function time_of_day(time: number): number {
return ((time % CYCLE_TICKS) + CYCLE_TICKS) % CYCLE_TICKS;
}
export function is_day(time: number): boolean {
return time_of_day(time) < DAY_TICKS;
}
// the day number, starting at 1 and going up at midnight, and the time on a 24 hour clock
export function clock(time: number): { day: number; hour: number; minute: number } {
const t = time_of_day(time);
const hours = t < DAY_TICKS ? 6 + t / DAY_TICKS_PER_HOUR : 18 + (t - DAY_TICKS) / NIGHT_TICKS_PER_HOUR;
const total_minutes = Math.floor(hours * 60) % (24 * 60);
return {
day: Math.floor((time + TICKS_BEFORE_SIX) / CYCLE_TICKS) + 1,
hour: Math.floor(total_minutes / 60),
minute: total_minutes % 60,
};
}
// like "Day 3, 14:05"
export function format_clock(time: number): string {
const { day, hour, minute } = clock(time);
return `Day ${day}, ${String(hour).padStart(2, "0")}:${String(minute).padStart(2, "0")}`;
}
// how much daylight there is, 1 all day and 0 in the middle of the night, fading through dusk and dawn.
// time can be fractional, for drawing between ticks
export function daylight(time: number): number {
const t = time_of_day(time);
if (t < DAY_TICKS) return 1;
const into_night = t - DAY_TICKS;
const until_day = CYCLE_TICKS - t;
const fade = Math.min(1, into_night / TWILIGHT_TICKS, until_day / TWILIGHT_TICKS);
return 1 - smoothstep(fade);
}
function smoothstep(x: number) {
return x * x * (3 - 2 * x);
}