如何开发一款3d游戏有什么

2017年年底微信小程序再次发力推絀了风靡大江南北的有趣应用,其中又以“跳一跳”尤为引人瞩目“跳一跳”以简单有趣的游戏玩法设计以及流畅的交互体验,借助微信宿主环境迅速的传播在中国N亿网民的手机中。

受微信小程序潮流的刺激作为和微信小程序有着60%相似度定位的Light平台也着力研究在H5端网页运荇环境下、宿主为浏览器时如小程序这种3D界面效果的游戏程序的开发实现方式;“跳一跳”作为风口上的标杆型应用,自然而然成为Light为3D应鼡开发铺路所选用的标的

【从2D到3D】 三维计算机图形和二维计算机图形的不同之处在于计算机存储了几何数据的三维表示,其用于计算和繪制最终的二维图像


除了游戏开发者之外,可能大部分的开发者所接触的开发过程都是2D应用的开发过程与2D应用开发相比,3D应用拥有更炫的运行效果更加真实和沉浸式的交互体验;除了在游戏开发中广泛使用之外也可以使用在地图、VR等领域。

在H5中开发3D应用需要借助于 canvas 提供的 webgl 上下文对象

因运行环境而异提供了多个上下文供开发者使用,比如我们通常使用到的绘制图表如分时K线、柱状图、折线图都是使用其2D上下文而本文中要实现的“跳一跳复刻版”将要使用其webgl上下文以绘制3D图形。

webGL WebGL(Web Graphics Library)在 GPU 中运行因此需要使用能够在 GPU 上运行的代码。这样嘚代码需要提供成对的方法(其中一个叫顶点着色器 另一个叫片段着色器),并且使用一种类 C/C++ 的强类型语言GLSL(OpenGL Shading Language) 每一对方法组合起来称為一个

简而言之,WebGL是一种在任何可兼容的网页浏览器中渲染3D图形的JavaScript API但是直接使用WebGL来绘制图形需要很多额外的知识以及大量的开发成本,甴此 Three.js 这一3D应用的开发框架应运而生


WebGL在浏览器中的支持情况如下图所示:

three.js是使用js来绘制3D程序的库。three.js将许多webgl中的概念封装为易于操作的类目让开发者可以以面向对象的方法使用其开发3D应用。three.js的出现大大降低了开发基于WebGL的3D应用的门槛

本文中重点的内容就是基于three.js开发实现“跳┅跳”的Light版。但在正式的进入开发之前我们需要先了解一下两组Three.js中的重要的概念这是我们进入核心内容的关键知识储备。

一、场景(Scene)、渲染器(Renderer)、摄像机(Camera) 此三大组件是创建3D图形的必备组件其中:


1. 场景用来容纳图形元素。场景是一切被渲染物体的容器物体只有添加到场景中,才会被WebGL引擎渲染和处理
2. 相机的作用是定义可视域,即确定哪些物体是可见的
3. 渲染器则负责决定如何渲染出图像。

二、形状(Geometry)、材质(Material)、模型(Mesh) 此三大组件是构建可供渲染的物体的关键组件其中:


1. 形状即是点的集合,代表在3D的坐标系下的各种几何形状几何形状和具体的物体展示是无关的。常用的几何形状包好立方体、球体、圆柱体等
2. 材质与图形表示方法是相关的,比如我们下攵中将要使用到的MeshLambertMaterial材质就是常用材质的一种材质决定了最终模型对光照的反应,Lambert材质一般用来表示只有漫反射的物体如塑料;而phong材质鼡来表示有镜面反射的物体,如镜子
3. 模型是指最终的网格模型,也就是最终可展示物体效果模型=形状+材质。

【使用Light完成跳一跳复刻版】 在Light体系下实现“跳一跳”小游戏并不复杂除了以上需要的对Three.js的了解之外,其余知识要求与普通的light程序并无二致在这里也不再涉及light工程具体的创建和开发流程,如有需要可以参考Light文档;由微信中“跳一跳”中的视图范围可以看出游戏界面可以由单个Light视图完成具体的开發目录如下所展示:

来初始化canvas的可操作对象,并通过对canvas当前dom节点引用的操作完成获取3D上下文的流程

完成上下文环境的初始化之后就可以進行游戏具体功能的实现了,整个“跳一跳”的实现分为多个相互关联的部分既可以对应了前文描述各个要素,又可以划分为多个执行嘚阶段下面就一一道来。


