Guest User

Untitled

a guest
Jun 17th, 2020
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.65 KB | None | 0 0
  1. extends State
  2.  
  3.  
  4. # export variables
  5. export(int) var MAX_IDLE_MOVE_RADIUS := 3
  6. export(int) var MAX_MOVE_TIME_GAP_IN_SEC := 60
  7.  
  8.  
  9. # node references
  10. onready var parent_state_tree :StateTree = $'..'
  11. onready var debug_line :Line2D = $'../../DebugLine'
  12. onready var idle_debug_line :Line2D = $'../../IdleDebugLine'
  13. onready var wander_timer :Timer = $WanderTimer
  14. onready var wander_target :Position2D = $WanderTarget
  15.  
  16.  
  17. # member variables
  18. var rng :RandomNumberGenerator = RandomNumberGenerator.new()
  19. var npc :KinematicBody2D
  20. var nav_mesh :Navigation2D
  21. var current_tilemap :TileMap
  22. var last_move_timestamp :int
  23. var move_influence :float = 0.0
  24. var current_tile :Vector2
  25. var current_target :Vector2
  26. var is_moving :bool = false
  27. var path :PoolVector2Array
  28. var _player_temp :Player
  29. var _debug_path :PoolVector2Array
  30. var _debug_distance_to_target :float
  31.  
  32. # constants
  33. const MAX_MOVE_INFLUENCE := 100.0
  34. const MIN_DISTANCE_TO_TARGET := 10.0
  35. const SPEED := 150.0
  36.  
  37.  
  38. func _on_enable() -> void:
  39.     wander_timer.start()
  40.  
  41.  
  42. func _on_disable() -> void:
  43.     wander_timer.stop()
  44.  
  45.  
  46. func _init() -> void:
  47.     state_name = 'idle'
  48.     last_move_timestamp = OS.get_unix_time()
  49.  
  50.  
  51. # Called when the node enters the scene tree for the first time.
  52. func _ready() -> void:
  53.     npc = parent_state_tree.target_entity
  54.     nav_mesh = Game.get_current_world().find_node('Navigation2D')
  55.     current_tilemap = Game.get_current_world().find_node('BaseTileMap') as TileMap
  56.     debug_line.set_as_toplevel(true)
  57.     _player_temp = Game.get_player()
  58.    
  59.     current_tile = current_tilemap.world_to_map(npc.global_position)
  60. #   print('npc position in tilemap space: ', str(current_tile))
  61.    
  62.     rng.randomize()
  63.     print('tilemap cell_size: ', str(current_tilemap.cell_size))
  64.  
  65.  
  66. # Called every frame. 'delta' is the elapsed time since the previous frame.
  67. func _process(delta) -> void:
  68.     if is_moving:
  69.         move_to_target(delta)
  70.  
  71. # Updates the NPC's move influence. This influences the random chance that an NPC
  72. # will want to move to a different spot while idling
  73. #
  74. # the move influence increases more and more the longer the NPC hasn't moved
  75. func update_move_influence() -> void:
  76.     var current_timestamp := OS.get_unix_time()
  77.     var influence_interpolator := float(current_timestamp - last_move_timestamp) / MAX_MOVE_INFLUENCE
  78.     move_influence = lerp(0.0, MAX_MOVE_INFLUENCE, influence_interpolator)
  79.  
  80.  
  81. # Generates a random number between 0 and MAX_MOVE_INFLUENCE
  82. # if the number is >= 95% of MAX_MOVE_INFLUENCE's value then the NPC decides to move
  83. func decides_to_move() -> bool:
  84.     var decision := rng.randf_range(0.0, MAX_MOVE_INFLUENCE) + move_influence
  85.    
  86.     if decision >= MAX_MOVE_INFLUENCE - (MAX_MOVE_INFLUENCE / 20.0):
  87.         return true
  88.     else:
  89.         return false
  90.  
  91.  
  92. # Picks a random tile within the MAX_IDLE_MOVE_RADIUS to move to, and returns the
  93. # global(?) space Vector2 representing the center of the chosen tile to move to
  94. func get_random_move_target() -> void:
  95.     var move_x := rng.randi_range(-MAX_IDLE_MOVE_RADIUS, MAX_IDLE_MOVE_RADIUS)
  96.     var move_y := rng.randi_range(-MAX_IDLE_MOVE_RADIUS, MAX_IDLE_MOVE_RADIUS)
  97.  
  98.     var current_npc_tile = current_tilemap.world_to_map(npc.global_position)
  99.     var target_pos := current_tilemap.map_to_world(Vector2(move_x, move_y) + current_npc_tile)
  100.    
  101.     wander_target.global_position = target_pos
  102.  
  103.  
  104. func get_path_to_target() -> PoolVector2Array:
  105.     var nav_start := nav_mesh.to_local(npc.global_position)
  106.     var ideal_nav_target := nav_mesh.to_local(wander_target.global_position)
  107.     var nav_target := nav_mesh.get_closest_point(ideal_nav_target)
  108.    
  109.     print('nav target: ', str(nav_target))
  110. #   debug_line.clear_points()
  111. #   debug_line.add_point(nav_start)
  112. #   debug_line.add_point(nav_target)
  113. #   debug_line.add_point(nav_start)
  114. #   debug_line.add_point(_player_temp.global_position)
  115.    
  116.     var _path = nav_mesh.get_simple_path(nav_start, nav_target)
  117.    
  118.     if _path.size() == 0:
  119.         get_random_move_target()
  120.         get_path_to_target()
  121.    
  122.     _debug_path = path
  123.     var player_path = nav_mesh.get_simple_path(nav_start, _player_temp.global_position)
  124.     debug_line.points = path
  125.  
  126.     return _path
  127.  
  128.  
  129. # Moves to the specified target position using a path created from the current
  130. # world's Navigation2D node
  131. func move_to_target(delta: float) -> void:
  132.     if path.size() == 0:
  133.         return
  134.    
  135.     var distance_to_next := npc.global_position.distance_to(path[1])
  136.     var distance_to_target := npc.global_position.distance_to(path[path.size() - 1])
  137.     _debug_distance_to_target = distance_to_target
  138.    
  139.     if path.size() < 2 or distance_to_next <= MIN_DISTANCE_TO_TARGET:
  140.         print('path: ', str(path))
  141. #       print('player path: ', str(player_path))
  142.         last_move_timestamp = OS.get_unix_time()
  143.         is_moving = false
  144.         current_tile = current_tilemap.world_to_map(npc.global_position)
  145.         return
  146.    
  147.     elif distance_to_target > MIN_DISTANCE_TO_TARGET:
  148.         var move_direction := npc.global_position.direction_to(path[1])
  149.  
  150.         var move_velocity = move_direction * SPEED * delta
  151.  
  152.         var idle_movement := npc.move_and_collide(move_velocity)
  153.  
  154.         if idle_movement != null and idle_movement.remainder != Vector2.ZERO:
  155.             var slide_vec = idle_movement.remainder.slide(idle_movement.normal)
  156.  
  157.             var _slide = npc.move_and_collide(slide_vec)
  158.    
  159.     elif distance_to_next < MIN_DISTANCE_TO_TARGET:
  160.         path.remove(0)
  161.  
  162.  
  163. # temporary timer to debug values inside _process or functions run by _process
  164. func _on_Timer_timeout():
  165. #   print('move influence: ', move_influence)
  166.     print('path: ', path)
  167.     print('npc global position: ', npc.global_position)
  168.     print('distance to target: ', _debug_distance_to_target)
  169.     pass
  170.  
  171.  
  172. func _on_WanderTimer_timeout():
  173.     if not is_moving:
  174.         update_move_influence()
  175.    
  176.         if decides_to_move():
  177.             get_random_move_target()
  178.             path = get_path_to_target()
  179.             is_moving = true
Add Comment
Please, Sign In to add comment