fiirst
This commit is contained in:
parent
4f5cf7d425
commit
2d42f7f487
7 changed files with 4065 additions and 0 deletions
12
js/editor-actions.js
Normal file
12
js/editor-actions.js
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
(function () {
|
||||
'use strict';
|
||||
|
||||
const root = window.PixelIslandModules ||= {};
|
||||
|
||||
root.EditorActions = {
|
||||
apply(snapshot, pushHistory, mutate) {
|
||||
pushHistory(snapshot());
|
||||
mutate();
|
||||
}
|
||||
};
|
||||
})();
|
||||
68
js/lighting.js
Normal file
68
js/lighting.js
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
(function () {
|
||||
'use strict';
|
||||
|
||||
const root = window.PixelIslandModules ||= {};
|
||||
const clamp = (value, min, max) => Math.max(min, Math.min(max, value));
|
||||
const lerp = (a, b, t) => a + (b - a) * t;
|
||||
const mod = (n, m) => ((n % m) + m) % m;
|
||||
|
||||
function getCelestialLightForMinute(minute) {
|
||||
const isNight = minute >= 6;
|
||||
const local = isNight ? (minute - 6) / 4 : minute / 6;
|
||||
const t = clamp(local, 0, 1);
|
||||
const eased = t * t * (3 - 2 * t);
|
||||
const elevation = Math.max(.08, Math.sin(t * Math.PI));
|
||||
const sourceX = isNight ? lerp(-1.05, 1.05, eased) : lerp(1.18, -1.18, eased);
|
||||
const sourceY = isNight ? -.46 - elevation * .24 : -.58 - elevation * .34;
|
||||
return {
|
||||
x: sourceX,
|
||||
y: sourceY,
|
||||
elevation,
|
||||
isNight,
|
||||
shadeAlpha: isNight ? .18 : lerp(.20, .08, elevation)
|
||||
};
|
||||
}
|
||||
|
||||
function getShadowForMinute(minute) {
|
||||
const light = getCelestialLightForMinute(minute);
|
||||
const length = lerp(light.isNight ? 1.35 : 1.9, light.isNight ? .85 : .52, light.elevation);
|
||||
return {
|
||||
x: -light.x * 6.5 * length,
|
||||
y: Math.min(-1.8, light.y * 4.2 * length),
|
||||
length,
|
||||
alpha: light.isNight ? .085 : lerp(.27, .12, light.elevation)
|
||||
};
|
||||
}
|
||||
|
||||
function getPhase(dayMs, now = Date.now()) {
|
||||
const t = mod(now, dayMs);
|
||||
const minute = t / 60000;
|
||||
const stops = [
|
||||
{ at: 0, key: 'morning', label: 'Morning', darkness: 0.18, tint: [255, 208, 144, 0.12] },
|
||||
{ at: 1, key: 'day', label: 'Day', darkness: 0.00, tint: [255, 255, 255, 0.00] },
|
||||
{ at: 5, key: 'day', label: 'Day', darkness: 0.00, tint: [255, 255, 255, 0.00] },
|
||||
{ at: 6, key: 'evening', label: 'Evening', darkness: 0.18, tint: [255, 146, 114, 0.14] },
|
||||
{ at: 10, key: 'night', label: 'Night', darkness: 0.48, tint: [36, 47, 96, 0.18] }
|
||||
];
|
||||
let a = stops[0], b = stops[1];
|
||||
for (let i = 0; i < stops.length - 1; i++) {
|
||||
if (minute >= stops[i].at && minute < stops[i + 1].at) { a = stops[i]; b = stops[i + 1]; break; }
|
||||
if (minute >= 6) { a = stops[3]; b = stops[4]; }
|
||||
}
|
||||
const localT = clamp((minute - a.at) / Math.max(0.0001, b.at - a.at), 0, 1);
|
||||
const eased = localT * localT * (3 - 2 * localT);
|
||||
const tint = a.tint.map((v, i) => lerp(v, b.tint[i], eased));
|
||||
const label = minute < 1 ? 'Morning' : minute < 5 ? 'Day' : minute < 6 ? 'Evening' : 'Night';
|
||||
return {
|
||||
key: label.toLowerCase(),
|
||||
label,
|
||||
progress: t / dayMs,
|
||||
darkness: lerp(a.darkness, b.darkness, eased),
|
||||
tint: `rgba(${Math.round(tint[0])}, ${Math.round(tint[1])}, ${Math.round(tint[2])}, ${tint[3].toFixed(3)})`,
|
||||
light: getCelestialLightForMinute(minute),
|
||||
shadow: getShadowForMinute(minute)
|
||||
};
|
||||
}
|
||||
|
||||
root.Lighting = { getPhase, getShadowForMinute, getCelestialLightForMinute };
|
||||
})();
|
||||
11
js/render-pipeline.js
Normal file
11
js/render-pipeline.js
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
(function () {
|
||||
'use strict';
|
||||
|
||||
const root = window.PixelIslandModules ||= {};
|
||||
|
||||
root.RenderPipeline = {
|
||||
run(stages, context) {
|
||||
for (const stage of stages) stage(context);
|
||||
}
|
||||
};
|
||||
})();
|
||||
24
js/vector.js
Normal file
24
js/vector.js
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
(function () {
|
||||
'use strict';
|
||||
|
||||
const root = window.PixelIslandModules ||= {};
|
||||
|
||||
root.Vec2 = {
|
||||
add(a, b) {
|
||||
return { x: a.x + b.x, y: a.y + b.y };
|
||||
},
|
||||
sub(a, b) {
|
||||
return { x: a.x - b.x, y: a.y - b.y };
|
||||
},
|
||||
scale(v, amount) {
|
||||
return { x: v.x * amount, y: v.y * amount };
|
||||
},
|
||||
length(v) {
|
||||
return Math.hypot(v.x, v.y);
|
||||
},
|
||||
normalize(v) {
|
||||
const length = Math.hypot(v.x, v.y) || 1;
|
||||
return { x: v.x / length, y: v.y / length };
|
||||
}
|
||||
};
|
||||
})();
|
||||
Loading…
Add table
Add a link
Reference in a new issue