天下2:在DirectX中贴瓷砖:Part 2



绪论

朋友们大家好欢迎来到新章节!在第 2个部分我将在第部分基础上继续讨论贴瓷砖这个话题由于缺乏时间在本文中我仅仅讨论平滑滚动问题这样可能会使你们当中某些人失望但是请理解我我是学生我有自己要做时间日益减少对不起了 平滑滚动 你是否记得第部分内容我们设置了个简单瓷砖引擎其中使用了个2维并用DirectDrawBltFast将瓷砖贴到屏幕我们不能仅此而已!我们即将个大地图用滚动效果加入你游戏不要认为这步是令人畏缩旦你理解了这个原理其实还是非常容易

我们中有些人不懂“平滑滚动”所以我要谈个基于瓷砖背景在精灵背后移动这效果实施尽管主角(或在你游戏中所有你想要控制东西)正要从个格子运动到另个格子但它能被画到屏幕位置知道超级马丽吗?它就是个很好平滑滚动例子想不想实现它?

原理

滚动关键是保存大地图当前轨迹这样就可以计算出哪些瓷砖要被画到屏幕举个例子假设按下键盘右方向键游戏精灵将向右移动两个瓷砖在你画瓷砖你可以认可这个改变并且画出被切换了两个瓷砖系列瓷砖或者说将游戏背景向右移动64像素结果你精灵看上去就好像改变过了如果这个解释很难理解我很报慊但是我希望你能清晰理解以便我们能继续

接下来我们将创建两个变量来存储地图中改变这两个变量将用在最后版本Draw_tiles中以决定哪些瓷砖要被画到屏幕 原理就这些了如果你有些主意有关你游戏赶快加入这些技术到你代码中吧

设置

在我们重写draw_tiles这个我们必须定义些常量


# TILE_SIZE 32
# WORLD_SIZEX 20
# WORLD_SIZEY 20
# SCREEN_SIZEX 12
# SCREEN_SIZEY 12

在这儿我们定义了瓷砖尺寸是32像素地图大小为20*20个瓷砖屏幕大小为12*12个瓷砖这样我们就有12*12(144)个瓷砖能够被同时显示在屏幕上于此同时有20*20个瓷砖在我我们我们必须建立个比屏幕可视区域更大地图这样我们就能鉴证滚动行为了注意:你设置DirectX应用决定将使得你可能不能看到整个被瓷砖填充屏幕

world_camerax = 0;

world_cameray = 0;

我在原理那节中提到两个变量 world_cameraxworld_cameray 是为了跟踪地图中当前位置它们将决定哪些瓷砖要被画到屏幕上现在我们化这两个变量为0因此我们当前位置是(00)或者说在地图/最左上方world_camerax 将存储X位置或者说和0点X轴距离world_cameray 将存储Y位置或者说和0点Y轴距离如果你有问题请回顾原理如果你仍然有困难那么那可能是我过错了:) 最后要做是定义新地图格子(20*20个瓷砖)这要比向导地图大多了

char map[WORLD_SIZEY][WORLD_SIZEX] = {
{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 2},
{2, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 2},
{2, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 2},
{2, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 2},
{2, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 2},
{2, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 2},
{2, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}, };
漂亮地图格子就在这随同个小消息:)

平滑画出这些瓷砖

现在我们重写 draw_tiles 这个历程

void draw_tiles(void)
{
tile;
x, y;
scroll_x, scroll_y; // (NEW)
off_x, off_y; // (NEW)

RECT tile_src;
tile用来决定map[scroll_y][scroll_x]值例如当我们通过遍历地图map[scroll_y][scroll_x]将有个ID#=1或2x,y这两个变量决定在确切位置画出瓷砖RECT tile_src用来指定每个瓷砖对应图像位置指向屏幕偏移scroll_x and scroll_y 变量将服务于就好比向导中x,y变量服务于draw_tiles你也许会问“为什么不再用x,y?”问得好答案是对地图些计算必须用到x,y变量就如下步所示计算结果将被保存在scroll_xscroll_y 这样我们就能够使用x,y原始值来画出瓷砖 off_xoff_y 用来决定画出瓷砖精确位置这两个变量是平滑移动核心变量


for (y = 0; y < SCREEN_SIZEY; y)
{
for (x = 0; x < SCREEN_SIZEX; x)
{
// (NEW)
scroll_x = x + (world_camerax / TILE_SIZE);
scroll_y = y + (world_cameray / TILE_SIZE);

// (NEW)
off_x = world_camerax & (TILE_SIZE - 1);
off_y = world_cameray & (TILE_SIZE - 1);

tile = map[scroll_y][scroll_x];

ok,新代码在这首先个嵌套双重循环来遍历我们地图获得每个瓷砖ID#值 接下来分别设置 scroll_x ,scroll_y 值为x,y加上目前为止已经滚过瓷砖个数 然后设置绘图偏移量我们要做就是将瓷砖最后位置减去偏移量


tile_src.left = (tile - 1) * TILE_SIZE;
tile_src.top = 0;
tile_src.right = tile * TILE_SIZE;
tile_src.bottom = TILE_SIZE;
tile_src RECT 设置依赖于存储在map[scroll_y][scroll_x]中瓷砖ID


// (MODIFIED)
BltFast((x * TILE_SIZE) - off_x, (y * TILE_SIZE) - off_y, lpddsoffscreen, &tile_src, NULL);

}
}
}
现在我们将瓷砖画到屏幕确切位置用x,y值乘以32再减去偏移量我使用 lpddsoffscreen 作为DirectX 表面名字表面可以用区别名字

结束语

我们已经有了个平滑滚动引擎, 那么我们如何把他用在游戏中呢? 那非常容易. 你只要作如下事情:


    (keypress_right)
    {
    world_camerax 8;
    }

    (keypress_up)
    {
    world_cameray 8;
    }
现在玩家可以用键盘控制地图滚动当然地图和玩家运作还有许多工作要做但我确信你定能解决:) 注意:在这kepress_right等你可以使用DirectInput或者Win32 API 输入来得到如果你在文章中发现或bugs 请告诉我 未经作者同意不得转载. Part1



Tags:  风云2 天下2

延伸阅读

最新评论

发表评论