This is an old revision of the document!
For our regular monthly tutorial nights, we're basing our teaching on the wonderful series by AJ's Learning Lab, Godot FPS Tutorial - Learn Godot by making Wolfenstein 3D.
He has made the assets he uses freely available (please consider donating) here: https://ajslearninglab.itch.io/boganstein-3d-learn-godot-4-with-wolfenstein-3d/
All the code we use is available on AJ's Learning Lab github - https://github.com/AJsLearningLab/GodotFPS
Goal: Learn about Godot, create a world/room (floor and walls)
extends CanvasLayer
var ammo = 0
var current_weapon = "knife"
func _ready():
$AnimatedSprite2D.animation_finished.connect(_on_AnimatedSprite2D_animation_finished)
func _process(delta):
if Input.is_action_just_pressed("ui_select"):
if current_weapon == "knife":
$AnimatedSprite2D.play("stab")
elif current_weapon == "gun":
if ammo > 0:
$AnimatedSprite2D.play("shoot")
ammo -= 1
func _on_AnimatedSprite2D_animation_finished():
if current_weapon == "knife":
$AnimatedSprite2D.play("knife_idle")
elif current_weapon == "gun":
$AnimatedSprite2D.play("gun_idle")
extends CharacterBody3D
@onready var player : CharacterBody3D = get_tree().get_first_node_in_group("player")
const SPEED = 5.0
var gravity = ProjectSettings.get_setting("physics/3d/default_gravity") # Get the gravity from the project settings to be synced with RigidBody nodes.
var dead = false
var is_attacking = false
var attack_range = 5
func _ready():
add_to_group("enemy")
func _physics_process(delta):
if dead or is_attacking: # Check if the enemy is dead or attacking
return
if player == null:
return
var dir = player.global_position - global_position
dir.y = 0.0
dir = dir.normalized()
velocity = dir * SPEED
# Add the gravity.
if not is_on_floor():
velocity.y -= gravity * delta
move_and_slide()
attack()
func attack():
var dist_to_player = global_position.distance_to(player.global_position)
if dist_to_player > attack_range:
return
else:
is_attacking = true # Set the attacking flag
$AnimatedSprite3D.play("shoot")
await $AnimatedSprite3D.animation_finished # Wait for the animation to finish
is_attacking = false # Reset the attacking flag
func die():
dead = true # Corrected variable scope
$AnimatedSprite3D.play("die")
$CollisionShape3D.disabled = true