当前位置: 首页 > news >正文

实现一个均匀Tile的卷轴显示引擎

游戏的卷轴效果主要有两种形式,一种是将游戏分为若干个场景的页面卷轴,比如FC上的洛克人,当人物走到边缘时,就会切换整个场景;一种就是魂斗罗式的那种均匀平铺的卷轴,这种卷动更为平滑。因为我要用在2.5D显示引擎中,只能选择第二种卷轴技术——均匀tile卷轴。

1. 卷轴要卷动哪些东西

首先要清楚卷动的是什么东西,比如下面的一个KOK1的截图:

传送门

这是一个典型的2.5D游戏界面,这个界面上的所有元素全都是由位图所组成的,但是不难分析出实际要卷动的只有地面的位图。因为传送门和柱子、树等等都是可以遮挡住人的,即渲染顺序是:

(1) 根据世界坐标卷动的地面贴图

(2) 玩家单位、建筑、环境元素单位以从上至下的顺序渲染,这样就会产生2.5D效果,即近景遮挡住远景。

2. 均匀平铺显示引擎的设计与实现

由上图的地板不难看出,其实这些地面是由一小块一小块拼接而成的,这样可以使位图得以重用,就像红警95的地图编辑器一样,一个地形可以在地图中反复出现。所以我们实际要有一个位图文件来存放这些一块一块的地板,比如我随便画了这个(第一个是我自己用画笔画的,后面两个是截图截的,效果都一般,可见优秀美工的重要性),有三块86*40的地板:

地板

然后在程序中,我们需要创建一个显示表面的数组来分别存放这三个地板。

LPDIRECTDRAWSURFACE7 lpddsFloor[3];

接着,定义一个int数组来存放地图中地形的索引,比如我打算要创建一个3×3块地板的地图,则:

int map[3*3] = { 0, 0, 0, 1, 1, 1, 2, 2, 2 };

这样这个地图等于是第一行都是第0块地板,第二行都是第1块地板,第三行都是第2块地板。

现在就要创建世界表面,把世界加载到一个单独的大表面上:

lpddsMap = CreateSurface(MAP_WIDTH*TILE_WIDTH, MAP_HEIGHT*TILE_HEIGHT, 0); for (int y = 0; y < MAP_HEIGHT; ++y) { for (int x = 0; x < MAP_WIDTH; ++x) { RECT dest_rect = { x * TILE_WIDTH, y * TILE_HEIGHT, (x+1) * TILE_WIDTH, (y+1) * TILE_HEIGHT }; lpddsMap->Blt(&dest_rect, lpddsFloor[map[x + MAP_WIDTH * y]], NULL, DDBLT_WAIT, NULL); } }

现在所有的准备工作都做好了,就要在显示器显示的每一帧,根据视窗在世界中的坐标来Blt相关的区域到离屏表面,并且根据玩家的输入来调整视窗在世界中的坐标:

if (KEY_DOWN(VK_LEFT)) screen_x = screen_x > 5 ? screen_x - 5 : screen_x; if (KEY_DOWN(VK_UP)) screen_y = screen_y > 5 ? screen_y - 5 : screen_y; if (KEY_DOWN(VK_RIGHT)) screen_x = screen_x < MAP_WIDTH*TILE_WIDTH - SCREEN_WIDTH ? screen_x + 5 : screen_x; if (KEY_DOWN(VK_DOWN)) screen_y = screen_y < MAP_HEIGHT*TILE_HEIGHT - SCREEN_HEIGHT ? screen_y + 5 : screen_y; RECT rect = { screen_x, screen_y, screen_x + SCREEN_WIDTH, screen_y + SCREEN_HEIGHT}; lpddsoffscreen->Blt(NULL, lpddsMap, &rect, DDBLT_WAIT, NULL);

3. 放上一个截图,是完成的效果。

卷轴demo

相关文章:

  • linux rpm包解压
  • 教你彻底实现红黑树:红黑树的c源码实现与剖析
  • 【one day one linux】好用的数据处理工具awk
  • 新年新起点-荣获2011年度Silverlight方向Microsoft® MVP奖
  • java,关于POJO,查阅资料
  • 阅读计划
  • Android Installation error: INSTALL_FAILED_INSUFFICIENT_STORAGE
  • 基于tiny4412的Linux内核移植 -- 设备树的展开
  • 浅谈股市、美元汇率与原油价和黄金价格间的关系
  • pyVmomi入门
  • 清理sga组件
  • Java NIO和IO的主要区别
  • hibernate主键生成策略(转载)
  • 微软,苹果,Google用户体验设计原则
  • QT(1)准备好环境和.pro文件
  • 0基础学习移动端适配
  • 10个最佳ES6特性 ES7与ES8的特性
  • Android框架之Volley
  • React16时代,该用什么姿势写 React ?
  • React中的“虫洞”——Context
  • 百度小程序遇到的问题
  • 等保2.0 | 几维安全发布等保检测、等保加固专版 加速企业等保合规
  • 每个JavaScript开发人员应阅读的书【1】 - JavaScript: The Good Parts
  • 浅谈Kotlin实战篇之自定义View图片圆角简单应用(一)
  • 详解NodeJs流之一
  • 职业生涯 一个六年开发经验的女程序员的心声。
  • ​LeetCode解法汇总518. 零钱兑换 II
  • #【QT 5 调试软件后,发布相关:软件生成exe文件 + 文件打包】
  • $var=htmlencode(“‘);alert(‘2“); 的个人理解
  • (C语言)求出1,2,5三个数不同个数组合为100的组合个数
  • (Matalb分类预测)GA-BP遗传算法优化BP神经网络的多维分类预测
  • (Matalb时序预测)WOA-BP鲸鱼算法优化BP神经网络的多维时序回归预测
  • (阿里云万网)-域名注册购买实名流程
  • (附源码)ssm高校实验室 毕业设计 800008
  • (心得)获取一个数二进制序列中所有的偶数位和奇数位, 分别输出二进制序列。
  • (转)h264中avc和flv数据的解析
  • .NET MVC之AOP
  • .NET/C# 判断某个类是否是泛型类型或泛型接口的子类型
  • .NET应用架构设计:原则、模式与实践 目录预览
  • .pyc文件是什么?
  • @Autowired标签与 @Resource标签 的区别
  • @zabbix数据库历史与趋势数据占用优化(mysql存储查询)
  • [ Linux Audio 篇 ] 音频开发入门基础知识
  • [30期] 我的学习方法
  • [Angular] 笔记 18:Angular Router
  • [BUUCTF 2018]Online Tool
  • [BZOJ 4129]Haruna’s Breakfast(树上带修改莫队)
  • [C++][基础]1_变量、常量和基本类型
  • [ES-5.6.12] x-pack ssl
  • [hdu4622 Reincarnation]后缀数组
  • [INSTALL_FAILED_TEST_ONLY],Android开发出现应用未安装
  • [java] 23种设计模式之责任链模式
  • [Linux]创建新用户并授予root权限
  • [MT8766][Android12] 取消WIFI热点超过10分钟没有连接自动关闭设定
  • [NOIP 2015]Day.1 T2 信息传递 【最小环】