Add shooting enemy which shoots at future player pos

Works fairly well, although it doesn't account for changing acceleration which happens due to the changing gravity. I guess this is good enough, since it does hit if the player isn't careful
This commit is contained in:
karl 2021-06-07 16:41:56 +02:00
parent 9401fc9c97
commit 219c8731f5
9 changed files with 171 additions and 11 deletions

28
Bullet.gd Normal file
View File

@ -0,0 +1,28 @@
extends Spatial
var target := Vector3.ZERO
var acceleration := Vector3.ZERO
var velocity := Vector3.ZERO
export var acceleration_factor = 5.0
export var accelerating := false
func _ready():
$HitArea.connect("body_entered", self, "_on_hit_body")
func _on_hit_body(body):
if body.name == "Player":
print("Player hit!")
func _process(delta):
if accelerating:
var direction = (target - global_transform.origin).normalized()
acceleration += direction * acceleration_factor * delta
velocity += acceleration
global_transform.origin += velocity * delta

23
Bullet.tscn Normal file

File diff suppressed because one or more lines are too long

View File

@ -33,5 +33,3 @@ func _process(delta):
# Limit at length 1
if input.length() > 1.0:
input /= input.length()
print(input)

View File

@ -30,8 +30,6 @@ func _process(delta):
velocity = (translation - translation_before) / delta
print(velocity)
# Rotate according to gravity
var gravity_acceleration = get_node(solar_system).get_gravitation_acceleration(global_transform.origin)

View File

@ -10,7 +10,7 @@ const distance_multiplier = 318550 # thus, a radius of 20 results in an earth-
# If the gravity doesn't feel like it should, this scales it. A higher value means that the pull is
# stronger.
const gravity_multiplier = 5.0
const gravity_multiplier = 10.0
func get_gravitation_acceleration(position: Vector3) -> Vector3:

View File

@ -32,6 +32,10 @@ func _input(event):
jumping = false
func get_center():
return global_transform.origin + global_transform.basis.y
func apply_acceleration(acceleration):
# First drag, then add the new acceleration
# For drag: Lerp towards the target velocity

66
ShootyEnemy.gd Normal file
View File

@ -0,0 +1,66 @@
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
func _ready():
$ShotTimer.connect("timeout", self, "shoot_bullet")
func _process(delta):
# Project the player's position into the future
target = _get_future_position(
player.get_center(),
player.velocity
)
if target:
var gravity = solar_system.get_gravitation_acceleration(global_transform.origin)
look_at(target, gravity)
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
instance.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
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

24
ShootyEnemy.tscn Normal file
View File

@ -0,0 +1,24 @@
[gd_scene load_steps=4 format=2]
[ext_resource path="res://ShootyEnemy.gd" type="Script" id=1]
[sub_resource type="PrismMesh" id=1]
[sub_resource type="ConcavePolygonShape" id=2]
data = PoolVector3Array( 0, 1, 1, 1, -1, 1, -1, -1, 1, 0, 1, -1, -1, -1, -1, 1, -1, -1, 0, 1, 1, 0, 1, -1, 1, -1, 1, 0, 1, -1, 1, -1, -1, 1, -1, 1, 0, 1, -1, 0, 1, 1, -1, -1, -1, 0, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1 )
[node name="ShootyEnemy" type="KinematicBody"]
script = ExtResource( 1 )
[node name="MeshInstance" type="MeshInstance" parent="."]
transform = Transform( 1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0, 0 )
mesh = SubResource( 1 )
material/0 = null
[node name="CollisionShape" type="CollisionShape" parent="."]
transform = Transform( 1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0, 0 )
shape = SubResource( 2 )
[node name="ShotTimer" type="Timer" parent="."]
process_mode = 0
autostart = true

View File

@ -1,10 +1,11 @@
[gd_scene load_steps=18 format=2]
[gd_scene load_steps=19 format=2]
[ext_resource path="res://Player.gd" type="Script" id=1]
[ext_resource path="res://Planets.gd" type="Script" id=2]
[ext_resource path="res://Planet.gd" type="Script" id=3]
[ext_resource path="res://PlanetMaterial.tres" type="Material" id=4]
[ext_resource path="res://MovingPlatform.gd" type="Script" id=5]
[ext_resource path="res://ShootyEnemy.tscn" type="PackedScene" id=6]
[sub_resource type="CubeMesh" id=1]
size = Vector3( 4, 0.5, 4 )
@ -106,13 +107,14 @@ glow_bloom = 0.1
[node name="World" type="Spatial"]
[node name="MovingPlatformPivot" type="Position3D" parent="."]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -20, 0 )
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -125, 37, 60 )
[node name="MovingPlatform" type="KinematicBody" parent="MovingPlatformPivot" groups=[
"MovingPlatform",
]]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 30, 0 )
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 60, 0 )
script = ExtResource( 5 )
move_speed = 5.0
solar_system = NodePath("../../Planets")
[node name="MeshInstance" type="MeshInstance" parent="MovingPlatformPivot/MovingPlatform"]
@ -139,16 +141,28 @@ material/0 = null
[node name="CollisionShape" type="CollisionShape" parent="Planets/Earth"]
shape = SubResource( 7 )
[node name="StaticBody" type="StaticBody" parent="Planets"]
[node name="Mars" type="StaticBody" parent="Planets"]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -20, 37, 30 )
script = ExtResource( 3 )
mass = 5.0
[node name="MeshInstance" type="MeshInstance" parent="Planets/StaticBody"]
[node name="MeshInstance" type="MeshInstance" parent="Planets/Mars"]
mesh = SubResource( 8 )
material/0 = ExtResource( 4 )
[node name="CollisionShape" type="CollisionShape" parent="Planets/StaticBody"]
[node name="CollisionShape" type="CollisionShape" parent="Planets/Mars"]
shape = SubResource( 9 )
[node name="Jupiter" type="StaticBody" parent="Planets"]
transform = Transform( 3, 0, 0, 0, 3, 0, 0, 0, 3, -125, 37, 60 )
script = ExtResource( 3 )
mass = 40.0
[node name="MeshInstance" type="MeshInstance" parent="Planets/Jupiter"]
mesh = SubResource( 8 )
material/0 = ExtResource( 4 )
[node name="CollisionShape" type="CollisionShape" parent="Planets/Jupiter"]
shape = SubResource( 9 )
[node name="Player" type="KinematicBody" parent="."]
@ -176,3 +190,8 @@ environment = SubResource( 12 )
[node name="DirectionalLight" type="DirectionalLight" parent="WorldEnvironment"]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 10, 0 )
shadow_enabled = true
[node name="ShootyEnemy" parent="." instance=ExtResource( 6 )]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 8, 20 )
player_node = NodePath("../Player")
solar_system_node = NodePath("../Planets")