canvas实现鼠标控制方向2公里比赛游戏
代码语言:html
所属分类:游戏
代码描述:canvas实现鼠标控制方向2公里比赛游戏,纯js实现canvas游戏,无需第三方库
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> </head> <body style='margin:0;overflow:hidden'> <canvas id="c"></canvas> <script> // HUE JUMPER - By Frank Force // A 3D racing game in 2 Kilobytes! // // Click = Start // Mouse = Turn // Double Click = Jump // // The road ends at 1000... // draw settings const context = c.getContext`2d`; // canvas context const drawDistance = 800; // how far ahead to draw const cameraDepth = 1; // FOV of camera const segmentLength = 100; // length of each road segment const roadWidth = 500; // how wide is road const curbWidth = 150; // with of warning track const dashLineWidth = 9; // width of the dashed line const maxPlayerX = 2e3; // limit player offset const mountainCount = 30; // how many mountains are there const timeDelta = 1/60; // inverse frame rate const PI = Math.PI; // shorthand for Math.PI // player settings const height = 150; // high of player above ground const maxSpeed = 300; // limit max player speed const playerAccel = 1; // player forward acceleration const playerBrake = -3; // player breaking acceleration const turnControl = .2; // player turning rate const jumpAccel = 25; // z speed added for jump const springConstant = .01; // spring players pitch const collisionSlow = .1; // slow down from collisions const pitchLerp = .1; // rate camera pitch changes const pitchSpringDamp = .9; // dampen the pitch spring const elasticity = 1.2; // bounce elasticity const centrifugal = .002; // how much turns pull player const forwardDamp = .999; // dampen player z speed const lateralDamp = .7; // dampen player x speed const offRoadDamp = .98; // more damping when off road const gravity = -1; // gravity to apply in y axis const cameraTurnScale = 2; // how much to rotate camera const worldRotateScale = .00005; // how much to rotate world // level settings const maxTime = 20; // time to start const checkPointTime = 10; // add time at checkpoints const checkPointDistance = 1e5; // how far between checkpoints const maxDifficultySegment = 9e3; // how far until max difficulty const roadEnd = 1e4; // how far until end of road ////////////////////////////////////////////////////////////////// // mouse input ////////////////////////////////////////////////////////////////// mouseDown = mousePressed = mouseUpFrames = mouseX = 0; onmouseup =e=> mouseDown = 0; onmousedown =e=> mousePressed ? mouseDown = 1 : mousePressed = 1; onmousemove =e=> mouseX = e.x/window.innerWidth*2 - 1; ////////////////////////////////////////////////////////////////// // math and helper functions ////////////////////////////////////////////////////////////////// Clamp =(v, a, b) => Math.min(Math.max(v, a), b); ClampAngle=(a) => (a+PI) % (2*PI) + (a+PI<0? PI : -PI); Lerp=(p, a, b)=> a + Clamp(p, 0, 1) * (b-a); R =(a=1, b=0) => Lerp((Math.sin(++randSeed)+1)*1e5%1,a,b); LSHA =(l,s=0,h=0,a=1)=>`hsl(${h+hueShift},${s}%,${l}%,${a})`; // simple 3d vector class class Vec3 { constructor(x=0, y=0, z=0) {this.x = x; this.y = y; this.z = z;} Add=(v)=>( v = v < 1e5 ? new Vec3(v,v,v) : v, new Vec3( this.x + v.x, this.y + v.y, this.z + v.z )); Multiply=(v)=>( v = v < 1e5 ? new Vec3(v,v,v) : v, new Vec3( this.x * v.x, this.y * v.y, this.z * v.z )); } // draw a trapazoid shaped poly 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 DrawText=(text, posX)=> { // scale text so it works in tiny CodePen iframe const size = c.height/79; context.font = size+'em impact'; // set font size context.fillStyle = LSHA(99,0,0,.5); // set font color context.fillText(text, posX, size*14); // fill text context.lineWidth = size/2.5; // line width context.strokeText(text, posX, size*14); // outline text /* context.font = '9em impact'; // set font size context.fillStyle = LSHA(99,0,0,.5); // set font color context.fillText(text, posX, 129); // fill text context.lineWidth = 3; // line width context.strokeText(text, posX, 129); // outline text */ } ////////////////////////////////////////////////////////////////// // build the road with procedural generation ////////////////////////////////////////////////////////////////// roadGenLengthMax = // end of section roadGenLength = // distance left roadGenTaper = // length of taper roadGenFreqX = // X wave frequency roadGenFreqY = // Y wave frequency roadGenScaleX = // X wave amplitude roadGenScaleY = 0; // Y wave amplitude roadGenWidth = roadWidth; // starting road width startRandSeed = randSeed = Date.now(); // set random seed road = []; // clear road // generate the road for( i = 0; i < roadEnd*2; ++i ) // build road past end { if (roadGenLength++ > roadGenLengthMax) // is end of section? { // calculate difficulty percent d = Math.min(1, i/maxDifficultySegment); // randomize road settings roadGenWidth = roadWidth*R(1-d*.7,3-2*d); // road width roadGenFreqX = R(Lerp(d,.01,.02)); // X curves roadGenFreqY = R(Lerp(d,.01,.03)); // Y bumps roadGenScaleX = i>roadEnd ? 0 : R(Lerp(d,.2,.6));// X scale roadGenScaleY = R(Lerp(d,1e3,2e3)); // Y scale // apply taper and move back roadGenTaper = R(99, 1e3)|0; // random taper roadGenLengthMax = roadGenTaper + R(99,1e3); // random length roadGenLength = 0; // reset length i -= roadGenTaper; // subtract taper } // make a wavy road x = Math.sin(i*roadGenFreqX) * roadGenScaleX; y = Math.sin(i*roadGenFreqY) * roadGenScaleY; road[i] = road[i]? road[i] : {x:x, y:y, w:roadGenWidth}; // apply taper from last section and lerp values p = Clamp(roadGenLength / roadGenTaper, 0, 1); road[i].x = Lerp(p, road[i].x, x); road[i].y = Lerp(p, road[i].y, y); road[i].w = i > roadEnd ? 0 : Lerp(p, road[i].w, roadGenWidth); // calculate road pitch angle road[i].a = road[i-1] ? Math.atan2(road[i-1].y-road[i].y, segmentLength) : 0; } ////////////////////////////////////////////////////////////////// // init game ////////////////////////////////////////////////////////////////// // reset everything velocity = new Vec3 ( pitchSpring = pitchSpringSpeed = pitchRoad = hueShift = 0 ); position = new Vec3(0, height); // set player start pos nextCheckPoint = checkPointDistance; // init next checkpoint time = maxTime; // set the start time heading = randSeed; // random world heading ////////////////////////////////////////////////////////////////// // update and render frame ////////////////////////////////////////////////////////////////// Update=()=> { // get player road segment s = position.z / segmentLength | 0; // current road segment p = position.z / segmentLength % 1; // percent along segment // get lerped values between last and current road segment roadX = Lerp(p, road[s].x, road[s+1].x); roadY = Lerp(p, road[s].y, road[s+1].y) + height; roadA = Lerp(p, road[s].a, road[s+1].a); // update player velocity lastVelocity = velocity.Add(0); velocity.y += gravity; velocity.x *= lateralDamp; velocity.z = Math.max(0, time?forwardDamp*velocity.z:0); // add velocity to position position = position.Add(velocity); // limit player x position (how far off road) position.x = Clamp(position.x, -maxPlayerX, maxPlayerX); // check if on ground if (position.y < roadY) { position.y = roadY; // match y to ground plane airFrame = 0; // reset air frames // get the dot product of the ground normal and the velocity dp = Math.cos(roadA)*velocity.y + Math.sin(roadA)*velocity.z; // bounce velocity against ground normal velocity = new Vec3(0, Math.cos(roadA), Math.sin(roadA)) .Multiply(-elasticity * dp).Add(velocity); // apply player brake and accel velocity.z += mouseDown? playerBrake : Lerp(velocity.z/maxSpeed, mousePressed*playerAccel, 0); // check if off road if (Math.abs(position.x) > road[s].w) { velocity.z *= offRoadDamp; // slow down pitchSpring += Math.sin(position.z/99)**4/99; // rumble } } // update player turning and apply centrifugal force turn = Lerp(velocity.z/maxSpeed, mouseX * turnControl, 0); velocity.x += velocity.z * turn - velocity.z ** 2 * centrifugal * roadX; // update jump if (airFrame++<6 && time && mouseDown && mouseUpFrames && mouseUpFrames<9) { velocity.y +=jumpAccel; // apply jump velocity airFrame=9; // prevent jumping again } mouseUpFrames=mouseDown? 0 : mouseUpFrames+1; // pitch down with vertical velocity when in air airPercent=(position.y-roadY) / 99; pitchSpringSpeed +=Lerp(airPercent, 0, velocity.y/4e4); // update player pitch spring pitchSpringSpeed +=(velocity.z - lastVelocity.z)/2e3; pitchSpringSpeed -=pitchSpring * springConstant; pitchSpringSpeed *=pitchSpringDamp; pitchSprin.........完整代码请登录后点击上方下载按钮下载查看
网友评论0