From 2c2c8e7e73fb3038709fb78f67f9cc1ac1724c14 Mon Sep 17 00:00:00 2001 From: Nathan Date: Thu, 29 Mar 2018 16:03:26 +0900 Subject: [PATCH] Add path-following character Fix performance bug with 2-way connections in the Astar node --- 2d/navigation_astar/Game.tscn | 14 +++- 2d/navigation_astar/character.gd | 60 ++++++++++++++++++ 2d/navigation_astar/pathfind_astar.gd | 34 ++++++---- 2d/navigation_astar/sprites/character.png | Bin 0 -> 1202 bytes .../sprites/character.png.import | 32 ++++++++++ 5 files changed, 128 insertions(+), 12 deletions(-) create mode 100644 2d/navigation_astar/character.gd create mode 100644 2d/navigation_astar/sprites/character.png create mode 100644 2d/navigation_astar/sprites/character.png.import diff --git a/2d/navigation_astar/Game.tscn b/2d/navigation_astar/Game.tscn index 63893b2e..25c0f8ce 100644 --- a/2d/navigation_astar/Game.tscn +++ b/2d/navigation_astar/Game.tscn @@ -1,7 +1,9 @@ -[gd_scene load_steps=3 format=2] +[gd_scene load_steps=5 format=2] [ext_resource path="res://tileset/tileset.tres" type="TileSet" id=1] [ext_resource path="res://pathfind_astar.gd" type="Script" id=2] +[ext_resource path="res://character.gd" type="Script" id=3] +[ext_resource path="res://sprites/character.png" type="Texture" id=4] [node name="Game" type="Node" index="0"] @@ -28,4 +30,14 @@ script = ExtResource( 2 ) _sections_unfolded = [ "Cell" ] map_size = Vector2( 16, 16 ) +[node name="Character" type="Position2D" parent="." index="1"] + +script = ExtResource( 3 ) +SPEED = 200.0 + +[node name="Sprite" type="Sprite" parent="Character" index="0"] + +position = Vector2( 7, 0 ) +texture = ExtResource( 4 ) + diff --git a/2d/navigation_astar/character.gd b/2d/navigation_astar/character.gd new file mode 100644 index 00000000..979cbe01 --- /dev/null +++ b/2d/navigation_astar/character.gd @@ -0,0 +1,60 @@ +extends Position2D + +export(float) var SPEED = 200.0 + +enum STATES { IDLE, FOLLOW } +var _state = null + +var path = [] +var target_point_world = Vector2() +var target_position = Vector2() + +var velocity = Vector2() + +func _ready(): + _change_state(IDLE) + + +func _change_state(new_state): + if new_state == FOLLOW: + path = get_parent().get_node('TileMap').get_path(position, target_position) + if not path: + _change_state(IDLE) + return + # The index 0 is the starting cell + # we don't want the character to move back to it in this example + target_point_world = path[1] + _state = new_state + + +func _process(delta): + if not _state == FOLLOW: + return + var arrived_to_next_point = move_to(target_point_world) + if arrived_to_next_point: + path.remove(0) + if len(path) == 0: + _change_state(IDLE) + return + target_point_world = path[0] + + +func move_to(world_position): + var MASS = 10.0 + var ARRIVE_DISTANCE = 10.0 + + var desired_velocity = (world_position - position).normalized() * SPEED + var steering = desired_velocity - velocity + velocity += steering / MASS + position += velocity * get_process_delta_time() + rotation = velocity.angle() + return position.distance_to(world_position) < ARRIVE_DISTANCE + + +func _input(event): + if event.is_action_pressed('click'): + if Input.is_key_pressed(KEY_SHIFT): + global_position = get_global_mouse_position() + else: + target_position = get_global_mouse_position() + _change_state(FOLLOW) diff --git a/2d/navigation_astar/pathfind_astar.gd b/2d/navigation_astar/pathfind_astar.gd index 6d2f558b..cbd58977 100644 --- a/2d/navigation_astar/pathfind_astar.gd +++ b/2d/navigation_astar/pathfind_astar.gd @@ -27,13 +27,13 @@ func _ready(): # Click and Shift force the start and end position of the path to update # and the node to redraw everything -func _input(event): - if event.is_action_pressed('click') and Input.is_key_pressed(KEY_SHIFT): - # To call the setter method from this script we have to use the explicit self. - self.path_start_position = world_to_map(get_global_mouse_position()) - elif event.is_action_pressed('click'): - self.path_end_position = world_to_map(get_global_mouse_position()) - +#func _input(event): +# if event.is_action_pressed('click') and Input.is_key_pressed(KEY_SHIFT): +# # To call the setter method from this script we have to use the explicit self. +# self.path_start_position = world_to_map(get_global_mouse_position()) +# elif event.is_action_pressed('click'): +# self.path_end_position = world_to_map(get_global_mouse_position()) + # Loops through all cells within the map's bounds and # adds all points to the astar_node, except the obstacles @@ -82,7 +82,8 @@ func astar_connect_walkable_cells(points_array): # Note the 3rd argument. It tells the astar_node that we want the # connection to be bilateral: from point A to B and B to A # If you set this value to false, it becomes a one-way path - astar_node.connect_points(point_index, point_relative_index, true) + # As we loop through all points we can set it to false + astar_node.connect_points(point_index, point_relative_index, false) # This is a variation of the method above @@ -110,7 +111,18 @@ func calculate_point_index(point): return point.x + map_size.x * point.y -func recalculate_path(): +func get_path(world_start, world_end): + self.path_start_position = world_to_map(world_start) + self.path_end_position = world_to_map(world_end) + _recalculate_path() + var path_world = [] + for point in _point_path: + var point_world = map_to_world(Vector2(point.x, point.y)) + _half_cell_size + path_world.append(point_world) + return path_world + + +func _recalculate_path(): clear_previous_path_drawing() var start_point_index = calculate_point_index(path_start_position) var end_point_index = calculate_point_index(path_end_position) @@ -158,7 +170,7 @@ func _set_path_start_position(value): set_cell(value.x, value.y, 1) path_start_position = value if path_end_position and path_end_position != path_start_position: - recalculate_path() + _recalculate_path() func _set_path_end_position(value): @@ -171,4 +183,4 @@ func _set_path_end_position(value): set_cell(value.x, value.y, 2) path_end_position = value if path_start_position != value: - recalculate_path() \ No newline at end of file + _recalculate_path() \ No newline at end of file diff --git a/2d/navigation_astar/sprites/character.png b/2d/navigation_astar/sprites/character.png new file mode 100644 index 0000000000000000000000000000000000000000..96ae71d464a12342409814f8529a4924932fa007 GIT binary patch literal 1202 zcmV;j1Wo&iP)NDY`m6J078?z28!2#cQustM<8nt!X)-D^S-cJgTUg zAv_^GwQ8sqZwa?6>DaRHiEy7L7Zkp+^mv7zElySV(_$?W4uY*!*q!>t@n5W@wXCqb z98We=P=4-Xy`(vjo12x`E#8Svm=FQnOfp6gKZA_O?8l3bepyi?f8aZRhP>n|GOHBP zSRq9kgFaCUQavFtDSARihN9K~zkSt{L%vG&<^VK2n&xW{I5weNGR=aJmGiEpFJ#zf<=zf3PXGV_32;bRa{vGf6951U69E94oEQKA0@q1IK~!jg z?b=OG6F~sR@n^QPEnO<9ZcC*cG!_Uk#%PR*5)V)#7(96KgZK>$2hVWSvj@L`Hcbh_ zMHBUALX5lwIG{0z6xwdv*`@U$V_JD>OLuo>N&lzKbhnvbdg$)#0G&FCDLpV2OAn02 zM9-tu2tPT2xR)rjSvh1ism{*JOh8M|-Iu(W|8>%e~PZpFd7@la9 ztr(stlp`3P+bBmdJhxD;V0ccWT*dI5LJ7g}>_!R2@a#fKf#J1_k_y9X7WE?^csQ{# z|B;U=uFS5*whTY!Hgu%dBKV#U9C?l&G{aZI#{10R=p-ML62ohR($tD?AZ)zJ430hl zB**Y-Q9ld*y3Yc%O2Pqa3h)Sqw`KS-yAi>!Vm;`5mpPP5Bo$9#0H9j^yGBu)rdB9b zDvvyeIVsO!2mu~k-mV)nOvSP)%3CUEPNyoWG2HCkLnO%R#&=5U(&Xy9iYG89{fU+> zQq7j>GXRhp)96mXFcoWUH~4sbc_9TzifQ3?W_)60{xctw3e)b5rW6>v9sz`6?0z^C zf^q7x*;S0w3mUFq+*)dK6yx?Hpd%Pj%d@s(L@%7%f)S12wS|!d!8;X3HU#ewhALIh zzM!Rf<}+(wonPuHdiK>h-7VAQkbnQ*riPLJEDEL%J0%qnk8Nt81=E)SP`5+l|7Yx@ zk_o{(QyYQK))p;(aIkr9`e5^1Od-G?qoq9at>+khDKp~4yt=KiQzsYt1Ge9KJtWYl Q5C8xG07*qoM6N<$f~j*ONB{r; literal 0 HcmV?d00001 diff --git a/2d/navigation_astar/sprites/character.png.import b/2d/navigation_astar/sprites/character.png.import new file mode 100644 index 00000000..4fd7f02d --- /dev/null +++ b/2d/navigation_astar/sprites/character.png.import @@ -0,0 +1,32 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/character.png-eb70ac48a5acf508c4b7740ea4ac4fae.stex" + +[deps] + +source_file="res://sprites/character.png" +source_md5="8746d76344ac3bad60c33b1bc43e11fd" + +dest_files=[ "res://.import/character.png-eb70ac48a5acf508c4b7740ea4ac4fae.stex" ] +dest_md5="e874204705e06ca4dc2c9b0a90db7e8a" + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0