3D赛车【附源码】设计实现

3D赛车【附源码】设计实现,第1张

3D赛车

3D赛车【附源码】

我的网站已经上线了 http://javapub.net.cn/

文末源码、免费获取
文末源码、免费获取
文末源码、免费获取

点赞再看,养成习惯

适合人群:初级学习者和爱好者,下面有展示图。计算机毕业设计、java精品项目

文章目录
    • 1 前言
    • 2 正文
      • 2.1 展示预览
      • 2.2 项目结构
      • 2.2 主要代码展示
      • 源码下载
    • 系列推荐:
    • [查看更多博主首页更多实战项目 >>>](https://blog.csdn.net/qq_40374604/category_11708266.html)

1 前言

🚀获取源码,文末公众号回复【赛车】,即可。
⭐欢迎点赞留言

2 正文

公众号:JavaPub

2.1 展示预览

13MB GIF可以欣赏:
http://www.kaotop.com/file/tupian/20220428/007F3CC8ly1h1onp5g8z9g31fz0pi7ws.gif


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Pbf7X6O3-1651070934070)(http://www.kaotop.com/file/tupian/20220428/007F3CC8ly1h1onp5g8z9g31fz0pi7ws.gif)]

2.2 项目结构

2.2 主要代码展示
<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 * playerTurnControl, 0); // turning
    playerVelocity.x +=                                          // update x velocity
        playerVelocity.z * playerTurnAmount -                    // apply turn
        playerVelocity.z ** 2 * centrifugal * playerRoadX;       // apply centrifugal force
    playerPos.x = Clamp(playerPos.x, -maxPlayerX, maxPlayerX);   // limit player x position
    
    // check if on ground
    if (playerPos.y < playerRoadY)
    {
        // bounce velocity against ground normal
        playerPos.y = playerRoadY;                                                                // match y to ground plane
        playerAirFrame = 0;                                                                       // reset air grace frames
        playerVelocity = new Vector3(0, Math.cos(roadPitch), Math.sin(roadPitch))                 // get ground normal
            .Multiply(-elasticity *                                                               // apply bounce
               (Math.cos(roadPitch) * playerVelocity.y + Math.sin(roadPitch) * playerVelocity.z)) // dot of road and velocity
            .Add(playerVelocity);                                                                 // add velocity

        playerVelocity.z += 
            mouseDown? playerBrake :                                                // apply brake              
            Lerp(playerVelocity.z/playerMaxSpeed, mouseWasPressed*playerAccel, 0);  // apply accel
        
        if (Math.abs(playerPos.x) > road[playerRoadSegment].w)                      // check if off road
        {
            playerVelocity.z *= offRoadDamping;                                     // slow down when off road
            playerPitchSpring += Math.sin(playerPos.z/99)**4/99;                    // bump when off road
        }
    }
  
    // update jump
    if (playerAirFrame++<6 && mouseDown && mouseUpFrames && mouseUpFrames<9 && time)  // check for jump
    {
        playerVelocity.y += playerJumpSpeed;                                          // apply jump velocity
        playerAirFrame = 9;                                                           // prevent jumping again
    }
    mouseUpFrames = mouseDown? 0 : mouseUpFrames+1;                                   // update mouse up frames for double click
    const airPercent = (playerPos.y-playerRoadY)/99;                                  // calculate above ground percent
    playerPitchSpringVelocity += Lerp(airPercent,0,playerVelocity.y/4e4);             // pitch down with vertical velocity
    
    // update player pitch
    playerPitchSpringVelocity += (playerVelocity.z - playerVelocityLast.z)/2e3;       // pitch down with forward accel
    playerPitchSpringVelocity -= playerPitchSpring * playerSpringConstant;            // apply pitch spring constant
    playerPitchSpringVelocity *= pitchSpringDamping;                                  // dampen pitch spring
    playerPitchSpring += playerPitchSpringVelocity;                                   // update pitch spring        
    playerPitchRoad = Lerp(pitchLerp, playerPitchRoad, Lerp(airPercent,-roadPitch,0));// match pitch to road
    const playerPitch = playerPitchSpring + playerPitchRoad;                          // update player pitch
    
    if (playerPos.z > nextCheckPoint)          // crossed checkpoint
    {
        time += checkPointTime;                // add more time
        nextCheckPoint += checkPointDistance;  // set next checkpoint
        hueShift += 36;                        // shift hue
    }
    
    /
    // draw background - sky, sun/moon, mountains, and horizon
    /
    
    // multi use local variables
    let x, y, w, i;

    randomSeed = startRandomSeed;                                                                 // set start seed
    worldHeading = ClampAngle(worldHeading + playerVelocity.z * playerRoadX * worldRotateScale);  // update world angle
    
    // pre calculate projection scale, flip y because y+ is down on canvas
    const projectScale = (new Vector3(1, -1, 1)).Multiply(c.width/2/cameraDepth);                 // get projection scale
    const cameraHeading = playerTurnAmount * cameraHeadingScale;                                  // turn camera with player 
    const cameraOffset = Math.sin(cameraHeading)/2;                                               // apply heading with offset
    
    // draw sky
    const lighting = Math.cos(worldHeading);                                    // brightness from sun
    const horizon = c.height/2 - Math.tan(playerPitch) * projectScale.y;        // get horizon line
    const g = context.createLinearGradient(0,horizon-c.height/2,0,horizon);     // linear gradient for sky
    g.addColorStop(0,LSHA(39+lighting*25,49+lighting*19,230-lighting*19));      // top sky color
    g.addColorStop(1,LSHA(5,79,250-lighting*9));                                // bottom sky color
    DrawPoly(c.width/2, 0, c.width/2, c.width/2, c.height, c.width/2, g);       // draw sky
    
    // draw sun and moon
    for( i = 2; i--; )                                                          // 0 is sun, 1 is moon
    {
        const g = context.createRadialGradient(                                 // radial gradient for sun
            x = c.width*(.5+Lerp(                                               // angle 0 is center
                (worldHeading/Math.PI/2+.5+i/2)%1,                              // sun angle percent 
                4, -4)-cameraOffset),                                           // sun x pos, move far away for wrap
            y = horizon - c.width/5,                                            // sun y pos
            c.width/25,                                                         // sun size
            x, y, i?c.width/23:c.width);                                        // sun end pos & size
        g.addColorStop(0, LSHA(i?70:99));                                       // sun start color
        g.addColorStop(1, LSHA(0,0,0,0));                                       // sun end color
        DrawPoly(c.width/2, 0, c.width/2, c.width/2, c.height, c.width/2, g);   // draw sun
    }

    // draw mountains
    for( i = mountainCount; i--; )                                              // draw every mountain
    {
        const angle = ClampAngle(worldHeading+Random(19));                      // mountain random angle
        const lighting = Math.cos(angle-worldHeading);                          // mountain lighting
        DrawPoly(
            x = c.width*(.5+Lerp(angle/Math.PI/2+.5, 4, -4)-cameraOffset),      // mountain x pos, move far away for wrap
            y = horizon,                                                        // mountain base
            w = Random(.2,.8)**2*c.width/2,                                     // mountain width
            x+w*Random(-.5,.5),                                                 // random tip skew
            y - Random(.5,.8)*w, 0,                                             // mountain height
            LSHA(Random(15,25)+i/3-lighting*9,i/2+Random(19),Random(220,230))); // mountain color
    }
    
    // draw horizon
    DrawPoly(c.width/2, horizon, c.width/2, c.width/2, c.height, c.width/2,     // horizon pos & size
        LSHA(25, 30, 95));                                                      // horizon color
    
    /
    // draw road and objects
    /
    
    // calculate road x offsets and projections
    for( x = w = i = 0; i < drawDistance+1; )
    {
        // create road world position
        let p = new Vector3(                                                     // set road position
            x += w += road[playerRoadSegment+i].x,                               // sum local road offsets
            road[playerRoadSegment+i].y, (playerRoadSegment+i)*roadSegmentLength)// road y and z pos
                .Add(playerPos.Multiply(-1));                                    // subtract to get local space

        p.x = p.x*Math.cos(cameraHeading) - p.z*Math.sin(cameraHeading); // rotate camera heading
        
        // tilt camera pitch
        const z = 1 / (p.z*Math.cos(playerPitch) - p.y*Math.sin(playerPitch)); // invert z for projection
        p.y = p.y*Math.cos(playerPitch) - p.z*Math.sin(playerPitch);
        p.z = z;
        
        // project road segment to canvas space
        road[playerRoadSegment+i++].p =                 // set projected road point
            p.Multiply(new Vector3(z, z, 1))            // projection
            .Multiply(projectScale)                     // scale
            .Add(new Vector3(c.width/2,c.height/2))     // center on canvas
    }
    
    // draw the road segments
    let segment2 = road[playerRoadSegment+drawDistance];                     // store the last segment
    for( i = drawDistance; i--; )                                            // iterate in reverse
    {
        const segment1 = road[playerRoadSegment+i];                         
        randomSeed = startRandomSeed + playerRoadSegment + i;                // random seed for this segment
        const lighting = Math.sin(segment1.a) * Math.cos(worldHeading)*99;   // calculate segment lighting
        const p1 = segment1.p;                                               // projected point
        const p2 = segment2.p;                                               // last projected point
        
        if (p1.z < 1e5 && p1.z > 0)                                          // check near and far clip
        {
            // draw road segment
            if (i % (Lerp(i/drawDistance,1,9)|0) == 0)                       // fade in road resolution
            {
                // ground
                DrawPoly(c.width/2, p1.y, c.width/2, c.width/2, p2.y, c.width/2,    // ground top & bottom
                    LSHA(25+lighting, 30, 95));                                     // ground color

                // warning track
                if (segment1.w > 400)                                               // no warning track if thin
                    DrawPoly(p1.x, p1.y, p1.z*(segment1.w+warningTrackWidth),       // warning track top
                        p2.x, p2.y, p2.z*(segment2.w+warningTrackWidth),            // warning track bottom
                        LSHA(((playerRoadSegment+i)%19<9? 50: 20)+lighting));       // warning track stripe color
                
                // road
                const z = (playerRoadSegment+i)*roadSegmentLength;                  // segment distance
                DrawPoly(p1.x, p1.y, p1.z*segment1.w,                               // road top
                    p2.x, p2.y, p2.z*segment2.w,                                    // road bottom
                    LSHA((z%checkPointDistance < 300 ? 70 : 7)+lighting)); // road color and checkpoint
                    
                // dashed lines
                if (segment1.w > 300)                                               // no dash lines if very thin
                    (playerRoadSegment+i)%9==0 && i < drawDistance/3 &&             // make dashes and skip if far out
                        DrawPoly(p1.x, p1.y, p1.z*dashLineWidth,                    // dash lines top
                        p2.x, p2.y, p2.z*dashLineWidth,                             // dash lines bottom
                        LSHA(70+lighting));                                         // dash lines color

                segment2 = segment1;                                                // prep for next segment
            }

            // random object (tree or rock)
            if (Random()<.2 && playerRoadSegment+i>29)                           // check for road object
            {
                // player object collision check
                const z = (playerRoadSegment+i)*roadSegmentLength;               // segment distance
                const height = (Random(2)|0) * 400;                              // object type & height
                x = 2*roadWidth * Random(10,-10) * Random(9);                    // choose object pos
                if (!segment1.h                                                  // prevent hitting the same object
                    && Math.abs(playerPos.x - x) < 200                           // x collision
                    && Math.abs(playerPos.z - z) < 200                           // z collision
                    && playerPos.y-playerHeight < segment1.y+200+height)         // y collision + object height
                {
                    playerVelocity = playerVelocity.Multiply(segment1.h = playerCollisionSlow); // stop player and mark hit
                }

                // draw road object
                const alpha = Lerp(i/drawDistance, 4, 0);                        // fade in object alpha
                if (height)                                                      // tree           
                {
                    DrawPoly(x = p1.x+p1.z * x, p1.y, p1.z*29,                   // trunk bottom
                        x, p1.y-99*p1.z, p1.z*29,                                // trunk top
                        LSHA(5+Random(9), 50+Random(9), 29+Random(9), alpha));   // trunk color
                    DrawPoly(x, p1.y-Random(50,99)*p1.z, p1.z*Random(199,250),   // leaves bottom
                        x, p1.y-Random(600,800)*p1.z, 0,                         // leaves top
                        LSHA(25+Random(9), 80+Random(9), 9+Random(29), alpha));  // leaves color
                }
                else                                                                           // rock
                {
                    DrawPoly(x = p1.x+p1.z * x, p1.y, p1.z*Random(200,250),                    // rock bottom
                        x+p1.z*(Random(99,-99)), p1.y-Random(200,250)*p1.z, p1.z*Random(99),   // rock top
                        LSHA(50+Random(19), 25+Random(19), 209+Random(9), alpha));             // rock color
                }
            }
        }
    }
    
    UpdateDebugPost(); // DEBUG REMOVE FROM MINFIED
    
    /
    // draw and update time
    /
    
    if (mouseWasPressed)
    {
        DrawText(Math.ceil(time = Clamp(time - timeDelta, 0, maxTime)), 9); // show and update time
        context.textAlign = 'right';                                        // set right alignment for distance
        DrawText(0|playerPos.z/1e3, c.width-9);                             // show distance
    }
    else
    {
        context.textAlign = 'center';        // set center alignment for title
        DrawText('HUE JUMPER', c.width/2);   // draw title text
    }
    
    requestAnimationFrame(Update);           // kick off next frame
}
    
