引言

这次聊什么呢?因为我们正在实现一个横版游戏,咱们这次就聊聊横版游戏里非常重要的技术——视差背景。

作为横版的 2D 游戏而言,如果想要提升画面效果,想必很多人想到的就是做视差背景。也因此市面上大部分横版游戏多多少少都会使用视差背景来增强游戏画面的视觉效果:

泰拉瑞亚的视差背景,是比较简单的平铺背景,没有太多特效

Braid 中也使用了视差背景,但要比一般游戏的复杂很多

这里我们主要对其中的技术细节进行介绍。

什么是视差背景?

简单地说,视差背景其实就是通过多层次的背景来模拟透视视差效果:就是当发生移动时,离照相机越近的背景移动越快;反之越慢。这样,我们的背景就会形成类似于透视视差的效果。

那么,既然需要透视效果,为何不直接使用透视投影来做呢?这个原因是如果使用透视投影来产生视差的话,我们的远景必须真的是一个非常大的背景,你如果想模拟出一百倍于近景的远景,那么可能就需要相应尺寸的背景贴图。这种做法显然是做不到的。当然,如果是3D 背景的话有其他方式,不过对于2D 游戏而言,最直接有效的还是多层次背景模拟出视差效果。我们这里也主要聊聊如果通过多层次背景滚动的方式实现视差效果。

在整个视差背景实现过程中,需要完成两个主要工作:

  • 实现单层背景的滚动;
  • 复合多层背景的滚动,实现视差效果;

实现单层背景的滚动

背景滚动是实现视差效果的核心也是最重要的问题。背景滚动存在横向和纵向两种。所有使用视差背景的游戏都会有横向滚动的情况,而纵向滚动则未必都会有。我们这里以横向滚动来介绍背景滚动。我们有四种常规方式可以实现背景的滚动:

  • 通过移动一个四边形顶点的 UV 移动形成滚动,之后就称之为 UV 滚动方式;
  • 通过滚动移动多个连续的背景精灵形成滚动,之后就称之为精灵滚动方式;
  • 添加背景层照相机,移动照相机形成滚动,之后就称之为照相机移动方式;
  • 精灵滚动方式和照相机移动方式混合使用,之后就称之为混合滚动方式;

为了更好地解释这几种实现方式,需要几张图片用于介绍:

我们使用一个黄框精灵代表屏幕取景区域:

接下来是三张可拼接的背景精灵:

UV 滚动方式:

使用 UV 坐标移动形成滚动的效果看起来是这样的:

在 UV 坐标移动的方法中,我们只是用一个和照相机取景区域一样大的精灵作为背景渲染区域。然后通过调整它的 UV 坐标和采样方式实现平铺背景以及背景滚动。具体实现步骤:

  • 准备一个覆盖整个屏幕的四边形顶点,并使用它显示背景贴图;
  • 调整 UV 坐标和纹理之间的采样方式,以实现纹理连续显示;
  • 移动时,修改四个顶点的 UV 坐标形成滚动;

因为我们只使用一张精灵,我们区域采样的方式就是通过 UV 坐标。因此此方式下 UV 坐标存在两个作用:

  • UV 坐标的整数部分标记了当前采样位置使用哪一张背景贴图;
  • UV 坐标小数部分为选中背景贴图的采样 UV 坐标;
  • 因此,此精灵的 UV 坐标必定会大于[0,1]区间。

如果背景使用的背景贴图只有一张的话,这个问题很容易解决。我们只要设置图形 API(OpenGL 或 DirectX,这里以 OpenGL 为例)的纹理包装类型(即所谓的 wrapping 类型)即可。所谓的包装类型即指定了当 UV 坐标值在[ 0,1 ]区间之外时,如何获取纹理。那么这里,我们需要让一张纹理重复出现。在 OpenGL 中,我们需要调用此函数来完成包装类型的设置:glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );稍微解释一下此函数:glTexParameteri 函数会对指定的纹理的参数进行设置。我们这里针对2D 纹理(第一参数 GL_TEXTURE_2D)的 x 方向即横向(第二参数 GL_TEXTURE_WRAP_S)的包装模式设置为重复出现的方式(第三参数 GL_REPEAT)。

不过如果背景是多张不同的纹理连续出现的话,就不能使用上面的方法解决了。这个时候我们需要编写一个简单的 shader 在 shader 中完成 UV 坐标映射。手机游戏转让这里截取出演示 demo 中,获取纹理相关的 shader 代码(GLSL 代码)提供大家参考:

  1. //我们有三张背景贴图,对 UV 坐标对3取模,得到使用哪一种背景贴图。
  2. int _index = int( mod( v_TexCoord.x, 3.0 ));
  3. //使用此贴图并使用 UV 坐标的小数部分进行像素采样。
  4. gl_FragData[0] = texture( u_BackgroundTextures[_index], fract(v_TexCoord));

复制代码

UV 方式有着非常良好的性能,但是缺点就是只能处理简单的平铺背景,对于有着复杂结构或是效果的滚动背景没有办法使用。

