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 条评论
登录 后参与评论

相关文章

来自专栏马洪彪

IniHelper——INI操作辅助类

使用INI配置文件,简单便捷。 该辅助工具类为C#操作INI文件的辅助类,源码在某位师傅的基础上完善的来,因为忘记最初的来源了,因此不能提及引用,在此深感遗憾,...

42170
来自专栏一枝花算不算浪漫

[JavaWeb]关于DBUtils中QueryRunner的一些解读.

70860
来自专栏我和未来有约会

[Silverlight动画]转向行为 - 躲避行为

躲避就是追捕的反行为。就像追捕类似于寻找,躲避类似于避开。 本质上讲,是预测出机车将要去到的位置并远离它。在这里所有的原则都和追捕相同。实际上,就连实现都几乎一...

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

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

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

42090
来自专栏码匠的流水账

聊聊sentinel的FlowSlot

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

18710
来自专栏岑玉海

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

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

30650
来自专栏Hongten

Java Annotation(Java 注解)

如果你想知道java annotation是什么?你可以先看看:“http://www.infoq.com/articles/Annotation-Hammer...

22340
来自专栏LanceToBigData

JDBC(一)之细说JDBC

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

59080
来自专栏杨建荣的学习笔记

设计模式之工厂方法(r4笔记第89天)

设计模式中,工厂方法模式的使用还是很频繁的,但是似乎在工作中没有留意或者重视。 在各大网站中对于工厂方法模式的例子一般都是举女娲造人的例子,我就不做重复工作了,...

37370
来自专栏Hongten

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

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

14030

扫码关注云+社区

领取腾讯云代金券