From be767f3d05521ab159034d990ca6bbb2713ee7a5 Mon Sep 17 00:00:00 2001 From: Frank Force Date: Mon, 23 Sep 2024 21:29:12 -0500 Subject: [PATCH] gameplay tweaks --- code/game.js | 6 ++-- code/levels.js | 20 ++++++++---- code/scene.js | 12 +++++-- code/track.js | 2 +- code/trackGen.js | 85 +++++++++++++++++++++++------------------------- code/vehicle.js | 12 ++++--- 6 files changed, 75 insertions(+), 62 deletions(-) diff --git a/code/game.js b/code/game.js index 0fa23ab..fc8d239 100644 --- a/code/game.js +++ b/code/game.js @@ -40,8 +40,8 @@ let testDrive = 0; let freeCamMode = 0; let testLevelInfo; const testQuick = 0; -const js13kBuild = 1; -const js13kBuildLevel2 = 0; +const js13kBuild = 1; // hacks made when building for js13k +const js13kBuildLevel2 = 0; // if more space is needed for js13k /////////////////////////////////////////////////// @@ -120,7 +120,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) : 1; + worldHeading = titleScreenMode ? rand(7) : .9; checkpointTimeLeft = startCheckpointTime; nextCheckpointDistance = checkpointDistance; startCountdownTimer = new Timer; diff --git a/code/levels.js b/code/levels.js index 0cef916..f32cd36 100644 --- a/code/levels.js +++ b/code/levels.js @@ -183,6 +183,8 @@ function initLevelInfos() LI.billboardRate = 23; // more billboards in city LI.billboardChance = .5 LI.horizonSpriteSize = 1; + if (!js13kBuildLevel2) + LI.horizonFlipChance = .3; LI.sunHeight = .5; LI.sunColor = hsl(.15,1,.8); LI.sideStreets = 1; @@ -304,16 +306,16 @@ function initLevelInfos() trackSprites.grass_flower1, trackSprites.rock_huge2, trackSprites.rock_huge, - ], trackSprites.tree_pink); - LI.trackSideRate = 30; + ], trackSprites.tree_pink, trackSprites.horizon_mountains); + LI.trackSideRate = 21; LI.skyColorTop = hsl(.2,1,.9); LI.skyColorBottom = hsl(.55,1,.5); LI.roadColor = hsl(0,0,.1); LI.groundColor = hsl(.1,.5,.7); LI.cloudColor = hsl(0,0,1,.5); - LI.sunHeight = .7; LI.tunnel = trackSprites.tunnel1; - LI.horizonSpriteSize = 0; // no horizon + LI.sunHeight = .6; + LI.horizonSpriteSize = .5; // mountains, most difficult level LI.turnChance = .8; @@ -333,11 +335,15 @@ function initLevelInfos() trackSprites.grass_plain, trackSprites.tree_oak, trackSprites.tree_bush, - ], trackSprites.tree_oak); + ], trackSprites.tree_oak, trackSprites.horizon_mountains); LI.sceneryListBias = 1; LI.groundColor = hsl(.2,.3,.5); - LI.trackSideRate = LI.laneCount = LI.billboardChance = 0; - LI.sunHeight = .7; // should match previous level + LI.trackSideRate = LI.billboardChance = 0; + LI.bumpScaleMin = 1e3; // hill in the distance + + // match settings to previous level + LI.sunHeight = .6; + LI.horizonSpriteSize = .5; } const getLevelInfo = (level) => testLevelInfo || levelInfoList[level|0] || levelInfoList[0]; diff --git a/code/scene.js b/code/scene.js index bbd1352..6fbf33f 100644 --- a/code/scene.js +++ b/code/scene.js @@ -80,14 +80,22 @@ function drawSky() const p = i/99; const ltp = lerp(p,1,2); const ltt = .1; - const levelTransition = levelFloat<.5 ? 1 : levelPercent < ltt ? (levelPercent/ltt)**ltp : + const levelTransition = levelFloat<.5 || levelFloat > levelGoal-.5 ? 1 : levelPercent < ltt ? (levelPercent/ltt)**ltp : levelPercent > 1-ltt ? 1-((levelPercent-1)/ltt+1)**ltp : 1; const parallax = lerp(p, 1.01, 1.07); const s = random.float(1e2,2e2)*horizonSpriteSize; const size = vec3(random.float(1,2)*(horizonSprite.canMirror ? s*random.sign() : s),s,s); const x = mod(worldHeading*headingScale/parallax + random.float(range),range) - range/2; - const y = lerp(levelTransition, -s*1.5, random.float(s)); + + const yMax = size.y*.75; + if (!js13kBuildLevel2 && levelInfo.horizonFlipChance) + { + // horizon spites that can be flipped vertically + if (random.bool(levelInfo.horizonFlipChance)) + size.y *= -1; + } + const y = lerp(levelTransition, -yMax*1.5, yMax); const c = horizonSprite.getRandomSpriteColor(); pushSprite(cameraPos.add(vec3( x, y, skyZ)), size, c, horizonSpriteTile); } diff --git a/code/track.js b/code/track.js index 895088d..5cd9637 100644 --- a/code/track.js +++ b/code/track.js @@ -43,7 +43,7 @@ function drawRoad(zwrite) { const segmentIndex = cameraTrackSegment+i; segment1 = track[segmentIndex]; - if (!segment2) + if (!segment1 || !segment2) { segment2 = segment1; continue; diff --git a/code/trackGen.js b/code/trackGen.js index 0145e6f..d09ad29 100644 --- a/code/trackGen.js +++ b/code/trackGen.js @@ -12,10 +12,12 @@ function initTrackSprites() // trees trackSprites.tree_palm = new TrackSprite(vec3(0,1),1500,.2,.1,.04); + trackSprites.tree_palm.trackFace = 1; trackSprites.tree_oak = new TrackSprite(vec3(1,1),2e3,.5,.06,.1); trackSprites.tree_stump = new TrackSprite(vec3(2,1),1e3,.6,.04); trackSprites.tree_dead = new TrackSprite(vec3(3,1),800,.3,.03,.06); trackSprites.tree_pink = new TrackSprite(vec3(4,1),1500,.3,.1,.04); + trackSprites.tree_pink.trackFace = 1; trackSprites.tree_bush = new TrackSprite(vec3(5,1),1e3,.5,.1,.06); trackSprites.tree_fall = new TrackSprite(vec3(6,1),1500,.3,.1,.1); //TB(trackSprites.tree_flower = new TrackSprite(vec3(7,1),2e3,.3,.05,200)); @@ -23,10 +25,7 @@ function initTrackSprites() trackSprites.tree_yellow = new TrackSprite(vec3(5,3),1e3,.3,.06,.1) trackSprites.tree_huge = new TrackSprite(vec3(3,1),1e4,.5,.1,.1) trackSprites.tree_huge.colorHSL = vec3(.8, 0, .5); - - // must face track - trackSprites.tree_palm.trackFace = - trackSprites.tree_pink.trackFace = 1; + trackSprites.tree_huge.shadowScale = 0; // smaller tree shadows trackSprites.tree_palm.shadowScale = @@ -37,8 +36,7 @@ function initTrackSprites() trackSprites.tree_bush.shadowScale = trackSprites.tree_fall.shadowScale = trackSprites.tree_snow.shadowScale = - trackSprites.tree_yellow.shadowScale = - trackSprites.tree_huge.shadowScale = .7; + trackSprites.tree_yellow.shadowScale = .7; // grass and flowers trackSprites.grass_plain = new TrackSprite(vec3(0,3),500,.5,1); @@ -83,105 +81,101 @@ function initTrackSprites() trackSprites.rock_tall = new TrackSprite(vec3(1,4),1e3,.3,0,.6,0); trackSprites.rock_big = new TrackSprite(vec3(2,4),800,.2,0,.6,0); trackSprites.rock_huge = new TrackSprite(vec3(1,4),5e3,.7,0,.6,0); + trackSprites.rock_huge.shadowScale = 0; trackSprites.rock_huge.colorHSL = vec3(.08, 1, .8); trackSprites.rock_huge.hueRandomness = .01; trackSprites.rock_huge2 = new TrackSprite(vec3(2,4),8e3,.5,0,.25,0); + trackSprites.rock_huge2.shadowScale = 0; trackSprites.rock_huge2.colorHSL = vec3(.05, 1, .8); trackSprites.rock_huge2.hueRandomness = .01; trackSprites.rock_huge3 = new TrackSprite(vec3(2,4),8e3,.7,0,.5,0); + trackSprites.rock_huge3.shadowScale = 0; trackSprites.rock_huge3.colorHSL = vec3(.05, 1, .8); trackSprites.rock_huge3.hueRandomness = .01; trackSprites.rock_weird = new TrackSprite(vec3(2,4),5e3,.5,0,1,0); + trackSprites.rock_weird.shadowScale = 0; trackSprites.rock_weird.colorHSL = vec3(.8, 1, .8); trackSprites.rock_weird.hueRandomness = .2; trackSprites.rock_weird2 = new TrackSprite(vec3(1,4),1e3,.5,0,.5,0); trackSprites.rock_weird2.colorHSL = vec3(0, 0, .2); trackSprites.tunnel1 = new TrackSprite(vec3(6,4),1e4,.0,0,0,0); + trackSprites.tunnel1.shadowScale = 0; trackSprites.tunnel1.colorHSL = vec3(.05, 1, .8); trackSprites.tunnel1.tunnelArch = 1; trackSprites.tunnel2 = new TrackSprite(vec3(7,4),5e3,0,0,0,0); + trackSprites.tunnel2.shadowScale = 0; trackSprites.tunnel2.colorHSL = vec3(0, 0, .1); trackSprites.tunnel2.tunnelLong = 1; trackSprites.tunnel2Front = new TrackSprite(vec3(7,4),5e3,0,0,0,0); + trackSprites.tunnel2Front.shadowScale = 0; trackSprites.tunnel2Front.colorHSL = vec3(0,0,.8); //trackSprites.tunnel2_rock = new TrackSprite(vec3(6,6),1e4,.2,0,.5,0); //trackSprites.tunnel2_rock.colorHSL = vec3(.15, .5, .8); // hazards trackSprites.hazard_rocks = new TrackSprite(vec3(3,4),600,.2,0,.9); + trackSprites.hazard_rocks.shadowScale = 0; + trackSprites.hazard_rocks.isBump = 1; + trackSprites.hazard_rocks.spriteYOffset = -.02; trackSprites.hazard_sand = new TrackSprite(vec3(4,4),600,.2,0,.9); - trackSprites.hazard_rocks.isBump = + trackSprites.hazard_sand.shadowScale = 0; trackSprites.hazard_sand.isSlow = 1; - trackSprites.hazard_rocks.spriteYOffset = trackSprites.hazard_sand.spriteYOffset = -.02; //trackSprites.hazard_snow = new TrackSprite(vec3(6,6),500,.1,0,300,0); //trackSprites.hazard_snow.isSlow = 1; // special sprites trackSprites.water = new TrackSprite(vec3(5,4),6e3,.5,1); - trackSprites.sign_start = new TrackSprite(vec3(5,0),2300,0,.01,0,0); + trackSprites.water.shadowScale = 0; + trackSprites.sign_start = new TrackSprite(vec3(1,6),2300,0,.01,0,0); + trackSprites.sign_start.shadowScale = 0; trackSprites.sign_goal = new TrackSprite(vec3(0,6),2300,0,.01,0,0); + trackSprites.sign_goal.shadowScale = 0; trackSprites.sign_checkpoint1 = new TrackSprite(vec3(6,0),1e3,0,.01,0,0); + trackSprites.sign_checkpoint1.shadowScale = 0; trackSprites.sign_checkpoint2 = new TrackSprite(vec3(7,0),1e3,0,.01,0,0); + trackSprites.sign_checkpoint2.shadowScale = 0; 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.lightnessRandomness = .5; trackSprites.light_tunnel = new TrackSprite(vec3(0,0),200,0,0,0,0); + trackSprites.light_tunnel.shadowScale = 0; // horizon sprites trackSprites.horizon_city = new TrackSprite(vec3(3,6),0,0,0,0,1); trackSprites.horizon_city.hueRandomness = - trackSprites.horizon_city.lightnessRandomness = .1; + 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; trackSprites.horizon_redMountains = new TrackSprite(vec3(7,6)); trackSprites.horizon_redMountains.colorHSL = vec3(.05, .7, .7); + trackSprites.horizon_redMountains.canMirror = 0; trackSprites.horizon_brownMountains = new TrackSprite(vec3(7,6)); trackSprites.horizon_brownMountains.colorHSL = vec3(.1, .5, .6); + trackSprites.horizon_brownMountains.canMirror = 0; trackSprites.horizon_smallMountains = new TrackSprite(vec3(6,6)); trackSprites.horizon_smallMountains.colorHSL = vec3(.1, .5, .6); + trackSprites.horizon_smallMountains.canMirror = 0; trackSprites.horizon_desert = new TrackSprite(vec3(6,6)); trackSprites.horizon_desert.colorHSL = vec3(.15, .5, .8); + trackSprites.horizon_desert.canMirror = 0; trackSprites.horizon_snow = new TrackSprite(vec3(7,6)); trackSprites.horizon_snow.colorHSL = vec3(0,0,1); + trackSprites.horizon_snow.canMirror = 0; trackSprites.horizon_graveyard = new TrackSprite(vec3(6,6)); trackSprites.horizon_graveyard.colorHSL = vec3(.2, .4, .8); + trackSprites.horizon_graveyard.canMirror = 0; trackSprites.horizon_weird = new TrackSprite(vec3(7,6)); trackSprites.horizon_weird.colorHSL = vec3(.7, .5, .6); - - // no mirror on horizon sprites - trackSprites.horizon_islands.canMirror = 0; - trackSprites.horizon_redMountains.canMirror = 0; - trackSprites.horizon_brownMountains.canMirror = 0; - trackSprites.horizon_smallMountains.canMirror = 0; - trackSprites.horizon_desert.canMirror = 0; - trackSprites.horizon_snow.canMirror = 0; - trackSprites.horizon_graveyard.canMirror = 0; trackSprites.horizon_weird.canMirror = 0; - - // no shadow on these sprites - ///trackSprites.tunnel2_rock.shadowScale = 0; - trackSprites.light_tunnel.shadowScale = 0; - trackSprites.hazard_rocks.shadowScale = 0; - trackSprites.hazard_sand.shadowScale = 0; - //trackSprites.hazard_snow.shadowScale = 0; - trackSprites.tunnel1.shadowScale = 0; - trackSprites.tunnel2.shadowScale = 0; - trackSprites.tunnel2Front.shadowScale = 0; - trackSprites.water.shadowScale = 0; - trackSprites.rock_huge.shadowScale = 0; - trackSprites.rock_huge2.shadowScale = 0; - trackSprites.rock_huge3.shadowScale = 0; - trackSprites.rock_weird.shadowScale = 0; - trackSprites.tree_huge.shadowScale = 0; - trackSprites.sign_start.shadowScale = 0; - trackSprites.sign_goal.shadowScale = 0; - trackSprites.sign_checkpoint1.shadowScale = 0; - trackSprites.sign_checkpoint2.shadowScale = 0; } // a sprite that can be placed on the track @@ -252,8 +246,8 @@ class TrackSegment { constructor(segmentIndex,offset,width) { - if (segmentIndex > levelGoal*checkpointTrackSegments) - width = 0; + if (segmentIndex >= levelGoal*checkpointTrackSegments) + width = 0; // no track after end this.offset = offset; this.width = width; @@ -265,7 +259,6 @@ class TrackSegment const level = this.level = testLevelInfo ? testLevelInfo.level : levelFloat|0; const levelInfo = getLevelInfo(level); const levelInfoNext = getLevelInfo(levelFloat+1); - //const levelLerpPercent = percent(levelFloat%1, 0, levelLerpRange); const levelLerpPercent = percent(levelFloat%1, 1-levelLerpRange, 1); const checkpointLine = segmentIndex > 25 && segmentIndex < 30 @@ -428,10 +421,9 @@ function buildTrack() isBetweenLevels |= startOfTrack; // start of track //const nextCheckpoint = (level+1)*checkpointTrackSegments; - if (isBetweenLevels || i > trackEnd - 500) // straight at end + if (isBetweenLevels) { // transition at start or end of level - // reset stuff sectionXEndDistance = sectionYEndDistance = sectionTurn = 0; } else @@ -472,6 +464,9 @@ function buildTrack() } } + if (i > trackEnd - 500) + sectionTurn = 0; // no turns at end + turn = lerp(.02,turn, sectionTurn); // smooth out turns // apply noise to height @@ -488,7 +483,7 @@ function buildTrack() //turn = .5; height = 0; //turn = Math.sin(i/100)*.7; - //height = noise1D(i/29)*400;turn =0; // jumps test + //height = noise1D(i/29)*-1700;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 f86b6fa..17bfe32 100644 --- a/code/vehicle.js +++ b/code/vehicle.js @@ -291,7 +291,7 @@ class PlayerVehicle extends Vehicle } } - const hitBump=(amount = .97)=> + const hitBump=(amount = .98)=> { this.velocity.z *= amount; if (this.bumpTime < 0) @@ -471,10 +471,14 @@ class PlayerVehicle extends Vehicle this.velocity.z -= playerBrake; else if (playerInputGas) { - const accel = playerInputGas*playerAccel*lerp(speedPercent, 1, .45); // extra boost at low speeds - const lowSpeedPercent = percent(this.velocity.z, 80, 0)**2; - this.velocity.z += accel * lerp(lowSpeedPercent, 1, 9); + const lowSpeedPercent = percent(this.velocity.z, 100, 0)**2; + const accel = playerInputGas*playerAccel*lerp(speedPercent, 1, .5) + * lerp(lowSpeedPercent, 1, 7); + + // apply acceleration in angle of road + const accelVec = vec3(0,0,accel).rotateX(trackSegment.pitch); + this.velocity = this.velocity.add(accelVec); } else if (this.velocity.z < 30) this.velocity.z *= .9; // slow to stop