SHARE
TWEET

Untitled

a guest Apr 18th, 2019 92 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. """
  2. NPC starts locked in a cage, then flocks to the player when released.
  3. It'll shoot toward the mouse cursor when the player shoots.
  4.  
  5. It should seek a new position if it's shot is blocked by the player,
  6. but that's not 100% solved yet.
  7.  
  8. """
  9.  
  10.  
  11. extends KinematicBody2D
  12.  
  13. # Declare member variables here. Examples:
  14. enum States { CAPTIVE, FREE }
  15. var State = States.CAPTIVE
  16. var velocity : Vector2 = Vector2.ZERO
  17. var speed = 200.0
  18. var shooting : bool = false
  19. var blocked : bool = false
  20. var leader : KinematicBody2D # probably global.player, but maybe someday we'll have other groups in formations.
  21.  
  22. var formation_position : Vector2
  23.  
  24. export (PackedScene) var bulletScene = load("res://Projectiles/Arrow/Arrow.tscn")
  25.  
  26.  
  27. signal projectile_requested(projectile, vel, pos, rot)
  28. signal follower_acquired(node)
  29.  
  30. # Called when the node enters the scene tree for the first time.
  31. func _ready():
  32.     call_deferred("start")
  33.    
  34. func start():
  35.     connect("projectile_requested", global.current_level, "_on_projectile_requested")
  36.  
  37.  
  38. # Called every frame. 'delta' is the elapsed time since the previous frame.
  39. func _process(delta):
  40.     if State == States.FREE:
  41.         velocity = aggregate_vectors()
  42.         var collision = move_and_collide(velocity * speed * delta)
  43.         if collision:
  44.             pass
  45.  
  46.  
  47. func aggregate_vectors():
  48.     var returnVec : Vector2 = Vector2.ZERO
  49.     var blocked = is_blocked()
  50.  
  51.     if blocked:
  52.         returnVec += get_formation_vector()
  53.     else:
  54.         returnVec += get_follow_leader_vector()
  55.    
  56.     returnVec += get_avoid_allies_vector()
  57.    
  58.     return returnVec.normalized()
  59.  
  60. func get_formation_vector():
  61.     # store an array of idealized positions (assuming the leader is facing Vector2.RIGHT)
  62.     # find your position, based on your order in parent node
  63.     # go toward that position.
  64.    
  65.     var returnVec = Vector2.ZERO
  66.     var myPos = get_global_position()
  67.     var leaderPos = leader.get_global_position()
  68.     var mousePos = get_global_mouse_position()
  69.     var offset = 45
  70.     var formation_positions = [ Vector2(-1, -1)*offset, Vector2(-1, 1)*offset, Vector2(-2, -2)*offset, Vector2(-2, 2)*offset]
  71.     var leader_targeting_angle = Vector2.RIGHT.angle_to_point(mousePos - leaderPos)
  72.     var my_ideal_position = leaderPos + formation_positions[get_position_in_parent()].rotated(leader_targeting_angle)
  73.     formation_position = my_ideal_position
  74.     update()
  75.    
  76.     returnVec += (my_ideal_position - myPos).normalized()
  77.    
  78.     return returnVec
  79.    
  80.  
  81. func _draw():
  82.     draw_circle(to_local(formation_position), 15, Color.antiquewhite)
  83.    
  84. func get_follow_leader_vector():
  85.     return (leader.get_global_position() - self.get_global_position()).normalized()
  86.  
  87. func get_avoid_allies_vector():
  88.     var returnVec = Vector2.ZERO
  89.     var avoid_distance = 45.0
  90.    
  91.     # do this for the player and each NPC ally following the player.
  92.     var myPos = get_global_position()
  93.     if myPos.distance_squared_to(leader.get_global_position()) < avoid_distance * avoid_distance:
  94.         returnVec += (self.get_global_position() - leader.get_global_position()).normalized()
  95.    
  96.     for NPC in get_parent().get_children():
  97.         # check for all sibling NPCs
  98.         if NPC != self:
  99.             if myPos.distance_squared_to(NPC.get_global_position()) < avoid_distance * avoid_distance:
  100.                 returnVec += (myPos - NPC.get_global_position()).normalized()
  101.     if returnVec != Vector2.ZERO:
  102.         return returnVec.normalized()
  103.     else:
  104.         return returnVec
  105.  
  106. func _on_cage_unlocked(rescuer):
  107.     State = States.FREE
  108.     leader = rescuer # most likely global.player
  109.    
  110.     if leader.has_method("_on_NPC_follower_acquired"):
  111.         connect("follower_acquired", leader, "_on_NPC_follower_acquired")
  112.         emit_signal("follower_acquired", self) # tell the player we're following them
  113.  
  114. func commence_shooting():
  115.     shooting = true
  116.     shoot()
  117.     $ReloadTimer.start()
  118.    
  119. func stop_shooting():
  120.     shooting = false
  121.     $ReloadTimer.stop()
  122.    
  123. func _on_player_started_shooting():
  124.     commence_shooting()
  125.    
  126. func _on_player_stopped_shooting():
  127.     stop_shooting()
  128.  
  129. func is_blocked():
  130.     var ray = $RayCast2D
  131.     var rot = Vector2(1,0).angle_to_point(get_global_position()-get_global_mouse_position())
  132.     var bulletVelocity = velocity + Vector2(global.options["arrow_speed"],0).rotated(rot)
  133.    
  134.     ray.set_cast_to(bulletVelocity / 5)
  135.     if ray.is_colliding() == true:
  136.         var obstacle = ray.get_collider()
  137.         if obstacle:
  138.            
  139.             if obstacle.is_in_group("player") or obstacle.is_in_group("player_allies"):
  140.                
  141.                 return true
  142.     return false
  143.    
  144.  
  145. func shoot():
  146.     # check for a clean line of sight. Move if you don't have one. Then shoot.
  147.     var rot = Vector2(1,0).angle_to_point(get_global_position()-get_global_mouse_position())
  148.     var bulletVelocity = velocity + Vector2(global.options["arrow_speed"],0).rotated(rot)
  149.    
  150.     if not is_blocked():
  151.         emit_signal("projectile_requested", bulletScene, bulletVelocity, get_global_position(), rad2deg(rot))
  152.    
  153.    
  154.  
  155. func _on_ReloadTimer_timeout():
  156.     if shooting == true:
  157.         shoot()
  158.         $ReloadTimer.start()
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top