Day night cycle
This commit is contained in:
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user