小程序中的游戏场景如以下的截图所示:
当前游戏画面中的关键场景要素可以抽象为:地板、箱子、jumper以及辅助え素光照、阴影等几个方面我们将从最基本的界面元素--地板开始一步步添加并完善游戏界面,并在最后实现跳跃动画等步骤

主场景 场景(Scene)是一个简单但是不容忽视的概念。场景包含了展示、绘制的内容同时有代表了其所包含的展示、绘制的内容。场景是一切内容的嫆器要真正的运行产生可供观察的内容,父容器必不可少


以下所涉及的内容都被父容器所包含,可以通过 Three.js 的 Scene 构造其初始化一个父容器不需要任何入参。

渲染器 作为游戏环节的关键实现步骤 Three.js 的3D引擎(渲染器)初始化是至关重要的第一步。 Three.js 提供的WebGLRenderer 是直接基于 WebGL 来展示内容通过 canvas 的3D上下文来绘制内容。

WebGLRenderer 的构造器接受对象变量的入参该对象支持多种参数。一般来说我们实际使用到的参数主要有以下两个:


1. antialias ,是否启动防锯齿特性通过此属性的配置可以提高内容展示的流畅度以及效果优化。开启防锯齿后会加重资源消耗
2. canvas ,该参数制定当前內容绘制所使用的canvas对象注意此参数的值为canvas节点的dom对象而非其context对象。在light框架中可以直接从this变量中的$refs取得针对dom节点中canvas的引用

另外,为了获嘚全屏展示的效果还需要设置初始化后的渲染器--renderer的绘制区域。可以直接使用WebGLRenderer 的实例方法 setSize 来设置绘制区域一般来说,应该将绘图区域的寬度设置为屏幕的宽度--window.innerWidth 将绘图取悦的高度设置为屏幕的高度-- window.innerHeight 。

最后为了确保最终渲染效果中有对阴影的展示和处理,还需要打开渲染器的渲染阴影开关主要是针对WebGLRenderer 实例对象中的 shadowMap 属性的配置, shadowMap 支持的可配置参数中可以通过 enabled 打开阴影的渲染开关通过 type 属性配置阴影处理的類型(不同的阴影类型的最终展示效果有较大的不同,具体可以参考官方的文档)

坐标系 完成了渲染器的初始化之后,接下来就需要对峩们当前的场景中添加地板了但是在此之前我们需要先来熟悉一下 WebGL 中的3D坐标系。

在 WebGL 坐标系中任何一个点的位置可以通过一个三维的向量來确认--如(1,2,-1)分别对应(x,y,z)三轴上的值在WebGL中Z轴表示深度,z轴正值表示该点是在屏幕/观众近而z的负值表示该点远离屏幕。同样地x的正值表示该點是到屏幕右侧的和负值表示点在屏幕左侧;y轴的正值表示点在屏幕顶部,负值代表点在屏幕底部简单来记忆就是: WebGL 中的坐标系是个“右掱坐标系”,伸出你的右手除拇指外的四指并拢并和手臂垂直,拇指和四指也垂直此时手臂所在的坐标系就是z轴,拇指是x轴四指所茬的坐标系就是y轴。注意这里的坐标系和我们在初中数学课本中所了解到的坐标系是不一样的。中学学习的坐标系是“左手坐标系”具体的区别可以参考下图。

完成坐标系确认后“地板”这一关键游戏元素的位置也就可以确认了。原则来说地板可以放置在任何的位置以任何的角度(为什么?想像一瓶矿泉水是不是可以以任何角度摆放)但是为了方便我们对元素的绘制和处理,最后将地板放置在与(x,z)岼面平行的平面上(以下简称零平面)这样看起来更像“地板”,具体的位置为(x,-1,z)也就是说,地板的位置在(x,z)平面的真正零平面的底部(屏幕底部)距离零平面1个标准距离。这里选择1个标准距离主要是因为我们最终绘制的箱子的高度是2箱子的排布会从坐标远点开始排布(0,0,0),所以这样保证后期放置的箱子可以保持一半在零平面以上一半在零平面以下这个在我们设置箱子放置的时候会再次详细说明,现在不需要关心

确认地板所在的位置之后,使用 Three.js 的平面(PlaneGeometry)构建函数新建一个平面并放置到对应的位置即可 PlaneGeometry 默认接收4个数字类型的入参,分別代表平面的宽度(x坐标)、长度(y坐标)、x向切分数(widthSegments)、y向切分数(heightSegments)heightSegments和widthSegments的默认值都为1,一般来说并不需要设置只需要设置长度囷宽度即可。

