261 lines
8.1 KiB
JavaScript
261 lines
8.1 KiB
JavaScript
'use strict';
|
|
|
|
const debug = 1;
|
|
let enhancedMode = 1;
|
|
let enableAsserts = 1;
|
|
let devMode = 0;
|
|
let downloadLink, debugMesh, debugTile, debugCapture, debugCanvas;
|
|
let debugGenerativeCanvas=0, debugInfo=0, debugSkipped=0;
|
|
let debugGenerativeCanvasCached, showMap;
|
|
let freeCamPos, freeCamRot, mouseDelta;
|
|
const js13kBuildLevel2 = 0; // more space is needed for js13k
|
|
|
|
function ASSERT(assert, output)
|
|
{ enableAsserts&&(output ? console.assert(assert, output) : console.assert(assert)); }
|
|
function LOG() { console.log(...arguments); }
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
function debugInit()
|
|
{
|
|
freeCamPos = vec3();
|
|
freeCamRot = vec3();
|
|
mouseDelta = vec3();
|
|
debugCanvas = document.createElement('canvas');
|
|
downloadLink = document.createElement('a');
|
|
}
|
|
function debugUpdate()
|
|
{
|
|
if (!devMode)
|
|
return;
|
|
|
|
if (keyWasPressed('KeyG')) // free Cam
|
|
{
|
|
freeCamMode = !freeCamMode;
|
|
if (!freeCamMode)
|
|
{
|
|
document.exitPointerLock();
|
|
cameraPos = vec3();
|
|
cameraRot = vec3();
|
|
}
|
|
}
|
|
if (freeCamMode)
|
|
{
|
|
if (!document.pointerLockElement)
|
|
{
|
|
mainCanvas.requestPointerLock();
|
|
freeCamPos = cameraPos.copy();
|
|
freeCamRot = cameraRot.copy();
|
|
}
|
|
|
|
const input = vec3(
|
|
keyIsDown('KeyD') - keyIsDown('KeyA'),
|
|
keyIsDown('KeyE') - keyIsDown('KeyQ'),
|
|
keyIsDown('KeyW') - keyIsDown('KeyS'));
|
|
|
|
const moveSpeed = keyIsDown('ShiftLeft') ? 500 : 100;
|
|
const turnSpeed = 2;
|
|
const moveDirection = input.rotateX(freeCamRot.x).rotateY(-freeCamRot.y);
|
|
freeCamPos = freeCamPos.add(moveDirection.scale(moveSpeed));
|
|
freeCamRot = freeCamRot.add(vec3(mouseDelta.y,mouseDelta.x).scale(turnSpeed));
|
|
freeCamRot.x = clamp(freeCamRot.x, -PI/2, PI/2);
|
|
mouseDelta = vec3();
|
|
}
|
|
|
|
if (keyWasPressed('Digit1') || keyWasPressed('Digit2'))
|
|
{
|
|
const d = keyWasPressed('Digit2') ? 1 : -1;
|
|
playerVehicle.pos.z += d * checkpointDistance;
|
|
playerVehicle.pos.z = max(playerVehicle.pos.z, 0);
|
|
checkpointTimeLeft = 40;
|
|
debugSkipped = 1;
|
|
}
|
|
if (keyIsDown('Digit3') || keyIsDown('Digit4'))
|
|
{
|
|
const v = keyIsDown('Digit4') ? 1e3 : -1e3;
|
|
playerVehicle.pos.z += v;
|
|
playerVehicle.pos.z = max(playerVehicle.pos.z, 0);
|
|
|
|
const trackInfo = new TrackSegmentInfo(playerVehicle.pos.z);
|
|
playerVehicle.pos.y = trackInfo.offset.y;
|
|
playerVehicle.pos.x = 0;
|
|
|
|
// update world heading based on speed and track turn
|
|
const cameraTrackInfo = new TrackSegmentInfo(cameraOffset);
|
|
worldHeading += v*cameraTrackInfo.offset.x/turnWorldScale;
|
|
debugSkipped = 1;
|
|
}
|
|
if (keyWasPressed('Digit5'))
|
|
checkpointTimeLeft=12
|
|
if (keyWasPressed('Digit6'))
|
|
{
|
|
// randomize track
|
|
trackSeed = randInt(1e9);
|
|
|
|
//initGenerative();
|
|
const endLevel = levelInfoList.pop();
|
|
shuffle(endLevel.scenery);
|
|
shuffle(levelInfoList);
|
|
for(let i=levelInfoList.length; i--;)
|
|
{
|
|
const info = levelInfoList[i];
|
|
info.level = i;
|
|
info.randomize();
|
|
}
|
|
levelInfoList.push(endLevel);
|
|
buildTrack();
|
|
|
|
for(const s in spriteList)
|
|
{
|
|
const sprite = spriteList[s];
|
|
if (sprite instanceof GameSprite)
|
|
sprite.randomize();
|
|
}
|
|
|
|
const playerTrackInfo = new TrackSegmentInfo(playerVehicle.pos.z);
|
|
playerVehicle.pos.y = playerTrackInfo.offset.y;
|
|
//gameStart();
|
|
}
|
|
if (keyWasPressed('Digit7'))
|
|
debugGenerativeCanvas = !debugGenerativeCanvas;
|
|
if (keyWasPressed('Digit0'))
|
|
debugCapture = 1;
|
|
if (keyWasPressed('KeyQ') && !freeCamMode)
|
|
testDrive = !testDrive
|
|
if (keyWasPressed('KeyU'))
|
|
sound_win.play();
|
|
if (debug && keyWasPressed('KeyV'))
|
|
spawnVehicle(playerVehicle.pos.z-1300)
|
|
//if (!document.hasFocus())
|
|
// testDrive = 1;
|
|
}
|
|
|
|
function debugDraw()
|
|
{
|
|
if (!debug)
|
|
return;
|
|
|
|
if (debugInfo && !debugCapture)
|
|
drawHUDText((averageFPS|0) + 'fps / ' + glBatchCountTotal + ' / ' + glDrawCalls + ' / ' + vehicles.length, vec3(.98,.12),.03, undefined, 'monospace','right');
|
|
|
|
const c = mainCanvas;
|
|
const context = mainContext;
|
|
|
|
if (testDrive && !titleScreenMode && !freeRide)
|
|
drawHUDText('AUTO', vec3(.5,.95),.05,RED);
|
|
|
|
if (showMap)
|
|
{
|
|
// draw track map preview
|
|
context.save();
|
|
context.beginPath();
|
|
for(let k=2;k--;)
|
|
{
|
|
let x=0, v=0;
|
|
let p = vec3();
|
|
let d = vec3(0,-.5);
|
|
for(let i=0; i < 1e3; i++)
|
|
{
|
|
let j = playerVehicle.pos.z/trackSegmentLength+i-100|0;
|
|
if (!track[j])
|
|
continue;
|
|
|
|
const t = track[j];
|
|
const o = t.offset;
|
|
v += o.x;
|
|
p = p.add(d.rotateZ(v*.005));
|
|
if (j%5==0)
|
|
{
|
|
let y = o.y;
|
|
let w = t.width/199;
|
|
const h = k ? 5 : -y*.01;
|
|
context.fillStyle=hsl(y*.0001,1,k?0:.5,k?.5:1);
|
|
context.fillRect(c.width-200+p.x,c.height-100+p.y+h,w,w);
|
|
//context.fillRect(c.width-200+x/199,c.height-100-i/2+o,w,w);
|
|
}
|
|
}
|
|
}
|
|
context.restore();
|
|
}
|
|
|
|
if (debugGenerativeCanvas)
|
|
{
|
|
const s = 512;
|
|
//context.imageSmoothingEnabled = false;
|
|
context.drawImage(debugGenerativeCanvasCached, 0, 0, s, s);
|
|
// context.strokeRect(0, 0, s, s);
|
|
}
|
|
|
|
if (debugCapture)
|
|
{
|
|
debugCapture = 0;
|
|
const context = debugCanvas.getContext('2d');
|
|
debugCanvas.width = mainCanvas.width;
|
|
debugCanvas.height = mainCanvas.height;
|
|
context.fillStyle = '#000';
|
|
context.fillRect(0,0,mainCanvas.width,mainCanvas.height);
|
|
context.drawImage(glCanvas, 0, 0);
|
|
context.drawImage(mainCanvas, 0, 0);
|
|
debugSaveCanvas(debugCanvas);
|
|
}
|
|
|
|
{
|
|
// test render
|
|
//debugMesh = cylinderMesh;
|
|
debugMesh && debugMesh.render(buildMatrix(cameraPos.add(vec3(0,400,1000)), vec3(0,time,0), vec3(200)), WHITE);
|
|
|
|
//debugTile = vec3(0,1)
|
|
if (debugTile)
|
|
{
|
|
const s = 256*2, w = generativeTileSize, v = debugTile.scale(w);
|
|
const x = mainCanvas.width/2-s/2;
|
|
context.fillStyle = '#5f5';
|
|
context.fillRect(x, 0, s, s);
|
|
context.drawImage(debugGenerativeCanvasCached, v.x, v.y, w, w, x, 0, s, s);
|
|
context.strokeRect(x, 0, s, s);
|
|
//pushTrackObject(cameraPos.add(vec3(0,0,100)), vec3(100), WHITE, debugTile);
|
|
}
|
|
}
|
|
|
|
if (0) // world cube
|
|
{
|
|
const r = vec3(0,-worldHeading,0);
|
|
const m1 = buildMatrix(vec3(2220,1e3,2e3), r, vec3(200));
|
|
cubeMesh.render(m1, hsl(0,.8,.5));
|
|
}
|
|
|
|
if (0)
|
|
{
|
|
// test noise
|
|
context.fillStyle = '#fff';
|
|
context.fillRect(0, 0, 500, 500);
|
|
context.fillStyle = '#000';
|
|
for(let i=0; i < 1e3; i++)
|
|
{
|
|
const n = noise1D(i/129-time*9)*99;
|
|
context.fillRect(i, 200+n, 9, 9);
|
|
}
|
|
}
|
|
|
|
//cubeMesh.render(buildMatrix(vec3(0,-500,0), vec3(0), vec3(1e5,10,1e5)), RED); // ground
|
|
//cylinderMesh.render(buildMatrix(cameraPos.add(vec3(0,400,1000)), vec3(time,time/2,time/3), vec3(200)), WHITE);
|
|
//let t = new Tile(vec3(64*2,0), vec3(128));
|
|
//pushSprite(cameraPos.add(vec3(0,400,1000)), vec3(200), WHITE, t);
|
|
|
|
glRender();
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
function debugSaveCanvas(canvas, filename='screenshot', type='image/png')
|
|
{ debugSaveDataURL(canvas.toDataURL(type), filename); }
|
|
|
|
function debugSaveText(text, filename='text', type='text/plain')
|
|
{ debugSaveDataURL(URL.createObjectURL(new Blob([text], {'type':type})), filename); }
|
|
|
|
function debugSaveDataURL(dataURL, filename)
|
|
{
|
|
downloadLink.download = filename;
|
|
downloadLink.href = dataURL;
|
|
downloadLink.click();
|
|
} |