71 lines
2.0 KiB
GDScript
71 lines
2.0 KiB
GDScript
extends KinematicBody
|
|
|
|
|
|
export(NodePath) var player_node
|
|
onready var player = get_node(player_node)
|
|
|
|
export(NodePath) var solar_system_node
|
|
onready var solar_system = get_node(solar_system_node)
|
|
|
|
var bullet_scene = preload("res://Bullet.tscn")
|
|
var bullet_velocity = 40.0
|
|
|
|
var target
|
|
var velocity := Vector3(0.0, 1.0, 1.0)
|
|
|
|
|
|
func _ready():
|
|
$ShotTimer.connect("timeout", self, "shoot_bullet")
|
|
|
|
|
|
func _physics_process(delta):
|
|
# Project the player's position into the future
|
|
target = _get_future_position(
|
|
player.get_center(),
|
|
player.velocity - velocity
|
|
)
|
|
|
|
if target:
|
|
var gravity = solar_system.get_gravity_acceleration(global_transform.origin)
|
|
look_at(target, gravity)
|
|
|
|
global_transform.origin += velocity * delta
|
|
|
|
|
|
func shoot_bullet():
|
|
if not target:
|
|
# Player can't be hit right now, abort
|
|
return
|
|
|
|
var instance = bullet_scene.instance()
|
|
get_tree().get_root().add_child(instance)
|
|
|
|
instance.global_transform.origin = global_transform.origin - global_transform.basis.z
|
|
instance.velocity = velocity + (target - global_transform.origin).normalized() * bullet_velocity
|
|
|
|
|
|
func _get_future_position(position, velocity):
|
|
# Solution to the quadratic formula gives us the time at which the player would be hit
|
|
# TODO: Take acceleration into account as well!
|
|
var a = pow(velocity.x, 2) + pow(velocity.y, 2) + pow(velocity.z, 2) - pow(bullet_velocity, 2)
|
|
var b = 2 * (velocity.x * (position.x - global_transform.origin.x)
|
|
+ velocity.y * (position.y - global_transform.origin.y)
|
|
+ velocity.z * (position.z - global_transform.origin.z))
|
|
|
|
var c = pow(position.x - global_transform.origin.x, 2.0) \
|
|
+ pow(position.y - global_transform.origin.y, 2.0) \
|
|
+ pow(position.z - global_transform.origin.z, 2.0)
|
|
|
|
var discriminant = pow(b, 2) - 4 * a * c
|
|
|
|
if (discriminant < 0): return null # Can't hit the target :(
|
|
|
|
var t1 = (-b + sqrt(discriminant)) / (2 * a)
|
|
var t2 = (-b - sqrt(discriminant)) / (2 * a)
|
|
|
|
# Choose the smallest positive t value
|
|
var t = min(t1, t2)
|
|
if t < 0: t = max(t1, t2)
|
|
|
|
return position + t * velocity
|