WOW小地图生成

参考wowmapview写了一个小地图查看的控件, 可以载入*.wdl文件解析出一张类似于"卫星图"的东西

WDL文件保存的是WOW地图的低精度高度数据, 冒似用来做远处的LOD的

每个地图最大是64*64个tile, 而一个tile它保存了17*17 + 16*16个16位的高度数据.

如果生成一张512*512大小的小地图的话, 每个tile就只有8*8个像素

因此, 我们只取17*17中的偶数点

下面这张是Kalimdor的生成效果

#pragma once  
using namespace System;  
using namespace System::ComponentModel;  
using namespace System::Collections;  
using namespace System::Windows::Forms;  
using namespace System::Data;  
using namespace System::Drawing;  
using namespace System::Drawing::Imaging;  
using namespace System::IO;  
namespace WOWMinimap {  
 typedef unsigned int uint;  
 typedef unsigned char byte;  
 /// <summary>  
 /// Summary for MiniMap  
 /// </summary>  
 public ref class MiniMap : public System::Windows::Forms::UserControl  
    {  
 public:  
 static const int MINIMAP_SIZE = 512;  
 static const int MAX_WIDTH_IN_TILE = 64;  
 static const int MAX_TILE_NUM = MAX_WIDTH_IN_TILE * MAX_WIDTH_IN_TILE;  
 static const int TILE_WIDTH_IN_PIXEL = 8;  
 static const int TILE_WIDTH_IN_VERTEX = 17;  
 static const int TILE_VERTEX_NUM = TILE_WIDTH_IN_VERTEX * TILE_WIDTH_IN_VERTEX;  
 public:  
        MiniMap(void)  
        {  
            InitializeComponent();  
 //  
 //TODO: Add the constructor code here  
 //  
 this->bitmap = gcnew Bitmap(MINIMAP_SIZE, MINIMAP_SIZE, PixelFormat::Format32bppArgb);  
        }  
 void LoadMapHeight(String^ filename)  
        {  
            FileStream^ fs = gcnew FileStream(filename, FileMode::Open);  
            BinaryReader^ br = gcnew BinaryReader(fs);  
 // abort the version chunk  
            fs->Seek(0x10, SeekOrigin::Begin);  
 // load tile's file offsets  
            array<uint>^ offsets = gcnew array<uint>(MAX_WIDTH_IN_TILE*MAX_WIDTH_IN_TILE);  
 for (int i = 0; i < MAX_TILE_NUM; i++)  
            {  
                offsets[i] = br->ReadUInt32();  
            }  
 // load tile height  
 for (int i = 0; i < MAX_TILE_NUM; i++)  
            {  
                Console::WriteLine("{0}%", 100.0f * i / float(MAX_TILE_NUM-1));  
 if (0 == offsets[i])  
                {  
 // tile is not used  
 continue;  
                }  
                LoadTileHeight(i, offsets[i], fs);  
            }  
 // repaint  
 this->Invalidate();  
            fs->Close();  
        }  
 private:  
 void LoadTileHeight(uint index, uint offset, FileStream^ fs)  
        {  
            fs->Seek(offset + 8, SeekOrigin::Begin);  
            BinaryReader^ br = gcnew BinaryReader(fs);  
 // read heights  
            array<short>^ heights = gcnew array<short>(TILE_VERTEX_NUM);  
 for (int i = 0; i < TILE_VERTEX_NUM; i++)  
            {  
                heights[i] = br->ReadUInt16();  
            }  
 int left = index % MAX_WIDTH_IN_TILE * TILE_WIDTH_IN_PIXEL;  
 int top = index / MAX_WIDTH_IN_TILE * TILE_WIDTH_IN_PIXEL;  
            Rectangle rect(left, top, TILE_WIDTH_IN_PIXEL, TILE_WIDTH_IN_PIXEL);  
            BitmapData^ bmpData = this->bitmap->LockBits(rect, ImageLockMode::WriteOnly, this->bitmap->PixelFormat);  
 int* color = (int*)bmpData->Scan0.ToPointer();  
 // convert to color  
 for (int z = 0; z < TILE_WIDTH_IN_PIXEL; z++)  
            {  
 for (int x = 0; x < TILE_WIDTH_IN_PIXEL; x++)  
                {  
 short height = heights[(z * 2) * TILE_WIDTH_IN_VERTEX + x * 2];  
                    color[x] = HeightToColor(height).ToArgb();  
                }  
                color += MINIMAP_SIZE;  
            }  
 this->bitmap->UnlockBits(bmpData);  
        }  
        Color HeightToColor(short height)  
        {  
            byte r1,r2,g1,g2,b1,b2;  
 float t;  
            byte r, g, b;  
 if (height < 0)  
            {  
 // water = blue  
 if (height < -511) height = -511;  
                height /= -2;  
                r = g = 0;  
                b = 255 - height;  
            }  
 else 
            {  
 // green: 20,149,7      0-600  
 // brown: 137, 84, 21   600-1200  
 // gray: 96, 96, 96     1200-1600  
 // white: 255, 255, 255  
 if (height < 600)  
                {  
                    r1 = 20;  
                    r2 = 137;  
                    g1 = 149;  
                    g2 = 84;  
                    b1 = 7;  
                    b2 = 21;  
                    t = height / 600.0f;  
                }  
 else if (height < 1200)  
                {  
                    r2 = 96;  
                    r1 = 137;  
                    g2 = 96;  
                    g1 = 84;  
                    b2 = 96;  
                    b1 = 21;  
                    t = (height-600) / 600.0f;  
                }  
 else /*if (height < 1600)*/ 
                {  
                    r1 = 96;  
                    r2 = 255;  
                    g1 = 96;  
                    g2 = 255;  
                    b1 = 96;  
                    b2 = 255;  
 if (height >= 1600) height = 1599;  
                    t = (height-1200) / 600.0f;  
                }  
                r = (byte)(r2*t + r1*(1.0f-t));  
                g = (byte)(g2*t + g1*(1.0f-t));  
                b = (byte)(b2*t + b1*(1.0f-t));  
            }  
 return Color::FromArgb(r, g, b);  
        }  
 protected:  
 /// <summary>  
 /// Clean up any resources being used.  
 /// </summary>  
        ~MiniMap()  
        {  
 if (components)  
            {  
 delete components;  
            }  
        }  
 virtual void OnPaint(PaintEventArgs^ e) override  
        {  
            e->Graphics->DrawImage(this->bitmap, 0, 0, this->Width, this->Height);  
        }  
 private:  
 /// <summary>  
 /// Required designer variable.  
 /// </summary>  
        System::ComponentModel::Container ^components;  
        Bitmap^ bitmap;  
#pragma region Windows Form Designer generated code  
 /// <summary>  
 /// Required method for Designer support - do not modify  
 /// the contents of this method with the code editor.  
 /// </summary>  
 void InitializeComponent(void)  
        {  
 this->SuspendLayout();  
 //   
 // MiniMap  
 //   
 this->Name = L"MiniMap";  
 this->SizeChanged += gcnew System::EventHandler(this, &MiniMap::MiniMap_SizeChanged);  
 this->ResumeLayout(false);  
        }  
#pragma endregion  
 private: System::Void MiniMap_SizeChanged(System::Object^  sender, System::EventArgs^  e) {  
 this->Invalidate();  
             }  
};  
}  

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏成长道路

