Update turret script to account for gravity when firing.
This commit is contained in:
parent
e3b2b02bd0
commit
3fa4987bbb
|
@ -29,9 +29,11 @@ ammo_cap = 10
|
|||
fire_cooldown_time = 0.2
|
||||
reload_time = 1.0
|
||||
bullet_scene = ExtResource("3_kpsgq")
|
||||
fire_position = Vector3(0, 1, 0)
|
||||
shot_impulse = 100.0
|
||||
lead_shot_factor = 0.01
|
||||
fire_position = Vector3(0, 2.1, 0)
|
||||
shot_velocity = 20.0
|
||||
lead_shots = true
|
||||
compensate_for_gravity = true
|
||||
use_artillery_firing_solution = false
|
||||
|
||||
[node name="MeshInstance3D" parent="." index="0"]
|
||||
material_override = SubResource("StandardMaterial3D_cgb0l")
|
||||
|
|
|
@ -110,6 +110,7 @@ continuous_cd = true
|
|||
contact_monitor = true
|
||||
max_contacts_reported = 1
|
||||
script = ExtResource("1_rsjgb")
|
||||
damage_per_speed = 100.0
|
||||
min_damage = 1.0
|
||||
lifetime = 5.0
|
||||
|
||||
|
|
|
@ -1,12 +1,20 @@
|
|||
extends Building
|
||||
class_name Turret
|
||||
|
||||
@export var ammo_cap: int = 10
|
||||
@export var fire_cooldown_time: float = 0.2
|
||||
@export var reload_time: float = 1.0
|
||||
@export var bullet_scene: PackedScene = preload("res://objects/bullet.tscn")
|
||||
@export var fire_position: Vector3 = Vector3(0,1,0)
|
||||
@export var shot_impulse: float = 100
|
||||
@export var lead_shot_factor: float = 0.01
|
||||
@export_group("Ammunition")
|
||||
@export var ammo_cap: int = 10 ## The number of shots per "magazine", i.e. reload.
|
||||
@export var fire_cooldown_time: float = 0.2 ## The time between shots, in seconds.
|
||||
@export var reload_time: float = 1.0 ## The time taken to reload, in seconds.
|
||||
|
||||
@export_group("Bullet Spawning")
|
||||
@export var bullet_scene: PackedScene = preload("res://objects/bullet.tscn") ## The entity to spawn as a bullet.
|
||||
@export var fire_position: Vector3 = Vector3(0,1,0) ## The local position to fire from.
|
||||
|
||||
@export_group("Ballistics")
|
||||
@export var shot_velocity: float = 100 ## The velocity that bullets are fired at, in m/s.
|
||||
@export var lead_shots: bool = true ## Turn on to make the turret aim ahead of moving targets.
|
||||
@export var compensate_for_gravity: bool = true ## Turn on to make the turret aim above distant targets to arc it's shots.
|
||||
@export var use_artillery_firing_solution: bool = false ## If compensating for gravity, turn this on to make the turret aim high instead of low.
|
||||
|
||||
enum LoadState {UNLOADED, RELOADING, LOADED}
|
||||
|
||||
|
@ -23,7 +31,6 @@ func _process(delta: float) -> void:
|
|||
super(delta)
|
||||
if loaded == LoadState.UNLOADED:
|
||||
if consumer.take_any_item_from_storage():
|
||||
#Engine.time_scale = 1.0
|
||||
loaded = LoadState.RELOADING
|
||||
if loaded == LoadState.RELOADING:
|
||||
reload_timer += delta
|
||||
|
@ -70,17 +77,55 @@ func fire_at_target() -> void:
|
|||
#Engine.time_scale = 0.1
|
||||
var bullet: RigidBody3D = bullet_scene.instantiate()
|
||||
add_child(bullet)
|
||||
bullet.global_position = to_global(fire_position)
|
||||
var bullet_pos: Vector3 = to_global(fire_position)
|
||||
bullet.global_position = bullet_pos
|
||||
|
||||
var target_range: float = bullet_pos.distance_to(current_target.global_position)
|
||||
var shot_time: float = (target_range / shot_velocity)
|
||||
|
||||
var aim_target: Vector3 = current_target.global_position
|
||||
var target_range: float = global_position.distance_to(current_target.global_position)
|
||||
aim_target += current_target.linear_velocity * lead_shot_factor * target_range
|
||||
DebugDraw3D.draw_sphere(aim_target, 0.25, Color.RED, 0.1)
|
||||
if lead_shots:
|
||||
aim_target += current_target.linear_velocity * shot_time
|
||||
target_range = bullet_pos.distance_to(aim_target)
|
||||
DebugDraw3D.draw_sphere(aim_target, 0.25, Color.RED, shot_time)
|
||||
|
||||
bullet.look_at(aim_target)
|
||||
bullet.apply_impulse((aim_target - bullet.global_position).normalized()*shot_impulse)
|
||||
var fire_direction: Vector3
|
||||
if compensate_for_gravity:
|
||||
var elevation: float = find_fire_angle(target_range, aim_target.y - bullet_pos.y, use_artillery_firing_solution)
|
||||
var azimuth: float = Vector3.FORWARD.signed_angle_to(aim_target-global_position, Vector3.UP)
|
||||
print("Shot params: θ=%d φ=%d" % [rad_to_deg(elevation), rad_to_deg(azimuth)])
|
||||
if elevation < -PI or elevation > PI:
|
||||
print("wtf?? θ=%d" % rad_to_deg(elevation))
|
||||
return
|
||||
fire_direction = Vector3.FORWARD
|
||||
fire_direction = fire_direction.rotated(Vector3(1,0,0), elevation)
|
||||
fire_direction = fire_direction.rotated(Vector3(0,1,0), azimuth)
|
||||
else:
|
||||
fire_direction = (aim_target - bullet_pos).normalized()
|
||||
|
||||
DebugDraw3D.draw_arrow_ray(bullet_pos, fire_direction, target_range, Color.RED, 0.5, true, shot_time)
|
||||
|
||||
bullet.look_at(bullet_pos+fire_direction)
|
||||
bullet.linear_velocity = (-bullet.global_basis.z) * shot_velocity
|
||||
#bullet.apply_impulse((aim_target - bullet.global_position).normalized()*shot_impulse)
|
||||
bullet.angular_velocity = (bullet.global_basis * Vector3(0,0,-10))
|
||||
current_target = null
|
||||
ammo -= 1
|
||||
if ammo <= 0:
|
||||
Engine.time_scale = 1.0
|
||||
loaded = LoadState.UNLOADED
|
||||
|
||||
func find_fire_angle(distance: float, height: float, high_solution: bool = true) -> float:
|
||||
# theta = arctan( ( (v^2) ± sqrt( v^4 - g*( g*x^2 + 2*y*v^2 ) ) ) / g*x )
|
||||
const g: float = 9.8
|
||||
var gx2: float = g * pow(distance, 2)
|
||||
var twoyv2: float = 2 * height * pow(shot_velocity,2)
|
||||
var v2: float = pow(shot_velocity, 2)
|
||||
var v4: float = pow(shot_velocity, 4)
|
||||
|
||||
var arc_x: float = g * distance
|
||||
var arc_y_offs: float = sqrt(v4 - g * (gx2 + twoyv2))
|
||||
var arc_y: float = v2 + arc_y_offs * (1 if high_solution else -1)
|
||||
|
||||
var theta: float = atan2(arc_y, arc_x)
|
||||
return clamp(theta, -PI/2, PI/2)
|
||||
|
|
Loading…
Reference in New Issue