精灵滚动方式:

使用精灵滚动形成滚动的效果看起来是这样的:

这种方式应该是比较直接的。我们首先使用背景精灵拼接出背景取景区域覆盖到的背景区域。然后在发生背景移动时,我们依然不需要移动背景取景区域,而是通过滚动移动所有的背景精灵来实现背景移动的效果。

这种方式实现简单直接,但缺点是发生背景移动时,需要对所有的背景精灵进行移动。对于结构复杂元素较多的背景需要占用更多的性能。

照相机移动方式:

使用照相机移动形成滚动的效果看起来是这样的:

这种方式与精灵滚动方式正好相反。在这种方式下,我们需要使用背景精灵拼接出完整的背景。同时在背景移动时,不移动背景精灵转而移动背景取景区域来实现背景移动效果。

这种方式在移动过程中由于只需要移动背景照相机,所以有种很好的移动性能。但是为了使用此方法。我们需要预先将整个背景全部拼接。这样导致同时存在过多的背景精灵在场景中。如果使用的游戏引擎没有场景管理器或是场景管理器性能不佳的情况下,此方式反而会带来额外的性能消耗。

混合滚动方式:

使用混合滚动方式形成的滚动效果看起来是这样的:

顾名思义,混合移动混合了精灵移动和照相机移动两种方式。我们在移动背景取景区域的同时,适时地滚动背景精灵。使得背景取景区域内的背景正确。

这种方式结合了精灵滚动方式和照相机移动方式。避免了精灵滚动方式移动过程中,因为需要移动所有背景精灵带来的额外性能开销;也避免了照相机移动方式中,需要预先构建完整的背景而导致场景中存在过多的背景精灵带来的额外性能开销。当然,和照相机移动方式一样,避免不了每一层背景都需要有一个独立的背景照相机。同时在代码实现良好的情况下,性能比前两者都要好。

四种方式的优劣

平均性能:

UV 滚动方式只使用了一个四边形并且移动时也只是单纯改变了 UV 采样方式。它的性能是最好的;其次是混合滚动方式;照相机移动方式有更多的空间开销,同时此开销对性能的影响与游戏引擎的场景管理模块密切关联;精灵方式则有最大的移动性能消耗。

对复杂背景的支持:

即四种方式所实现的背景可以有多复杂。UV 滚动方式碍于实现只能做简单的平铺背景的滚动效果;精灵滚动方式和混合滚动方式可以实现更为复杂一点的背景,可以在简单的平铺背景之上加入一些其他背景精灵元素;而照相机移动方式对背景的构建没有要求,它可以支持非常复杂的背景。

是否可以无限延伸:

理论上四种方式都可以实现无限延伸。但是对于照相机移动方式来说,实现起来会比较麻烦。而另外三种方式都是循环利用同一个背景,所以天然支持无限延伸的背景。

复合多层背景的滚动,实现视差效果:

有了上面的工作,这一步也是顺其自然就可以完成:

我们首先要构建多层背景,多层背景可以同时只是用一种滚动方式;也可以不同层背景使用不同的滚动方式。比如最远的背景由于基本上都是简单的平铺可以使用 UV 滚动方式构建;而再近一点细节较多的背景层可以考虑后几种滚动方式构建背景。

之后是移动,我们需要根据每一层背景的距离决定其在移动过程中的移动速度。速度如何决定并没有统一的方法或是模式。总之,这一点听听美术们的意见是比较合适的。

其它问题

完成以上工作,我们的视差背景就算顺利建立起来了。不过,在实现中我们依旧会碰到一些其他的问题:

比如当开发者构建了一个有着复杂结构的背景,且使用了除去照相机移动方式以外的其他背景滚动方式实现了背景滚动。可能需要将背景取景区域覆盖的背景精灵左右都扩展一个背景精灵作为缓冲。以防止建立在背景精灵之上的背景布景(比如开发者在表示平原的背景精灵之上,放了另一个树的精灵作为此平原背景精灵的布景)在显示过程中出现突然出现和突然消失的情况。

或者在有些情况下,背景本身就会移动(比如云层背景)或者是背景之上存在一些独立移动的背景布景。这个时候我们也需要对上面的背景滚动方式进行相应的调整。

也可能是背景上需要支持某些特效,这种情况下我们的背景也可能需要特殊处理。

这里就不一一列举了。这里描述的是一些视差背景的基本细节,具体问题还需要在具体实现中留给开发者们自己去解决。

