Compare commits

...

4 Commits

Author SHA1 Message Date
ElementalAlchemist f6f42fbb45 Minor cleanup of the standard mode 1 week ago
ElementalAlchemist 96a71c3519 Add point progress mode
Adds a new mode that makes the full width be exactly one point, and the bus drives across the canvas.

This also resizes the canvas to the requested size (1580x62).
1 week ago
ElementalAlchemist 5410b5c1fe Shorten refresh interval to 2.5 seconds 1 week ago
ElementalAlchemist 8b7b87d450 Fix bus stops disappearing early
The existing code tried to avoid infinite loops due to floating point math. It turns out the +1 was overzealous and caused bus stop signs to disappear before expected at high scale numbers.
1 week ago

Binary file not shown.

Before

Width:  |  Height:  |  Size: 439 B

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 520 B

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 173 B

After

Width:  |  Height:  |  Size: 4.2 KiB

@ -3,7 +3,7 @@
margin-top: 20px; margin-top: 20px;
} }
#scale-disclaimer { .settings-disclaimer {
font-size: 75%; font-size: 75%;
font-style: italic; font-style: italic;
} }

@ -7,13 +7,18 @@
<script src="drive.js"></script> <script src="drive.js"></script>
</head> </head>
<body> <body>
<canvas id="road" width="1920" height="100"></canvas> <canvas id="road" width="1580" height="62"></canvas>
<label id="scale"> <label id="scale">
Scale: Scale:
<input id="scale-input" type="number" value="1" min="0.1" step="0.1" /> <input id="scale-input" type="number" value="1" min="0.1" step="0.1" />
</label> </label>
<p id="scale-disclaimer"> <label id="point-progress">
Scale modifications will be applied on the next update, which occur every 10 seconds. <input id="point-progress-checkbox" type="checkbox" />
Point Progress Mode
</label>
<p class="settings-disclaimer">
Settings modifications will be applied on the next update, which occur every 2.5 seconds.
</p> </p>
<p class="settings-disclaimer">The scale setting is ignored in Point Progress Mode.</p>
</body> </body>
</html> </html>