单纯的PlaneGeometry实例并不具有任何可以展示的效果必须搭配材质(Material)才可以被展示和渲染以及针对不同的光照产生不同的反应,这裏我们使用MeshLambertMaterial这个材质来生成对应的平面MeshLambertMaterial可以针对特定的光照产生阴影的效果。关于Geometry、Material和Mesh的关系可以参考前文的内容

另外,为了在地板Φ可以渲染出箱子和jumper投射的影子还需要针对平面设置其 receiveShadow 属性,打开接受阴影渲染的开关以产生合适的阴影平面创建成功后可以通过父嫆器实例的add方法直接添加至父容器的场景中。只要添加至父容器的内容才可以被渲染和展示否则将不会产生任何效果。

这里需要注意的昰默认平面的位置是在(x,y,0)平面上,平面创建完成后还需要进行简单的角度转置才能正确的放置到(x,-1,z)的位置上这里又要回到中学数學中学习到的角度的概念,两种表示角度的方法:角度和弧度

在JavaScript中只能使用弧度表示法来处理旋转问题,其中PI的值可以从 Math.PI 中读取


因为默认平面的位置是在(x,y,0)平面,要旋转到(x,-1,z)需要先沿着X轴逆向旋转90度( -0.5*Math.PI )然后移动到Y轴的(0,-1,0)位置上。旋转角度可以通过设置平面实唎的rotation属性中的对应的坐标轴的弧度数来完成移动位置可以通过设置平面实例的position属性的对应坐标轴的标准长度来完成。 放置箱子 “地板”准备好了接下来我们就放一个箱子在地板上。

“箱子(CubeGeometry)”并不像平面一样没有高度“箱子”是三维坐标下的立方体,有长、宽、高彡个特征包含8个定点和6个平面。我们可以使用 Three.js 中的 CubeGeometry 的构造函数默认接收三个数字类型的参数分别代表“箱子”的长、宽、高。默认创建出来的“箱子”的位置为(0,0,0)但是我们并不需要移动箱子的位置箱子就自然处于“地板”之上而且紧贴地板,这是因为我们在设置地板位置的时候沿着Y轴设置了-1的位置上而箱子的下平面正好是(x,-1,z)和地板所在的平面是一致的。

另外箱子是应该在地板中投影出阴影的,所以设置箱子实例的 castShadow 开关是至关重要的一步同上,为了让此“箱子”被WebGL引擎渲染依然需要将此“箱子”添加到父容器的场景中。

放置jumper “箱子”有了接下来是“jumper”登场了。

微信“跳一跳”中的jumper是一个十分简单的形象生搬硬套从来不是light的风格。我们需要对jumper进行本地化处理使其具备恒生特色,那就是“COOSS”宝“COOSS”将作为一个恒生版本的“jumper”在游戏中迎风跳跃。当然这并不是一个简单的过程,在Three.js中并没有“COOSS”這个模型也就无从创建,好在Three.js引擎支持渲染加载各种3D建模工具如玛雅等工具的导出对象(JSON)可以通过此导入对象来实例化模型。关于洳何使用3D建模工具来制作模型可以参考对应的资料在这里也就不详细展开了。本文中使用的“COOSS”模型来源于“BOSS谢”半天的设计成果不計版权,大家可以自由使用

接下来就是需要导入外部工具创建的模型并实例化成可供Three.js渲染的对象了。对此我们可以使用Three.js默认提供的JSONLoader来加載导出的JSON文件加载成功后会产生一个Geometry对象,然后结合特定的材料就可以产生可供渲染的“jumper”了

另外,jumper也是是应该在地板中投影出阴影嘚所以需要设置jumper实例的 castShadow 开关。


同上为了让此“jumper”被WebGL引擎渲染,依然需要将此“jumper”添加到父容器的场景中
JSONLoader 处理导出模型的方式是异步嘚,但这并不会影响世界想过的展示用户并不会察觉内容是一部分一部分的缓慢出现。这是因为内容是按帧渲染的而短时间内如1s内会渲染几十次,这个帧数越高用户的使用会越流畅帧数的数值受设备性能和程序代码的逻辑复杂度影响。一般来说30帧以上就不会感觉到明顯的卡顿

jumper初始化完毕以后,还需要将jumper站立在第一个箱子上有了前面的经验,这个就简单多了只需要知道jumper的高度,然后调整jumper在Y轴上的唑标就可以了

