前言
迪斯尼《Find Your Way to OZ》这个贴近地气的游戏我在最新一期《程序员》杂志的《从HTML5移动应用现状谈发展趋势》这篇文章里有所提及,它借用了近期上映的《魔境仙踪》电影的设定(设定来自于经典故事《绿野仙踪》,看过这个电影的同学们会深有感触),构建了一个等同的宏大游戏世界。同时迪斯尼又和谷歌合作,把它作为Chrome浏览器性能和HTML5技术的一个show case。对于这样一个使用了WebGL 3D、摄像头、3D音效等多种先进技术、支持桌面和移动端、品质出色的HTML5游戏,了解它背后的实现原理和技巧必然对于我们来说有着非常巨大的参考意义。
这篇文章我早就想翻译出来,帮助大家更好的了解HTML5在游戏开发里的应用和国外的应用情况,但是这篇文章实在太长,所以只能分次刊载,以飨读者。
此教程在我近期HTML5介绍的文章中难度可称高级,适合有一定经验的开发者阅读和学习。
介绍
“寻找奥兹之路”是迪斯尼为谷歌Chrome带来的全新体验。它让你在互动的旅程中穿越堪萨斯马戏团,然后通过一个巨大的风暴到达奥兹王国。
我们的目标是结合浏览器的技术能力,以创建一种充满乐趣、身临其境的体验,用户可以与电影之间形成一个强大的联系。
这个游戏的工作实在是太庞大,所以我们只能列出一些章节,把我们认为有趣的技术故事写出来。教程的难度随着进度会逐渐增加。
我们有很多人努力工作来创建更好的体验,但是太多无法一一列举。请访问该网站,体验整个页面下的完整故事。
预览
在PC端《寻找奥兹之路》是一个丰富的身临其境的世界。我们把3D和传统的电影制作灵感结合起来,创造一个好几层的接近现实的场景效果。其中最突出的技术是用Three.js引入WebGL,使用CSS3特性来定制着色器和DOM动画元素。除此之外,getUserMedia API(WebRTC)增强了互动体验,允许用户直接从摄像头添加自己的形象,以及WebAudio带来了3D音效。
但是这种技术体验的神奇之处在于它们是如何融合为一体的。这也是面临的主要挑战之一:如何把视觉效果和互动元素融合在一起来创建一个一致的场景?这种视觉的复杂性非常难以管理:很难说清楚我们在任何一个时间需要开发什么场景。
为了解决视觉效果和优化这一问题,我们大量使用了一个控制面板,用于捕获我们正在检查的那个时间点的所有相关设置。在浏览器中可以实时修正场景中的一切,例如亮度,纵向深度,伽玛线等等。任何人都可以在体验中尝试调整重要参数的值,参与并发现什么效果最好。
在分享我们的秘密之前,我要提醒你,它可能会导致崩溃。确保你没有正在浏览什么重要的东西,并且在访问该网站的网址时添加?debug=on。等待网站加载,一旦你进入后按Ctrl+I键,会看到右手边出现一个下拉菜单。如果取消选中“退出相机路径”选项,你可以使用A、W、S、D键和鼠标在空间中自由的移动。
我们不会详述这里的所有设置,但是我们鼓励你试验:按键显示不同的场景中不同的设置。在最后的风暴场景中有一组额外的按键:Ctrl+A,可以切换播放的动画。在这个场景中,如果你按Esc(退出鼠标锁定功能),再次按下Ctrl+I键可以进入风暴场景的特殊设置。看看四周,并且截取一些像下面这样的漂亮明信片。
要做到这一点以确保其对我们的需求具有足够的灵活性,我们采用了一个很棒的名为dat.gui的框架(可以在这里看看过去关于如何使用它的教程)。它允许我们能够迅速改变暴露给游客的设置。
有点像绘景
许多经典的迪士尼电影和动画创建场景意味着合并不同的层。有外景层、单元动画层,以及物理设置层和通过玻璃绘画获得的顶层:这种技术称为绘景。
在许多方面我们创造的体验的结构是相似的,即使有些“层”远远超过了静态的视觉效果。事实上,它们根据更为复杂的计算影响事物看起来的方式。然而,至少在大画面的水平,我们处理视图,将一个合成到另外一个之上合。在顶部,你看到一个UI层,其下是3D场景:它由不同的场景组件组成。
顶部接口层使用DOM和CSS 3创建。事件通信使用Backbone路由器+ onHashChange HTML5事件来控制哪块区域响应动画。(项目源代码:/develop/coffee/router/Router.coffee)。
教程:Sprite表和视网膜支持
我们依赖一种有趣的优化技术,把多个接口层图像合并为一张单独的PNG来减少服务器请求。在这个项目中,接口由多于70 张的图像组成(不包括3D纹理),并且全部预加载以减少网站延 迟。你可以在这里看到最新的Sprite表:
正常显示 - http://findyourwaytooz.com/img/home/interface_1x.png
Retina显示屏 - http://findyourwaytooz.com/img/home/interface_2x.png
下面是我们如何发挥Sprite表优势的一些技巧,在视网膜设备上如何使用它们,以及如何将接口尽可能设置的简洁而整齐。
创建Sprite表
我们使用TexturePacker来创建任何你需要的Sprite表格式。在这种情况下,我们采用EaselJS,它非常整洁,并且可以用于创建动画Sprite。
使用生成的Sprite表
一旦创建了Sprite表,你应该看到这样的一个JSON文件:
{ "images": ["interface_2x.png"], "frames": [ [2, 1837, 88, 130], [2, 2, 1472, 112], [1008, 774, 70, 68], [562, 1960, 86, 86], [473, 1960, 86, 86] ], "animations": { "allow_web":[0], "bottomheader":[1], "button_close":[2], "button_facebook":[3], "button_google":[4] }, }
其中:
- images指向sprite表的地址
- frames是每个UI元素的坐标[x, y, width, height]
- animations 是每项内容的名称
请注意,我们已经使用了高清图像来创建Sprite表,然后我们只需通过调整图像尺寸为一半来创建正常版本。
融合一切
现在,我们只需要一段Javascript代码来使用它。
var SSAsset = function (asset, div) { var css, x, y, w, h; // Divide the coordinates by 2 as retina devices have 2x density x = Math.round(asset.x / 2); y = Math.round(asset.y / 2); w = Math.round(asset.width / 2); h = Math.round(asset.height / 2); // Create an Object to store CSS attributes css = { width : w, height : h, 'background-image' : "url(" + asset.image_1x_url + ")", 'background-size' : "" + asset.fullSize[0] + "px " + asset.fullSize[1] + "px", 'background-position': "-" + x + "px -" + y + "px" }; // If retina devices if (window.devicePixelRatio === 2) { /* set -webkit-image-set for 1x and 2x All the calculations of X, Y, WIDTH and HEIGHT is taken care by the browser */ css['background-image'] = "-webkit-image-set(url(" + asset.image_1x_url + ") 1x,"; css['background-image'] += "url(" + asset.image_2x_url + ") 2x)"; } // Set the CSS to the DIV div.css(css); };
这是你如何使用它的代码:
logo = new SSAsset( { fullSize : [1024, 1024], // image 1x dimensions Array [x,y] x : 1790, // asset x coordinate on SpriteSheet y : 603, // asset y coordinate on SpriteSheet width : 122, // asset width height : 150, // asset height image_1x_url : 'img/spritesheet_1x.png', // background image 1x URL image_2x_url : 'img/spritesheet_2x.png' // background image 2x URL },$('#logo'));
如果要多了解一些可变像素密度,你可以看看Boris SMUS的这篇文章。
3D内容管道
环境体验建立在WebGL层之上。当你想到一个3D场景,最棘手的问题之一是要如何确保你从建模,动画和特效这些领域都可以创建最富有表现潜力的内容。从许多方面来说,这个问题的核心是内容管道:用一个定好的程序从3D场景来创建内容。
我们想创造一个令人振奋的世界,所以需要一个可靠的进程帮助3D艺术家来创建它。他们将需要给予他们的三维建模和动画软件尽可能多的表达自由,而我们将需要通过代码将它们呈现在屏幕上。
我们在这类问题上已经工作了一段时间,因为过去每次我们创建了一个3D网站,所以发现之前使用工具的一些限制。后来我们创造了这个被称为3D Librarian的工具,正准备要把它应用到真正的工作上。
这个工具有一些历史:它最初是为了Flash诞生的,它会允许你把一个大的Maya场景作为一个单一的压缩文件为拆包运行时进行优化。这是最优的原因是因为它有效的把场景包装为基本相同的数据结构,在渲染和动画时进行操作。这样在文件加载时只需要做很少的解析。Flash中的解包速度非常快,因为文件是AMF格式,Flash能够原生 解压。在WebGL中使用相同的格式,需要CPU多做一些工作。事实上,我们不得不重新创建一个解压数据JavaScript代码层,这基本上会将这些文件解压,并重新创建WebGL所需的数据结构。解压整个3D场景是对CPU有一些负担:解包游戏的场景1在中高端机上需要约2秒钟。所以为此我们在“场景设置”时间(实际上是场景出现之前)用Web Workers技术来实现,所以不会影响用户的体验。
这个方便的工具可以导入3D场景:模型、纹理和骨骼动画。你可以创建一个单一的库文件,它稍后能被3D引擎所载入。
不过我们曾经遇到一个问题,现在用WebGL来处理。因此,我们创建了一个特定的JavaScript层,使用3D库来压缩3D场景文件,并把它们翻译成正确的WebGL能理解的格式。
教程:要有风
在“寻找奥兹之路”中一个反复出现的主题就是风。剧情的主线由弱到强的风所串起。
狂欢节的第一个场景相对平静。经历各种场景,用户逐渐体验强风,最后来到最终的场景,风暴中。
因此,重要的是提供一个身临其境的风的效果。
为了实现这种效果,我们在3个狂欢节的场景中填充比较软的对象,例如帐篷和气球。
(待续)
译自:http://www.html5rocks.com/en/tutorials/casestudies/oz/
转载请注明:来自蒋宇捷的博客(http://blog.csdn.net/hfahe)