/
// math and helper functions
/
    
const LSHA       = (l, s=0, h=0, a=1) =>`hsl(${ h + hueShift },${ s }%,${ l }%,${ a })`;
const Clamp      = (v, min, max)      => Math.min(Math.max(v, min), max);
const ClampAngle = (a)                => (a+Math.PI) % (2*Math.PI) + (a+Math.PI<0? Math.PI : -Math.PI);
const Lerp       = (p, a, b)          => a + Clamp(p, 0, 1) * (b-a);
const Random     = (max=1, min=0)     => Lerp((Math.sin(++randomSeed)+1)*1e5%1, min, max);
   
// simple 3d vector class
class Vector3 
{
    constructor(x=0, y=0, z=0) { this.x = x; this.y = y; this.z = z }
	Add(v)      { v = isNaN(v) ? v : new Vector3(v,v,v); return new Vector3( this.x + v.x, this.y + v.y, this.z + v.z); }
	Multiply(v) { v = isNaN(v) ? v : new Vector3(v,v,v); return new Vector3( this.x * v.x, this.y * v.y, this.z * v.z); }
}
    
// draw a trapazoid shaped poly
function DrawPoly(x1, y1, w1, x2, y2, w2, fillStyle) 
{
    context.beginPath(context.fillStyle = fillStyle);
    context.lineTo(x1-w1, y1|0);
    context.lineTo(x1+w1, y1|0);
    context.lineTo(x2+w2, y2|0);
    context.lineTo(x2-w2, y2|0);
    context.fill();
}

