From 74814d722e058339469ef4187107e564d6079d44 Mon Sep 17 00:00:00 2001 From: OddlyTimbot Date: Mon, 15 Jul 2024 13:09:25 -0400 Subject: [PATCH] adding basic example week 1 --- week1/GodotSpeedRun/.gitattributes | 2 + week1/GodotSpeedRun/.gitignore | 2 + week1/GodotSpeedRun/icon.svg | 1 + week1/GodotSpeedRun/icon.svg.import | 37 +++++++ week1/GodotSpeedRun/project.godot | 24 +++++ week1/GodotSpeedRun/scenes/game.tscn | 100 ++++++++++++++++++ .../GodotSpeedRun/scripts/CharacterBody2D.gd | 34 ++++++ week1/GodotSpeedRun/scripts/Trigger.gd | 8 ++ week1/GodotSpeedRun/scripts/gamecontroller.gd | 15 +++ week1/godotintro.md | 26 ++--- 10 files changed, 236 insertions(+), 13 deletions(-) create mode 100644 week1/GodotSpeedRun/.gitattributes create mode 100644 week1/GodotSpeedRun/.gitignore create mode 100644 week1/GodotSpeedRun/icon.svg create mode 100644 week1/GodotSpeedRun/icon.svg.import create mode 100644 week1/GodotSpeedRun/project.godot create mode 100644 week1/GodotSpeedRun/scenes/game.tscn create mode 100644 week1/GodotSpeedRun/scripts/CharacterBody2D.gd create mode 100644 week1/GodotSpeedRun/scripts/Trigger.gd create mode 100644 week1/GodotSpeedRun/scripts/gamecontroller.gd diff --git a/week1/GodotSpeedRun/.gitattributes b/week1/GodotSpeedRun/.gitattributes new file mode 100644 index 0000000..8ad74f7 --- /dev/null +++ b/week1/GodotSpeedRun/.gitattributes @@ -0,0 +1,2 @@ +# Normalize EOL for all files that Git considers text files. +* text=auto eol=lf diff --git a/week1/GodotSpeedRun/.gitignore b/week1/GodotSpeedRun/.gitignore new file mode 100644 index 0000000..4709183 --- /dev/null +++ b/week1/GodotSpeedRun/.gitignore @@ -0,0 +1,2 @@ +# Godot 4+ specific ignores +.godot/ diff --git a/week1/GodotSpeedRun/icon.svg b/week1/GodotSpeedRun/icon.svg new file mode 100644 index 0000000..b370ceb --- /dev/null +++ b/week1/GodotSpeedRun/icon.svg @@ -0,0 +1 @@ + diff --git a/week1/GodotSpeedRun/icon.svg.import b/week1/GodotSpeedRun/icon.svg.import new file mode 100644 index 0000000..d4c54c1 --- /dev/null +++ b/week1/GodotSpeedRun/icon.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://d24mluxxgy878" +path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icon.svg" +dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/week1/GodotSpeedRun/project.godot b/week1/GodotSpeedRun/project.godot new file mode 100644 index 0000000..1ff598a --- /dev/null +++ b/week1/GodotSpeedRun/project.godot @@ -0,0 +1,24 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[application] + +config/name="GodotSpeedRun" +run/main_scene="res://scenes/game.tscn" +config/features=PackedStringArray("4.2", "Forward Plus") +config/icon="res://icon.svg" + +[file_customization] + +folder_colors={ +"res://assets/": "green", +"res://scenes/": "yellow", +"res://scripts/": "red" +} diff --git a/week1/GodotSpeedRun/scenes/game.tscn b/week1/GodotSpeedRun/scenes/game.tscn new file mode 100644 index 0000000..6fb4b9c --- /dev/null +++ b/week1/GodotSpeedRun/scenes/game.tscn @@ -0,0 +1,100 @@ +[gd_scene load_steps=9 format=3 uid="uid://y083suj12rld"] + +[ext_resource type="Script" path="res://scripts/gamecontroller.gd" id="1_77wyw"] +[ext_resource type="Script" path="res://scripts/CharacterBody2D.gd" id="1_u4sui"] +[ext_resource type="Script" path="res://scripts/Trigger.gd" id="2_nfj1w"] + +[sub_resource type="WorldBoundaryShape2D" id="WorldBoundaryShape2D_3u4a8"] + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_4vo4d"] +size = Vector2(55, 55) + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_cq7kj"] +size = Vector2(91, 20) + +[sub_resource type="CircleShape2D" id="CircleShape2D_ubfw4"] +radius = 13.0384 + +[sub_resource type="CircleShape2D" id="CircleShape2D_x8qck"] +radius = 60.2993 + +[node name="Game" type="Node2D"] +script = ExtResource("1_77wyw") + +[node name="StaticBody2D" type="StaticBody2D" parent="."] +position = Vector2(236, 415) +metadata/_edit_group_ = true + +[node name="CollisionShape2D" type="CollisionShape2D" parent="StaticBody2D"] +shape = SubResource("WorldBoundaryShape2D_3u4a8") + +[node name="RigidBody2D" type="RigidBody2D" parent="."] +position = Vector2(87, 18) +rotation = 0.740513 + +[node name="CollisionShape2D" type="CollisionShape2D" parent="RigidBody2D"] +position = Vector2(206.535, 208.174) +rotation = -0.555892 +shape = SubResource("RectangleShape2D_4vo4d") +debug_color = Color(0.815686, 0.4, 0.207843, 0.419608) + +[node name="CollisionShape2D2" type="CollisionShape2D" parent="RigidBody2D"] +position = Vector2(206.535, 208.174) +rotation = -0.555892 +shape = SubResource("RectangleShape2D_4vo4d") +debug_color = Color(0.815686, 0.4, 0.207843, 0.419608) + +[node name="groundblock" type="StaticBody2D" parent="."] +position = Vector2(124, 357) +metadata/_edit_group_ = true + +[node name="CollisionShape2D" type="CollisionShape2D" parent="groundblock"] +position = Vector2(-1.5, 0) +shape = SubResource("RectangleShape2D_cq7kj") + +[node name="groundblock2" type="StaticBody2D" parent="."] +position = Vector2(91, 430) +scale = Vector2(3.76, 1) +metadata/_edit_group_ = true + +[node name="CollisionShape2D" type="CollisionShape2D" parent="groundblock2"] +position = Vector2(-1.5, 0) +shape = SubResource("RectangleShape2D_cq7kj") + +[node name="level" type="Node2D" parent="."] + +[node name="groundblock2" type="StaticBody2D" parent="level"] +position = Vector2(548, 315) +metadata/_edit_group_ = true + +[node name="CollisionShape2D" type="CollisionShape2D" parent="level/groundblock2"] +position = Vector2(-1.5, 0) +shape = SubResource("RectangleShape2D_cq7kj") + +[node name="groundblock3" type="StaticBody2D" parent="level"] +position = Vector2(404, 353) +metadata/_edit_group_ = true + +[node name="CollisionShape2D" type="CollisionShape2D" parent="level/groundblock3"] +position = Vector2(-1.5, 0) +shape = SubResource("RectangleShape2D_cq7kj") + +[node name="CharacterBody2D" type="CharacterBody2D" parent="."] +position = Vector2(155, 328) +script = ExtResource("1_u4sui") +metadata/_edit_group_ = true + +[node name="CollisionShape2D" type="CollisionShape2D" parent="CharacterBody2D"] +shape = SubResource("CircleShape2D_ubfw4") + +[node name="Area2D" type="Area2D" parent="."] +position = Vector2(260, 352) +script = ExtResource("2_nfj1w") +metadata/_edit_group_ = true + +[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"] +shape = SubResource("CircleShape2D_x8qck") +debug_color = Color(0.556863, 0.415686, 0.964706, 0.419608) + +[connection signal="areatrigger" from="Area2D" to="." method="_on_area_2d_areatrigger"] +[connection signal="body_entered" from="Area2D" to="Area2D" method="_on_body_entered"] diff --git a/week1/GodotSpeedRun/scripts/CharacterBody2D.gd b/week1/GodotSpeedRun/scripts/CharacterBody2D.gd new file mode 100644 index 0000000..04d8501 --- /dev/null +++ b/week1/GodotSpeedRun/scripts/CharacterBody2D.gd @@ -0,0 +1,34 @@ +extends CharacterBody2D + + +const SPEED = 300.0 +const JUMP_VELOCITY = -300.0 +const PUSH_FORCE = 50 + +# Get the gravity from the project settings to be synced with RigidBody nodes. +var gravity = ProjectSettings.get_setting("physics/2d/default_gravity") + + +func _physics_process(delta): + # Add the gravity. + if not is_on_floor(): + velocity.y += gravity * delta + + # Handle jump. + if Input.is_action_just_pressed("ui_accept") and is_on_floor(): + velocity.y = JUMP_VELOCITY + + # Get the input direction and handle the movement/deceleration. + # As good practice, you should replace UI actions with custom gameplay actions. + var direction = Input.get_axis("ui_left", "ui_right") + if direction: + velocity.x = direction * SPEED + else: + velocity.x = move_toward(velocity.x, 0, SPEED) + + move_and_slide() + for i in get_slide_collision_count(): + var c = get_slide_collision(i) + if c.get_collider() is RigidBody2D: + c.get_collider().apply_central_impulse(-c.get_normal() * PUSH_FORCE) + diff --git a/week1/GodotSpeedRun/scripts/Trigger.gd b/week1/GodotSpeedRun/scripts/Trigger.gd new file mode 100644 index 0000000..cd8dc49 --- /dev/null +++ b/week1/GodotSpeedRun/scripts/Trigger.gd @@ -0,0 +1,8 @@ +extends Area2D + +@export var effect = "alert" +signal areatrigger(effect, Object) + +func _on_body_entered(body): + print("detected a body") + areatrigger.emit(effect, body) diff --git a/week1/GodotSpeedRun/scripts/gamecontroller.gd b/week1/GodotSpeedRun/scripts/gamecontroller.gd new file mode 100644 index 0000000..0ad265d --- /dev/null +++ b/week1/GodotSpeedRun/scripts/gamecontroller.gd @@ -0,0 +1,15 @@ +extends Node2D + + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass + + +func _on_area_2d_areatrigger(effect, Object): + print("Game Controller sees the trigger") diff --git a/week1/godotintro.md b/week1/godotintro.md index 5eeab65..24f0ccf 100644 --- a/week1/godotintro.md +++ b/week1/godotintro.md @@ -133,7 +133,7 @@ Tip: Besides your main game, and your character scene, set yourself up with a ve By setting up a ‘test room’ like this you will not need to launch your full game with all of it’s graphics, sounds, lighting etc. when all you need is to test some features in isolation. -Nodes and Scenes (Composition) +### Nodes and Scenes (Composition) From our quick review of the interface, you’ll have noticed that a fair amount of the editor is set up for managing “scenes”, and you’ll quickly learn that scenes are composed of “nodes”. @@ -149,16 +149,16 @@ In our example, you would develop the car scene by using “nodes”. In Godot, nodes are discrete reusable bits of functionality intended to be used across many scenes for describing the features of the scene. Because nodes are the essential building blocks of a game, they get grouped into categories based on their intended purpose. Some are for showing graphics, others relate to the physics engine, lighting, UI, networking functions and anything else you could think of. Some very common nodes you will use include: -Sprite nodes - allow you to show an image in the scene -Animated sprite nodes - show sequences of images -Collision Shape nodes - detect intersection with other objects -Control nodes - show user interface, accept input +* Sprite nodes - allow you to show an image in the scene +* Animated sprite nodes - show sequences of images +* Collision Shape nodes - detect intersection with other objects +* Control nodes - show user interface, accept input A very common “recipe” for a scene is to include this mix of nodes -A 2D or 3D node that includes a “transform” - information about the position, size, and scale of an object -A sprite or mesh node that shows a game asset like an image or 3D model -A collider node that interacts with the physics engine to notice collisions -A script that defines the behaviour of the scene using code for decision-making +* A 2D or 3D node that includes a “transform” - information about the position, size, and scale of an object +* A sprite or mesh node that shows a game asset like an image or 3D model +* A collider node that interacts with the physics engine to notice collisions +* A script that defines the behaviour of the scene using code for decision-making In that recipe, each node in the scene has a specific job to do. The 2DNode positions the object in space and keeps track of where it is positioned. @@ -216,7 +216,7 @@ Impulse - a temporary motivator, delivered as a pulse (think a kick, shove, shot The big four allow us to be the laws of fixes regarding imparting forces and impulses in the following ways. -Static Body +### Static Body A static body allows physics to register interactions, but does not allow the physics engine to employ a reaction to those interactions. Their transform can not be affected by collision with other bodies. @@ -225,7 +225,7 @@ Uses: these are excellent bodies to use for building out the game world. Floors, Exercise 1: Create a floor boundary object for our game world Exercise 2: Create a reusable block for walls, platforms, etc. -Rigid Body +### Rigid Body The rigid body IS affected by the physics engine, both in terms of detecting collisions and reacting to them. Rigid bodies transforms can be affected by collisions that impart either a force or an impulse to them. @@ -236,7 +236,7 @@ Uses: bullets that ricochet, debris, interactable objects Exercise 1: Create a “crate” that conforms to physics Exercise 2: Make the crate its own scene, and duplicate it to produce more crates -Character Body +### Character Body Character bodies, as their name implies, are used for players and often for non-player characters such as enemies. Character bodies, like static bodies, do not react to physics, though they can trigger collisions. Think of them like feather-light objects moving through the game world, unable to push anything in their way. @@ -250,7 +250,7 @@ Exercise 1: Use a default script template to give movement to a player object Exercise 2: Use code to impart a physics impulse to crates (rigid bodies) as the player moves around Optional: Improve upon the default movement template -Areas +### Areas Areas are different than other bodies in that they are not usually intended to have any visible graphics associated with them. They need only a collider and they can then detect collisions, and even the state of the collisions i.e. detecting when a body has entered an area, or left it.