Files
kicking-high/proto1/npc.gd
2019-07-17 16:01:38 +03:00

133 lines
4.1 KiB
GDScript

extends KinematicBody2D
signal arrived
enum {STATE_IDLE, STATE_WALKTO, STATE_DIALOGUE, STATE_FOLLOW, STATE_CONTROL}
var destination = Vector2()
var state = STATE_IDLE
var velocity = Vector2()
var next_dst = Vector2()
var nav: Navigation2D
var arrived = false
var dst_node
func _ready():
nav = get_node("/root/main/nav")
add_to_group("npc")
func calc_next_dst():
var path = nav.get_simple_path(nav.get_closest_point(global_position), nav.get_closest_point(destination))
if path.size() > 1:
var ok = false
for p in path:
if global_position.distance_squared_to(p) >= 25.0:
next_dst = p
ok = true
break
if !ok:
if global_position.distance_squared_to(destination) < 25.0:
next_dst = destination
else:
next_dst = global_position + (destination - global_position).normalized() * 20.0 + Vector2(randf() - 0.5, randf() - 0.5) * 40.0
else:
next_dst = destination
func update_destination():
destination = dst_node.global_position
func walkto(p: Vector2):
arrived = false
destination = p
state = STATE_WALKTO
calc_next_dst()
func follow(n: Node2D):
arrived = false
state = STATE_FOLLOW
dst_node = n
update_destination()
calc_next_dst()
func avoidance(delta):
var avdst = 800.0
var velsum = Vector2()
for n in get_tree().get_nodes_in_group("npc"):
if n == self:
continue
var dist = n.global_position.distance_squared_to(global_position)
if dist < avdst:
var d = global_position - n.global_position
velsum += d
velocity = velocity.linear_interpolate(velsum.normalized() * velocity.length() + Vector2(randf() - 0.5, randf() - 0.5) * velocity.length() * 0.3, delta)
func flock(delta):
var avdst = 3600.0
var maxdst = 10000.0
var velsum = Vector2()
for n in get_tree().get_nodes_in_group("npc"):
if n == self:
continue
var dist = n.global_position.distance_squared_to(global_position)
if dist > avdst && dist < maxdst:
var d = global_position - n.global_position
velsum += -d
velocity = velocity.linear_interpolate(velsum.normalized() * velocity.length() + Vector2(randf() - 0.5, randf() - 0.5) * velocity.length() * 0.3, delta)
func attack():
var bodies = $capture.get_overlapping_bodies()
for b in bodies:
if b is RigidBody2D:
var e = velocity
if e.length() == 0:
e = Vector2(randf() - 0.5, randf() - 0.5)
b.apply_impulse(Vector2(), e.normalized() * (100.0 + 100.0 * randf()))
elif b.is_in_group("npc"):
var e = velocity * 2.0
if e.length() == 0:
e = Vector2(randf() - 0.5, randf() - 0.5) * 5000.0
b.velocity = e
b.move_and_slide(e)
func _process(delta):
match(state):
STATE_IDLE:
if randf() > 0.99:
velocity = velocity.linear_interpolate(Vector2(randf() * 300.0 - 150.0, randf() * 300.0 - 150.0), 0.1 + delta * 0.9)
else:
velocity = velocity.linear_interpolate(Vector2(), delta)
avoidance(delta)
flock(delta)
velocity = move_and_slide(velocity)
STATE_WALKTO:
var vel_base = 540.0
if global_position.distance_squared_to(next_dst) < 25.0:
calc_next_dst()
if global_position.distance_squared_to(next_dst) < 900.0:
vel_base = 160.0
var dir = (next_dst - position).normalized()
velocity = velocity.linear_interpolate(dir * vel_base, 0.3 * delta)
avoidance(delta)
flock(delta)
if velocity.length() < 3.0:
velocity += Vector2(randf() - 0.5, randf() - 0.5) * 6.0
attack()
velocity = move_and_slide(velocity)
if global_position.distance_squared_to(destination) < 25.0:
emit_signal("arrived", destination)
state = STATE_IDLE
arrived = true
STATE_FOLLOW:
var vel_base = 540.0
update_destination()
calc_next_dst()
if global_position.distance_squared_to(next_dst) < 900.0:
vel_base = 160.0
var dir = (next_dst - position).normalized()
velocity = velocity.linear_interpolate(dir * vel_base, 0.3 * delta)
avoidance(delta)
flock(delta)
if velocity.length() < 3.0:
velocity += Vector2(randf() - 0.5, randf() - 0.5) * 6.0
attack()
velocity = move_and_slide(velocity)
if global_position.distance_squared_to(destination) < 25.0:
emit_signal("arrived", destination)
state = STATE_IDLE
arrived = true
STATE_DIALOGUE:
pass
STATE_CONTROL:
pass