// draw outlined hud text
function DrawText(text, posX) 
{
    context.font = '9em impact';           // set font size
    context.fillStyle = LSHA(99,0,0,.5);   // set font 
    context.fillText(text, posX, 129);     // fill text
    context.lineWidth = 3;                 // line width
    context.strokeText(text, posX, 129);   // outline text
}

/////////////////////////////////////////////////////////////////////////////////////
// mouse input
/////////////////////////////////////////////////////////////////////////////////////

let mouseDown       = 0; 
let mouseWasPressed = 0;
let mouseUpFrames   = 0;
let mouseX          = 0;
let mouseLockX      = 0;
let touchMode       = 0;
    
onmouseup   = e => mouseDown = 0;
onmousedown = e =>
{
    if (mouseWasPressed)
        mouseDown = 1;
    mouseWasPressed = 1;
    if (usePointerLock && e.button == 0 && document.pointerLockElement !== c)
    {
        c.requestPointerLock = c.requestPointerLock || c.mozRequestPointerLock;
        c.requestPointerLock();
        mouseLockX = 0;
    }
}

onmousemove = e => 
{
    if (!usePointerLock)
    {
        mouseX = e.x/window.innerWidth*2-1
        return;
    }
    
    if (document.pointerLockElement !== c)
        return;
    
    // adjust for pointer lock 
    mouseLockX += e.movementX;
    mouseLockX = Clamp(mouseLockX, -window.innerWidth/2,  window.innerWidth/2);
    
    // apply curve to input
    const inputCurve = 1.5;
    mouseX = mouseLockX;
    mouseX /= window.innerWidth/2;
    mouseX = Math.sign(mouseX) * (1-(1-Math.abs(mouseX))**inputCurve);
    mouseX *= window.innerWidth/2;
    mouseX += window.innerWidth/2;
    mouseX = mouseX/window.innerWidth*2-1
}

