Add driveclock to thrimbletrimmer
After Width: | Height: | Size: 439 B |
After Width: | Height: | Size: 520 B |
After Width: | Height: | Size: 196 B |
After Width: | Height: | Size: 196 B |
After Width: | Height: | Size: 196 B |
After Width: | Height: | Size: 196 B |
@ -0,0 +1,54 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#road-container {
|
||||||
|
width: 100%;
|
||||||
|
height: 100px;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
position: absolute;
|
||||||
|
// margin: 980px 0 0 -100px; // uncomment to move to bottom of screen
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
#road-container div {
|
||||||
|
height: 100px;
|
||||||
|
width: 100%;
|
||||||
|
position: absolute;
|
||||||
|
background-position: 0px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sky-left {
|
||||||
|
z-index: 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sky-right {
|
||||||
|
z-index: 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
#stops {
|
||||||
|
z-index: 6;
|
||||||
|
background-image: url(stops.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
#bus {
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
margin-left: 27px;
|
||||||
|
z-index: 8;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="road-container">
|
||||||
|
<div id="bus"></div>
|
||||||
|
<div id="sky-left"></div>
|
||||||
|
<div id="sky-right"></div>
|
||||||
|
<div id="stops"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="drive.js"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
@ -0,0 +1,120 @@
|
|||||||
|
|
||||||
|
const PAGE_WIDTH = 1920;
|
||||||
|
const MINUTES_PER_PAGE = 60;
|
||||||
|
const POINT_WIDTH = PAGE_WIDTH * 8 * 60 / MINUTES_PER_PAGE;
|
||||||
|
const MILES_PER_PAGE = 45;
|
||||||
|
const BUS_POSITION_X = 93;
|
||||||
|
const BASE_ODO = 109.3;
|
||||||
|
const UPDATE_INTERVAL_MS = 5000
|
||||||
|
const WUBLOADER_URL = "";
|
||||||
|
const SKY_URLS = {
|
||||||
|
day: "db_day.png",
|
||||||
|
dawn: "db_dawn.png",
|
||||||
|
dusk: "db_dusk.png",
|
||||||
|
night: "db_night.png",
|
||||||
|
};
|
||||||
|
const BUS_URLS = {
|
||||||
|
day: "bus_day.png",
|
||||||
|
dawn: "bus_day.png",
|
||||||
|
dusk: "bus_day.png",
|
||||||
|
night: "bus_night.png",
|
||||||
|
};
|
||||||
|
|
||||||
|
function setSkyElements(left, right, timeToTransition) {
|
||||||
|
const leftElement = document.getElementById("sky-left");
|
||||||
|
const rightElement = document.getElementById("sky-right");
|
||||||
|
const busElement = document.getElementById("bus");
|
||||||
|
|
||||||
|
leftElement.style.backgroundImage = `url(${SKY_URLS[left]})`;
|
||||||
|
rightElement.style.backgroundImage = `url(${SKY_URLS[right]})`;
|
||||||
|
|
||||||
|
if (left === right) {
|
||||||
|
leftElement.style.width = "100%";
|
||||||
|
} else {
|
||||||
|
const transitionPercent = timeToTransition / MINUTES_PER_PAGE;
|
||||||
|
leftElement.style.width = `${transitionPercent * 100}%`
|
||||||
|
}
|
||||||
|
|
||||||
|
bus.style.backgroundImage = `url(${BUS_URLS[left]})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function nextSkyTransition(timeofday, clock) {
|
||||||
|
switch (timeofday) {
|
||||||
|
case "dawn":
|
||||||
|
case "day":
|
||||||
|
return [19 * 60, "dusk"]; // 7pm
|
||||||
|
case "dusk":
|
||||||
|
return [20 * 60, "night"]; // 8pm
|
||||||
|
case "night":
|
||||||
|
return [6 * 60 + 40, "dawn"]; // 6:40am
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setSky(timeofday, clock) {
|
||||||
|
const [transition, newSky] = nextSkyTransition(timeofday, clock);
|
||||||
|
// 1440 minutes in 24h, this code will return time remaining even if
|
||||||
|
// the transition is in the morning and we're currently in the evening.
|
||||||
|
const timeToTransition = (1440 + transition - clock) % 1440;
|
||||||
|
if (timeToTransition < MINUTES_PER_PAGE) {
|
||||||
|
// Transition on screen
|
||||||
|
setSkyElements(timeofday, newSky, timeToTransition);
|
||||||
|
} else {
|
||||||
|
// No transition on screen
|
||||||
|
setSkyElements(timeofday, timeofday, undefined);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setOdo(odo) {
|
||||||
|
const distancePixels = PAGE_WIDTH * (odo - BASE_ODO) / MILES_PER_PAGE;
|
||||||
|
const offset = (BUS_POSITION_X - distancePixels) % POINT_WIDTH;
|
||||||
|
|
||||||
|
const stopsElement = document.getElementById("stops");
|
||||||
|
stopsElement.style.backgroundPosition = `${offset}px 0px`;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function update() {
|
||||||
|
const busDataResponse = await fetch(`${WUBLOADER_URL}/thrimshim/bus/buscam`);
|
||||||
|
if (!busDataResponse.ok) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const busData = await busDataResponse.json();
|
||||||
|
console.log("Got data:", busData);
|
||||||
|
setOdo(busData.odometer);
|
||||||
|
setSky(busData.timeofday, busData.clock_minutes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initial conditions, before the first refresh finishes
|
||||||
|
setSky("day", 7 * 60);
|
||||||
|
setOdo(BASE_ODO);
|
||||||
|
|
||||||
|
// Testing mode. Set true to enable.
|
||||||
|
const test = false;
|
||||||
|
if (test) {
|
||||||
|
let h = 0;
|
||||||
|
// Set to how long 1h of in-game time should take in real time
|
||||||
|
const hourTimeMs = 1 * 1000;
|
||||||
|
// Set to how often to update the screen
|
||||||
|
const interval = 30;
|
||||||
|
setInterval(() => {
|
||||||
|
h += interval / hourTimeMs;
|
||||||
|
setOdo(BASE_ODO + 45 * h);
|
||||||
|
if (h < 19) {
|
||||||
|
setSky("day", 60 * h);
|
||||||
|
} else {
|
||||||
|
m = (h % 24) * 60;
|
||||||
|
let tod;
|
||||||
|
if (m < 6 * 60 + 40) {
|
||||||
|
tod = "night";
|
||||||
|
} else if (m < 19 * 60) {
|
||||||
|
tod = "dawn";
|
||||||
|
} else if (m < 20 * 60) {
|
||||||
|
tod = "dusk";
|
||||||
|
} else {
|
||||||
|
tod = "night";
|
||||||
|
}
|
||||||
|
setSky(tod, m);
|
||||||
|
}
|
||||||
|
}, interval);
|
||||||
|
} else {
|
||||||
|
setInterval(update, UPDATE_INTERVAL_MS);
|
||||||
|
}
|
After Width: | Height: | Size: 7.2 KiB |