精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

265行代碼實現第一人稱游戲引擎

開發 項目管理 后端
本文沒有涉及復雜的數學計算,只用到了光線投射技術。你可能已經見識過這種技術了,比如《上古卷軸2 : 匕首雨》、《毀滅公爵3D》還有 Notch Persson 最近在 ludum dare 上的參賽作品。Notch 認為它夠好,我就認為它夠好!

今天,讓我們進入一個可以伸手觸摸的世界吧。在這篇文章里,我們將從零開始快速完成一次第一人稱探索。本文沒有涉及復雜的數學計算,只用到了光線投射技術。你可能已經見識過這種技術了,比如《上古卷軸2 : 匕首雨》、《毀滅公爵3D》還有 Notch Persson 最近在 ludum dare 上的參賽作品。Notch 認為它夠好,我就認為它夠好!

 [Demo (arrow keys / touch)] [Source]

[[114219]]

用了光線投射就像開掛一樣,作為一名懶得出油的程序員,我表示非常喜歡。你可以舒暢地浸入到3D環境中而不受“真3D”復雜性的束縛。舉例來說,光線投射算法消耗線性時間,所以不用優化也可以加載一個巨大的世界,它執行的速度跟小型世界一樣快。水平面被定義成簡單的網格而不是多邊形網面樹,所以即使沒有 3D 建模基礎或數學博士學位也可以直接投入進去學習。

利用這些技巧很容易就可以做一些讓人嗨爆的事情。15分鐘之后,你會到處拍下你辦公室的墻壁,然后檢查你的 HR 文檔看有沒有規則禁止“工作場所槍戰建模”。

玩家

我們從何處投射光線?這就是玩家對象(Player)的作用,只需要三個屬性 x,y,direction。

  1. function Player(x, y, direction) {  
  2.   this.x = x;  
  3.   this.y = y;  
  4.   this.direction = direction;  
  5. }  

地圖

我們將地圖存作簡單的二維數組。數組中,0代表沒墻,1代表有墻。你還可以做得更復雜些,比如給墻設任意高度,或者將多個墻數據的“故事(stories)”打包進數組。但作為我們的第一次嘗試,用0-1就足夠了。

  1. function Map(size) {  
  2.   this.size = size;  
  3.   this.wallGrid = new Uint8Array(size * size);  
  4. }  

投射一束光線

這里就是竅門:光線投射引擎不會一次性繪制出整個場景。相反,它把場景分成獨立的列然后一條一條地渲染。每一列都代表從玩家特定角度投射出的一條光線。如果光線碰到墻壁,引擎會計算玩家到墻的距離然后在該列中畫出一個矩形。矩形的高度取決于光線的長度——越遠則越短。

[[114220]]

繪畫的光線越多,顯示效果就會越平滑。

 

1. 找到每條光線的角度

我們首先找出每條光線投射的角度。角度取決于三點:玩家面向的方向,攝像機的視野,還有正在繪畫的列。

  1. var angle = this.fov * (column / this.resolution - 0.5);  
  2. var ray = map.cast(player, player.direction + angle, this.range); 

2. 通過網格跟蹤每條光線

接下來,我們要檢查每條光線經過的墻。這里的目標是最終得出一個數組,列出了光線離開玩家后經過的每面墻。

[[114221]]

