This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
godot [2024/03/18 12:29] admin |
godot [2024/04/08 19:33] (current) admin |
||
---|---|---|---|
Line 1: | Line 1: | ||
====== Getting Started with Godot ====== | ====== Getting Started with Godot ====== | ||
+ | This event runs monthly on the **2nd Monday** of the month. See the [[start|home page]] for the date of our next monthly event. | ||
For our regular monthly tutorial nights, we're basing our teaching on the wonderful series by [[https://www.youtube.com/@AJsLearningLab|AJ's Learning Lab]], [[https://www.youtube.com/playlist?list=PL4vjw0qHwNZIQZScBFaON0WGkz-BMyoCh|Godot FPS Tutorial - Learn Godot by making Wolfenstein 3D]]. | For our regular monthly tutorial nights, we're basing our teaching on the wonderful series by [[https://www.youtube.com/@AJsLearningLab|AJ's Learning Lab]], [[https://www.youtube.com/playlist?list=PL4vjw0qHwNZIQZScBFaON0WGkz-BMyoCh|Godot FPS Tutorial - Learn Godot by making Wolfenstein 3D]]. | ||
Line 42: | Line 43: | ||
* In the world scene, drag the player scene into the world | * In the world scene, drag the player scene into the world | ||
* In the three dot menu (world scene), use 'Add Sun to scene', 'add environment to scene' | * In the three dot menu (world scene), use 'Add Sun to scene', 'add environment to scene' | ||
- | * In the player scene, use the Mesh button to add a 'Simplified Convext Collision Sibling' mesh to the player's MeshInstance3D | + | * In the player scene, use the Mesh button to add a 'Simplified Convex Collision Sibling' mesh to the player's MeshInstance3D (not 'Single', that'll cause performance issues - why?) |
* Set up WASD controls in the Project Settings | * Set up WASD controls in the Project Settings | ||
Line 131: | Line 132: | ||
if Global.current_weapon != "knife" and Global.ammo <= 0: | if Global.current_weapon != "knife" and Global.ammo <= 0: | ||
Global.current_weapon = "knife" | Global.current_weapon = "knife" | ||
- | $AnimatedSprite2D.player("knife_idle") | + | $AnimatedSprite2D.play("knife_idle") |
</code> | </code> | ||
* Tweak first if statement, change to: | * Tweak first if statement, change to: | ||
Line 278: | Line 279: | ||
$CollisionShape3D.disabled = true | $CollisionShape3D.disabled = true | ||
+ | </code> | ||
+ | ==== Part 8 ==== | ||
+ | **Goal: Enemy Death and Raycasting** | ||
+ | * Edit the ui.gd script. Tweak the can_shoot variable, set it in the object scope (top) and remove "var" from "var can_shoot" from the _process() | ||
+ | * Access the 3D view of the player. Add a new node as a child of the camera 3D, type: RayCast3D | ||
+ | * Set the target position to y:0, z: -20 | ||
+ | * Make sure the raycast has access to collision mask layers 1+2 | ||
+ | * Check the guard scene, collision should be on layer 2, mask 1+2 | ||
+ | * Check Player is layer 1, mask is 1+2 | ||
+ | * Edit the player script, add new const at the top | ||
+ | <code> | ||
+ | @onready var ui_script = $ui | ||
+ | @onready var ray = $Camera3D/RayCast3D | ||
+ | </code> | ||
+ | * At the bottom, just above move_and_slide(), add the following code: | ||
+ | <code> | ||
+ | if Input.is_action_just_pressed("ui_accept"): | ||
+ | if ui_script.can_shoot: | ||
+ | shoot() | ||
+ | </code> | ||
+ | * Add the shoot function | ||
+ | <code bash> | ||
+ | func shoot(): | ||
+ | if ray.is_colliding() and ray.get_collider().has_method("die"): | ||
+ | ray.get_collider().die() | ||
+ | </code> | ||
+ | * To allow strafing, change the ''If Input.is_action_just_pressed("ui_accept"):'' to | ||
+ | <code> | ||
+ | if Input.is_action_pressed("ui_accept"): | ||
+ | </code> | ||
+ | |||
+ | ===== Part 9 ===== | ||
+ | **Goal: HUD labels and player death** | ||
+ | * Add a player health variable to the player.gd script | ||
+ | <code> | ||
+ | var player_health = 100 | ||
+ | </code> | ||
+ | * Create two new Label nodes as a child of the UI, name one 'health'. | ||
+ | * Create a new function in the ui.gd script | ||
+ | <code> | ||
+ | function update_player_health(): | ||
+ | $health.text = str(get_parent().player_health) | ||
+ | </code> | ||
+ | * Add the function to the bottom of the _process() function in the ui.gd script | ||
+ | <code> | ||
+ | update_player_health() | ||
+ | </code> | ||
+ | * Edit the player script and add a new function: | ||
+ | <code> | ||
+ | func damage(): | ||
+ | player_health -= 10 | ||
+ | print(player_health) | ||
+ | if player_health <= 0: | ||
+ | queue_free() | ||
+ | </code> | ||
+ | * Add a RayCast3D to the guard scene | ||
+ | * Set Y = 0, Z = 5 | ||
+ | * After the ''play(shoot)'' line in the attack() function, add: | ||
+ | <code> | ||
+ | if $RayCast3D.is_colliding() and $RayCast3D.get_collider().has_method('damage'): | ||
+ | $RayCast3D.get_collider().damage() | ||
+ | </code> | ||
+ | |||
+ | ===== Part 10 ===== | ||
+ | **Goal: Ammo pickups** | ||
+ | |||
+ | |||
+ | ===== Next Steps ===== | ||
+ | **Goal: Add sound effects** | ||
+ | * Import the sound effect files (gun.ogg, machine.ogg, mini.ogg) | ||
+ | * In the player scene, add a new node, AudioStreamPlayer. | ||
+ | * Add the following code to the player shoot() function: | ||
+ | <code> | ||
+ | var sound_player = $AudioStreamPlayer | ||
+ | match Global.current_weapon: | ||
+ | "gun": | ||
+ | sound_player.stream = preload("res://gun.ogg") | ||
+ | "machine": | ||
+ | sound_player.stream = preload("res://machine.ogg") | ||
+ | "mini": | ||
+ | sound_player.stream = preload("res://mini.ogg") | ||
+ | sound_player.play() | ||
</code> | </code> |