Browse Source

ft: 六边形地图算法添加

master
SisMaker 1 year ago
parent
commit
0f6e7304c9
4 changed files with 194 additions and 16 deletions
  1. +2
    -2
      include/utComMisc.hrl
  2. +13
    -13
      src/bStar/bStar.erl
  3. +178
    -0
      src/hexMap/hexMap.erl
  4. +1
    -1
      src/testCase/funTest.erl

+ 2
- 2
include/utComMisc.hrl View File

@ -1,6 +1,6 @@
%%
-define(IIF(Cond, Then, That), case Cond of true -> Then; _ -> That end).
-define(IIF(Expr, Expect, Then, ExprRet, That), case Expr of Expect -> Then; ExprRet -> That end).
-define(CASE(Cond, Then, That), case Cond of true -> Then; _ -> That end).
-define(CASE(Expr, Expect, Then, ExprRet, That), case Expr of Expect -> Then; ExprRet -> That end).
%% IF-DO表达式
-define(IF(IFTure, DoThat), (IFTure) andalso (DoThat)).

+ 13
- 13
src/bStar/bStar.erl View File

@ -90,7 +90,7 @@ start_search(#bstar_map{open_list = [CurrentCell | Rest], target = Target} = BSt
%% 沿
Dir = get_branchDir(CurrentCell#cell.branch, CurrentCell#cell.dir),
Dir2 = Dir + ?MAX_DIRECTION - 1,
Dir3 = ?IIF(Dir2 >= ?MAX_DIRECTION, Dir2 - ?MAX_DIRECTION, Dir2),
Dir3 = ?CASE(Dir2 >= ?MAX_DIRECTION, Dir2 - ?MAX_DIRECTION, Dir2),
case get_branch(CurrentCell, CurrentCell#cell.branch, Dir3, BStarMap) of
{true, OpenCell, BStarMap2} ->
BStarMap3 = close_cell(BStarMap2, CurrentCell),
@ -152,9 +152,9 @@ get_left_right(CurrentCell, NextCell, BranchDir, Dir, #bstar_map{origin = Origin
Angle = g_GetDirAngle(Origin#cell.x, Origin#cell.y, Cell2#cell.x, Cell2#cell.y, NextCell#cell.x, NextCell#cell.y),
Angle2 = case BranchDir of
?branch_dir_left ->
?IIF(Angle > 32, 64 - Angle, 0 - Angle);
?CASE(Angle > 32, 64 - Angle, 0 - Angle);
_ ->
?IIF(Angle > 32, Angle - 64, Angle)
?CASE(Angle > 32, Angle - 64, Angle)
end,
Cell4 = Cell3#cell{reel = Count + 1, s = ?cell_state_open, angle = Angle2},
BStarMap2 = save_cell(BStarMap, Cell4),
@ -203,7 +203,7 @@ get_branch(CurrentCell, BranchDir, Dir, BStarMap) ->
get_branch([], _CurrentCell, _BranchDir, _Dir, BStarMap) ->
{false, BStarMap};
get_branch([Count | Rest], CurrentCell, BranchDir, Dir, #bstar_map{target = Target, map_config = #map_config{weight = Weight, height = Height}} = BStarMap) ->
Dir2 = ?IIF(Dir >= ?MAX_DIRECTION, Dir - ?MAX_DIRECTION, Dir),
Dir2 = ?CASE(Dir >= ?MAX_DIRECTION, Dir - ?MAX_DIRECTION, Dir),
NextDir = branchAround(BranchDir, Dir2),
Around = around(NextDir),
NextX = CurrentCell#cell.x + Around#pos.x,
@ -277,16 +277,16 @@ get_branch2(_CurrentCell, _NextCell, _BranchDir, _NextDir, _Count, BStarMap) ->
%%
get_branch_i(CurrentCell, NextCell, BranchDir, NextDir, Count, #bstar_map{origin = Origin} = _BStarMap) ->
Reel = CurrentCell#cell.reel + Count - 1,
Reel2 = ?IIF(Reel < 0, 0, Reel),
Reel2 = ?CASE(Reel < 0, 0, Reel),
Angle = g_GetDirAngle(Origin#cell.x, Origin#cell.y, NextCell#cell.x, NextCell#cell.y, CurrentCell#cell.x, CurrentCell#cell.y),
Angle2 = case BranchDir of
?branch_dir_left -> ?IIF(Angle > 32, 64 - Angle, 0 - Angle);
_ -> ?IIF(Angle > 32, Angle - 64, Angle)
?branch_dir_left -> ?CASE(Angle > 32, 64 - Angle, 0 - Angle);
_ -> ?CASE(Angle > 32, Angle - 64, Angle)
end,
Angle3 = CurrentCell#cell.angle + Angle2,
{Angle4, Reel3} = ?IIF(Angle3 >= 64, {Angle3 - 64, Reel2 - 4}, {Angle3, Reel2}),
{Angle4, Reel3} = ?CASE(Angle3 >= 64, {Angle3 - 64, Reel2 - 4}, {Angle3, Reel2}),
NextCell2 = NextCell#cell{reel = Reel3, s = ?cell_state_open, angle = Angle4},
?IIF(NextCell2#cell.reel > 0, NextCell2#cell{branch = BranchDir, dir = NextDir}, NextCell2#cell{branch = ?branch_dir_none, dir = -1, angle = 0}).
?CASE(NextCell2#cell.reel > 0, NextCell2#cell{branch = BranchDir, dir = NextDir}, NextCell2#cell{branch = ?branch_dir_none, dir = -1, angle = 0}).
%%
find_next(CurrentCell, BStarMap) ->
@ -318,7 +318,7 @@ get_cell(#bstar_map{cell_dict = Dict, map_config = MapConfig}, X, Y) ->
case dict:find({X, Y}, Dict) of
{ok, O} -> O;
_ ->
CellState = ?IIF(lib_map:is_walkable_by_index(MapConfig, X, Y), ?cell_state_none, ?cell_state_balk),
CellState = ?CASE(lib_map:is_walkable_by_index(MapConfig, X, Y), ?cell_state_none, ?cell_state_balk),
#cell{x = X, y = Y, s = CellState}
end.
@ -343,8 +343,8 @@ g_GetDirDiff(OriginX, OriginY, TargetX, TargetY, X, Y) ->
TargetDir = g_GetDirIndex(OriginX, OriginY, TargetX, TargetY),
TestDir = g_GetDirIndex(OriginX, OriginY, X, Y),
DirDiff = TargetDir - TestDir,
DirDiff2 = ?IIF(DirDiff < 0, DirDiff + 64, DirDiff),
?IIF(DirDiff2 > 32, 64 - DirDiff2, DirDiff2).
DirDiff2 = ?CASE(DirDiff < 0, DirDiff + 64, DirDiff),
?CASE(DirDiff2 > 32, 64 - DirDiff2, DirDiff2).
%%
g_GetDirAngle(OriginX, OriginY, TargetX, TargetY, X, Y) ->
@ -430,7 +430,7 @@ get_branchAround(CurrentCell, Branch, TestDir, BStarMap) ->
get_branchAround([], _CurrentCell, _Branch, _TestDir, _BStarMap) ->
false;
get_branchAround([Count | Rest], CurrentCell, Branch, TestDir, #bstar_map{map_config = #map_config{weight = Weight, height = Height}} = BStarMap) ->
TestDir2 = ?IIF(TestDir =:= ?MAX_DIRECTION, 0, TestDir),
TestDir2 = ?CASE(TestDir =:= ?MAX_DIRECTION, 0, TestDir),
BranchAround = branchAround(Branch, TestDir2),
Around = around(BranchAround),
NextX = CurrentCell#cell.x + Around#pos.x,

+ 178
- 0
src/hexMap/hexMap.erl View File

@ -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.

+ 1
- 1
src/testCase/funTest.erl View File

@ -66,7 +66,7 @@ ok(N) ->
ok(N - 1).
test(A) ->
?IIF(lists:keyfind(a, 1, A), false, none, {_, V}, V).
?CASE(lists:keyfind(a, 1, A), false, none, {_, V}, V).
ams1(A) -> ok.
ams2(A) -> fun() -> A end.

Loading…
Cancel
Save