聊聊 2D 游戏视差背景的实现相关推荐

  1. unity图片变成马赛克如何取像素并改变颜色_聊聊 2D 游戏的像素化中的问题

    来indienova官网,挖掘独立游戏的更多乐趣 引言 既然我是在做像素游戏,这次就聊一聊在对 2D 游戏像素化的过程中都会碰到的问题吧. 1. 照相机的投影 对于引擎来说,其实不管是 2D 游戏还是 ...

  2. Unity3d C#利用材质(Material)贴图的偏移实现2D游戏单背景图无限移动背景效果功能(含源码)

    前言 2D的游戏背景基本是一张图,前后可以无缝拼接的那种,无限的背景滚动的效果,可以通过多张的图拼接起来,随着相机移动动态的创建/移位背景图可以实现,不过,本文介绍的方法是使用单张Sprite实现,具 ...

  3. 使用Unity3D制作2D游戏的重点做法

    官网上有提供一个2D游戏的教学范例,这个游戏只不过把镜头摆放在横向位置跟随角色移动,游戏内物件运动时固定一个轴不动,使他像横轴式的2D游戏来玩,本质上其实还是个3D游戏,所以如果没有3D建模的话不就没 ...

  4. 《HTML5 2D游戏编程核心技术》——第2章,第2.3节使用CSS背景

    **本节书摘来自华章出版社<HTML5 2D游戏编程核心技术>一书中的第2章,第2.3节,作者[美] 戴维·吉尔里,更多章节内容可以访问云栖社区"华章计算机"公众号查看 ...

  5. 【Unity3D】学习笔记(第2记) 2D游戏开发基本技巧之背景制作

    最近看了龚老师的u3d视频讲座游戏<Platform>7讲,是关于2D游戏开发的,现将一些个人学习笔记记录于此. 1 背景图导入 首先创建一个Cube,通过缩放调整成和背景图一样的宽高,然 ...

  6. 9个让2D游戏创作更轻松的工具

    Unity 2D开发挑战赛正在火热进行中,为了方便开发者们参加本次挑战赛,我们特别盘点了9个让2D游戏创作更轻松的工具,希望帮助大家在2D的开发中事半功倍. Unity编辑器中拥有所有制作精美2D内容 ...

  7. HTML5 2D 游戏开发(一): Snail Bait 简介

    开始您的第一个平台视频游戏 在本系列中,HTML5 专家 David Geary 将向您展示如何逐步实现一个 HTML5 2D 视频游戏.第一期的文章将向您展示一个已完成的游戏,然后引导您从头开始实现 ...

  8. 《HTML5 2D游戏编程核心技术》——第1章,第1.1节Snail Bait游戏

    本节书摘来自华章出版社<HTML5 2D游戏编程核心技术>一书中的第1章,第1.1节,作者[美] 戴维·吉尔里,更多章节内容可以访问云栖社区"华章计算机"公众号查看. ...

  9. 微信小游戏开发教程-2D游戏原理讲解

    微信小游戏开发教程-2D游戏原理讲解 原理 为了更加形象的描述,这里先上一张图: 背景 a. 首先,我们看到背景好像是一张无限长的图片在向下移动.实际则不然,这是一张顶部和底部刚好重叠的图片.这是一种 ...

最新文章

  1. tvm模型部署c++ 分析
  2. poj_2479 动态规划
  3. 这可能是最全的机器学习工具手册!
  4. dubbo之注册管理中心
  5. Linux执行df -h等操作卡住问题
  6. Python从菜鸟到高手(4):导入Python模块
  7. gridreport如何设置打印3次_如何设置光固化3D打印机切片参数
  8. 西安电子科技大学研究生计算机专业王宇平教授学生就业岗位,西安电子科技大学计算机学院导师信息情况...
  9. 大数据可视化html模板开源_8个可靠好用的开源数据可视化工具推荐
  10. 任达华遇袭是效仿“宏颜获水”事件?百度回应:严惩肇事者 以儆效尤
  11. 数据结构--------二叉排序树
  12. RF射频技术-si4438C芯片介绍
  13. 程序猿周末副职业_早上,晚上和周末:我如何改变职业并成为程序员
  14. odoo python生成二维码图片
  15. 《TiDB 6.x in Action》发布,凝聚社区集体智慧的 6.x 实践汇总!
  16. java统计字数_JAVA 仿 MS word 字数统计
  17. 探索Java中empty()与isEmpty()的区别
  18. html页面传递list参数,thinkphp中html:list标签传递多个参数实例,thinkphplist_PHP教程...
  19. STM32WL LoRaWAN节点设备学习记录(一)
  20. 高等数学(第七版)同济大学 习题12-2 个人解答

热门文章

  1. 难度上涨,减少专业!安徽大学计算机考研改考
  2. 关于CDialog类的OnOK、OnCancel、OnClose和OnDestroy
  3. 2022年武汉理工大学数据库系统综合实验5.1,5.2安全性语言及多用户事务管理
  4. 交换机和生成树知识点
  5. 批量收集照片并按规则命名
  6. 海报 样机 字体 高清图 你想要的平面素材 应有尽有哦!
  7. js 正则匹配邮箱_JS正则匹配邮箱格式
  8. 【DP】洛谷公开赛 CYJian的水题大赛 T1 八百标兵奔北坡
  9. 单词背诵 2023.5.8
  10. LabVIEW数据采集:视频教程附录1手把手安装LabVIEW