From 36992b435c76326bc575f75efbafac54dc2757a0 Mon Sep 17 00:00:00 2001 From: nsensfel Date: Fri, 15 Jun 2018 13:47:17 +0200 Subject: Cleans up RangeIndicator.elm, tries marker icons. Not satisfied with the current look of those markers, though. --- src/asset/www/svg/marker/blade.svg | 14 +- src/asset/www/svg/marker/brokenshield.svg | 185 +++++++++++++++ src/asset/www/svg/marker/pawprint.svg | 44 ++-- src/battlemap/src/Struct/Navigator.elm | 2 +- src/battlemap/src/Struct/RangeIndicator.elm | 352 ++++++++++++++++------------ src/battlemap/www/style.css | 74 +++++- 6 files changed, 484 insertions(+), 187 deletions(-) create mode 100644 src/asset/www/svg/marker/brokenshield.svg diff --git a/src/asset/www/svg/marker/blade.svg b/src/asset/www/svg/marker/blade.svg index e84734e..824a1fb 100644 --- a/src/asset/www/svg/marker/blade.svg +++ b/src/asset/www/svg/marker/blade.svg @@ -16,7 +16,7 @@ version="1.1" id="svg8" inkscape:version="0.92.2 5c3e80d, 2017-08-06" - sodipodi:docname="badsword2.svg"> + sodipodi:docname="blade.svg"> image/svg+xml - + @@ -63,11 +63,11 @@ transform="translate(0,-265)" style="display:inline"> + r="15.500278" /> diff --git a/src/asset/www/svg/marker/brokenshield.svg b/src/asset/www/svg/marker/brokenshield.svg new file mode 100644 index 0000000..9e43115 --- /dev/null +++ b/src/asset/www/svg/marker/brokenshield.svg @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/src/asset/www/svg/marker/pawprint.svg b/src/asset/www/svg/marker/pawprint.svg index a391da6..6fc1dee 100644 --- a/src/asset/www/svg/marker/pawprint.svg +++ b/src/asset/www/svg/marker/pawprint.svg @@ -16,7 +16,7 @@ version="1.1" id="svg8" inkscape:version="0.92.2 5c3e80d, 2017-08-06" - sodipodi:docname="pawprintsi3.svg"> + sodipodi:docname="pawprint.svg"> image/svg+xml - + - + style="display:inline"> + + transform="matrix(1.100568,1.1037005,-1.1037005,1.100568,323.12892,-47.049468)" + style="fill:#ffffff"> + style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.37077442;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" /> + style="fill:#ffffff;stroke:none;stroke-width:0.2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + style="fill:#ffffff;stroke:none;stroke-width:0.2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + style="fill:#ffffff;stroke:none;stroke-width:0.2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + style="fill:#ffffff;stroke:none;stroke-width:0.37077442;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> diff --git a/src/battlemap/src/Struct/Navigator.elm b/src/battlemap/src/Struct/Navigator.elm index 1b3f170..46ad92c 100644 --- a/src/battlemap/src/Struct/Navigator.elm +++ b/src/battlemap/src/Struct/Navigator.elm @@ -80,7 +80,7 @@ new start_loc mov_dist atk_dist def_dist cost_fun = start_loc mov_dist atk_dist - 0 + def_dist (cost_fun) ), cost_fun = cost_fun diff --git a/src/battlemap/src/Struct/RangeIndicator.elm b/src/battlemap/src/Struct/RangeIndicator.elm index 06b34ec..2b70ecd 100644 --- a/src/battlemap/src/Struct/RangeIndicator.elm +++ b/src/battlemap/src/Struct/RangeIndicator.elm @@ -6,8 +6,6 @@ module Struct.RangeIndicator exposing get_path ) --- FIXME: This module is still too much of a mess... - -- Elm ------------------------------------------------------------------------- import Dict import List @@ -31,6 +29,19 @@ type alias Type = marker: Struct.Marker.Type } +type alias SearchParameters = + { + maximum_distance: Int, + maximum_attack_range: Int, + minimum_defense_range: Int, + cost_function: (Struct.Location.Type -> Int) + } + +type alias LocatedIndicator = + { + location_ref: Struct.Location.Ref, + indicator: Type + } -------------------------------------------------------------------------------- -- LOCAL ----------------------------------------------------------------------- -------------------------------------------------------------------------------- @@ -38,186 +49,238 @@ get_closest : ( Int -> Struct.Location.Ref -> Type -> - (Struct.Location.Ref, Type) -> - (Struct.Location.Ref, Type) + LocatedIndicator -> + LocatedIndicator ) -get_closest dist ref indicator (prev_ref, prev_indicator) = - if +get_closest max_dist ref indicator current_best = + if (is_closer max_dist indicator current_best.indicator) + then + { + location_ref = ref, + indicator = indicator + } + else + current_best + +is_closer : Int -> Type -> Type -> Bool +is_closer max_dist candidate current = ( - (indicator.distance < prev_indicator.distance) + -- It's closer when moving + (candidate.distance < current.distance) || ( - (indicator.distance > dist) - && (prev_indicator.distance > dist) - && (indicator.atk_range < prev_indicator.atk_range) + -- Or neither are reachable by moving, + (max_dist <= candidate.distance) + && (max_dist <= current.distance) + -- but the new one is closer when attacking. + && (candidate.atk_range < current.atk_range) ) ) - then - (ref, indicator) - else - (prev_ref, prev_indicator) -is_closer : Int -> Int -> Type -> Bool -is_closer new_dist new_range neighbor = +generate_neighbor : ( + SearchParameters -> + Struct.Location.Type -> + Struct.Direction.Type -> + Type -> + (Int, Type) + ) +generate_neighbor search_params neighbor_loc dir src_indicator = + let + node_cost = (search_params.cost_function neighbor_loc) + new_dist = (src_indicator.distance + node_cost) + new_atk_range = (src_indicator.atk_range + 1) + new_true_range = (src_indicator.true_range + 1) + can_defend = (new_true_range > search_params.minimum_defense_range) + in + if (new_dist > search_params.maximum_distance) + then + ( + node_cost, + { + distance = (search_params.maximum_distance + 1), + atk_range = new_atk_range, + true_range = new_true_range, + path = (dir :: src_indicator.path), + marker = + if (can_defend) + then + Struct.Marker.CanAttackCanDefend + else + Struct.Marker.CanAttackCantDefend + } + ) + else + ( + node_cost, + { + distance = new_dist, + atk_range = 0, + true_range = new_true_range, + path = (dir :: src_indicator.path), + marker = + if (can_defend) + then + Struct.Marker.CanGoToCanDefend + else + Struct.Marker.CanGoToCantDefend + } + ) + +candidate_is_acceptable : (SearchParameters -> Int -> Type -> Bool) +candidate_is_acceptable search_params cost candidate = + (cost /= Constants.Movement.cost_when_out_of_bounds) + && ( - (new_dist < neighbor.distance) + (candidate.distance <= search_params.maximum_distance) || - ( - (neighbor.distance > new_dist) - && (new_range < neighbor.atk_range) - ) + (candidate.atk_range <= search_params.maximum_attack_range) ) +candidate_is_an_improvement : ( + SearchParameters -> + Struct.Location.Ref -> + Type -> + (Dict.Dict Struct.Location.Ref Type) -> + Bool + ) +candidate_is_an_improvement search_params loc_ref candidate alternatives = + case (Dict.get loc_ref alternatives) of + (Just alternative) -> + (is_closer search_params.maximum_distance candidate alternative) + + Nothing -> + True handle_neighbors : ( - Type -> - Struct.Location.Type -> - Int -> - Int -> - Int -> + LocatedIndicator -> (Dict.Dict Struct.Location.Ref Type) -> - (Struct.Location.Type -> Int) -> + SearchParameters -> Struct.Direction.Type -> (Dict.Dict Struct.Location.Ref Type) -> (Dict.Dict Struct.Location.Ref Type) ) -handle_neighbors - src_indicator src_loc - dist - atk_range def_range - results cost_fun dir rem = +handle_neighbors src results search_params dir remaining = let + src_loc = (Struct.Location.from_ref src.location_ref) neighbor_loc = (Struct.Location.neighbor dir src_loc) + neighbor_loc_ref = (Struct.Location.get_ref neighbor_loc) in - case (Dict.get (Struct.Location.get_ref neighbor_loc) results) of - (Just _) -> rem + case (Dict.get neighbor_loc_ref results) of + (Just _) -> + -- A minimal path for this location has already been found + remaining Nothing -> let - node_cost = (cost_fun neighbor_loc) - new_dist = (src_indicator.distance + node_cost) - new_atk_range = (src_indicator.atk_range + 1) - new_true_range = (src_indicator.true_range + 1) - can_defend = (new_true_range >= def_range) + (candidate_cost, candidate) = + (generate_neighbor + search_params + neighbor_loc + dir + src.indicator + ) in if - ( - ( - case - (Dict.get - (Struct.Location.get_ref neighbor_loc) - rem - ) - of - (Just neighbor) -> - (is_closer new_dist new_atk_range neighbor) - - Nothing -> - True - ) - && - (node_cost /= Constants.Movement.cost_when_out_of_bounds) - && - ( - (new_dist <= dist) - || - (new_atk_range <= atk_range) - ) + ( + (candidate_is_acceptable + search_params + candidate_cost + candidate ) - then - (Dict.insert - (Struct.Location.get_ref neighbor_loc) - ( - if (new_dist > dist) - then - { - distance = (dist + 1), - atk_range = new_atk_range, - true_range = new_true_range, - path = (dir :: src_indicator.path), - marker = - if (can_defend) - then - Struct.Marker.CanAttackCanDefend - else - Struct.Marker.CanAttackCantDefend - } - else - { - distance = new_dist, - atk_range = 0, - true_range = new_true_range, - path = (dir :: src_indicator.path), - marker = - if (can_defend) - then - Struct.Marker.CanGoToCanDefend - else - Struct.Marker.CanGoToCantDefend - } - ) - rem + && + (candidate_is_an_improvement + search_params + neighbor_loc_ref + candidate + remaining ) + ) + then + (Dict.insert neighbor_loc_ref candidate remaining) else - rem + remaining + +find_closest_in : ( + SearchParameters -> + (Dict.Dict Struct.Location.Ref Type) -> + LocatedIndicator + ) +find_closest_in search_params remaining = + (Dict.foldl + (get_closest search_params.maximum_distance) + { + location_ref = (-1, -1), + indicator = + { + distance = Constants.Movement.cost_when_out_of_bounds, + path = [], + atk_range = Constants.Movement.cost_when_out_of_bounds, + true_range = Constants.Movement.cost_when_out_of_bounds, + marker = Struct.Marker.CanAttackCanDefend + } + } + remaining + ) + +resolve_marker_type : SearchParameters -> Type -> Type +resolve_marker_type search_params indicator = + {indicator | + marker = + case + ( + (indicator.atk_range > 0), + (indicator.true_range <= search_params.minimum_defense_range) + ) + of + (True, True) -> Struct.Marker.CanAttackCantDefend + (True, False) -> Struct.Marker.CanAttackCanDefend + (False, True) -> Struct.Marker.CanGoToCantDefend + (False, False) -> Struct.Marker.CanGoToCanDefend + } + +insert_in_dictionary : ( + LocatedIndicator -> + (Dict.Dict Struct.Location.Ref Type) -> + (Dict.Dict Struct.Location.Ref Type) + ) +insert_in_dictionary located_indicator dict = + (Dict.insert + located_indicator.location_ref + located_indicator.indicator + dict + ) search : ( (Dict.Dict Struct.Location.Ref Type) -> (Dict.Dict Struct.Location.Ref Type) -> - Int -> - Int -> - Int -> - (Struct.Location.Type -> Int) -> + SearchParameters -> (Dict.Dict Struct.Location.Ref Type) ) -search result remaining dist atk_range def_range cost_fun = +search result remaining search_params = if (Dict.isEmpty remaining) then result else let - (min_loc_ref, min) = - (Dict.foldl - (get_closest dist) - ( - (-1,-1), - { - distance = Constants.Movement.cost_when_out_of_bounds, - path = [], - atk_range = Constants.Movement.cost_when_out_of_bounds, - true_range = Constants.Movement.cost_when_out_of_bounds, - marker = Struct.Marker.CanAttackCanDefend - } - ) - remaining - ) + closest_located_indicator = (find_closest_in search_params remaining) + finalized_clos_loc_ind = + {closest_located_indicator| + indicator = + (resolve_marker_type + search_params + closest_located_indicator.indicator + ) + } in (search - (Dict.insert - min_loc_ref - {min | - marker = - case - ((min.atk_range > 0), (min.true_range <= def_range)) - of - (True, True) -> Struct.Marker.CanAttackCantDefend - (True, False) -> Struct.Marker.CanAttackCanDefend - (False, True) -> Struct.Marker.CanGoToCantDefend - (False, False) -> Struct.Marker.CanGoToCanDefend - } - result - ) + (insert_in_dictionary finalized_clos_loc_ind result) (List.foldl (handle_neighbors - min - (Struct.Location.from_ref min_loc_ref) - dist - atk_range - def_range + finalized_clos_loc_ind result - (cost_fun) + search_params ) - (Dict.remove min_loc_ref remaining) + (Dict.remove finalized_clos_loc_ind.location_ref remaining) [ Struct.Direction.Left, Struct.Direction.Right, @@ -225,10 +288,7 @@ search result remaining dist atk_range def_range cost_fun = Struct.Direction.Down ] ) - dist - atk_range - def_range - (cost_fun) + search_params ) -------------------------------------------------------------------------------- @@ -242,7 +302,7 @@ generate : ( (Struct.Location.Type -> Int) -> (Dict.Dict Struct.Location.Ref Type) ) -generate location dist atk_range def_range cost_fun = +generate location max_dist atk_range def_range cost_fun = (search Dict.empty (Dict.insert @@ -261,10 +321,12 @@ generate location dist atk_range def_range cost_fun = } Dict.empty ) - dist - atk_range - def_range - (cost_fun) + { + maximum_distance = max_dist, + maximum_attack_range = atk_range, + minimum_defense_range = def_range, + cost_function = (cost_fun) + } ) get_marker : Type -> Struct.Marker.Type diff --git a/src/battlemap/www/style.css b/src/battlemap/www/style.css index 04bce9a..4b1db1b 100644 --- a/src/battlemap/www/style.css +++ b/src/battlemap/www/style.css @@ -463,7 +463,6 @@ .battlemap-marker-icon {z-index: 2;} .battlemap-path-icon-above-markers {z-index: 3;} .battlemap-character-icon {z-index: 4;} -.battlemap-marker-icon.battlemap-navigator-non-interactive {z-index: 5;} .battlemap-marker-icon, .battlemap-character-icon, @@ -549,29 +548,31 @@ opacity: 0.3; transition: opacity 0.3s ease-out; } + .battlemap-can-go-to-cant-defend-marker.battlemap-navigator-interactive { background: repeating-linear-gradient( -55deg, - rgba(255,255,255,0.3), - rgba(255,255,255,0.3) 3px, - rgba(0,0,0,0.3) 3px, - rgba(0,0,0,0.3) 7px + rgb(255,255,255), + rgb(255,255,255) 3px, + rgba(0,0,0,0) 3px, + rgba(0,0,0,0) 7px ); opacity: 0.3; transition: opacity 0.3s ease-out; } -.battlemap-can-go-to-can-defend-marker.battlemap-navigator-interactive:hover +.battlemap-can-go-to-can-defend-marker.battlemap-navigator-interactive:hover, +.battlemap-can-go-to-cant-defend-marker.battlemap-navigator-interactive:hover { - background-color: rgba(255, 255, 255, 0.9); - opacity: 1; + opacity: 0.9; } .battlemap-can-attack-can-defend-marker.battlemap-navigator-interactive { - background-color:rgba(0,0,0,0.7); + background-color: #000; + opacity: 0.7; width: 28px; /*min-width: 28px; max-width: 28px;*/ @@ -580,14 +581,69 @@ border-radius: 0; } +.battlemap-can-attack-cant-defend-marker.battlemap-navigator-interactive +{ + background: + repeating-linear-gradient( + -55deg, + rgba(255,255,255,0), + rgba(255,255,255,0) 3px, + rgb(0,0,0) 3px, + rgb(0,0,0) 7px + ); + width: 28px; + /*min-width: 28px; + max-width: 28px;*/ + opacity: 0.7; + height: 28px; + margin: 2px 0 0 2px; + border-radius: 0; +} + .battlemap-can-attack-can-defend-marker.battlemap-navigator-non-interactive { background-image: url(/asset/svg/marker/blade.svg); +} + +.battlemap-can-attack-cant-defend-marker.battlemap-navigator-non-interactive +{ + background-image: + url(/asset/svg/marker/blade.svg), + url(/asset/svg/marker/brokenshield.svg); +} + +.battlemap-can-go-to-cant-defend-marker.battlemap-navigator-non-interactive +{ + background-image: + url(/asset/svg/marker/pawprint.svg), + url(/asset/svg/marker/brokenshield.svg); +} + +.battlemap-can-attack-cant-defend-marker.battlemap-navigator-non-interactive, +.battlemap-can-go-to-cant-defend-marker.battlemap-navigator-non-interactive +{ + width: 24px; + height: 24px; + background-position: top left, bottom right; + background-size: 50%, 50%; + background-repeat: no-repeat, no-repeat; + margin: 2px; } .battlemap-can-go-to-can-defend-marker.battlemap-navigator-non-interactive { background-image: url(/asset/svg/marker/pawprint.svg); +} + +.battlemap-can-attack-can-defend-marker.battlemap-navigator-non-interactive, +.battlemap-can-attack-cant-defend-marker..battlemap-navigator-non-interactive +{ + z-index: 5; +} + +.battlemap-can-go-to-can-defend-marker, +.battlemap-can-go-to-cant-defend-marker +{ z-index: 3; } -- cgit v1.2.3-70-g09d2