Day11_MapTiles是怎么绘制出来的

返回目录

OpenTTD的界面通过viewport.cpp 实现,界面上由相对静止的网格Tile以及不断移动的交通工具vehicle组成,在Tile上可能是各种气候条件的陆地、海洋、工业设施、城镇等,交通工具则主要包括汽车、火车、轮船和飞机四大类。我们看一下网格Tile绘制的原理。viewport.cpp ViewportAddLandscape()是绘制Tile的关键,这个函数通过双重循环,先行row再列column 实现了各种气候地形和建筑物的绘制。

viewport.cpp Line1164
static void ViewportAddLandscape()
{
...
                _tile_type_procs[tile_type]->draw_tile_proc(&tile_info);  <- 说明1
...

说明1:函数指针,根据每个tile的定义完成对应的函数调用

如下图 _cmd.cpp 文件 定义 DrawTile_开头的函数实现,我们以海面的Tile绘制为例
在这里插入图片描述

构造海面Tile绘制调用链
viewport.cpp AddTileSpriteToDraw()
<- DrawGroundSpriteAt() // Draws a ground sprite at a specific world-coordinate relative to the current tile.
<- DrawGroundSprite() // Draws a ground sprite for the current tile.
<- water_cmd.cpp DrawSeaWater() // Draw a plain sea water tile with no edges
<- DrawWaterClassGround()
<- DrawTile_Water()

viewport.cpp ViewportAddLandscape()通过 TileTypeProcs类型的函数指针_tile_type_procs , 调用 DrawTile_Water() 完成海面的Tile绘制

viewport.cpp Line498
static void AddTileSpriteToDraw(SpriteID image, PaletteID pal, int32 x, int32 y, int z, const SubSprite *sub = nullptr, int extra_offs_x = 0, int extra_offs_y = 0)
{
...
    TileSpriteToDraw &ts = _vd.tile_sprites_to_draw.emplace_back();  <- 说明1
...
}

说明1:emplace_back() 实现Vector容器插入操作

底层实现也是和交通工具移动一致,通过tile_sprites_to_draw 这个vector实现

viewport.cpp Line1713
ViewportDoDraw({
...
    if (_vd.tile_sprites_to_draw.size() != 0) ViewportDrawTileSprites(&_vd.tile_sprites_to_draw);  <- 说明1
...

说明1:<- ViewportDrawTileSprites()函数 通过循环体遍历Vector调用 blitter实现屏幕绘制的底层实现

下面我们回过头分析 ViewportAddLandscape() 双重循环的row和column

int left_column = (upper_left.y - upper_left.x) / (int)TILE_SIZE - 2;
int right_column = (upper_right.y - upper_right.x) / (int)TILE_SIZE + 2;

int row = (upper_left.x + upper_left.y) / (int)TILE_SIZE - 2;

和表格的定义一样,row根据垂直方向变化,如果键盘向下的话,row随之变大;column根据水平方向变化,键盘向左变小、向右变大,
通过增加下面2个DEBUG,运行程序,我们进一步了解到 每一个Tile对应一半的row和column ,那么如果是64*64的地图,row范围[1到128], column范围 [-64到64]

viewport.cpp Line1164
static void ViewportAddLandscape()
{
...
    bool last_row = false;
DEBUG(misc,2,"ViewportAddLandscape(): begin loop left[%d,%d],right[%d,%d]",upper_left.x,upper_left.y,upper_right.x,upper_righ.y);  <- 说明1
    for (; !last_row; row++) {
        last_row = true;
DEBUG(misc,2,"                                            row(%) column [%d to %d]",row, left_column, right_column); <- 说明2
        for (int column = left_column; column <= right_column; column++) {
            /* Valid row/column? */
            if ((row + column) % 2 != 0) continue;
...

说明1:双循环启动前
说明2:每一个row循环,输出范围

当我们打开一个64*64的地图,把主视角放到最大
地图最上面 row[ -4 to 18] column [ 0 to 5] <- 思考:为什么row会小于0
地图最下面 row[127 to 131] column [ 0 to 5] <- 思考: 为什么row会大于128
地图最左边 row[ 57 to 69] column [-61 to -57]
地图最右边 row[ 57 to 69] column [ 62 to 66] <- 思考:为什么column会大于64
在这里插入图片描述

现在Tile的绘制逻辑就很清晰了,程序根据当前屏幕左上角和右上角的坐标点确定 column,根据左上角顶点确定第一行row,然后通过双循环,把屏幕内的所有Tile刷新一遍

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
全能电子地图下载器,是一个专门下载地图瓦片数据的工具,可以从Google地图,MapABC,SOSO地图,雅虎地图,必应地图,诺基亚地图等网络地图中下载瓦片地图(256x256的图片),并可无缝拼接成大图,是各居家旅行探险者的必备良伴。软件有以下特点: 支持多线程高速下载(默认为10线程,最大支持20线程),线程数可由用户根据自己的网络带宽情况自行设置。 提供海量地图下载,下载图片数量无任何限制,如何你的硬盘够大,网络速度够快,可以把整个网络地图下载下来。 提供了全国主要城市边界坐标,内置了全国共有34个省级行政区和300多个地级行政区划单位边界坐标,县级行政区边界坐标可自动从网络搜索获取。 下载方式灵活多样,操作简单方便,只要拖动几下鼠标,就可按圆形,矩形,不规则多边形和行政区范围下载。 可无缝拼接单张大图,可拼接成BMP、PNG、JPG大图,最大支4G,GeoTIFF可拼接为无限制大图。 可生成精确坐标文件,可将所下载的图片精确地叠加到其它软件中,比如Global Mapper。 可自动升级地图版本(仅谷歌地图) 支持下载完成后自动关机。 提供了地名搜索,坐标定位。 支持任务的断点续传,智能下载。 支持HTTP代理下载。 提供测量距离,测量面积,书签等人性化功能。 提供绿色版和安装版,均无需安装JAVA虚拟机或.NET Framework,小巧轻便,运行快速稳定。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值