|
|
@ -0,0 +1,178 @@ |
|
|
|
%%基于六边形地图的slg后端需要的相关算法 |
|
|
|
-module(hexMap). |
|
|
|
-include("utComMisc.hrl"). |
|
|
|
|
|
|
|
-compile([export_all]). |
|
|
|
|
|
|
|
%%六边形画线算法 算法说明 http://zvold.blogspot.com/2010/01/bresenhams-line-drawing-algorithm-on_26.html |
|
|
|
-define(samePoint(SX, SY, TX, TY), SX == TX andalso SY == TY). |
|
|
|
lineDraw({SX, SY}, {TX, TY}) -> %% 11 |
|
|
|
case ?samePoint(SX, SY, TX, TY) of |
|
|
|
true -> |
|
|
|
[{SX, SY}]; |
|
|
|
_ -> |
|
|
|
X_2old = 2 * (TX - SX) + abs(TY rem 2) - abs(SY rem 2), |
|
|
|
Y_old = TY - SY, |
|
|
|
case abs(Y_old) < abs(X_2old) of |
|
|
|
true -> |
|
|
|
X_sign = ?CASE(X_2old >= 0, 1, -1), |
|
|
|
Y_sign = ?CASE(Y_old >= 0, 1, -1), |
|
|
|
X_diff = 3 * abs(X_2old), |
|
|
|
Y_diff = 3 * abs(Y_old), |
|
|
|
S = 0, |
|
|
|
lineDrawH(SX, SY, TX, TY, X_sign, Y_sign, X_diff, Y_diff, abs(X_2old), S, [{SX, SY}]); |
|
|
|
_ -> |
|
|
|
X_sign = ?CASE(X_2old >= 0, 1, -1), |
|
|
|
Y_sign = ?CASE(Y_old >= 0, 1, -1), |
|
|
|
X_diff = abs(X_2old), |
|
|
|
Y_diff = abs(Y_old), |
|
|
|
S = 0, |
|
|
|
lineDrawV(SX, SY, TX, TY, X_sign, Y_sign, X_diff, Y_diff, S, [{SX, SY}]) |
|
|
|
end |
|
|
|
end. |
|
|
|
|
|
|
|
lineDrawH(SX, SY, TX, TY, X_sign, Y_sign, X_diff, Y_diff, AX_2old, S, Acc) -> |
|
|
|
case ?samePoint(SX, SY, TX, TY) of |
|
|
|
true -> |
|
|
|
Acc; |
|
|
|
_ -> |
|
|
|
TS = S + Y_diff, |
|
|
|
case TS > AX_2old of |
|
|
|
true -> |
|
|
|
{NX, NY} = dir_point(X_sign, Y_sign, SX, SY), |
|
|
|
NS = TS - X_diff, |
|
|
|
lineDrawH(NX, NY, TX, TY, X_sign, Y_sign, X_diff, Y_diff, AX_2old, NS, [{NX, NY} | Acc]); |
|
|
|
_ -> |
|
|
|
{NX, NY} = dir_point(0, X_sign, SX, SY), |
|
|
|
NS = TS + Y_diff, |
|
|
|
lineDrawH(NX, NY, TX, TY, X_sign, Y_sign, X_diff, Y_diff, AX_2old, NS, [{NX, NY} | Acc]) |
|
|
|
end |
|
|
|
end. |
|
|
|
|
|
|
|
lineDrawV(SX, SY, TX, TY, X_sign, Y_sign, X_diff, Y_diff, S, Acc) -> |
|
|
|
case ?samePoint(SX, SY, TX, TY) of |
|
|
|
true -> |
|
|
|
Acc; |
|
|
|
_ -> |
|
|
|
TS = S + X_diff, |
|
|
|
case TS > 0 of |
|
|
|
true -> |
|
|
|
{NX, NY} = dir_point(X_sign, Y_sign, SX, SY), |
|
|
|
NS = TS - Y_diff, |
|
|
|
lineDrawV(NX, NY, TX, TY, X_sign, Y_sign, X_diff, Y_diff, NS, [{NX, NY} | Acc]); |
|
|
|
_ -> |
|
|
|
{NX, NY} = dir_point(-X_sign, Y_sign, SX, SY), |
|
|
|
NS = TS + Y_diff, |
|
|
|
lineDrawV(NX, NY, TX, TY, X_sign, Y_sign, X_diff, Y_diff, NS, [{NX, NY} | Acc]) |
|
|
|
end |
|
|
|
end. |
|
|
|
|
|
|
|
%%六边形视线算法 算法说明 http://zvold.blogspot.com/2010/02/line-of-sight-on-hexagonal-grid.html |
|
|
|
lineSight(SX, SY, TX, TY) -> |
|
|
|
case ?samePoint(SX, SY, TX, TY) of |
|
|
|
true -> |
|
|
|
[{SX, SY}]; |
|
|
|
_ -> |
|
|
|
TwoXOld = 2 * (TX - SX) + abs(TY rem 2) - abs(SY rem 2), |
|
|
|
YOld = TY - SY, |
|
|
|
SignX = ?CASE(TwoXOld >= 0, 1, -1), |
|
|
|
SignY = ?CASE(YOld >= 0, 1, -1), |
|
|
|
ADiffX = abs(TwoXOld), |
|
|
|
ADiffY = abs(YOld), |
|
|
|
S = -2 * ADiffX, |
|
|
|
lineSight(SX, SY, TX, TY, SignX, SignY, ADiffX, ADiffY, S, [{SX, SY}]) |
|
|
|
end. |
|
|
|
|
|
|
|
lineSight(SX, SY, TX, TY, SignX, SignY, ADiffX, ADiffY, S, Acc) -> |
|
|
|
case ?samePoint(SX, SY, TX, TY) of |
|
|
|
true -> |
|
|
|
Acc; |
|
|
|
_ -> |
|
|
|
case S >= 0 of |
|
|
|
true -> |
|
|
|
{NX, NY} = dir_point(-SignX, SignY, SX, SY), |
|
|
|
NS = S - 3 * ADiffY - 3 * ADiffX, |
|
|
|
lineSight(NX, NY, TX, TY, SignX, SignY, ADiffX, ADiffY, NS, [{NX, NY} | Acc]); |
|
|
|
_ -> |
|
|
|
TS = S + 3 * ADiffY, |
|
|
|
case TS > -ADiffX of |
|
|
|
true -> |
|
|
|
{NX, NY} = dir_point(SignX, SignY, SX, SY), |
|
|
|
NS = TS - 3 * ADiffX, |
|
|
|
lineSight(NX, NY, TX, TY, SignX, SignY, ADiffX, ADiffY, NS, [{NX, NY} | Acc]); |
|
|
|
_ -> |
|
|
|
case TS < -3 * ADiffX of |
|
|
|
true -> |
|
|
|
{NX, NY} = dir_point(SignX, -SignY, SX, SY), |
|
|
|
NS = TS + 3 * ADiffX, |
|
|
|
lineSight(NX, NY, TX, TY, SignX, SignY, ADiffX, ADiffY, NS, [{NX, NY} | Acc]); |
|
|
|
_ -> |
|
|
|
{NX, NY} = dir_point(0, SignX, SX, SY), |
|
|
|
NS = TS + 3 * ADiffY, |
|
|
|
lineSight(NX, NY, TX, TY, SignX, SignY, ADiffX, ADiffY, NS, [{NX, NY} | Acc]) |
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
|
end. |
|
|
|
|
|
|
|
-define(HexDirRightUp, 1). |
|
|
|
-define(HexDirRight, 2). |
|
|
|
-define(HexDirRightDown, 3). |
|
|
|
-define(HexDirLeftDown, 4). |
|
|
|
-define(HexDirLeft, 5). |
|
|
|
-define(HexDirLeftUp, 6). |
|
|
|
|
|
|
|
dir_point(-1, -1, SX, SY) -> |
|
|
|
get_point_xy(SX, SY, ?HexDirLeftDown); |
|
|
|
dir_point(-1, 1, SX, SY) -> |
|
|
|
get_point_xy(SX, SY, ?HexDirLeftUp); |
|
|
|
dir_point(1, -1, SX, SY) -> |
|
|
|
get_point_xy(SX, SY, ?HexDirRightDown); |
|
|
|
dir_point(1, 1, SX, SY) -> |
|
|
|
get_point_xy(SX, SY, ?HexDirRightUp); |
|
|
|
dir_point(0, -1, SX, SY) -> |
|
|
|
get_point_xy(SX, SY, ?HexDirLeft); |
|
|
|
dir_point(0, 1, SX, SY) -> |
|
|
|
get_point_xy(SX, SY, ?HexDirRight). |
|
|
|
|
|
|
|
%% ---------------------------------------------------- |
|
|
|
%% @doc |
|
|
|
%% 根据方向获取坐标 |
|
|
|
%% @end |
|
|
|
%% ---------------------------------------------------- |
|
|
|
get_point_xy(X, Y, D) -> |
|
|
|
Bool = (Y rem 2) =:= 0,%% D band 1 等效 |
|
|
|
if |
|
|
|
Bool ->%%偶数列 |
|
|
|
NX = element(D + 1, ?HEXAGON_X) + X, |
|
|
|
NY = element(D + 1, ?HEXAGON_Y) + Y, |
|
|
|
{NX, NY}; |
|
|
|
true -> |
|
|
|
NX = element(D + 1, ?HEXAGON_X1) + X, |
|
|
|
NY = element(D + 1, ?HEXAGON_Y) + Y, |
|
|
|
{NX, NY} |
|
|
|
end. |
|
|
|
|
|
|
|
-define(HEXAGON_X, {0, 1, -1, -1, 0, 0, 0, -1}).%%六边形格子偶数行 |
|
|
|
-define(HEXAGON_X1, {1, 1, 0, -1, 0, 1, 0, 0}).%%六边形格子基数行 |
|
|
|
-define(HEXAGON_Y, {-1, 0, 1, 0, 0, 1, 0, -1}).%%六边形格子列 |
|
|
|
-define(HEXAGON_DIRECTION, [2, 5, 3, 1, 7, 0]).%%六边形格子的方向 |
|
|
|
|
|
|
|
-define(HEXAGON_DIRECTION_RIGHT_DOWN, 0). %% 右下 |
|
|
|
-define(HEXAGON_DIRECTION_RIGHT, 1). %% 右 |
|
|
|
-define(HEXAGON_DIRECTION_LEFT_TOP, 2). %% 左上 |
|
|
|
-define(HEXAGON_DIRECTION_LEFT, 3). %% 左 |
|
|
|
-define(HEXAGON_DIRECTION_RIGHT_TOP, 5). %% 右上 |
|
|
|
-define(HEXAGON_DIRECTION_LEFT_DOWN, 7). %% 左下 |
|
|
|
|
|
|
|
getDirXY(X, Y, Dir) -> |
|
|
|
case (Y rem 2) of |
|
|
|
0 -> |
|
|
|
NX = element(Dir + 1, ?HEXAGON_X) + X, |
|
|
|
NY = element(Dir + 1, ?HEXAGON_Y) + Y, |
|
|
|
{NX, NY}; |
|
|
|
_ -> |
|
|
|
NX = element(Dir + 1, ?HEXAGON_X1) + X, |
|
|
|
NY = element(Dir + 1, ?HEXAGON_Y) + Y, |
|
|
|
{NX, NY} |
|
|
|
end. |