從玩家開始,我們找出最接近的橫向(stepX)和縱向(stepY)網格坐標線。移到最近的地方然后檢查是否有墻(inspect)。一直重復檢查直到跟蹤完每條線的所有長度。

  1. function ray(origin) {  
  2.   var stepX = step(sin, cos, origin.x, origin.y);  
  3.   var stepY = step(cos, sin, origin.y, origin.x, true);  
  4.   var nextStep = stepX.length2 < stepY.length2  
  5.     ? inspect(stepX, 1, 0, origin.distance, stepX.y)  
  6.     : inspect(stepY, 0, 1, origin.distance, stepY.x);  
  7.    
  8.   if (nextStep.distance > range) return [origin];  
  9.   return [origin].concat(ray(nextStep));  

尋找網格交點很簡單:只需要對 x 向下取整(1,2,3…),然后乘以光線的斜率(rise/run)得出 y。

  1. var dx = run > 0 ? Math.floor(x + 1) - x : Math.ceil(x - 1) - x;  
  2. var dy = dx * (rise / run); 

現在看出了這個算法的亮點沒有?我們不用關心地圖有多大!只需要關注網格上特定的點——與每幀的點數大致相同。樣例中的地圖是32×32,而32,000×32,000的地圖一樣跑得這么快!

 

3. 繪制一列

跟蹤完一條光線后,我們就要畫出它在路徑上經過的所有墻。

  1. var z = distance * Math.cos(angle);  
  2. var wallHeight = this.height * height / z; 

我們通過墻高度的最大除以 z 來覺得它的高度。越遠的墻,就畫得越短。

 

額,這里用 cos 是怎么回事?如果直接使用原來的距離,就會產生一種超廣角的效果(魚眼鏡頭)。為什么?想象你正面向一面墻,墻的左右邊緣離你的距離比墻中心要遠。于是原本直的墻中心就會膨脹起來了!為了以我們真實所見的效果去渲染墻面,我們通過投射的每條光線一起構建了一個三角形,通過 cos 算出垂直距離。如圖:

[[114222]]

我向你保證,這里已經是本文最難的數學啦。

 

渲染出來

我們用攝像頭對象 Camera 從玩家視角畫出地圖的每一幀。當我們從左往右掃過屏幕時它會負責渲染每一列。

 
在繪制墻壁之前,我們先渲染一個天空盒(skybox)——就是一張大的背景圖,有星星和地平線,畫完墻后我們還會在前景放個武器。
  1. Camera.prototype.render = function(player, map) {  
  2.   this.drawSky(player.direction, map.skybox, map.light);  
  3.   this.drawColumns(player, map);  
  4.   this.drawWeapon(player.weapon, player.paces);  
  5. }; 

攝像機最重要的屬性是分辨率(resolution)、視野(fov)和射程(range)。

  • 分辨率決定了每幀要畫多少列,即要投射多少條光線。
  • 視野決定了我們能看的寬度,即光線的角度。
  • 射程決定了我們能看多遠,即光線長度的最大值

組合起來

使用控制對象 Controls 監聽方向鍵(和觸摸事件)。使用游戲循環對象 GameLoop 調用 requestAnimationFrame 請求渲染幀。這里的 gameloop 只有三行

  1. oop.start(function frame(seconds) {  
  2.   map.update(seconds);  
  3.   player.update(controls.states, map, seconds);  
  4.   camera.render(player, map);  
  5. });   
 

細節

雨滴

雨滴是用大量隨機放置的短墻模擬的。

  1. var rainDrops = Math.pow(Math.random(), 3) * s;  
  2. var rain = (rainDrops > 0) && this.project(0.1, angle, step.distance);  
  3.    
  4. ctx.fillStyle = '#ffffff';  
  5. ctx.globalAlpha = 0.15;  
  6. while (--rainDrops > 0) ctx.fillRect(left, Math.random() * rain.top, 1, rain.height); 

這里沒有畫出墻完全的寬度,而是畫了一個像素點的寬度。

 

照明和閃電

照明其實就是明暗處理。所有的墻都是以完全亮度畫出來,然后覆蓋一個帶有一定不透明度的黑色矩形。不透明度決定于距離與墻的方向(N/S/E/W)。

  1. ctx.fillStyle = '#000000';  
  2. ctx.globalAlpha = Math.max((step.distance + step.shading) / this.lightRange - map.light, 0);  
  3. ctx.fillRect(left, wall.top, width, wall.height); 

要模擬閃電,map.light 隨機達到2然后再快速地淡出。

 

碰撞檢測

要防止玩家穿墻,我們只要用他要到的位置跟地圖比較。分開檢查 x 和 y 玩家就可以靠著墻滑行。

  1. Player.prototype.walk = function(distance, map) {  
  2.   var dx = Math.cos(this.direction) * distance;  
  3.   var dy = Math.sin(this.direction) * distance;  
  4.   if (map.get(this.x + dx, this.y) <= 0) this.x += dx;  
  5.   if (map.get(this.x, this.y + dy) <= 0) this.y += dy;  
  6. }; 

墻壁貼圖

沒有貼圖(texture)的墻面看起來會比較無趣。但我們怎么把貼圖的某個部分對應到特定的列上?這其實很簡單:取交叉點坐標的小數部分。

  1. step.offset = offset - Math.floor(offset);  
  2. var textureX = Math.floor(texture.width * step.offset); 

舉例來說,一面墻上的交點為(10,8.2),于是取小數部分0.2。這意味著交點離墻左邊緣20%遠(8),離墻右邊緣80%遠(9)。所以我們用 0.2 * texture.width 得出貼圖的 x 坐標。

 

試一試

恐怖廢墟中逛一逛。
還有人擴展了社區版
 

接下來做什么?

因為光線投射器是如此地快速、簡單,你可以快速地實現許多想法。你可以做個地牢探索者(Dungeon Crawler)、第一人稱射手、或者俠盜飛車式沙盒。靠!常數級的時間消耗真讓我想做一個老式的大型多人在線角色扮演游戲,包含大量的、程序自動生成的世界。這里有一些帶你起步的難題:

  • 浸入式體驗。樣例在求你為它加上全屏、鼠標定位、下雨背景和閃電時同時出現雷響。
  • 室內級別。用對稱漸變取代天空盒。或者,你覺得自己很屌的話,嘗試用瓷片渲染地板和天花板。(可以這么想:所有墻面畫出來之后,畫面剩下的空隙就是地板和天花板了)
  • 照明對象。我們已經有了一個相當健壯的照明模型。為何不將光源放到地圖上,通過它們計算墻的照明?光源占了80%大氣層。
  • 良好的觸摸事件。我已經搞定了一些基本的觸摸操作,手機和平板的小伙伴們可以嘗試一樣 demo。但這里還有巨大的提升空間。
  • 攝像機特效。比如放大縮小、模糊、醉漢模式等等。有了光線投射器這些都顯得特別簡單。先從控制臺中修改 camera.fov 開始。

同往常一樣,如果你造了什么炫爆的東西或者有什么相關的研究要分享,發 email 給我或 tweet 我,我會分享給大家的。

 

討論

Hacker News 上的討論。

感謝

本來打算寫兩個鐘的文章結果寫了三周。沒有以下的幫助我不可能寫完這篇文章:

原文鏈接: A first-person engine in 265 lines   翻譯: 伯樂在線 - Jaward華仔

譯文鏈接: http://blog.jobbole.com/70956/

責任編輯:林師授 來源: 伯樂在線
相關推薦

2021-10-15 06:24:38

AIAR眼鏡人工智能

2012-12-24 09:21:45

iOSUnity3D

2012-12-24 09:13:23

iOSUnity3D

2013-10-18 09:29:53

編程開發

2013-01-04 13:14:25

筆記本

2013-05-24 14:02:42

2025-10-17 08:54:00

AI智能體模型

2021-10-15 15:05:32

AI 數據人工智能

2025-07-07 08:41:00

數據模型AI

2010-05-06 21:09:18

2025-06-25 09:02:05

2023-04-24 15:41:27

ChatGPT人工智能

2021-04-23 11:22:57

ThreadJava進階Runnable

2023-05-18 15:28:20

人工智能計算機科學

2021-06-02 16:19:14

技術研發指標

2025-10-03 02:00:00

視頻人體動作EgoTwin

2014-09-24 10:47:56

程序員
點贊
收藏

51CTO技術棧公眾號

国产精品户外野外| 亚洲精品国产精品国自产观看浪潮 | 视频在线这里都是精品| 成人深夜在线观看| 日本最新高清不卡中文字幕| 日本女人性生活视频| 欧美2区3区4区| 欧美日韩在线影院| 熟女视频一区二区三区| 天堂在线中文字幕| 国产一区二区不卡| 国产97在线|亚洲| 久草资源在线视频| 日韩精品第一区| 日韩欧美成人一区二区| 天美星空大象mv在线观看视频| 91高清在线观看视频| 国产偷国产偷精品高清尤物| 91黄色精品| 国产精品51麻豆cm传媒| 日韩视频二区| 精品国偷自产在线视频| 久久美女免费视频| 97视频一区| 精品视频免费看| 131美女爱做视频| 99福利在线| 国产女同互慰高潮91漫画| 国产精品久久波多野结衣| 亚洲一区二区激情| 日一区二区三区| 97在线精品视频| 玖玖爱免费视频| 三区四区不卡| 精品性高朝久久久久久久| 国产成人精品一区二区三区在线观看| 欧美性生活一级| 91久久国产最好的精华液| 亚洲 自拍 另类小说综合图区| 国产精品扒开做爽爽爽的视频| 久久精品亚洲精品国产欧美kt∨ | 在线观看亚洲一区二区| 99热这里只有精品8| 欧美疯狂xxxx大交乱88av| 成年人网站在线观看视频| 精品国产一区二区三区小蝌蚪| 亚洲国产精品一区二区三区| 欧美体内she精高潮| 日韩毛片在线| 欧美最猛性xxxxx直播| 国产精品后入内射日本在线观看| 日韩精品亚洲人成在线观看| 亚洲精品免费视频| 一区二区不卡在线观看| 最新国产在线观看| 国产精品久线观看视频| 亚洲一区二区三区精品在线观看| 国产日产精品久久久久久婷婷| 久久婷婷国产综合国色天香| 欧美精品123| 国产区高清在线| 国产欧美一区二区三区在线看蜜臀| 欧美一区二视频在线免费观看| 欧洲亚洲在线| 中文字幕乱码亚洲精品一区| 一区二区成人国产精品| 日韩精品毛片| 夜色激情一区二区| 久草免费福利在线| 青青青免费在线视频| 日韩欧美高清在线视频| 538在线视频观看| 日日夜夜精品| 日韩精品一区二区三区四区| 国产 xxxx| 精品理论电影在线| 久色乳综合思思在线视频| 久久久久亚洲av成人片| 国产亚洲欧洲| 国产啪精品视频| 国产黄a三级三级看三级| av毛片久久久久**hd| 欧美日韩精品免费看| 素人av在线| 亚洲综合成人在线| 国产在线观看福利| 99精品视频在线免费播放| 亚洲а∨天堂久久精品9966| av网站免费在线播放| 日韩欧美视频专区| 欧美国产乱视频| 91精品国产高清一区二区三密臀| 奇米888四色在线精品| 91香蕉电影院| 人成在线免费视频| 国产精品理论片在线观看| 六月婷婷激情综合| 91精品影视| 欧美一区午夜视频在线观看 | 91国产精品一区| 成人国产精品免费| 性高潮久久久久久久久| 韩国日本一区| 欧美精三区欧美精三区| 日本护士做爰视频| 国产精品久久久久久久久妇女| 国产69精品久久久久99| 中文字幕乱码一区二区 | 欧美午夜一区二区三区免费大片| 亚洲欧美日韩一二三区| 男女男精品视频| 亚洲福利视频二区| 欧美人妻一区二区三区| 欧美精品综合| 国产精品女人久久久久久| 国产91免费看| 成人免费在线观看入口| 国产福利视频在线播放| 成人国产精品一区二区网站| 亚洲精品成人久久久| www.涩涩爱| 国产日韩欧美在线播放不卡| 91中文精品字幕在线视频| 免费在线视频你懂得| 亚洲午夜在线视频| 激情图片中文字幕| 成人精品影院| 日本不卡视频在线播放| 蜜桃91麻豆精品一二三区| 亚洲欧洲性图库| 奇米影音第四色| 欧美人与牛zoz0性行为| 欧美一级黑人aaaaaaa做受| 亚洲成人第一区| 中文字幕综合网| 九九九九九国产| 99久久精品费精品国产风间由美| 国产精品jizz在线观看麻豆| 五月婷婷丁香花| 亚洲va欧美va天堂v国产综合| av在线网站免费观看| 四虎成人av| 国产日本欧美一区二区三区在线| av中文天堂在线| 91九色最新地址| 中文字幕第24页| 日韩在线一二三区| 视频一区国产精品| a屁视频一区二区三区四区| 国产亚洲一区二区在线| 超碰在线观看91| 欧美国产精品一区二区| jizz18女人| 国产精品久久占久久| 成人h猎奇视频网站| 黄色免费在线网站| 日韩欧美成人午夜| 日韩手机在线观看| 91麻豆免费在线观看| 99久久国产宗和精品1上映| 国产传媒欧美日韩成人精品大片| 国产精品亚洲综合天堂夜夜| 日本中文字幕在线观看| 日韩一卡二卡三卡| 动漫精品一区一码二码三码四码| 99久久99久久精品免费看蜜桃| 国产精品宾馆在线精品酒店| 国产日产精品_国产精品毛片| 国产成人jvid在线播放| 77777影视视频在线观看| 337p亚洲精品色噜噜狠狠| 可以直接看的黄色网址| 国产69精品久久777的优势| 精品中文字幕av| 日韩欧美视频在线播放| www久久99| 这里有精品可以观看| 中文字幕一区二区精品| 国产99视频在线| 欧美性猛交xxxx乱大交蜜桃| 久久久久99精品成人| 国产电影精品久久禁18| 久久国产亚洲精品无码| 欧美电影《睫毛膏》| 成人av免费在线看| 日本免费久久| 欧美精品在线免费观看| 裸体xxxx视频在线| 这里只有精品视频在线观看| 国产黄色片免费看| 国产精品视频一二三| 中文字幕乱码在线人视频| 欧美一级一区| 国产精品av免费观看| 国产伦精品一区二区三区千人斩 | 免费一级a毛片| 亚洲欧美日韩中文字幕一区二区三区| 国产伦精品一区三区精东| 免费成人av资源网| 欧美成人高潮一二区在线看| 欧美mv日韩| 久久久影院一区二区三区| 亚洲一区二区小说| 日韩免费在线看| 国产桃色电影在线播放| 中文一区二区视频| 婷婷视频在线观看| 在线播放日韩导航| 欧美日韩a v| 天天综合天天综合色| 免费在线观看黄色小视频| 91蝌蚪国产九色| 女人扒开双腿让男人捅| 久久精品国产一区二区三 | 国产性生活网站| 欧美国产禁国产网站cc| 北岛玲一区二区| 国产精品亚洲а∨天堂免在线| 一级特黄性色生活片| 亚洲欧美久久| 免费一级特黄毛片| 欧美日韩国产探花| 日本丰满大乳奶| 久久精品不卡| 翔田千里亚洲一二三区| 国产一区二区三区日韩精品| 麻豆传媒一区| 欧美性生活一级片| 国产98在线|日韩| 久久伊人影院| 亚洲综合av影视| www 久久久| 国产原创欧美精品| 成人av色网站| 国产精品久久久久久久久免费看 | 红桃视频欧美| 国产精品av免费观看| 亚洲欧美一级二级三级| av电影一区二区三区| 中文字幕一区二区三区久久网站| 一区二区冒白浆视频| 久久要要av| 永久域名在线精品| 999精品色在线播放| 在线亚洲美日韩| 亚洲影视一区二区三区| 亚洲色图都市激情| 欧美一区亚洲| 久草视频国产在线| 国产日韩高清一区二区三区在线| 丰满少妇久久久| 国产精品日韩久久久| 99福利在线观看| 欧美综合二区| 亚洲免费av一区二区三区| 奇米777欧美一区二区| 一个色综合久久| 国产真实乱子伦精品视频| 91aaa精品| 成人免费观看视频| 中文字字幕码一二三区| 国产精品网曝门| 欧美精品入口蜜桃| 欧美日韩亚洲精品一区二区三区| 国产精品久免费的黄网站| 日韩欧美在线第一页| 中文字幕福利视频| 日韩一级在线观看| 十九岁完整版在线观看好看云免费| 国产视频精品xxxx| 日本精品一区二区三区在线播放| 久热国产精品视频| 黄色激情在线播放| 国产99久久精品一区二区 夜夜躁日日躁| 欧美大片欧美激情性色a∨久久| 草草视频在线| 国产精品第一视频| 日韩视频在线直播| 欧美精品一区二区三区四区五区| 日韩免费在线| 日韩视频在线视频| 男女男精品视频| 国产高潮失禁喷水爽到抽搐| 久久精品亚洲乱码伦伦中文 | eeuss一区二区三区| 蜜桃tv一区二区三区| 国产精品夜夜夜爽张柏芝| 亚洲三级影院| 天美星空大象mv在线观看视频| 国产精品一区二区久久精品爱涩| 国产肉体xxxx裸体784大胆| 国产精品久久看| 精品成人av一区二区在线播放| 欧美视频一区二区在线观看| 成人午夜免费在线观看| 国产午夜一区二区| 丁香花视频在线观看| 国产精品视频999| 久久久伦理片| 精品嫩模一区二区三区| 久久精品二区三区| 三大队在线观看| 国产精品污网站| 久久一区二区三区视频| 日韩你懂的电影在线观看| 国产乱视频在线观看| 欧美激情网站在线观看| 95精品视频| 色99中文字幕| 国产欧美精品| 人妻互换一二三区激情视频| 国产精品电影一区二区三区| 日本中文字幕在线| 亚洲成人网在线观看| 麻豆tv入口在线看| 日本亚洲欧美成人| 欧美顶级毛片在线播放| www.18av.com| 国产乱码精品1区2区3区| av永久免费观看| 日韩欧美一区二区三区| 日韩在线一区二区三区四区| 欧美成年人在线观看| 日韩一区二区三区四区五区| 国产免费久久精品| 久久精品国产亚洲av无码娇色 | 亚洲精品成人一区| 色阁综合av| 美日韩精品视频| 亚洲中文字幕无码av| 亚洲在线视频网站| www.色播.com| 久久国产精品久久久久| 亚洲成人高清| 亚洲一区二区三区欧美| 日本成人在线一区| 在线观看国产精品一区| 福利视频导航一区| 亚洲欧美日韩免费| 97在线视频免费播放| 亚洲精品v亚洲精品v日韩精品| 伊人久久青草| 国产在线视频精品一区| 免费看特级毛片| 日韩一区二区三区电影| 人人超在线公开视频| 91成人在线看| 国内精品福利| 午夜剧场免费看| 欧美午夜性色大片在线观看| 天堂av在线播放| 欧美一区三区三区高中清蜜桃| 亚洲专区视频| 欧美伦理片在线看| 国产精品久久夜| 国产又大又粗又硬| 欧美成人中文字幕| 97人人澡人人爽91综合色| 国产69精品久久久久999小说| 97se亚洲国产综合自在线观| 日本特级黄色片| 在线观看亚洲视频| 色综合视频一区二区三区日韩| aaa免费在线观看| 国产成人a级片| 在线观看日韩中文字幕| 亚洲天堂久久av| 亚洲综合伊人| 蜜臀精品一区二区| 91麻豆精品秘密| 中文字幕日韩经典| 久久不射热爱视频精品| 波多野结衣在线一区二区| 动漫av网站免费观看| 国产精品视频一二| 性网爆门事件集合av| 97在线视频观看| 欧美好骚综合网| 国产精品成人无码专区| 欧美午夜片在线观看| 日韩经典av| 日韩中文一区| 国产91精品欧美| 无码人妻久久一区二区三区| 久久这里只有精品99| 天堂日韩电影| 色噜噜狠狠一区二区三区狼国成人| 亚洲国产aⅴ天堂久久| 国产黄色在线| 不卡视频一区| 美国毛片一区二区三区| 日本视频www| 精品国产一区二区三区久久久| 久久久久高潮毛片免费全部播放| 亚洲成人天堂网| 精品免费在线观看| 1024在线播放| 日韩伦理一区二区三区av在线| 成人三级伦理片| 国产乱叫456在线|