diff --git a/code/debug.js b/code/debug.js index 53e0b6a..b9d1f69 100644 --- a/code/debug.js +++ b/code/debug.js @@ -141,7 +141,7 @@ function debugUpdate() debugCapture = 1; if (keyWasPressed('KeyQ') && !freeCamMode) testDrive = !testDrive - if (keyWasPressed('KeyP')) + if (keyWasPressed('KeyU')) sound_win.play(); if (debug && keyWasPressed('KeyV')) spawnVehicle(playerVehicle.pos.z-1300) diff --git a/code/game.js b/code/game.js index 3afa56b..02dcd8c 100644 --- a/code/game.js +++ b/code/game.js @@ -26,9 +26,8 @@ Features */ -//devMode = 1 +//devMode = debugInfo = 1 //soundVolume = 0 -//debugInfo = 1 //debugGenerativeCanvas = 1 //autoPause = 0 @@ -63,7 +62,7 @@ const drawDistance = 1e3; // how many track segments to draw for scener const cameraPlayerOffset = vec3(0,680,1050); const checkpointTrackSegments = testQuick?1e3:4500; const checkpointDistance = checkpointTrackSegments*trackSegmentLength; -const startCheckpointTime = 50; +const startCheckpointTime = 45; const extraCheckpointTime = 40; const levelLerpRange = .1; const levelGoal = 10; @@ -102,10 +101,14 @@ function gameInit() mainContext = mainCanvas.getContext('2d'); const styleCanvas = 'position:absolute;' + // position - 'top:50%;left:50%;transform:translate(-50%,-50%);' + // center + (clampAspectRatios?'top:50%;left:50%;transform:translate(-50%,-50%);':'') + // center (pixelate?' image-rendering: pixelated':''); // pixelated + glCanvas.style.cssText = mainCanvas.style.cssText = styleCanvas; + if (!clampAspectRatios) + document.body.style.margin = '0px'; + drawInit(); inputInit() initGenerative(); @@ -120,7 +123,7 @@ function gameStart() time = frame = frameTimeLastMS = averageFPS = frameTimeBufferMS = cameraOffset = checkpointTimeLeft = raceTime = playerLevel = playerWin = playerNewDistanceRecord = playerNewRecord = freeRide = checkpointSoundCount = 0; startCountdown = quickStart || testLevel ? 0 : 4; - worldHeading = titleScreenMode ? rand(7) : .9; + worldHeading = titleScreenMode ? rand(7) : .8; checkpointTimeLeft = startCheckpointTime; nextCheckpointDistance = checkpointDistance; startCountdownTimer = new Timer; @@ -250,25 +253,7 @@ function gameUpdateInternal() } } } - - // spawn in more vehicles - const playerIsSlow = titleScreenMode || playerVehicle.velocity.z < 20; - const trafficPosOffset = playerIsSlow? 0 : 18e4; // check in front/behind - const trafficLevel = (playerVehicle.pos.z+trafficPosOffset)/checkpointDistance; - const trafficLevelInfo = getLevelInfo(trafficLevel); - const trafficDensity = trafficLevelInfo.trafficDensity; - const maxVehicleCount = 10*trafficDensity; - if (trafficDensity) - if (vehicles.length!o.destroyed); + updateCars(); } function gameUpdate(frameTimeMS=0) diff --git a/code/generative.js b/code/generative.js index 42d6fdc..97cb264 100644 --- a/code/generative.js +++ b/code/generative.js @@ -598,7 +598,7 @@ function generateTetures() } else { - // city building + // y flippable city building color(BLACK); for(let i=19; i--;) { diff --git a/code/hud.js b/code/hud.js index 6823afb..696ef6b 100644 --- a/code/hud.js +++ b/code/hud.js @@ -131,7 +131,7 @@ function drawHUD() if (debugInfo&&!titleScreenMode) // mph { - const mph = playerVehicle.velocity.z>>1; + const mph = playerVehicle.velocity.z|0; const mphPos = vec3(.01,.95); drawHUDText(mph+' MPH', mphPos, .08, undefined,undefined,'left',900,'italic'); } diff --git a/code/input.js b/code/input.js index d57a32f..26c788b 100644 --- a/code/input.js +++ b/code/input.js @@ -1,7 +1,6 @@ 'use strict'; const gamepadsEnable = enhancedMode; -const gamepadDirectionEmulateStick = 1; const inputWASDEmulateDirection = enhancedMode; const allowTouch = enhancedMode; const isTouchDevice = allowTouch && window.ontouchstart !== undefined; @@ -11,23 +10,23 @@ const touchGamepadAlpha = .3; /////////////////////////////////////////////////////////////////////////////// // Input user functions -const keyIsDown = (key) => inputData[key] & 1; -const keyWasPressed = (key) => inputData[key] & 2 ? 1 : 0; +const keyIsDown = (key) => inputData[key] & 1; +const keyWasPressed = (key) => inputData[key] & 2 ? 1 : 0; const keyWasReleased = (key) => inputData[key] & 4 ? 1 : 0; const clearInput = () => inputData = []; -let mousePos = vec3(); -const mouseIsDown = keyIsDown; -const mouseWasPressed = keyWasPressed; +let mousePos; +const mouseIsDown = keyIsDown; +const mouseWasPressed = keyWasPressed; const mouseWasReleased = keyWasReleased; let isUsingGamepad; -const gamepadIsDown = (key, gamepad=0) => !!(gamepadData[gamepad][key] & 1); -const gamepadWasPressed = (key, gamepad=0) => !!(gamepadData[gamepad][key] & 2); +const gamepadIsDown = (key, gamepad=0) => !!(gamepadData[gamepad][key] & 1); +const gamepadWasPressed = (key, gamepad=0) => !!(gamepadData[gamepad][key] & 2); const gamepadWasReleased = (key, gamepad=0) => !!(gamepadData[gamepad][key] & 4); -const gamepadStick = (stick, gamepad=0) => +const gamepadStick = (stick, gamepad=0) => gamepadStickData[gamepad] ? gamepadStickData[gamepad][stick] || vec3() : vec3(); -const gamepadGetValue = (key, gamepad=0) => gamepadDataValues[gamepad][key]; +const gamepadGetValue = (key, gamepad=0) => gamepadDataValues[gamepad][key]; /////////////////////////////////////////////////////////////////////////////// // Input event handlers @@ -36,6 +35,9 @@ let inputData = []; // track what keys are down function inputInit() { + if (!js13kBuildLevel2) + mousePos = vec3(); + if (gamepadsEnable) { gamepadData = []; @@ -177,6 +179,7 @@ function gamepadsUpdate() isUsingGamepad ||= !i && button.pressed; } + const gamepadDirectionEmulateStick = 1; if (gamepadDirectionEmulateStick) { // copy dpad to left analog stick when pressed diff --git a/code/levels.js b/code/levels.js index f32cd36..74e64a0 100644 --- a/code/levels.js +++ b/code/levels.js @@ -17,6 +17,7 @@ function initLevelInfos() LI.horizonSpriteSize = .5; //LI.tunnel = trackSprites.tunnel2; // test tunnel LI.billboardChance = .3 // more billboards at start + LI.trafficDensity = .7; // less traffic start // mostly straight with few well defined turns or bumps LI.turnChance = .6; @@ -58,7 +59,7 @@ function initLevelInfos() LI.bumpFreqMin = .4; //LI.bumpFreqMax = .7; //LI.bumpScaleMin = 50; - LI.bumpScaleMax = 120; + LI.bumpScaleMax = 140; // Level 3 - desert - // has long straight thin roads and tunnel @@ -199,7 +200,7 @@ function initLevelInfos() LI.bumpFreqMin = .3; LI.bumpFreqMax = .6; LI.bumpScaleMin = 80; - LI.bumpScaleMax = 160; + LI.bumpScaleMax = 200; // Level 7 - graveyard - LI = new LevelInfo(level++, [ @@ -226,12 +227,10 @@ function initLevelInfos() // thin road over hills in graveyard //LI.turnChance = .5; - LI.turnMin = .1; - LI.turnMax = .7; - LI.bumpChance = .7; - LI.bumpFreqMin = .3; - LI.bumpFreqMax = .7; - LI.bumpScaleMin = 100; + LI.turnMax = .6; + LI.bumpChance = .6; + LI.bumpFreqMin = LI.bumpFreqMax = .7; + LI.bumpScaleMin = 80; //LI.bumpScaleMax = 150; // Level 8 - jungle - dirt road, many trees @@ -267,9 +266,9 @@ function initLevelInfos() LI.turnMax = .3; // lots of slight turns LI.bumpChance = 1; LI.bumpFreqMin = .4; - LI.bumpFreqMax = .8; + LI.bumpFreqMax = .6; LI.bumpScaleMin = 10; - LI.bumpScaleMax = 60; + LI.bumpScaleMax = 80; // Level 9 - strange area LI = new LevelInfo(level++, [ @@ -297,7 +296,7 @@ function initLevelInfos() LI.bumpFreqMin = .5; LI.bumpFreqMax = .9; LI.bumpScaleMin = 100; - //LI.bumpScaleMax = 150; + LI.bumpScaleMax = 200; // Level 10 - mountains - hilly, rocks on sides LI = new LevelInfo(level++, [ @@ -306,7 +305,7 @@ function initLevelInfos() trackSprites.grass_flower1, trackSprites.rock_huge2, trackSprites.rock_huge, - ], trackSprites.tree_pink, trackSprites.horizon_mountains); + ], trackSprites.tree_pink); LI.trackSideRate = 21; LI.skyColorTop = hsl(.2,1,.9); LI.skyColorBottom = hsl(.55,1,.5); @@ -314,14 +313,19 @@ function initLevelInfos() LI.groundColor = hsl(.1,.5,.7); LI.cloudColor = hsl(0,0,1,.5); LI.tunnel = trackSprites.tunnel1; - LI.sunHeight = .6; - LI.horizonSpriteSize = .5; + if (js13kBuildLevel2) + LI.horizonSpriteSize = 0; + else + { + LI.sunHeight = .6; + LI.horizonSprite = trackSprites.horizon_mountains + LI.horizonSpriteSize = .5; + } // mountains, most difficult level LI.turnChance = .8; //LI.turnMin = 0; - LI.turnMax = 1; - LI.bumpChance = 1; + LI.turnMax = LI.bumpChance = 1; LI.bumpFreqMin = .3; LI.bumpFreqMax = .9; //LI.bumpScaleMin = 50; @@ -335,15 +339,21 @@ function initLevelInfos() trackSprites.grass_plain, trackSprites.tree_oak, trackSprites.tree_bush, - ], trackSprites.tree_oak, trackSprites.horizon_mountains); + ], trackSprites.tree_oak); LI.sceneryListBias = 1; LI.groundColor = hsl(.2,.3,.5); LI.trackSideRate = LI.billboardChance = 0; LI.bumpScaleMin = 1e3; // hill in the distance // match settings to previous level - LI.sunHeight = .6; - LI.horizonSpriteSize = .5; + if (js13kBuildLevel2) + LI.horizonSpriteSize = 0; + else + { + LI.sunHeight = .6; + LI.horizonSprite = trackSprites.horizon_mountains + LI.horizonSpriteSize = .5; + } } const getLevelInfo = (level) => testLevelInfo || levelInfoList[level|0] || levelInfoList[0]; diff --git a/code/trackGen.js b/code/trackGen.js index d09ad29..8c70ee6 100644 --- a/code/trackGen.js +++ b/code/trackGen.js @@ -138,7 +138,7 @@ function initTrackSprites() trackSprites.telephonePole = new TrackSprite(vec3(0,4),1800,0,0,.03,0); //trackSprites.parts_girder = new TrackSprite(vec3(0,6),500,0,.05,30,0); trackSprites.telephonePole.shadowScale = .3; - trackSprites.grave_stone = new TrackSprite(vec3(2,6),500,.4,.05,.5,0); + trackSprites.grave_stone = new TrackSprite(vec3(2,6),500,.3,.05,.5,0); trackSprites.grave_stone.lightnessRandomness = .5; trackSprites.light_tunnel = new TrackSprite(vec3(0,0),200,0,0,0,0); trackSprites.light_tunnel.shadowScale = 0; @@ -149,9 +149,6 @@ function initTrackSprites() trackSprites.horizon_city.lightnessRandomness = .15; trackSprites.horizon_city.colorHSL = vec3(1); // vary color - trackSprites.horizon_mountains = new TrackSprite(vec3(7,6)); - trackSprites.horizon_mountains.colorHSL = vec3(0, 0, .7); - trackSprites.horizon_mountains.canMirror = 0; trackSprites.horizon_islands = new TrackSprite(vec3(7,6)); trackSprites.horizon_islands.colorHSL = vec3(.25, .5, .6); trackSprites.horizon_islands.canMirror = 0; @@ -176,6 +173,12 @@ function initTrackSprites() trackSprites.horizon_weird = new TrackSprite(vec3(7,6)); trackSprites.horizon_weird.colorHSL = vec3(.7, .5, .6); trackSprites.horizon_weird.canMirror = 0; + if (!js13kBuildLevel2) + { + trackSprites.horizon_mountains = new TrackSprite(vec3(7,6)); + trackSprites.horizon_mountains.colorHSL = vec3(0, 0, .7); + trackSprites.horizon_mountains.canMirror = 0; + } } // a sprite that can be placed on the track @@ -483,7 +486,7 @@ function buildTrack() //turn = .5; height = 0; //turn = Math.sin(i/100)*.7; - //height = noise1D(i/29)*-1700;turn =0; // jumps test + //height = noise1D((i-50)/99)*2700;turn =0; // jumps test // create track segment const o = vec3(turn, height, i*trackSegmentLength); diff --git a/code/vehicle.js b/code/vehicle.js index 3f37e03..0d9894c 100644 --- a/code/vehicle.js +++ b/code/vehicle.js @@ -6,6 +6,28 @@ function drawCars() v.draw(); } +function updateCars() +{ + // spawn in more vehicles + const playerIsSlow = titleScreenMode || playerVehicle.velocity.z < 20; + const trafficPosOffset = playerIsSlow? 0 : 18e4; // check in front/behind + const trafficLevel = (playerVehicle.pos.z+trafficPosOffset)/checkpointDistance; + const trafficLevelInfo = getLevelInfo(trafficLevel); + const trafficDensity = trafficLevelInfo.trafficDensity; + const maxVehicleCount = 10*trafficDensity; + if (trafficDensity) + if (vehicles.length!o.destroyed); +} + function spawnVehicle(z) { if (!aiVehicles) @@ -61,7 +83,7 @@ class Vehicle { const levelInfo = getLevelInfo(this.pos.z/checkpointDistance); const lane = levelInfo.laneCount - 1 - this.lane; // flip side - return max(120,120 + lane*22); // faster on left + return max(120,120 + lane*20); // faster on left } getLaneOffset() @@ -108,10 +130,11 @@ class Vehicle { // slow down if behind if (v != this && v != playerVehicle) - if (this.pos.z < v.pos.z + 500 && this.pos.z > v.pos.z - 2e3) + if (this.pos.z < v.pos.z + (js13kBuildLevel2?0:500) && this.pos.z > v.pos.z - 2e3) if (abs(x-v.laneOffset) < 500) // lane space { - this.destroyed |= (this.pos.z >= v.pos.z); // get rid of overlaps + if (!js13kBuildLevel2) + this.destroyed |= (this.pos.z >= v.pos.z); // get rid of overlaps this.velocity.z = min(this.velocity.z, v.velocity.z++); // clamp velocity & push this.isBraking = 20; break; @@ -290,7 +313,7 @@ class PlayerVehicle extends Vehicle } } - const hitBump=(amount = .98)=> + const hitBump=(amount = .97)=> { this.velocity.z *= amount; if (this.bumpTime < 0) @@ -318,6 +341,8 @@ class PlayerVehicle extends Vehicle ++playerLevel; nextCheckpointDistance += checkpointDistance; checkpointTimeLeft += extraCheckpointTime; + if (enhancedMode) + checkpointTimeLeft = min(60,checkpointTimeLeft); if (playerLevel >= levelGoal && !gameOverTimer.isSet()) { @@ -354,8 +379,8 @@ class PlayerVehicle extends Vehicle if (v != this && d.x < s.x && d.z < s.z) { // collision - this.velocity.z = v.velocity.z*.8; - v.velocity.z = max(v.velocity.z, this.velocity.z*1.2); // push other car + this.velocity.z = v.velocity.z/2; + v.velocity.z = max(v.velocity.z, this.velocity.z*1.5); // push other car this.velocity.x = 99*sign(this.pos.x-v.pos.x); // push away from car playHitSound(); } @@ -414,7 +439,7 @@ class PlayerVehicle extends Vehicle { --this.engineTime; const f = sound_velocity; - sound_engine.play(.1,f*f/8e3+rand(.1)); + sound_engine.play(.1,f/40+rand(.1)); } // player settings @@ -423,9 +448,9 @@ class PlayerVehicle extends Vehicle const gravity = -3; // gravity to apply in y axis const lateralDamping = .5; // dampen player x speed const playerAccel = 1; // player acceleration - const playerBrake = 4; // player acceleration when braking + const playerBrake = 3; // player acceleration when braking const playerMaxSpeed = 200; // limit max player speed - const speedPercent = clamp(this.velocity.z/playerMaxSpeed); + const speedPercent = this.velocity.z/playerMaxSpeed; // update physics this.velocity.y += gravity; @@ -478,13 +503,15 @@ class PlayerVehicle extends Vehicle else if (playerInputGas) { // extra boost at low speeds - const lowSpeedPercent = percent(this.velocity.z, 100, 0)**2; + //const lowSpeedPercent = this.velocity.z**2/1e4; + const lowSpeedPercent = percent(this.velocity.z, 90, 0)**2; const accel = playerInputGas*playerAccel*lerp(speedPercent, 1, .5) - * lerp(lowSpeedPercent, 1, 7); + * lerp(lowSpeedPercent, 1, 6); // apply acceleration in angle of road - const accelVec = vec3(0,0,accel).rotateX(trackSegment.pitch); - this.velocity = this.velocity.add(accelVec); + //const accelVec = vec3(0,0,accel).rotateX(trackSegment.pitch); + //this.velocity = this.velocity.add(accelVec); + this.velocity.z += accel; } else if (this.velocity.z < 30) this.velocity.z *= .9; // slow to stop @@ -496,8 +523,8 @@ class PlayerVehicle extends Vehicle this.onGround = 0; } - { - // clamp z velocity + { + // dampen z velocity & clamp this.velocity.z = max(0, this.velocity.z*forwardDamping); // turning diff --git a/favicon.png b/favicon.png index 8d34d73..e735397 100644 Binary files a/favicon.png and b/favicon.png differ diff --git a/index.html b/index.html index 8bdf803..23a69c6 100644 --- a/index.html +++ b/index.html @@ -3,17 +3,17 @@ Dr1v3n Wild! 🚗🌴 - + - - - + + + - + @@ -27,18 +27,18 @@ document.body.style.backgroundColor = '#222'; } - - - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + \ No newline at end of file