/
// touch control
/

if (typeof ontouchend != 'undefined')
{
    let ProcessTouch = e =>
    {
        e.preventDefault();
        mouseDown = !(e.touches.length > 0);
        mouseWasPressed = 1;
        touchMode = 1;
        
        if (mouseDown)
            return;

        // average all touch positions
        let x = 0, y = 0;
        for (let touch of e.touches)
        {
            x += touch.clientX;
            y += touch.clientY;
        }
        mouseX = x/e.touches.length;
        mouseX = mouseX/window.innerWidth*2-1
    }

    c.addEventListener('touchstart',  ProcessTouch, false);
    c.addEventListener('touchmove',   ProcessTouch, false);
    c.addEventListener('touchcancel', ProcessTouch, false);
    c.addEventListener('touchend',    ProcessTouch, false);
}
    
/
// debug stuff
/

let debugPrintLines;
let snapshot;
    
function UpdateDebugPre()
{
    debugPrintLines = [];
    
    if (inputWasPushed[82]) // R = restart
    {
        mouseLockX = 0;
        StartLevel(); 
    }
    
    if (inputWasPushed[49]) // 1 = screenshot
    {
        snapshot = 1;
        
        // use 1080p resolution
        c.width = 1920;
        c.height = 1080;
    }
}
    
