Attention | Topic was automatically imported from the old Question2Answer platform. | |
Asked By | unwiseone |
I’m trying to create a laser weapon for my game but I’ve been struggling to get both the damage (raycast) and beam (Line2D) to both go to the correct target position. Currently, the the Line2D representing the beam is drawing in the correction direction, but when the player fires any direction other than towards (1, 0), the raycast doesn’t appear to cast in the expected direction.
I think I’ve narrowed the problem to how I am applying transforms to the raycast and the Line2D, but I’ve reached end of my knowledge on how to proceed further to correct it. This the relevant part of the player scene:
- Player (KinematicBody2D; scene root)
- BodyPivot (Position2D)
- Body (Sprite)
- CurrentWeaponSprite (Sprite)
- Muzzle (Position2D)
- Inventory (Node)
- LaserRifle (Area2D; scene instance)
- Sprite
The ‘CurrentWeaponSprite’ node rotates like turret to aim wherever the player moves the mouse, while all the other node do not rotate.
I’m using the following code:
"""LaserRifle.gd"""
extends Area2D
var DAMAGE = 5
shot_duration = 0.25
knockback_speed = 50
knockback_duration = 0.12
stun_duration = 0.25
var beam
var beam_color = Color.crimson
func shoot(projectile_start_position):
muzzle_position = projectile_start_position
var result = _cast_ray(muzzle_position)
if result:
_create_beam(muzzle_position, result)
_inflict_damage(result)
yield(get_tree().create_timer(shot_duration), "timeout")
_destroy_beam()
func _cast_ray(projectile_start_position):
var CurrentWeaponSprite = CarriedBy.current_weapon_sprite()
var space_state = get_world_2d().direct_space_state
var result = space_state.intersect_ray(projectile_start_position, projectile_start_position + CarriedBy.transform.x * 1000, [self, CarriedBy])
func _create_beam(muzzle_position, result):
var CurrentWeaponSprite = CarriedBy.current_weapon_sprite() # The var CarriedBy is a reference to the 'actor' using the weapon.
beam = Line2D.new()
CurrentWeaponSprite.get_node("Muzzle").add_child(beam) # 'Muzzle' node is a Position2D node.
beam.width = 2
beam.default_color = beam_color
beam.end_cap_mode = Line2D.LINE_CAP_ROUND
beam.add_point(CurrentWeaponSprite.get_node("Muzzle").position)
beam.add_point(CarriedBy.transform.xform_inv(result.position))global coordiantes to local.
func _destroy_beam():
beam.queue_free()
func _inflict_damage(collision_info):
if collision_info.collider.has_node("Health"):
collision_info.collider.take_damage(DAMAGE, self, stun_duration, knockback_speed, knockback_duration)
Any suggestions on how I might fix this issue?
Note that:
beam.add_point(CurrentWeaponSprite.get_node("Muzzle").position)
beam.add_point(CarriedBy.transform.xform_inv(result.position))global coordiantes to local.
Because you put the beam as child of the muzzle shooting it, none of that code is required, because the beam already rotates based on where that weapon is looking at. It might as well be this:
beam.add_point(Vector2(0, 0))
beam.add_point(Vector2(1000, 0))
Are you sure your raycast is shooting at the right direction? Try to print its positions to make sure. If they are correct, your problem is the line.
Zylann | 2019-09-06 12:54
On r/Godot, someone suggested changing CarriedBy.transform.x
to CarriedBy.global_transform.x
. With that change, the raycast is now firing in the correct direction. I confirmed this by adding the following two lines to the end of the ‘_cast_ray()’ function, before the return…
if result:
_debug_draw_triangle(result.position)
… with this function definition…
func _debug_draw_triangle(hit_result_position):
var triangle = Polygon2D.new()
LevelYSort.add_child(triangle) # LevelYSort is "get_node('/root/Level/YSort')".
triangle.global_position = hit_result_position
triangle.polygon = [Vector2(0, 0), Vector2(-5, 10), Vector2(5, 10)]
I’m still trying to figure out the correct transform for drawing the Line2D beam’s second point (i.e. ‘endpoint’), however. I’ll experiment further and hopeful stumble across a solution.
unwiseone | 2019-09-08 21:03