点亮这个世界 至此,游戏界面的场景装配工作就做完了我们依次完成了地板、箱子、jumper的初始化和位置、角度设定。但是如果现在去运行已有的代码,浏览器依然会是空空如也我们还需要给这个“世界”内加上“光源(Light)”。

“光源”也是WebGL的一个重要的概念如前文所述,有种类繁多的光源类型当前的游戏了我们主要使用了两种官员,一种散射光(AmbientLight)主要是用来给整个场景一个初始煷度添加出一种柔和的效果;另一种是直射光(DirectionalLight),主要使用来产生投影效果光源的效果和现实中有这个很大的相似性,比如散射光是柔和的光线各个角度都能覆盖和照射到;而直射光是平行光线,照射到物体上可以产生投影效果

散射光也叫环境光,可以通过Three.js的AmbientLight对象來实例化其接收两个参数来设置光源的效果。其一为光源的色值也就是整个环境的色调;其二为官员的亮度,最亮为1可以设置为小於1的值。


散射光的添加的实际效果调整最好是在运行中查看不断寻找合适的值这也是最有效的方法。

直射光可以通过Three.js的DirectionalLight的对象来实例化其所接收的参数和AmbientLight一致,只不过可以设置光源的位置直射光的光线是照向(0,0,0)远点位置。


默认的直射光也是不能产生阴影效果的需要配置DirectionalLight的实例属性中的shadow属性来调整阴影的参数,实际阴影的效果受这个阴影参数的应用比较大使用过程中最好也是在运行中查看不断寻找合適的值。

同上为了让光源的设置产生效果,依然需要分别将散射光源和直射光源添加到父容器的场景中

揭开这层幕布 万事俱备,只欠東风初始的内容的展示和配置都已经处理完毕,接下来才是见证奇迹的时刻

Three.js的内容如需正常的渲染与运行,至少需要三个关键的元素:场景(Scene)、渲染器(Renderer)、摄像机(Camera)有关场景和渲染器的东西我们上文中都已经讲解完毕,下面来说一说摄像机(Camera)理解上,摄像機就是观察者眼镜所在的位置想象一下从不同的角度看同样一个物体的场景,当眼镜(摄像机)所处的角度不同的时候所看(渲染)箌的景象(投影-场景)也是不一样的。Three.js所使用到的摄像机的概念也是基于同样的类比

在Three.js中提供了两种主要的摄像机类型:透视投影摄像機(PerspectiveCamera)和正交投影摄像机(OrthographicCamera)。抛开其具体的指标、特性不谈就单单从字面上理解透视投影摄像机应该是基于透视的原理而正交投影摄潒机应该和正交有关(正交依然是中学数学里的概念,正交就是垂直)正交这个似乎不好理解,我们先来解释透视摄像机

我所理解的“透视”就是“近大远小”,是符合人眼视物规律的一种说法换言之,使用透视相机后渲染出来的内容将会和人眼在实际世界中看到嘚景象很相符合。而正交相机则是“远近皆同”物体大小不会受到距离远近的影响,所渲染出来的内容都是物体在相机平面的正投影

換个方法来解释,个人理解上西方的油画应该都是属于“透视相机”渲染的效果很真实;而中国的国画应该就是属于“正交相机”渲染嘚效果,很不真实(抽象、写意)又比如我们经常玩的游戏,王者荣耀这种显然是“正交投影”而PC上的吃鸡游戏必然是“透视投影”。


本游戏使用“正交投影摄像机”以保持观察效果的一致这也符合原版“跳一跳”的效果。正交投影摄像机(OrthographicCamera)的初始化可以使用Three.js中的OrthographicCamera類型来实例化OrthographicCamera的构造函数接受六个参数的入参,分别对应了立方体的左右上下前后六个平面这六个值的计算非常复杂,具体可以参考丅图(源图来自Google):
这里需要注意的一点是:正交投影摄像机所处理的立方体的长宽比必须和渲染所在canvas的长宽比相等 关于相机的说明就箌这里,下面是时候解开画布上的这块幕布了将我们的内容渲染在页面上。
renderer.render(scene, camera);//scene就是上文中所提及的父容器通过以上的代码内容会渲染在页媔当中至此就可以看到我们前文所设置的各项内容了。

让jumper动起来 静止效果的游戏任谁都是不可能产生兴趣的所以我们的最后一步也是夲文的最后一部分内容,让镜头的内容动起来

离成功只差这最后一步。磨刀不误砍柴工开工之前我们需要来了解一下WebGL中的动画的原理昰什么?众所周知“动画”其实就是“静画”的组合连续播放,当连续播放超过可人眼识别的频率(24赫兹)以后就是连续运动的效果這个频率就是静画的每秒播放张数,就是上文提及的帧率

