Create Your First Godot 4 Game

Lesson 9: Creating the player projectile

Video Notes

It’s time for the bad guys to meet a fiery end. We’re going to give our raptor an explosive fireball to shoot.

Corrections:

In Godot 4 Beta 16 or higher, the AnimatedSprite2D’s Playing checkbox has been removed from the Inspector. It has been replaced by the Autoplay button, which can be found in SpriteFrames panel next to the trashcan icon.


After you add the player’s projectile, you might notice an error in the console: Move functions do not work together with ‘sync to physics’ option. To fix this, open the Projectile scene, select the Projectile node, and uncheck the Sync to Physics option in the Inspector.


There’s a small bug in the video where you can still shoot while the Player is dying. Luckily, there is an easy fix. You can change this line:

if event.is_action_pressed("fire") and ammo > 0:

to:

if event.is_action_pressed("fire") and ammo > 0 and active == true:

  • Lefterispap
    Nov. 7, 2022 at 7:23 p.m.

    Hey, In my projectile script when I move it with the move_and_collide() method it keeps throwing errors.

    E 0:00:00:0488   _physics_process: Move functions do not work together with 'sync to physics' option. Please read the documentation.
      <C++ Source>   scene/2d/physics_body_2d.cpp:79 @ move_and_collide()
      <Stack Trace>  projectile.gd:20 @ _physics_process()
    
    • amit
      Nov. 8, 2022 at 12:35 a.m.

      According to the documentation, you can’t use move_and_collide() with “Sync to Physics” turned on. Can you try turning off “Sync to Physics” in the inspector? Also, which version of Godot are using?


  • ManoShu
    Oct. 21, 2023 at 12:29 a.m.

    Weirdly the hit animation for the projectile was unused, when the collision happens it just removes the node.

    Here is my complete projectile script, it look a little awkward (something could be done to have it “stuck” position-wise to whatever it collided, but in this case I deemed it good enough):

    extends AnimatableBody2D
    
    var death_time = 0
    
    const PROJECTILE_SPEED = 1000
    
    @onready var sprite = $AnimatedSprite2D
    
    # Called when the node enters the scene tree for the first time.
    func _ready():
    	death_time = Time.get_ticks_msec() + 2000
    
    
    # Called every frame. 'delta' is the elapsed time since the previous frame.
    func _process(delta):
    	if(Time.get_ticks_msec() > death_time):
    		queue_free()
    
    func _physics_process(delta):
    	# if we are on the hit animation there is no need to move it further
    	if (sprite.animation == "hit"):
    		return
    		
    	var distance = Vector2.RIGHT * PROJECTILE_SPEED * delta
    	var collision = move_and_collide(distance)
    	if collision:
    		sprite.play("hit")
    		sprite.animation_finished.connect(_on_animation_finished)
    		
    		if(collision.get_collider().is_in_group("enemy")):
    			collision.get_collider().die()
    
    func _on_animation_finished():
    	queue_free()
    
    • amit
      Oct. 23, 2023 at 2:39 p.m.

      Thanks for the contribution! We couldn’t squeeze everything we wanted to in this short tutorial, so thanks for showing other people how to implement this.

Want to get into the mix? Sign in or register to comment.

Next lesson