JDBC静态sql语句连接的工具类编写

为了方便静态SQL语句进行增删改查的操作,编写了一个工具类进行操作。 import java.sql.Connection; import java.sql....

2330
来自专栏Hongten

java画图程序_图片用字母画出来_源码发布

主要是把一些调试的截图发布出来,现在程序调试我认为可以了(当然,你如果还想调试的话,也可以下载源码自己调试)。

1153
来自专栏菩提树下的杨过

Silverlight Telerik控件学习:RadTransitionControl

如果展示类似这种比较cool的图片轮换效果,用RadTransitionControl控件就对了,它提供的过渡效果非常cool! 原理并不复杂,可参见以前写的 ...

2247
来自专栏技术之路

WPF MVVM实现TreeView

今天有点时间,做个小例子WPF MVVM 实现TreeView 只是一个思路大家可以自由扩展 文章最后给出了源码下载地址 图1 ?    图2     ? 模...

2439
来自专栏码匠的流水账

聊聊sentinel的FlowSlot

com/alibaba/csp/sentinel/slots/block/flow/FlowSlot.java

1281
来自专栏岑玉海

RavenDb学习(七) 异步工作以及维度查询

1、异步执行 var entity = new Company {Name = "Async Company #2", Id = "companies/2"}...

2915
来自专栏菩提树下的杨过

asp中的md5/sha1/sha256算法收集

对于asp这种古董级的技术,这年头想找一些有用的资料已经不容易了,下面是一些常用的加密算法: md5 (将以下代码另存为md5.inc) <% Private ...

3699
来自专栏码匠的流水账

springboot2的hikari数据库连接池默认配置

Spring-Boot-2.0.0-M1版本将默认的数据库连接池从tomcat jdbc pool改为了hikari,这里主要研究下hikari的默认配置

7471
来自专栏闻道于事

JavaWeb 例子 JDBC+JSP登陆注册留言板

注册页面: <%@ page language="java" contentType="text/html; charset=UTF-8" pageEn...

3666
来自专栏LanceToBigData

JDBC(一)之细说JDBC

今天这一篇写的是关于JDBC的内容。之前一直在学习mysql数据库,那数据库怎么和我们的程序相互交互呢,它们之间的桥梁就是JDBC。接下来让我们直接进入正题! ...

5408

扫码关注云+社区