@ -21,10 +21,8 @@ const COLORS = {
}, },
}; };
const KEY_OUT_COLOR = "#2b6ec6";
// The width from the left side of the bus image to the front of the bus // The width from the left side of the bus image to the front of the bus
const BUS_FRONT_OFFSET = 73; const BUS_FRONT_OFFSET = 72;
// Start time of each day phase // Start time of each day phase
const DAY_START_MINUTES = 450; const DAY_START_MINUTES = 450;
@ -49,7 +47,12 @@ const POINT_IMAGE = new Image();
POINT_IMAGE.src = "point.png"; POINT_IMAGE.src = "point.png";
// This should match the HTML canvas width // This should match the HTML canvas width
const CANVAS_PIXEL_WIDTH = 1920; const CANVAS_PIXEL_WIDTH = 1580;
const BUS_TRAVEL_WIDTH = CANVAS_PIXEL_WIDTH - BUS_FRONT_OFFSET;
const PIXELS_PER_MILE = BUS_TRAVEL_WIDTH / 360;
const PIXELS_PER_MINUTE = BUS_TRAVEL_WIDTH / 480;
const FULL_SPEED_MILES_PER_MINUTE = 0.75;
function nextPhase(timeOfDay) { function nextPhase(timeOfDay) {
switch (timeOfDay) { switch (timeOfDay) {
@ -81,17 +84,12 @@ function drawBackground(context, timeOfDay, leftX, width) {
const groundColor = COLORS[timeOfDay].ground; const groundColor = COLORS[timeOfDay].ground;
const surfaceColor = COLORS[timeOfDay].surface; const surfaceColor = COLORS[timeOfDay].surface;
context.fillStyle = KEY_OUT_COLOR;
context.fillRect(leftX, 80, width, 20);
context.fillStyle = COLORS[timeOfDay].sky; context.fillStyle = COLORS[timeOfDay].sky;
context.fillRect(leftX, 0, width, 80); context.fillRect(leftX, 0, width, 56);
context.fillStyle = COLORS[timeOfDay].surface; context.fillStyle = COLORS[timeOfDay].surface;
context.fillRect(leftX, 80, width, 1); context.fillRect(leftX, 56, width, 1);
context.fillStyle = COLORS[timeOfDay].ground; context.fillStyle = COLORS[timeOfDay].ground;
context.fillRect(leftX, 81, width, 7); context.fillRect(leftX, 57, width, 5);
context.fillRect(leftX, 89, width, 3);
context.fillRect(leftX, 94, width, 2);
context.fillRect(leftX, 99, width, 1);
} }
async function drawRoad() { async function drawRoad() {
@ -108,19 +106,62 @@ async function drawRoad() {
const context = canvas.getContext("2d"); const context = canvas.getContext("2d");
// Clear the previous canvas before starting // Clear the previous canvas before starting
context.clearRect(0, 0, CANVAS_PIXEL_WIDTH, 100); context.clearRect(0, 0, CANVAS_PIXEL_WIDTH, 62);
// Background the whole thing as the key-out color in case we need to bail
// out before drawing (e.g. we're in a non-DB game menu) const pointModeCheckbox = document.getElementById("point-progress-checkbox");
context.fillStyle = KEY_OUT_COLOR; if (pointModeCheckbox.checked) {
context.fillRect(0, 0, CANVAS_PIXEL_WIDTH, 100); drawRoadPoint(context, busData);
} else {
drawRoadDynamic(context, busData);
}
}
function drawRoadPoint(context, busData) {
const busDistance = (busData.odometer + 250.7) % 360;
const busRemainingDistance = 360 - busDistance;
const busRemainingDistancePixels = busRemainingDistance * PIXELS_PER_MILE;
const busDistancePixels = busDistance * PIXELS_PER_MILE;
let x = busDistancePixels + BUS_FRONT_OFFSET;
drawBackground(context, busData.timeofday, 0, x);
let currentTimeOfDay = busData.timeofday;
let currentTime = busData.clock_minutes;
while (x < CANVAS_PIXEL_WIDTH) {
const nextTimeOfDay = nextPhase(currentTimeOfDay);
const nextStartTime = phaseStartTime(nextTimeOfDay);
let thisDuration = nextStartTime - currentTime;
if (thisDuration < 0) {
thisDuration += 1440;
}
const pixelWidth = thisDuration * PIXELS_PER_MINUTE;
drawBackground(context, currentTimeOfDay, x, pixelWidth);
x += pixelWidth;
currentTimeOfDay = nextTimeOfDay;
currentTime += thisDuration;
}
context.drawImage(POINT_IMAGE, CANVAS_PIXEL_WIDTH - POINT_OFFSET, 0);
for (const busStopDistance of BUS_STOP_POSITIONS) {
const busStopPixelPosition =
BUS_FRONT_OFFSET + PIXELS_PER_MILE * busStopDistance - BUS_STOP_OFFSET;
context.drawImage(BUS_STOP_IMAGE, busStopPixelPosition, 16);
}
if (busData.timeofday === "night") {
context.drawImage(BUS_NIGHT_IMAGE, busDistancePixels, 32);
} else {
context.drawImage(BUS_DAY_IMAGE, busDistancePixels, 32);
}
}
const currentTime = busData.clock_minutes; function drawRoadDynamic(context, busData) {
const distance = busData.odometer; const distance = busData.odometer;
const timeOfDay = busData.timeofday; const timeOfDay = busData.timeofday;
drawBackground(context, timeOfDay, 0, BUS_FRONT_OFFSET); drawBackground(context, timeOfDay, 0, BUS_FRONT_OFFSET);
const maxWidth = CANVAS_PIXEL_WIDTH - BUS_FRONT_OFFSET;
// The default scaling factor (1) is 20 seconds per pixel at max speed. // The default scaling factor (1) is 20 seconds per pixel at max speed.
// This gives us // This gives us
// - 3px per minute // - 3px per minute
@ -131,13 +172,11 @@ async function drawRoad() {
} }
const startMinute = busData.clock_minutes; const startMinute = busData.clock_minutes;
const timeDuration = maxWidth / (3 * scaleFactor);
let previousTime = startMinute; let previousTime = startMinute;
let previousTimeOfDay = timeOfDay; let previousTimeOfDay = timeOfDay;
let remainingDuration = timeDuration;
let x = BUS_FRONT_OFFSET; let x = BUS_FRONT_OFFSET;
while (remainingDuration > 0) { while (x < CANVAS_PIXEL_WIDTH) {
const nextTimeOfDay = nextPhase(previousTimeOfDay); const nextTimeOfDay = nextPhase(previousTimeOfDay);
const nextStartTime = phaseStartTime(nextTimeOfDay); const nextStartTime = phaseStartTime(nextTimeOfDay);
@ -146,11 +185,9 @@ async function drawRoad() {
thisDuration += 1440; thisDuration += 1440;
} }
// TODO Figure out scaling factor
const pixelWidth = thisDuration * 3 * scaleFactor; const pixelWidth = thisDuration * 3 * scaleFactor;
drawBackground(context, previousTimeOfDay, x, pixelWidth); drawBackground(context, previousTimeOfDay, x, pixelWidth);
remainingDuration -= thisDuration;
previousTime = nextStartTime; previousTime = nextStartTime;
previousTimeOfDay = nextTimeOfDay; previousTimeOfDay = nextTimeOfDay;
x += pixelWidth; x += pixelWidth;
@ -187,7 +224,7 @@ async function drawRoad() {
const distanceTrackedOnRoute = distanceTracked % 360; const distanceTrackedOnRoute = distanceTracked % 360;
let nextBusStopPosition = null; let nextBusStopPosition = null;
for (const busStopPosition of BUS_STOP_POSITIONS) { for (const busStopPosition of BUS_STOP_POSITIONS) {
if (busStopPosition >= distanceTrackedOnRoute + 1) { if (busStopPosition >= distanceTrackedOnRoute + 0.05) {
nextBusStopPosition = busStopPosition; nextBusStopPosition = busStopPosition;
break; break;
} }
@ -198,17 +235,17 @@ async function drawRoad() {
const nextBusStopDistance = nextBusStopPosition - distanceTrackedOnRoute; const nextBusStopDistance = nextBusStopPosition - distanceTrackedOnRoute;
distanceTracked += nextBusStopDistance; distanceTracked += nextBusStopDistance;
x += nextBusStopDistance * 4 * scaleFactor; x += nextBusStopDistance * 4 * scaleFactor;
context.drawImage(BUS_STOP_IMAGE, x - BUS_STOP_OFFSET, 0); context.drawImage(BUS_STOP_IMAGE, x - BUS_STOP_OFFSET, 16);
} }
if (timeOfDay === "night") { if (timeOfDay === "night") {
context.drawImage(BUS_NIGHT_IMAGE, 0, 0); context.drawImage(BUS_NIGHT_IMAGE, 0, 32);
} else { } else {
context.drawImage(BUS_DAY_IMAGE, 0, 0); context.drawImage(BUS_DAY_IMAGE, 0, 32);
} }
} }
window.addEventListener("DOMContentLoaded", (event) => { window.addEventListener("DOMContentLoaded", (event) => {
drawRoad(); drawRoad();
setInterval(drawRoad, 10000); setInterval(drawRoad, 2500);
}); });

Binary file not shown.

Before

Width:  |  Height:  |  Size: 397 B

After

Width:  |  Height:  |  Size: 4.4 KiB

Loading…
Cancel
Save