function UpdateDebugPost()
{
    if (snapshot)
    {
        SaveSnapshot();
        snapshot = 0;
    }
    
    UpdateInput();
    
    if (!debug)
        return;
    
    UpdateFps();
    
    context.font='2em"';
    for (let i in debugPrintLines)
    {
        let line = debugPrintLines[i];
        context.fillStyle = line.color;
        context.fillText(line.text,c.width/2,35+35*i);
    }
}
    
function DebugPrint(text, color='#F00')
{
    if (!debug)
        return;
    
    if (typeof text == 'object')
        text += JSON.stringify(text);
    
    let line = {text:text, color:color};
    debugPrintLines.push(line);
}
    
function SaveSnapshot()
{    
    downloadLink.download="snapshot.png";
    downloadLink.href=c.toDataURL("image/jpg").replace("image/jpg", "image/octet-stream");
    downloadLink.click();
}

/
// frame rate counter
/
    
let lastFpsMS = 0;
let averageFps = 0;
function UpdateFps()
{
    let ms = performance.now();
    let deltaMS = ms - lastFpsMS;
    lastFpsMS = ms;
    
    let fps = 1/(deltaMS/1e3);
    averageFps = averageFps*.9 + fps*.1;
    context.font='3em"';
    context.fillStyle='#0007';
    context.fillText(averageFps|0,c.width-90,c.height-40);
}

/
// keyboard control
/

let inputIsDown = [];
let inputWasDown = [];
let inputWasPushed = [];
onkeydown = e => inputIsDown[e.keyCode] = 1;
onkeyup   = e => inputIsDown[e.keyCode] = 0;
function UpdateInput()
{
    inputWasPushed = inputIsDown.map((e,i) => e && !inputWasDown[i]);
    inputWasDown = inputIsDown.slice();
}
    
/
// init hue jumper
/
   
// startup and kick off update loop
StartLevel();
Update();
    
</script>
</body>
</html>

JavaPub

源码下载

获取源码,公众号回复【赛车】,即可。更多最新Java面试题加群、见群公告。~

不会还有人没 点赞 + 关注 + 收藏 吧!

系列推荐:

Java 实现 捕鱼达人 小游戏【附源码】

Java 实现 贪吃蛇 小游戏【附源码】

Java 实现 1024 小游戏【附源码】

Java实现一个坦克大战的小游戏【附源码】

Java实现一个打飞机的小游戏【附源码】

Java 实现 植物大战僵尸 小游戏【附源码】

查看更多博主首页更多实战项目 >>>

项目源码获取方法

点赞本文,然后私信我,我免费分享给你哈~

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/757396.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-30
下一篇 2022-04-30

发表评论

登录后才能评论

评论列表(0条)

保存