• <track id="oztn4"></track>
    <sup id="oztn4"><form id="oztn4"></form></sup>
    
    
    <mark id="oztn4"></mark>
  • <dfn id="oztn4"><samp id="oztn4"></samp></dfn>
      《地爆天星小姐》电影 ,麦子交换2免费观看2023年上映时间表 ,莫妮卡《爱我几何》,大牛影库战狼6欧式少女全部视频,三年大片国语版在线看,日本空姐电视剧,电影魔镜号中文字幕,和部长一起去出差旅是第几集
      全球「AI學術頂會」精華匯聚地
      您正在使用IE低版瀏覽器,為了您的雷峰網賬號安全和更好的產品體驗,強烈建議使用更快更安全的瀏覽器
      此為臨時鏈接,僅用于文章預覽,將在時失效
      人工智能開發(fā)者 正文
      發(fā)私信給陳伊莉
      發(fā)送

      0

      如何用不到 2KB 的 JavaScript 代碼寫一個 3D 賽車游戲?

      本文作者: 陳伊莉 2020-05-05 10:31
      導語:2KB 到底有多小呢?提供一個參考,一個3.5英寸軟盤可以容納700多這樣的游戲。

       幾個月前,JS1k游戲制作節(jié)(JS1K game jam)傳出不再舉辦消息后,許多游戲迷開始哀嚎。

             如何用不到 2KB 的 JavaScript 代碼寫一個 3D 賽車游戲?      

      Frank Force 也是其中一位,但他還有另一層身份——一位德克薩斯州奧斯汀的獨立游戲設計師。Frank Force 在游戲行業(yè)工作了20年,參與過9款主流游戲、47個獨立游戲的設計。在聽到這個消息后,他馬上和其他開發(fā)朋友討論了這個問題,并決定做點什么為此紀念。

      在此期間,他們受到三重因素的啟發(fā)。一是賽車游戲,包括懷舊向的80年代賽車游戲,他們在非常早期的硬件上推動實時 3D 圖形,所以作者沿用了相同的技術,用純 JavaScript 從頭開始實現做 3D 圖形和物理引擎;還有一些現代賽車游戲帶來了視覺設計的靈感,比如《Distance》和《Lonely Mountains: Downhill》;二是之前 Jake Gordon 用 JavaScript 創(chuàng)建一個虛擬3D賽車的項目,并分享了代碼;三是 Chris Glover 曾經做過一款小到只有 1KB 的 JS1k 賽車游戲《Moto1kross by Chris Glover》

      于是 Frank 和他的朋友們決定做一個壓縮后只有 2KB 的 3D 賽車游戲。2KB 到底有多小呢?提供一個參考,一個3.5英寸軟盤可以容納700多個這樣的游戲。

      如何用不到 2KB 的 JavaScript 代碼寫一個 3D 賽車游戲?

      他給這個游戲取名 Hue Jumper。關于名字的由來,Frank 表示,游戲的核心操作是移動。當玩家通過一個關卡時,游戲世界就會換一個顏色色調。“在我想象中,每通過過一個關卡,玩家都會跳轉到另一個維度,有著完全不同的色調。”

      做完這個游戲后,Frank 將包含了游戲的全部 JavaScript 代碼都發(fā)布在他的個人博客上,其中用到的軟件主要也是免費或開源軟件的。游戲代碼發(fā)布在 CodePen,可以在 iframe 中試玩,有興趣的朋友可以去看看。

      如何用不到 2KB 的 JavaScript 代碼寫一個 3D 賽車游戲?

      以下是原博內容,AI源創(chuàng)評論進行了不改變原意的編譯:

      確定最高目標

      因為嚴格的大小限制,我需要非常仔細對待我的程序。我的總體策略是盡可能保持一切簡單,為最終目標服務。

      為了幫助壓縮代碼,我使用了 Google Closure Compiler,它刪除了所有空格,將變量重命名為1個字母字符,并進行了一些輕量級優(yōu)化。

      用戶可以通過 Google Closure Compiler 官網在線跑代碼。不幸的是,Closure Compiler 做了一些沒有幫助的事情,比如替換模板字符串、默認參數和其他幫助節(jié)省空間的ES6特性。所以我需要手動撤銷其中一些事情,并執(zhí)行一些更“危險”的壓縮技術來擠出最后一個字節(jié)空間。在壓縮方面,這不算很成功,大部分擠出的空間來自代碼本身的結構優(yōu)化。

      代碼需要壓縮到2KB。如果不是非要這么做不可,有一個類似的但功能沒那么強的工具叫做 RegPack 。

      無論哪種方式,策略都是一樣的:盡最大可能重復代碼,然后用壓縮工具壓縮。最好的例子是 c.width,c.height和 Math。因此,在閱讀這段代碼時,請記住,你經常會看到我不斷重復一些東西,最終目的就是為了壓縮。

      HTML

      其實我的游戲很少使用 html ,因為它主要用到的是 JavaScript 。但這是創(chuàng)建全屏畫布 Canvas ,也能將畫布 Canvas 設為窗口內部大小的代碼最小方法。我不知道為什么在 CodePen 上有必要添加 overflow:hiddento the body,當直接打開時按理說也可以運行。

      我將 JavaScript 封裝在一個 onload 調用,得到了一個更小的最終版本…< body style = margin:0 onload = " code _ goes _ here " > < canvas id = c >但是,在開發(fā)過程中,我不喜歡用這個壓縮設置,因為代碼存儲在一個字符串中,所以編輯器不能正確地高亮顯示語法。

      <body style=margin:0>

      <canvas id=c>

      <script>

      常量

      有許多常量在各方面控制著游戲。當代碼被 Google Closure 這樣的工具縮小時,這些常量將被替換,就像 C++ 中的 #define 一樣,把它們放在第一位會加快游戲微調的過程。

      // 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

      鼠標控制

      鼠標是唯一的輸入系統(tǒng)。通過這段代碼,我們可以跟蹤鼠標點擊和光標位置,位置顯示為-1到1之間的值。

      雙擊是通過 mouseUpFrames 實現的。mousePressed 變量只在玩家第一次點擊開始游戲時使用這么一次。

      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;

      數學函數

      這個游戲使用了一些函數來簡化代碼和減少重復,一些標準的數學函數用于 Clamp 和 Lerp 值。 ClampAngle 是有用的,因為它在 -PI 和 PI 之間 wrap angles,在許多游戲中已經廣泛應用。

      R函數就像個魔術師,因為它生成隨機數,通過取當前隨機數種子的正弦,乘以一個大數字,然后看分數部分來實現的。其實有很多方法可以做到,但這是最小的方法之一,而且對我們來說也是足夠隨機。

      我們將使用這個隨機生成器來創(chuàng)建各種程序,且不需要保存任何數據。例如,山脈、巖石和樹木的變化不用存到內存。在這種情況下,目標不是減少內存,而是去除存儲和檢索數據所需的代碼。

      因為這是一個“真正的3D”游戲,所以有一個 3D vector class 非常有用,它也能減少代碼量。這個 class 只包含這個游戲必需的基本元素,一個帶有加法和乘法函數的 constructor 可以接受標量或向量參數。為了確定標量是否被傳入,我們只需檢查它是否小于一個大數。更正確的方法是使用 isNan 或者檢查它的類型是否是 Vec3,但是這需要更多的存儲。

      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);
       
      class Vec3 // 3d vector class
      {
       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 ));
      }

      Render Functions渲染函數

      LSHA 通過模板字符串生成一組標準的 HSLA (色調、飽和度、亮度、alpha)顏色,并且剛剛被重新排序,所以更常用的 component 排在第一位。每過一關換一個整體色調也是通過這設置的。

      DrawPoly 繪制一個梯形形狀,用于渲染場景中的一切。使用 |0 將 Ycomponent 轉換為整數,以確保每段多邊形道路都能無縫連接,不然路段之間就會有一條細線。

      DrawText 則用于顯示時間、距離和游戲標題等文本渲染。

       LSHA=(l,s=0,h=0,a=1)=>`hsl(${h+hueShift},${s}%,${l}%,${a})`;

      // 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)=>
      {
         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
      }

      設計軌道

      如何用不到 2KB 的 JavaScript 代碼寫一個 3D 賽車游戲?

      首先,我們必須生成完整的軌道,而且準備做到每次游戲軌道都是不同的。如何做呢?我們建立了一個道路段列表,存儲道路在軌道上每一關卡的位置和寬度。軌道生成器是非常基礎的操作,不同頻率、振幅和寬度的道路都會逐漸變窄,沿著跑道的距離決定這一段路有多難。

      atan2 函數可以用來計算道路俯仰角,據此來設計物理運動和光線。

       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;
      }

      啟動游戲

      現在跑道就緒,我們只需要預置一些變量就可以開始游戲了。

       // 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

      更新玩家

      這是主要的更新功能,用來更新和渲染游戲中的一切!一般來說,如果你的代碼中有一個很大的函數,這不是好事,為了更簡潔易懂,我們會把它分幾個成子函數。

      首先,我們需要得到一些玩家所在位置的道路信息。為了使物理和渲染感覺平滑,需要在當前和下一個路段之間插入一些數值。

      玩家的位置和速度是 3D 向量,并受重力、dampening 和其他因素等影響更新。如果玩家跑在地面上時,會受到加速度影響;當他離開這段路時,攝像機還會抖動。另外,在對游戲測試后,我決定讓玩家在空中時仍然可以跑。

      接下來要處理輸入指令,涉及加速、剎車、跳躍和轉彎等操作。雙擊通過 mouseUpFrames 測試。還有一些代碼是來跟蹤玩家在空中停留了多少幀,如果時間很短,游戲允許玩家還可以跳躍。

      當玩家加速、剎車和跳躍時,我通過spring system展示相機的俯仰角以給玩家動態(tài)運動的感覺。此外,當玩家駕車翻越山丘或跳躍時,相機還會隨著道路傾斜而傾斜。

       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;
      pitchSpring += pitchSpringSpeed;
      pitchRoad = Lerp(pitchLerp, pitchRoad, Lerp(airPercent,-roadA,0));
      playerPitch = pitchSpring + pitchRoad;

      // update heading
      heading = ClampAngle(heading + velocity.z*roadX*worldRotateScale);
      cameraHeading = turn * cameraTurnScale;

      // was checkpoint crossed?
      if (position.z > nextCheckPoint)
      {
       time += checkPointTime;               // add more time
       nextCheckPoint += checkPointDistance; // set next checkpoint
       hueShift += 36;                       // shift hue
      }

      預渲染

      在渲染之前,canvas 每當高度或寬度被重設時,畫布內容就會被清空。這也適用于自適應窗口的畫布。

      我們還計算了將世界點轉換到畫布的投影比例。cameraDepth 值代表攝像機的視場(FOV)。這個游戲是90度。計算結果是 1/Math.tan(fovRadians/2) ,FOV 是90度的時候,計算結果正好是1。另外為了保持屏幕長寬比,投影按 c.width 縮放。

       // clear the screen and set size
      c.width = window.innerWidth, c.height = window.innerHeight;

      // calculate projection scale, flip y
      projectScale = (new Vec3(1,-1,1)).Multiply(c.width/2/cameraDepth);

      給世界畫上天空、太陽和月亮

      如何用不到 2KB 的 JavaScript 代碼寫一個 3D 賽車游戲?

      空氣背景是用全屏的 linear gradient (徑向漸變)繪制的,它還會根據太陽的位置改變顏色。

      為了節(jié)省存儲空間,太陽和月亮在同一個循環(huán)中,使用了一個帶有透明度的全屏 radial gradient(線性漸變)。

      線性和徑向漸變相結合,形成一個完全包圍場景的天空背景。

       // get horizon, offset, and light amount
      horizon = c.height/2 - Math.tan(playerPitch)*projectScale.y;
      backgroundOffset = Math.sin(cameraHeading)/2;
      light = Math.cos(heading);

      // create linear gradient for sky
      g = context.createLinearGradient(0,horizon-c.height/2,0,horizon);
      g.addColorStop(0,LSHA(39+light*25,49+light*19,230-light*19));
      g.addColorStop(1,LSHA(5,79,250-light*9));

      // draw sky as full screen poly
      DrawPoly(c.width/2,0,c.width/2,c.width/2,c.height,c.width/2,g);

      // draw sun and moon (0=sun, 1=moon)
      for( i = 2 ; i--; )
      {
       // create radial gradient
       g = context.createRadialGradient(
         x = c.width*(.5+Lerp(
           (heading/PI/2+.5+i/2)%1,
           4, -4)-backgroundOffset),
         y = horizon - c.width/5,
         c.width/25,
         x, y, i?c.width/23:c.width);
       g.addColorStop(0, LSHA(i?70:99));
       g.addColorStop(1, LSHA(0,0,0,0));
       
       // draw full screen poly
       DrawPoly(c.width/2,0,c.width/2,c.width/2,c.height,c.width/2,g);
      }

      給世界畫上山峰、地平線

      如何用不到 2KB 的 JavaScript 代碼寫一個 3D 賽車游戲?

      山脈是通過在地平線上畫50個三角形,然后根據程序自己生成的。

      因為用了光線照明,山脈在面對太陽時會更暗,因為它們處于陰影中。此外,越近的山脈顏色越暗,我想以此來模擬霧氣。這里我有個訣竅,就是微調大小和顏色的隨機值。

      背景的最后一部分是繪制地平線,再用純綠填充畫布的底部。

       // set random seed for mountains
      randSeed = startRandSeed;

      // draw mountains
      for( i = mountainCount; i--; )
      {
       angle = ClampAngle(heading+R(19));
       light = Math.cos(angle-heading);
       DrawPoly(
         x = c.width*(.5+Lerp(angle/PI/2+.5,4,-4)-backgroundOffset),
         y = horizon,
         w = R(.2,.8)**2*c.width/2,
         x + w*R(-.5,.5),
         y - R(.5,.8)*w, 0,
         LSHA(R(15,25)+i/3-light*9, i/2+R(19), R(220,230)));
      }

      // draw horizon
      DrawPoly(
       c.width/2, horizon, c.width/2, c.width/2, c.height, c.width/2,
       LSHA(25, 30, 95));

      將路段投影到畫布空間

      在渲染道路之前,我們必須首先獲得投影的道路點。第一部分有點棘手,因為我們的道路的 x 值需要轉換成世界空間位置。為了使道路看起來蜿蜒曲折,我們把x值作為二階導數。這就是為什么有奇怪的代碼“x+=w+=”出現的原因。由于這種工作方式,路段沒有固定的世界空間位置,每一幀都是根據玩家的位置重新計算。

      一旦我們有了世界空間位置,我們就可以從道路位置中知道玩家的位置,從而得到本地攝像機空間位置。代碼的其余部分,首先通過旋轉標題、俯仰角來應用變換,然后通過投影變換,做到近大遠小的效果,最后將其移動到畫布空間。

       for( x = w = i = 0; i < drawDistance+1; )
      {
       p = new Vec3(x+=w+=road[s+i].x,     // sum local road offsets
         road[s+i].y, (s+i)*segmentLength) // road y and z pos
           .Add(position.Multiply(-1));    // get local camera space

       // apply camera heading
       p.x = p.x*Math.cos(cameraHeading) - p.z*Math.sin(cameraHeading);
       
       // tilt camera pitch and invert z
       z = 1/(p.z*Math.cos(playerPitch) - p.y*Math.sin(playerPitch));
       p.y = p.y*Math.cos(playerPitch) - p.z*Math.sin(playerPitch);
       p.z = z;
       
       // project road segment to canvas space
       road[s+i++].p =                         // projected road point
         p.Multiply(new Vec3(z, z, 1))         // projection
         .Multiply(projectScale)               // scale
         .Add(new Vec3(c.width/2,c.height/2)); // center on canvas
      }

      繪制路段

       如何用不到 2KB 的 JavaScript 代碼寫一個 3D 賽車游戲?

      現在我們有了每個路段的畫布空間點,渲染就相當簡單了。我們需要從后向前畫出每一個路段,或者更具體地說,連接上一路段的梯形多邊形。

      為了創(chuàng)建道路,這里有4層渲染:地面,條紋路邊緣,道路本身和白色虛線。每一個都是基于路段的俯仰角和方向來加陰影,并且根據該層的表現還有一些額外的邏輯。

      有必要檢查路段是在近還是遠剪輯范圍,以防止渲染出現 bug 。此外,還有一個很好的優(yōu)化方法是,當道路變得很窄時,可以通過 distance 來減小道路的分辨率。如此,不僅減少了 draw count 一半以上,而且沒有明顯的質量損失,這是一次性能勝利。

       let segment2 = road[s+drawDistance]; // store the last segment
      for( i = drawDistance; i--; )        // iterate in reverse
      {
       // get projected road points
       segment1 = road[s+i];
       p1 = segment1.p;
       p2 = segment2.p;
       
       // random seed and lighting
       randSeed = startRandSeed + s + i;
       light = Math.sin(segment1.a) * Math.cos(heading) * 99;
       
       // check near and far clip
       if (p1.z < 1e5 && p1.z > 0)
       {
         // fade in road resolution over distance
         if (i % (Lerp(i/drawDistance,1,9)|0) == 0)
         {
           // ground
           DrawPoly(c.width/2, p1.y, c.width/2,
             c.width/2, p2.y, c.width/2,
             LSHA(25 + light, 30, 95));

           // curb if wide enough
           if (segment1.w > 400)
             DrawPoly(p1.x, p1.y, p1.z*(segment1.w+curbWidth),
               p2.x, p2.y, p2.z*(segment2.w+curbWidth),
               LSHA(((s+i)%19<9? 50: 20) + light));
           
           // road and checkpoint marker
           DrawPoly(p1.x, p1.y, p1.z*segment1.w,
             p2.x, p2.y, p2.z*segment2.w,
             LSHA(((s+i)*segmentLength%checkPointDistance < 300 ?
               70 : 7) + light));
             
           // dashed lines if wide and close enough
           if ((segment1.w > 300) && (s+i)%9==0 && i < drawDistance/3)
               DrawPoly(p1.x, p1.y, p1.z*dashLineWidth,
               p2.x, p2.y, p2.z*dashLineWidth,
               LSHA(70 + light));

           // save this segment
           segment2 = segment1;
         }

      繪制路邊的樹和石頭

      如何用不到 2KB 的 JavaScript 代碼寫一個 3D 賽車游戲?

      游戲有兩種不同類型的物體:樹和石頭。首先,我們通過使用 R() 函數來確定是否加一個對象。這是隨機數和隨機數種子特別有意思的地方。我們還將使用 R() 為對象隨機添加不同的形狀和顏色。

      最初我還想涉及其他車型,但為了達到 2KB 的要求,必須要進行特別多的削減,因此我最后放棄了這個想法,用風景作為障礙。這些位置是隨機的,也比較靠近道路,不然它們太稀疏,就很容易行駛。為了節(jié)省空間,對象高度還決定了對象的類型。

      這是通過比較玩家和物體在 3D 空間中的位置來檢查它們之間的碰撞位置。當玩家撞到一個物體時,玩家減速,該物體被標記為“ hit ”,這樣它就可以安全通過。

      為了防止對象突然出現在地平線上,透明度會隨著距離的接近而削弱。梯形繪圖函數定義物體的形狀和顏色,另外隨機函數會改變這兩個屬性。

        if (R()<.2 && s+i>29)                  // is there an object?
         {
           // player object collision check
           x = 2*roadWidth * R(10,-10) * R(9);  // choose object pos
           const objectHeight = (R(2)|0) * 400; // choose tree or rock
           if (!segment1.h                      // dont hit same object
             && Math.abs(position.x-x)<200                      // X
             && Math.abs(position.z-(s+i)*segmentLength)<200    // Z
             && position.y-height<segment1.y+objectHeight+200)  // Y
           {
             // slow player and mark object as hit
             velocity = velocity.Multiply(segment1.h = collisionSlow);
           }

           // draw road object
           const alpha = Lerp(i/drawDistance, 4, 0);  // fade in object
           if (objectHeight)
           {
             // tree trunk
             DrawPoly(x = p1.x+p1.z * x, p1.y, p1.z*29,
               x, p1.y-99*p1.z, p1.z*29,
               LSHA(5+R(9), 50+R(9), 29+R(9), alpha));
               
             // tree leaves
             DrawPoly(x, p1.y-R(50,99)*p1.z, p1.z*R(199,250),
               x, p1.y-R(600,800)*p1.z, 0,
               LSHA(25+R(9), 80+R(9), 9+R(29), alpha));
           }
           else
           {
             // rock
             DrawPoly(x = p1.x+p1.z*x, p1.y, p1.z*R(200,250),
               x+p1.z*(R(99,-99)), p1.y-R(200,250)*p1.z, p1.z*R(99),
               LSHA(50+R(19), 25+R(19), 209+R(9), alpha));
           }
         }
       }
      }

      畫上 HUD,更新時間,請求下一次更新

      如何用不到 2KB 的 JavaScript 代碼寫一個 3D 賽車游戲?

      游戲的標題、時間和距離是用一個非常基礎的字體渲染系統(tǒng)顯示出來的,就是之前設置的 DrawText 函數。在玩家點擊鼠標之前,它會在屏幕中央顯示標題。

      按下鼠標后,游戲開始,然后 HUD 會顯示剩余時間和當前距離。時間也在這塊更新,玩過此類游戲的都知道,時間只在比賽開始后減少。

      在這個 massive Update function 結束后,它調用 requestAnimationFrame (Update) 來觸發(fā)下一次更新。

       if (mousePressed)
      {
       time = Clamp(time - timeDelta, 0, maxTime); // update time
       DrawText(Math.ceil(time), 9);               // show time
       context.textAlign = 'right';                // right alignment
       DrawText(0|position.z/1e3, c.width-9);      // show distance
      }
      else
      {
       context.textAlign = 'center';      // center alignment
       DrawText('HUE JUMPER', c.width/2); // draw title text
      }

      requestAnimationFrame(Update); // kick off next frame

      } // end of update function

      代碼的最后一位

      HTML 需要一個結束腳本標簽來讓所有的代碼能夠跑起來。

       Update(); // kick off update loop
      </script>

      壓縮

      這就是整個游戲啦!下方的一小段代碼就是壓縮后的最終結果,我用不同的顏色標注了不同的部分。完成所有這些工作后,你能感受到我在2KB內就做完了整個游戲是多么讓我滿意了嗎?而這還是在zip之前的工作,zip還可以進一步壓縮大小。

      如何用不到 2KB 的 JavaScript 代碼寫一個 3D 賽車游戲?

      如何用不到 2KB 的 JavaScript 代碼寫一個 3D 賽車游戲?

      警告 Caveats

      當然,還有很多其他 3D 渲染方法可以同時保證性能和視覺效果。如果我有更多的可用空間,我會更傾向于使用一個 WebGL API 比如 three.js ,我在去年制作的一個類似游戲“Bogus Roads”中用過這個框架。此外,因為它使用的是 requestAnimationFrame ,所以需要一些額外的代碼來確保幀速率不超過60 fps,增強版本中我會這么用,盡管我更喜歡使用 requestAnimationFrame 而不是 setInterval ,因為它是垂直同期的(VSyn,VerticalSynchronization),所以渲染更絲滑。這種代碼的一個主要好處是它非常兼容,可以在任何設備上運行,盡管在我舊 iPhone 上運行有點慢。

      游戲代碼被我放到了 GitHub 上的 GPL-3.0 下(https://github.com/KilledByAPixel/HueJumper2k),所以你可以在自己的項目中自由使用它。該庫中還包含 2KB 版本的游戲,準確說是2031字節(jié)!歡迎你添加一些其他的功能,比如音樂和音效到“增強”版本中。

      后記

      雷鋒網注意到,Frank Force 在個人博客發(fā)了這篇文章后,在內容、標題的加持下,這篇文章后來被不少國外媒體轉載。在盛贊之余,也有質疑的聲音。網友“Anon”在原文下評論:你是如何在 2KB 安裝一個完整的 javascript 的,除非你可以隨意忽略 dependencies 插件庫的大小,或者你將整個游戲作為 dependency,大小才有可能控制到 2KB,否則就是欺騙。

      Frank 回復表示,大多數 small demos 都需要某種運行環(huán)境,即使它是可執(zhí)行的。在這種情況下,就是 javascript 運行時環(huán)境,沒有其他 dependencies.。因為 javascript 是解釋的,所以也可以說壓縮后的代碼是在2KB以內的。

      雷鋒網發(fā)現,有其他網友表示認可 Frank 的說法,他們認為 JS 是一種解釋語言,不能將其與其他編譯語言相比較。

      雷鋒網

      如何用不到 2KB 的 JavaScript 代碼寫一個 3D 賽車游戲?

      分享:
      相關文章

      編輯

      數據漫游天地間。 聯系可通過上方郵箱或WeChat(請注明身份、姓名、來意,thx)
      當月熱門文章
      最新文章
      請?zhí)顚懮暾埲速Y料
      姓名
      電話
      郵箱
      微信號
      作品鏈接
      個人簡介
      為了您的賬戶安全,請驗證郵箱
      您的郵箱還未驗證,完成可獲20積分喲!
      請驗證您的郵箱
      立即驗證
      完善賬號信息
      您的賬號已經綁定,現在您可以設置密碼以方便用郵箱登錄
      立即設置 以后再說
      主站蜘蛛池模板: 水润女人刘智贤主演| 野鸽子电视剧全集| 鮎川なお| 魔法科高中的优等生| 《斯巴达1帝国女版》海盗在线观看| 有情饮水饱国语| GAY取精潮喷10次龟责到哭| 隐藏的帽子韩国版在线观看| 玫瑰故事的电视连续剧免费看| 蓝色帽子隐身的韩国电影| 韩国 艳舞| 冰冷热带鱼 手机在线观看| 风俗校园祭动漫在线观看全集| 农民伯伯下乡三级片| ssni-025| 《特殊诊所》苍井空| 名侦探学院第六季免费观看完整版| 双子星公主 第2部| 女销售靠睡觉卖房子电影| 沈阳天空聊天室| 异形夺命舰免费观看中文版| 沉静如海| 晚安为我而我的妹妹| 甜蜜家园2今日播出| 女版战狼6免费观看999为什么播放不了 | bigtitsvideos| 爱我就别想太多免费版| 包青天93版免费观看西瓜影院| 黑白配1080完整版免费观看| 康姿百德健身全集下载| 王牌保安电影| 今日宜喜欢短剧| 边做饭边被躁BD水电工的艳遇| 女人的村庄完整版| 四位少妇按摩的电影| 激情艳女| 蛇姬 极乐诱惑| 大兵的寝室电影在线免费观看 | 出轨的味道在线观看| 冷风暴1-48集免费观看| 幻世录3下载| 惊声尖笑3免费版高清在线观看| 尖子攻略电视剧| 加勒比海盗3国语版| 八戒,八戒,八戒7| 南美超级杯| 塔城市| 阿尔梅洛| 齐天大圣2022电影在线观看| 电影《穿睡衣下楼取快递》| 那金花和她的女婿46| 寻秦记高清| 麦乐蒂女超人满天星| 花的勇气ppt| 若尔盖县| 蓝精灵动画片| 《欢乐岁月》| 暴躁少女完整版视频在线观看| 燧石行动电影| 东北往事之黑道风云二十年电视剧| 麦乐迪马克斯女超人满天星播放| 年经姨妈3电影| 林一未来短剧免费观看| 髙压监狱法版免费| 缘分五月在线看片| 人约离婚后国语高清| 《隔壁放荡人妻BD高清》在线| 狂暴飞车完整未删减版| 男女一起愁愁愁高清全集在线看| 天美星空mv在线观看| 大剑在线观看免费全集高清版| 凯登克罗斯在线免费观看| 佐佐木麻衣| 电视剧扫黑风暴40集在线观看| 陪讨厌部长去出差旅日本在线观看| 夜之女王| 瞄准 电视剧| 《初体验5》完整版| 不能说的秘密| 房术入门40个动作| 4999高清播放器| 风语者高清| 《法国空乘11》播放| 月夜闪灵| 幽灵行动电影| 电影《姐妹牙医》完整版在线播放| 伊金霍洛旗| 高清《天注定》电影| 朋友换麦子6| 朋友的姐姐线观高清3中语| 电影《娜塔莉》在线观看完整版中文 | 爱之色放| 憨豆先生在线观看| 壮志凌云女版啄木鸟满天星法版剧情介绍 | 荣誉电视剧| 电影《金悔瓶》徐少强叫什么名字就| 美国式禁忌1百度影音| 爱情呼叫转移电影| 酒店1—60集全集免费高清| 陈宝莲电影《满天星》在线播放 | 暴躁46集正版在线观看| 河西区| 陀地驱魔人结局| 莲花县| 维多利亚的秘密内衣| 孩子走丢妈妈冲上舞台求助| 《私人女性监狱》| 我是大哥大国语| 二十四小时日本中文在线观看| 高压监狱2法板145分钟| 单亲妈妈4免费高清完整版观看| 一起来看流星雨吻戏| 爱我几何完整版在线观看| 佐佐木麻衣| 笨贼妙探国语| 女版战狼10国语版免费观看电视剧| 遇见波莉| 我和我的时光少年电视剧免费观看| 韩剧办公室蓝色隐身帽子动漫| ママぷりっ!?| 惊天危机2完整免费| 天海冀| 亲爱的自己全集在线观看| shameless第十一季完整版| 大红灯笼高高挂在线观看| 小蜜蜂电影| 《执行秘书》2009| 仙逆113| 《瓜达卢佩的玫瑰》在线播放在线免费观看 | 铁梨花剧情介绍| 古墓丽影(法国版)女版| 很想很想你免费观看完整版| 一起愁愁电影免费观看高清| 惊天营救3免费观看完整| 办公室蓝色隐身帽子在线观看| 国少6:0大胜不丹| 步步惊心qvod| 天美影院在线观看| 内幕未删减| 再见了大别山吕继宏| 白峰电影免费播放在线| 请不要离我而去| 伍六七之暗影宿命 2023| 罗丽星克莱尔迷宫片长| 手机情缘| 敢死队5免费高清国语| 法国监狱(法国)电影观看| 立陶宛大使被通知离境| 密爱电影免费完整版在线观看| 特殊销售现在播放| 囧的呼唤| 孽海花传奇| 美国性妓院妓女k8播放| 而立之年电视剧全集| 咒电影完整版高清免费观看| 启航当风起时电视剧全集免费观看 | 女童乱小便被父亲倒挂窗外| 无名之辈电影高清免费| 麦乐迪家庭矛盾在线观看| 感官世界 在线| 拉拉电影免费观看电影| 一起对愁愁愁免费观看| 电视剧冰锋剧情介绍| 25岁女高中生在线观看| 色拉拉| 海贼王狂热行动在线观看| 宇宙战舰大和号复活| 安拉拉斋电影在免费播 | 《疾速追杀:芭蕾杀姬》| 电影斗牛下载| 北汽40| 蝴蝶行动电视剧全集30| 屋顶工垃拉电影免费观看| 大地中文8在线观看免费| 女儿的朋友2韩国电影| 公浮之5| 惊情电影| 暴力监狱| 做aj免费国语版电视剧| 《罪恶权力》在线观看韩剧 | 粉红大白菜(法国)| 辽宁舰试飞牺牲了多少人| 86警花不雅照| 《伊波拉病毒2》未删版| 变形金刚4枪版| 酒巷深深| 战狼9加拿大版高清版| 八十四句梵唱大悲咒| 蹉跎岁月主题歌| 《甜美的姐姐》动漫完整版 | 凹凸影视| 铜铿锵锵完整版免费看| 看见爱台剧有无删减版本| 电视剧梦幻天堂| 莫莉3特别的酒店| 林家铺子在线观看| 《纣王妲己》全集观看| 公之孚之中字50| 好看的美国爱情片| 私じゃなかったんだね谐音| 法国版《少女绣感》| 恰恰电影在线观看动漫| 使徒行者粤语15| 曹查理《怒警狂花》电影版| 肉蒲团在线观看| 困惑的浪漫在线观看| 法国版《女超人:麦乐迪》满天星 性的暴行电影中文字幕 | 电视连续剧锅哥警察| 男按摩师黄色电影| 铁在烧 电视剧| 韩国演艺圈悲惨1-33集| 特殊美容院待遇3| 清明上河图密码40集全| 公之孚手中字50| 超能姐姐大作战| 超级飞侠第十二季| 《束缚游戏》全集| 蜜桃成熟时33dqvod| 十三邀 第九季| 《和妽妽的关系》HD| 梦想城第40集免费播放| 天赋异禀北极星免费观看| 白峰美羽伦理片| 孝敬爸爸的好女儿父女| 千王之王谢贤版| 除却巫山无删减版txt| 奔跑吧3| 怎么哪个景区看起来都像有1亿人| 鬼子暴行少女电影vcd| 古惑仔5龙争虎斗| 我想有个家电视剧| 凯帕克63部电影合集在线观看| 策驰影院电视剧免费策驰电影| 晒晒我们家12岁儿子的小鸡| 唐诡西行电视剧| 彼女电影| 《越南暴行2》免| 钟表馆事件电视剧| 家族荣耀之继承者粤语在线观看| 《莫莉特别的酒店》电影在线观看| 以你为名的青春电视剧免费观看| 许冠杰电影全集粤语| 麦乐迪马克斯女超人免费观看| 烽火佳人| 光剑变装二维码| 中文字Dl幕岳 和女胥婷婷综合 | 电视剧骄阳伴我免费观看全集| 保险女王和她的商业秘密英文版| 张继科独特躲酒方法| 守护者们电视剧免费观看| 师生畸恋下载| 曹阳 MOKO| 长空之王电影| 石正丽简介| 日威电推剪| 四川少女免费观看电视连续剧| 公的浮之手中字40 | 电影安斋拉拉中文字幕| 刘兰芳评书打包下载| 情深深雨蒙蒙35| 公浮之手电影在线播放完整版 | 苍井空电影全集快播| 战狼6免费观看在线播放完整版| 电视剧莲花楼完整版免费观看| 韩国美人图| 插曲的30集全集免费播放| 赶尸艳谈恐怖电影免费观看高清版 | 莫妮卡《爱我几何》剧情介绍在线观看 | 拍的不错| 银瓶梅电视剧第5集电视剧在线观看泰国版 | 下一站婚姻主题曲| 体感预报在线观看免费完整版| 乡村爱情14 电视剧| 诱惑维修工| 杀戮之王电影在线观看| 私人家教韩国| 年轻的姐夫在线免费观看| 玄女心经2在线观看免费| 超级战舰国语版| 蜜桃成熟时1997百度影音| 第8号当铺全集| 在线观看电影免费高清完整版| 莎车县| 安徽卫视回放| 延禧攻略70集免费播放完整版| 何杜娟潜规则| 女大学生精油按摩| 幸福密码40集完整版| 妻子的诱惑电视剧| 爱我几何电影完整版在线播放免费观看莫尼卡 | 从结婚到恋爱电视剧免费观看全集| 绝世双骄主题曲| 恶夜活死鸡| 坎贝奇《无憾》电影播放| 刘宝瑞单口相声测字| 本乡爱电影合集在线观看完整版 | 年轻的老师4| 闪婚影帝短剧全集| 我要看熊出没之| 泰剧祁安《秘密爱》| 善良的母亲中字开头9个字出差| 国家命脉| 十七岁的天空插曲| 母乳喂养宣传片10分钟| 丰满的继牳性教育| 杨佑宁十七岁的天空| 男大当婚大结局| 4个少妇精油按摩| 最美的安排| 乐昌市| 千人斩在线观看| 霸王别姬电影| 白峰电影高清在线观看| 天龙八部24| 黑大佬的365天无删除完整翻译| 灯草和| 守护者联盟| 满天星《西部牛仔》 | 热辣披萨女孩电影高清版在线观看| 出来面试的妻子免费观看电视剧| 神探狄仁杰第四部| 教授小星| 夫の上司に犯白峰美羽| 高圆圆回应网友说她老了| 大凉山姑娘开放| 双女任务电影在线观看| 三生三世枕上电视剧| 我是余欢水下载| 林中小屋2百度影音| 动漫《侄女开发日记》免费观看完整 | 《品味人生》全集免费看 | 《我的健身教练2》| 聊斋艳谭之月光宝盒| 我怎么哭了| 金乡县| 生死之恋三部曲| 电视剧因法之名免费超清观看| 午夜寂寞安卓影院| 太平公主秘史 电视剧| 陈雅伦曹查理《我为卿痴狂》在哪里 | 年轻丰满的继牳2| 新金银悔1-5普通话一| 苹果电影片| 侠探杰克2迅雷下载| 涩涩屋在线观看免费 | 废柴兄弟| 黑白配高清国语观看| 武动乾坤动漫第二季| 在线观看神雕侠侣| 任达华舞男| 美丽妻子替丈夫还债电影完整版免费| 初二数学难题| 金瓶酶2全集观看| 叶子楣古装电影全集| 日本电影《牙医姐妹》在线 | 《游泳教练》免费观看| 信者无敌全集在线观看| 凶器未删减| 《在一起》免费观看| 内衣销售员的秘密| 爱人韩剧免费观看电视剧| 缺宅男女大结局| 娜塔莎电影| 女人和女人一起愁愁愁电视剧观看| 桃花请缨免费看全集| 七号差馆国语| 小泽彻主演的《老板老板的要求》电影播放| 还珠格格风儿阵阵吹| 电影《17.3》完整版| 逆袭之爱情故事电视剧免费观看| 《村妓HD高清| 特种部队2 影音| 联手复仇虐渣:双胞胎姐妹短剧全集| 狂飙2免费观看完整版电视剧全集| 十九岁大学生免费观看电视剧| 油菜花香电视剧全集| 美国XXXX69| 高清怦然与你| 烧饼皇后| 美女杀羊| 雪中悍刀行第三季免费播放 | 男女电视剧演员表免费观看| 禁忌5年转一代禁忌| 电视剧仁心俱乐部分集剧情| 一中学8个体育老师5个是班主任| 恐龙战士| 换伴| 接档夫妻联欢的下一个动画| 黄金未来5年还会到500以下吗| 大侦探福尔摩斯1在线| 需要爸爸的种子电影在线观看 | 混元24式太极拳| 《落魄贵族琉璃川》动漫免费| 离婚复仇:渣男完蛋短剧全集| 于东来连发11条动态| 别墅互换在线观看| 爱在空气中第八集| 学生的妈妈5字| 杏林春暖无删减| 战狼6欧式少女全集观看高清版| 功夫梦:融合之道未删减| 电影心灵奇旅| 张磊中国好声音| 电视剧今生有你全集| 大内密探零零发高清国语| 傈僳族怎么读| 锦衣之下免费观看全集芒果TV| 爱的解脱| 《overflower》第一季动漫真人版| 白鹿原电视剧完整版| 卖保险套的女销售完整版电影观看 | 锵锵锵锵锵免费完整观看最新章| 不信你不笑| 说谎的爱人在线观看| 曾国藩电视剧| 法国性瑜伽HD在线| 月光永不坠落短剧免费观看| 拜访者q| 飞驰人生2免费观看全集高清版 | 萨顶顶快去歌手顶一顶| 飞刀又见飞刀百度云| 英雄崛起百度影音| 《新金银悔1—5普通话》第21集武则天 | 美国禁忌1年转一代| 老板的女儿全集免费看| 日韩入室强奸片| 电视剧红楼梦87版| 混血儿的摇篮曲在线观看完整版| 绝对权力电视剧全集免费观看| 丽塔海华丝| 突如其来的假期| 《V酒店第二季》全集免费观看 | 黑白配HD1080免费播放下载| 爱上特种兵全集| 临终老人要走的6个手势| 明月照我心电视剧免费观看| 别墅换妻| 四方极爱电视剧免费观看高清| 火箭军原副司令员吴国华病逝| 亲吻姐姐 第二季全集| 美国禁忌7年转一代| 绿萝花电视剧免费观看| 奇怪的理发店在线播放| 关于爱电影完整版免费观看| 强伦妺妺免费播放视频| 灰姑娘2015电影下载| 湖北经视直播在线观看| 夏至未至免费观看| 修理工的艳遇HD电影在线观看| 天可怜见韩语中字| 终结者6:黑暗命运| 莫言的演讲| 《交换夫婦》木下凛凛子中文字幕在 | 年轻妻子剧情介绍| 覆面系男友| 法国电影肉蔻之香剧情介绍| 高清御赐小仵作2未删减| 千里桃花一世开免费观看全集| 追龙粤语| 银瓶梅全集在线观看免费 | 凯登·克罗斯主演电影在线观看| 监视者们2| 十一人的贼军免费观看高清| 中国式离婚 电视剧| 爸爸播种子,电视剧免费观看| 怦然与你未删减| 亦舞之城免费完整版| 追鱼传奇全集| 私人航空电影免费观看完整版在线播放 | Jizz日本| 香火电视剧| 最后一刻| 斗罗大陆114| the亲子伦| 忍者乱太郎粤语版| 春节的拼音| 羽生稀IPZ376在线播放观看| 门第31集在线观看| 香港| 一见你就笑全集| 雪中悍刀行第二部免费观看完整版| 莫莉特别的酒店| 都市巡警| 我的危险妻子| 吸血鬼女王百度影音| 满天星版《荒岛女儿国》在线观看| 战狼6欧式少女免费播放全部| 黑白禁区电视剧免费观看完整版| 愤怒的黄牛韩剧电影| 三位大学位按摩记角色评价解析| 法国《少女农场》1976| 《砖墙谜攻》| 斗罗大陆观看全集免费| 聚会的目的3高清完整版在线播放| 蜜桃伦理| 潜龙道全集免费观看| 爱我几何无删减在线观看完整版中文| 霸王别姬电影| 《激战丛林》电影观看| 下水道人鱼| 野花韩国视频观看免费高清视频| 影音先锋色播| 四少妇的秘密按摩在线观看伦理电影 | 巴黎 我爱你| 韩国电影售楼部的小姐| 西瓜膨大剂| 太古至尊两处闲愁| 西班牙电视剧《爱的释放》| 乌龙元首| 爆裂飞车22017| 一路向西电影完整视频在线| 男子地铁上数次扇脸女子质问爱谁| 法国版《女超人:麦乐迪》电影在线播| 我来也高清| 鹿鼎记在线观看| 十首最好老歌| 上海电视台节目表| 金塔县| 古代的口香糖叫什么| 璀璨人生65集| 女超人麦乐迪2013| 《斗罗大陆》.免费观看| 北欧精灵《麦乐迪女超人》在线| 年轻漂亮小在线观看| 高清原始战争| 聊斋在线观看免费全集| 日批发出来的声音录音| 麦乐迪家庭矛盾完整版| 大夏第一赘婿短剧全集免费观看 | 满天星《爱丽丝梦游辣境》| 杀戮天使第一季全集免费观看| 蓝可儿电梯事件| 姐姐6免费完整高清电视剧在线看| 《维修工的艳遇》金美贤| 美国女兵人4免费观看完整版| 歌曲《母鸡咯咯哒》| 熊出没之逆转时空完整| 人猿泰山1995版意大利经典电影| 3d 肉| 巴啦啦小魔仙之彩虹心石11| 温柔的背后吻戏| 战狼7高清版999加拿大版| 朝国年经继拇11| 男生和女生拔萝卜| 电影《牙医姐妹》1986版在线| 美剧《真探》第一季免费观看全集| 突围行动国语| 《《特殊的房产销售2》》HD免费免费在线观看-2003年全集纪录剧 - 天美影院 | 健男抢钱团| 韩国三姐妹| 出轨的女人全集| 按摩3一4| 极限挑战第2季 综艺| 梦幻天堂| 鬼作在线观看| 《女超人:麦乐迪》在线播放| 三毛丛军记| 《大长今》电视剧| 19岁大学生免费观看电视剧中文版| 美丽在望粤语| 时宴郑书意电视剧免费观看| 不良义姐在线观看免费| 初恋重逢:初心不变短剧全集| 韩雪后台| 老千电影| 《外卖奇遇记》周香允周免费观看| 两女 一杯在线观看| 只有你泰剧完整版免费观看| 三剑客电视剧| 《分娩按摩》| 布兰迪《军事不当行为2》在线观看完 | 第一炉香电影完整版观看| 美容院特殊待遇免费观看| 高清《我的娜塔莎》电视剧| 姐姐立正向前走| 陪部长出差在线观看| 最新韩国电视剧| 监狱战舰在线观看| 急诊护士免费观看| 一步之遥字幕下载| 独行月球在线观看| 侠盗高飞免费| 《大兵的寝室》美剧免费观看全集| 三打白骨精电影| 桔子在线观看免费高清电视剧| 女子私人监狱免费观看全集剧情介绍 | 《反击》在线观看完整版| 《女超人(麦乐迪)》在线观看 | 我爱喵星人免费高清观看完整版| 玄好心经8| 普通的孩子未删减| 电影《陌生人》| 木下凛凛子 电影| 金战演员表| 神隐35集| 图书馆的女友(日漫)第五集| 错错错 越南| 精英律师电视剧在线观看| 古墓丽影满天星全集免费看| (已屏蔽)| 也平凡1-45集免费观看| 成员函数指针| 杰克逊30周年演唱会| 97免费观看在线观看电视剧| 你妈妈也一样在线观看| 人间中毒在观完整有限中字| 追凶者也电影未删减版在线| 激情厨房3| 圣特佩罗斯的姑娘们| 灰姑娘电影HD版| 披荆斩棘2| 终物语下| 妓院里的中国姑娘在线观看| 《第一次亲密接触》| 魔具少女| 男士胸罩| 一生一世完整版免费| 妻子8免费播放在线观看第二季| 爱回家之二人世界| 二十世纪性格与X爱情观后感 | 高清《淡岛百景》电视剧| 加勒比海盗4(惊涛怪浪)电影| 迪迦奥特曼13| 放牛班的春天| 立功电视剧| 至尊马蒂| 康体水疗完整版在线观看免费播放| 第九区 电影| 刀郎演唱会为何引网友期待| 七夕潘甜甜牛郎织女资源| 夜关门欲望之花| 东京塔越南女兵电影完整版| 无法忍受的日子| 偷尝禁果在线观看| 海贼王969| 一闪一闪亮晶晶 电视剧| 激战丛林在线观看免费完整电影| 末代福晋| 星辰变在线观看全集免费播放 | 朴雅珍《隐身帽》在线| 少年包青天2土豆| 女武神的终末动漫在线观看| 埃博拉前线电视剧免费观看 | 被拒绝的爱:无尽篇未删减| 美国爸爸要播放的电影| 韩剧恋人主题曲| 单身即地狱综艺在线观看| 《朋友的妈妈》中字歌曲| 修理工的艳遇陶| 俄罗斯女超人| 高压监狱在线完整版观看| 再喊一声爹娘| 决杀令电视剧| 三姐妹瑜伽健身原版| 女超人麦乐迪种子 | 免费全集观看| 锦月如歌在线观看| 无憾坎贝奇英文在线完整观看| 公主日记在线观看| 我在岛屿读书| 一次邂逅| 人民的正义| 星球大战女版满天星免费观看 | 部长来家做客无删减版中文| 《女销售员的秘密》2| 中国女排3-2巴西女排| 东北往事之黑道风云20年21集| 契约到期:总裁不缠短剧全集| 战狼16欧式少女版| ooozzzxxx| 奔跑吧兄弟第三季| 了不起的埃莉诺电影| 徒然喜欢你| 墨西哥《瓜达卢佩玫瑰》| 总统之夜1997法国版第一季 | 四个贵妇精油按摩电影免费播放 | 和讨厌的部长一起去出差| 星落凝成糖电视剧免费| 卧底娇娃| 上党梆子打金枝| 《粉红大白菜》法国| 1979女超人| 电视剧神枪在线观看| 哈尔滨漫展麻衣学姐| 欢乐颂共多少集| 我是刑警40集在线观看| 《八佰》免费观看完整| overflowers全集免费第一季| 挚爱游戏短剧免费观看| 倩女幽魂电影在线观看免费完整版| 相爱十年 电视剧| 炸天小姐在线观看| 权欲武力| 木府风云主题曲净土| 北京石景山八女案| 由良千岁在线观看| 少儿不宜| 暴烈警官| 昭然若揭的意思| 柔术满天星电影在线播放| 合租屋交换做爰| 吞噬星空动漫在线观看39集| 进击的巨人第二季第三集| 贝拉电影1980美国版| 乔丹扣篮| 消失的罪证| 郭的秀 赵雅芝| 男女做爰猛烈叫床视频动态图| 买房子的女销售2| 酒店1-100集全集免费观看高清 | 恨锁金瓶在线观看3| 三德和尚与舂米六免费观看 | 星克莱尔在线观看| 中国古典美女| 《扫黑风暴》电视剧| 玩命追踪国语| 哪吒之魔童降临免费播放| 金银悔5普通话版免费播放| 高压监狱2在线观看免费版高清| 空姐不雅视频| 特殊精油按摩3电影| 炸裂白宫| 王牌对王牌免费播放完整版| 浪漫女家教在线观看电影| 张云熙| 一个女的被多人轮流扇耳光| 宝洁回应香皂嵌刀片| 电视剧前妻回家| 无敌幸运星粤语版| 我的xl司令第一季全集| 泽塔奥特曼中文版免费| 扫毒风暴免费观看全集电视剧| 兰若寺电影| 夏目彩春猛烈肉体破坏版| 《激战丛林》-罗莎·卡拉乔洛免费观| 支配教坛动漫免费版| 降头国语| 绝对隐私| 魔法咪路咪路第3季| 仙剑奇侠传3全集| 莫莉特别酒店3| 激战从林2电影免费观看| 青春期一| 印度合伙人| 画皮真爱无悔| 护国战神短剧全集| 日本战狼6免费完整版| 《特殊客房》| snis-986| 挡不住的风情 下载| 白峰美羽无码电影观看 | 满天星电影免费观看| 哇嘎全部高清在线观看| 政坛巨星| 甜蜜惩恶第一季免费观看全集高清| 遍地狼烟在线观看| 大河小虾| 木下凛凛子在线| 三年成全免费完整版电视剧| 艾回五子| 游戏007| 劫中劫之劫水| 省港大营救电视剧免费观看| 小凤新婚完整版免费看| 台湾怀旧绝版酋长的女儿| 《新三国》| 新版寒冰出装| 庆祝六一歌曲| 朴亚珍《蓝色隐身帽》全集| 《极恶老大》| 甜性涩ai| 关于爱情的英文诗| 欧美黑白配经典在线观看 | 金蝉脱壳1| 缉恶在线观看| 爱唯侦查DVD视频| 叶倩文三级大尺度电影| 假日暖洋洋2电视剧在线观看| 欢乐颂4免费观看全集电视剧完整版| 自古英雄出少年之岳飞| 太后吉祥电影| 安斋拉拉电影免费观看高清版2023年| 瓜达卢佩的玫瑰在线看完整版| 杰克逊MV| 这里的黎明静悄悄 电影| 18岁电影| 《永不磨灭的番号》电视剧| 美国式忌保罗讳1--4| 《伦理按摩2》电影| 平凡歌电视剧免费观看全集高清| 湖南下了特大暴雪| 精忠岳飞全集| 二战德军发泄室正版| 高清《碧血剑》电影| 各位游客请注意| 离人心上番外| 满天星电影在线观看完整免费高清原声满天 | 新精武门周星驰| 洛克王国动画片| 文豪野犬第季第三季| 南丰县| 销售的销售秘密6HD中字国 | 龙之谷夏萝莉的照片| 屠龙少年历险记| 双人调情按摩术韩国在线观看| 奇奇上司妻电视剧在线观看| 好心作怪粤语24| 我要涩女郎| 《荣誉守则》成人版| 第三类法庭主题曲| 《赶尸艳谈》无删减版| 女人的抗战 电视剧| 惊天危机在线完整版免费观看| 色诱水电工师傅激情毛片| 入室暴行电影在线看| 小小安妮第三季| 初次尝鲜免费观看全集完整版| 仁心解码电视剧| 密室大逃脱第三季免费观看完整版| 电影天海翼匿名侦探免费观看 | 上错花轿嫁对郎电视剧完整版| 高清《外出》免费观看完整| 朋友的妻子肉H| 向流星许愿的我们电视剧| 人猿泰山1995版迅雷| 小乔迪满天星电影免费观看| 乐环影院| 张莜雨人体艺术照| 加利福尼亚山谷女孩们| 卯水咲流| 《法国空乘5》| 360大佬爱上我第二季全集| 泽塔奥特曼中文版免费| 百日蔷薇ova2| 电视剧新亮剑| 小沈阳和他媳妇唱的歌| 刑侦12国语免费观看| 妈妈的职业5韩剧| 狂飙在线观看免费完整观看| 林丹装路人打球| 电视剧便衣支队| 美版HD古墓丽影山寨版满天星| 美容室.特除服务7| 九九电视剧免费观看| 蒋欣王凯宣布结婚| 金牌销售秘密| 重案六组第四部优酷| 重庆森林免费| 暗藏玄鸡| 女律师的壁落| 暖男的爱情与战争|