那在JavaScript中如何做到连续渲染?方法有二:

同样是循环触发函数,requestAnimationFrame有着更大的优势其是专门为逐帧动画实现设计的API,可以按帧重绘从而节省系统资源,提高系统性能改善视觉效果。


接下来的问题就简单了只要设置妀变场景内物体的角度、位置后重新调用 renderer.render(scene, camera)就可以了。
以上的代码通过不断的设置jumper在Y轴上的偏转角度来达成一种COOSS缓慢旋转的效果。

【总结】 本文详细介绍了在Light中使用Three.js框架实现一个小游戏的方法以一个复刻版的微信“跳一跳”小游戏的实现为例介绍了游戏开发中的关键要素鋶程。本文中设计的代码可以点击这里获取

另外,游戏开发过程中还有一些关键的环节不容忽视比如:碰撞处理、成功掉落、失败掉落、场景切换、计分体系等可以参考以上链接地址中的代码来了解。

Python运行速度慢如果要做复杂的游戲用C++会更好,但是它有很多开源项目可以开发一些简单的游戏,很适合新手入门Python有像,和这样的库在这个过程中有很多帮助。Pygame库专門用于游戏开发你可以尝试使用2D图形建模3D,并使用图像和简单渲染制作简单的游戏当你有了3d游戏有什么的逻辑时,可以学习PyOpenGL它是最棒的3D库之一。

给大家找了一些比较容易上手的项目也都是非常经典的游戏,估计大家都玩过

1、先先分享一个在GitHub上看到的一个教程:


每張卡都有一对。玩家翻过两张牌如果他们匹配,那么他们会被推翻玩家需要以最少的动作推翻所有牌以获胜。

4x4编号的瓷砖板有一个缺夨空间并随机设置为了赢得游戏,玩家必须将移动瓷砖使其按顺序排放

六种颜色的瓷砖网格随机开始。玩家可以在左上方的图块上执荇“填充更改相同颜色的任何相邻图块的颜色。如果玩家能够在一定数量的移动中使整个棋盘成为单一颜色则玩家获胜。

Orisinal网站拥有大量Flash游戏其中包含可以复制的非常简单的机制。

13、给大家找了一些Python游戏开发可能用得到的一些资源

  • :编程挑战主要是Python游戏开发方面的
  • :茬优秀的SDL库之上添加了更多功能。允许使用python语言创建功能齐全的游戏和多媒体程序具有高度的可移植性,几乎可以在所有平台和操作系統上运行
  • :Python 3的高级3d游戏有什么引擎紧密结合了渲染,物理动画和网络
  • : 用于OGRE 3D引擎的完整python包装器,以及用于GUI物理,特效声音等的15个其他图形和游戏相关库
  • :专门用于python的全功能开源3d引擎,但用c ++编写功能:性能,多平台支持场景图,导出/导入3D音频,碰撞检测物理,浏览器插件动画等。
  • :GNU GPL许可下的开源游戏引擎建模器,动画师和3D渲染器使用Python作为脚本语言。
  • :跨桌面游戏集成平台带有python包,包括等
  • :建立在SDL之上的游戏引擎
  • :跨平台2.5d游戏创建框架支持不同的等距视角
  • 免费的Python游戏是一个Apache2许可的库和免费的Python游戏集合,旨在教育和娱樂包括几个经典街机游戏的简化版本。

课程咨询欢迎添加班主任微信:

更多精彩IT课程尽在,欢迎体验(●ˇ?ˇ●)

  • 在我的这系列的第┅篇文章 中, 我已经讲解如何使用 Python 创建一个简单的、基于文本的骰子游戏这次,我将展...

  • 今天是什么日子 起床:6:50 就寝:11:00 天气:晴 心情:好 叫我起床的不是闹钟是梦想 年度目标及关键点:...

  • 如果你还不知道罗胖是谁知识跨年为何物?这篇文章你就不用看了罗胖红了,比网红還红知识付费很流行,没有为知识付过...

  • 多年前读过贾平凹的《丑石》,印象深刻今借一“丑”字,写一种桃 丑桃,是民间的俗称像大人给孩子...

  • 长大后,就得面对成人的世界 成人的世界也意味着更多的残酷。小时候我们可以用哭来要求很多长大了却只能自己独洎面对...

我要回帖

更多关于 3d游戏有什么 的文章

 

随机推荐