原生js编写的一款三维赛车游戏
代码语言:html
所属分类:游戏
代码描述:原生js编写的一款三维赛车游戏,玩法:鼠标 = 转向,点击 = 刹车,双击 = 跳转,R = 重新启动,1 = 屏幕截图。道路是随机生成的,每次都不同。您从 20 秒开始,通过检查点再获得 10 秒。通过转向或跳过岩石和树木来避开它们。路在1000结束,祝你好运!
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<html>
<!--/*
HUE JUMPER - By Frank Force
Low fi retro inspired endless runner in only 2 kilobytes!
Features
- Retro style 3D rendering engine in full HD
- Realistic driving physics and collisions
- Random level generation with increasing difficulty
- Gradient sky with sun and moon
- Procedurally generated mountain range
- Random trees and rocks
- Camera rumble and slow when off road
- Checkpoint system, road markers, and hue shift
- Time and distance display
*/-->
<title>Hue Jumper</title>
<meta charset="utf-8">
<body bgcolor=#000>
<canvas id=c style='touch-action:none;position:absolute;left:0px;top:0px;width:100%;height:100%'></canvas>
<a hidden id=downloadLink></a>
<script>
'use strict'; // strict mode
// debug settings
const debug = 0; // enable debug features
const usePointerLock = 1; // remove pointer lock for 2k build
// draw settings
const context = c.getContext('2d'); // canvas 2d context
const drawDistance = 800; // how many road segments to draw in front of player
const cameraDepth = 1; // FOV of camera (1 / Math.tan((fieldOfView/2) * Math.PI/180))
const roadSegmentLength = 100; // length of each road segment
const roadWidth = 500; // how wide is road
const warningTrackWidth = 150; // with of road plus warning track
const dashLineWidth = 9; // width of the dashed line in the road
const maxPlayerX = 2e3; // player can not move this far from center of road
const mountainCount = 30; // how many mountains are there
const timeDelta = 1/60; // inverse frame rate
// player settings
const playerHeight = 150; // how high is player above ground
const playerMaxSpeed = 300; // limit max player speed
const playerAccel = 1; // player acceleration
const playerBrake = -3; // player acceleration when breaking
const playerTurnControl = .2; // player turning rate
const playerJumpSpeed = 25; // z speed added for jump
const playerSpringConstant = .01; // spring players pitch
const playerCollisionSlow = .1; // slow down from collisions
const pitchLerp = .1; // speed that camera pitch changes
const pitchSpringDamping = .9; // dampen the pitch spring
const elasticity = 1.2; // bounce elasticity (2 is full bounce, 1 is none)
const centrifugal = .002; // how much to pull player on turns
const forwardDamping = .999; // dampen player z speed
const lateralDamping = .7; // dampen player x speed
const offRoadDamping = .98; // more damping when off road
const gravity = -1; // gravity to apply in y axis
const cameraHeadingScale = 2; // scale of player turning to rotate camera
const worldRotateScale = .00005; // how much to rotate world around turns
// level settings
const maxTime = 20; // time to start with
const checkPointTime = 10; // how much time for getting to checkpoint
const checkPointDistance = 1e5; // how far between checkpoints
const checkpointMaxDifficulty = 9; // how many checkpoints before max difficulty
const roadEnd = 1e4; // how many sections until end of the road
// global game variables
let playerPos; // player position 3d vector
let playerVelocity; // player velocity 3d vector
let playerPitchSpring; // spring for player pitch bounce
let playerPitchSpringVelocity; // velocity of pitch spring
let playerPitchRoad; // pitch of road, or 0 if player is in air
let playerAirFrame; // how many frames player has been in air
let worldHeading; // heading to turn skybox
let randomSeed; // random seed for level
let startRandomSeed; // save the starting seed for active use
let nextCheckPoint; // distance of next checkpoint
let hueShift; // current hue shift for all hsl colors
let road; // the list of road segments
let time; // time left before game over
let lastUpdate = 0; // time of last update
let timeBuffer = 0; // frame rate adjustment
function StartLevel()
{
/////////////////////////////////////////////////////////////////////////////////////
// build the road with procedural generation
/////////////////////////////////////////////////////////////////////////////////////
let roadGenSectionDistanceMax = 0; // init end of section distance
let roadGenWidth = roadWidth; // starting road width
let roadGenSectionDistance = 0; // distance left for this section
let roadGenTaper = 0; // length of taper
let roadGenWaveFrequencyX = 0; // X wave frequency
let roadGenWaveFrequencyY = 0; // Y wave frequency
let roadGenWaveScaleX = 0; // X wave amplitude (turn size)
let roadGenWaveScaleY = 0; // Y wave amplitude (hill size)
startRandomSeed = randomSeed = Date.now(); // set random seed
road = []; // clear list of road segments
// generate the road
for( let i = 0; i < roadEnd*2; ++i ) // build road past end
{
if (roadGenSectionDistance++ > roadGenSectionDistanceMax) // check for end of section
{
// calculate difficulty percent
const difficulty = Math.min(1, i*roadSegmentLength/checkPointDistance/checkpointMaxDifficulty); // difficulty
// randomize road settings
roadGenWidth = roadWidth*Random(1-difficulty*.7, 3-2*difficulty); // road width
roadGenWaveFrequencyX = Random(Lerp(difficulty, .01, .02)); // X frequency
roadGenWaveFrequencyY = Random(Lerp(difficulty, .01, .03)); // Y frequency
roadGenWaveScaleX = i > roadEnd ? 0 : Random(Lerp(difficulty, .2, .6)); // X scale
roadGenWaveScaleY = Random(Lerp(difficulty, 1e3, 2e3)); // Y scale
// apply taper and move back
roadGenTaper = Random(99, 1e3)|0; // randomize taper
roadGenSectionDistanceMax = roadGenTaper + Random(99, 1e3); // randomize segment distance
roadGenSectionDistance = 0; // reset section distance
i -= roadGenTaper; // subtract taper
}
// make a wavy road
const x = Math.sin(i*roadGenWaveFrequencyX) * roadGenWaveScaleX; // road X
const y = Math.sin(i*roadGenWaveFrequencyY) * roadGenWaveScaleY; // road Y
road[i] = road[i]? road[i] : {x:x, y:y, w:roadGenWidth}; // get or make road segment
// apply taper from last section
const p = Clamp(roadGenSectionDistance / roadGenTaper, 0, 1); // get taper percent
road[i].x = Lerp(p, road[i].x, x); // X pos and taper
road[i].y = Lerp(p, road[i].y, y); // Y pos and taper
road[i].w = i > roadEnd ? 0 : Lerp(p, road[i].w, roadGenWidth); // check for road end, width and taper
road[i].a = road[i-1] ? Math.atan2(road[i-1].y-road[i].y, roadSegmentLength) : 0; // road pitch angle
}
/////////////////////////////////////////////////////////////////////////////////////
// init game
/////////////////////////////////////////////////////////////////////////////////////
// reset everything
playerVelocity = new Vector3
(
playerPitchSpring =
playerPitchSpringVelocity =
playerPitchRoad =
hueShift = 0
);
playerPos = new Vector3(0, playerHeight); // set player pos
worldHeading = randomSeed; // randomize world heading
nextCheckPoint = checkPointDistance; // init next checkpoint
time = maxTime; // set the starting time
}
function Update()
{
// time regulation, in case running faster then 60 fps, though it causes judder REMOVE FROM MINFIED
const now = performance.now();
if (lastUpdate)
{
// limit to 60 fps
const delta = now - lastUpdate;
if (timeBuffer + delta < 0)
{
// running fast
requestAnimationFrame(Update);
return;
}
// update time buffer
timeBuffer += delta;
timeBuffer -= timeDelta * 1e3;
if (timeBuffer > timeDelta * 1e3)
timeBuffer = 0; // if running too slow
}
lastUpdate = now;
// start frame
if (snapshot) {c.width|0} else // DEBUG REMOVE FROM MINFIED
c.width = window.innerWidth,c.height = window.innerHeight; // clear the screen and set size
if (!c.width) // REMOVE FROM MINFIED
{
// fix bug on itch, wait for canvas before updating
requestAnimationFrame(Update);
return;
}
if (usePointerLock && document.pointerLockElement !== c && !touchMode) // set mouse down if pointer lock released
mouseDown = 1;
UpdateDebugPre(); // DEBUG REMOVE FROM MINFIED
/////////////////////////////////////////////////////////////////////////////////////
// update player - controls and physics
/////////////////////////////////////////////////////////////////////////////////////
// get player road segment
const playerRoadSegment = playerPos.z/roadSegmentLength|0; // current player road segment
const playerRoadSegmentPercent = playerPos.z/roadSegmentLength%1; // how far player is along current segment
// get lerped values between last and current road segment
const playerRoadX = Lerp(playerRoadSegmentPercent, road[playerRoadSegment].x, road[playerRoadSegment+1].x);
const playerRoadY = Lerp(playerRoadSegmentPercent, road[playerRoadSegment].y, road[playerRoadSegment+1].y) + playerHeight;
const roadPitch = Lerp(playerRoadSegmentPercent, road[playerRoadSegment].a, road[playerRoadSegment+1].a);
const playerVelocityLast = playerVelocity.Add(0); // save last velocity
playerVelocity.y += gravity; // gravity
playerVelocity.x *= lateralDamping; // apply lateral damping
playerVelocity.z = Math.max(0, time ? forwardDamping*playerVelocity.z : 0); // apply damping, prevent moving backwards
playerPos = playerPos.Add(playerVelocity); // add player velocity
const playerTurnAmount = Lerp(playerVelocity.z/playerMaxSpeed, mouseX * playerTurnCont.........完整代码请登录后点击上方下载按钮下载查看
网友评论0