C++瓦片地圖坐標轉(zhuǎn)換的實現(xiàn)詳解_第1頁
C++瓦片地圖坐標轉(zhuǎn)換的實現(xiàn)詳解_第2頁
C++瓦片地圖坐標轉(zhuǎn)換的實現(xiàn)詳解_第3頁
C++瓦片地圖坐標轉(zhuǎn)換的實現(xiàn)詳解_第4頁
C++瓦片地圖坐標轉(zhuǎn)換的實現(xiàn)詳解_第5頁
已閱讀5頁,還剩3頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第C++瓦片地圖坐標轉(zhuǎn)換的實現(xiàn)詳解目錄一、前言二、定義三、矩形瓦片四、菱形瓦片1.斜菱形瓦片2.正菱形瓦片五、點在菱形內(nèi)判斷

一、前言

嚴格來說,瓦片的角度并不是45度。因為為了美術(shù)作圖方便,圖片的寬高比一般為2:1,如下圖所示,它的實際角度為arctan(1/2),不過這個數(shù)值對我們不重要。正如魚香肉絲沒有魚一般,叫它45度瓦片也無妨,由于它是一個菱形,所以這里我們稱它為菱形瓦片。

寬高比為2:1的菱形瓦片

或許有人認為任意角度的瓦片都是可以的,其實不然,因為我們要考慮線條鋸齒的畫法,如果采用非整數(shù)比,則線條不是規(guī)律的(非像素游戲或許可以試試)。所以最常見的比例為2:1,其次是1:1。

還有一個問題,我們觀察菱形的四分之一部分,它將一個矩形一分為二。我們當然期望它是平分的,然而這根本做不到,因為它不是理論的對角線。對于正方形瓦片來說,邊緣是不會重疊的。而菱形瓦片不可避免的邊緣存在重疊。

邊緣必然重疊

二、定義

我們定義地圖上的一個點為世界(World)坐標,它是連續(xù)的,用浮點數(shù)表示。然后格子的索引叫地圖(Map)坐標,它是離散的,用有符號整數(shù)表示。不過這里地圖坐標的取值未考慮負數(shù),如要使用負數(shù)的地圖坐標則需要對代碼略微修改。

比如下圖的p點,我們假設(shè)格子寬10像素。則其世界坐標為(54,67),而地圖坐標為(5,6)。

矩形瓦片示例

三、矩形瓦片

矩形瓦片的代碼很簡單,如下:

//!矩形瓦片地圖

templateVector2TILE_SIZE

classRectangle

public:

*@brief地圖坐標-世界坐標

constexprVector2Map2World(constPointxy)

returntoVector2(xy)*TILE_SIZE;

*@brief世界坐標-地圖坐標

constexprPointWorld2Map(constVector2pos)

returntoPoint(pos/TILE_SIZE);

};

四、菱形瓦片

1.斜菱形瓦片

這里的斜指的是,整個地圖拼出來是斜著的,也是一個菱形,如下圖所示(這是常用的算法):

斜菱形瓦片

我們令xy為地圖(格子)坐標,xy為世界(像素)坐標,其中wh為瓦片寬高,則有如下關(guān)系:

上面這個式子通過簡單的變換,就可以得出:

轉(zhuǎn)換代碼如下,這里就體現(xiàn)出了將瓦片大?。═ILE_SIZE)作為模板的好處了,其中除2的操作會自動合并為常量表達式,世界坐標到地圖坐標的轉(zhuǎn)換其中加了0.5,是為了四舍五入。

//!斜45度瓦片地圖

templateVector2TILE_SIZE

classDiamondSlant

public:

*@brief地圖坐標-世界坐標

constexprVector2Map2World(constPointxy)

return{(xy[1]+xy[0])*TILE_SIZE[0]/2.0,(xy[1]-xy[0])*TILE_SIZE[1]/2.0};

*@brief世界坐標-地圖坐標

constexprPointWorld2Map(constVector2pos)

Vector2xy_div=pos/TILE_SIZE;

returntoPoint(Vector2{xy_div[0]-xy_div[1]+0.5,xy_div[0]+xy_div[1]-0.5});

};

2.正菱形瓦片

下面這種整體也是一個矩形,它的特點是x軸移動瓦片寬度,y軸只移動半個瓦片高度,當y為奇數(shù)時,x再往右移動半個瓦片寬度。(有些文章是y為偶數(shù)時x移動,原理相同)

正菱形瓦片

容易得到,從格子坐標到世界坐標,如下:

當y為偶數(shù)時:

當y為奇數(shù)時:

這里出現(xiàn)和上面不一樣的事了,無法簡單的逆推公式來表示xy。因為通過世界(像素)坐標無法輕松得到它的地圖(格子)坐標的y是奇數(shù)還是偶數(shù)。

從格子坐標到世界坐標的代碼如下:

/**

*@brief地圖坐標-世界坐標

constexprVector2Map2World(constPointxy)

Vector2pos={TILE_SIZE[0]*xy[0],TILE_SIZE[1]/2*xy[1]};

if(xy[1]%2!=0)

{//奇數(shù)行向右偏移w/2

pos[0]+=TILE_SIZE[0]/2;

returnpos;

}

而從世界坐標到格子坐標則比較麻煩了,如下,我們劃分網(wǎng)格:

劃分網(wǎng)格

明顯格子大小為(w,h),記世界坐標pos所在的格子為p,則有:

來看單個劃分網(wǎng)格內(nèi),如下:

單個劃分格子

設(shè)瓦片格子坐標為xy,則當pos在菱形內(nèi)時,有:

當pos在菱形外時,四個角則分別判斷:右下角偏移(0,1);左下角偏移(-1,1);左上角偏移(-1,-1);右上角偏移(0,-1)。

所以最終實現(xiàn)代碼如下:

//!平菱形瓦片地圖

templateVector2TILE_SIZE

classDiamondFlat

public:

*@brief地圖坐標-世界坐標

constexprVector2Map2World(constPointxy)

Vector2pos={TILE_SIZE[0]*xy[0],TILE_SIZE[1]/2*xy[1]};

if(xy[1]%2!=0)

{//奇數(shù)行向右偏移w/2

pos[0]+=TILE_SIZE[0]/2;

returnpos;

*@brief世界坐標-地圖坐標

constexprPointWorld2Map(constVector2pos)

constexprVector2TILE_SIZE_HALF=TILE_SIZE/2.0;

//四分之一矩形面積

constexprreals=Each::AccumulateMul(TILE_SIZE_HALF);

//先計算矩形下標

Pointp=toPoint(pos/TILE_SIZE);

//在矩形內(nèi)坐標

Vector2p1=pos-toVector2(p)*TILE_SIZE-TILE_SIZE_HALF;

//點圍成矩形面積

realsp=abs(p1[0]*TILE_SIZE_HALF[1])+abs(p1[1]*TILE_SIZE_HALF[0]);

p[1]*=2;

if(ssp)

if(p1[0]0p1[1]0)

returnp+Point{0,1};

elseif(p1[0]0p1[1]0)

returnp+Point{-1,1};

elseif(p1[0]0p1[1]0)

returnp+Point{-1,-1};

elseif(p1[0]0p1[1]0)

returnp+Point{0,-1};

else

returnp;

else

return

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論