├── DOWNLOAD_THIS.zip ├── README.md ├── Scenes ├── Inventory_Item.tscn ├── Inventory_Slot.tscn ├── Inventory_UI.tscn ├── Main.tscn ├── Player.tscn └── TileMap.tscn ├── Scripts ├── Global.gd ├── Inventory_Item.gd ├── Inventory_Slot.gd ├── Inventory_UI.gd ├── Main.gd └── Player.gd └── Sectional_Code ├── 01 - Project and Player Setup └── Scripts │ ├── Main.gd │ └── Player.gd ├── 02 - Inventory Manager └── Scripts │ ├── Global.gd │ ├── Main.gd │ └── Player.gd ├── 03 - Inventory Item - Part One └── Scripts │ ├── Global.gd │ ├── Inventory_Item.gd │ ├── Main.gd │ └── Player.gd ├── 04 - Inventory Item - Part Two └── Scripts │ ├── Global.gd │ ├── Inventory_Item.gd │ ├── Main.gd │ └── Player.gd ├── 05 - Inventory UI └── Scripts │ ├── Global.gd │ ├── Inventory_Item.gd │ ├── Inventory_UI.gd │ ├── Main.gd │ └── Player.gd ├── 06 - Inventory Slots (Creation) └── Scripts │ ├── Global.gd │ ├── Inventory_Item.gd │ ├── Inventory_Slot.gd │ ├── Inventory_UI.gd │ ├── Main.gd │ └── Player.gd ├── 07 - Inventory Slots (Adding Items) └── Scripts │ ├── Global.gd │ ├── Inventory_Item.gd │ ├── Inventory_Slot.gd │ ├── Inventory_UI.gd │ ├── Main.gd │ └── Player.gd ├── 08 - Inventory Slots (Dropping Items) └── Scripts │ ├── Global.gd │ ├── Inventory_Item.gd │ ├── Inventory_Slot.gd │ ├── Inventory_UI.gd │ ├── Main.gd │ └── Player.gd ├── 09 - Using Inventory Items └── Scripts │ ├── Global.gd │ ├── Inventory_Item.gd │ ├── Inventory_Slot.gd │ ├── Inventory_UI.gd │ ├── Main.gd │ └── Player.gd ├── 10 - Spawning Items └── Scripts │ ├── Global.gd │ ├── Inventory_Item.gd │ ├── Inventory_Slot.gd │ ├── Inventory_UI.gd │ ├── Main.gd │ └── Player.gd ├── 11 - Hotbar - Part 1 └── Scripts │ ├── Global.gd │ ├── Inventory_Hotbar.gd │ ├── Inventory_Item.gd │ ├── Inventory_Slot.gd │ ├── Inventory_UI.gd │ ├── Main.gd │ └── Player.gd ├── 12 - Hotbar - Part 2 ├── Scenes │ ├── Inv21E0.tmp │ ├── Inventory_Hotbar.tscn │ ├── Inventory_Item.tscn │ ├── Inventory_Slot.tscn │ ├── Inventory_UI.tscn │ ├── Main.tscn │ ├── Player.tscn │ └── TileMap.tscn └── Scripts │ ├── Global.gd │ ├── Inventory_Hotbar.gd │ ├── Inventory_Item.gd │ ├── Inventory_Slot.gd │ ├── Inventory_UI.gd │ ├── Main.gd │ └── Player.gd ├── 13 - Draggable Inventory └── Scripts │ ├── Global.gd │ ├── Inventory_Hotbar.gd │ ├── Inventory_Item.gd │ ├── Inventory_Slot.gd │ ├── Inventory_UI.gd │ ├── Main.gd │ └── Player.gd └── 14 - Draggable Hotbar └── Scripts ├── Global.gd ├── Inventory_Hotbar.gd ├── Inventory_Item.gd ├── Inventory_Slot.gd ├── Inventory_UI.gd ├── Main.gd └── Player.gd /DOWNLOAD_THIS.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/christinec-dev/GodotInventorySystem/85c2e69062bb1d61985c04b90f8db42e568a4d37/DOWNLOAD_THIS.zip -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Godot Inventory System 2 | This is the final source code for my Godot Inventory System series that I made for my YouTube channel. It consists of a slot-based inventory system where players can add, remove, or use items. 😊 3 | 4 | ## Resources 5 | - [Excalidraw Board](https://excalidraw.com/#json=cjPPFEnlQM-7r-plC8UJ4,iX6E_Q0e7USp2IAlVJQM5g) 6 | 7 | ## Outline of Features/Functionalities of this System 8 | #### Dynamic Inventory Management 9 | - Players can pick up, use, and drop items. 10 | - Inventory slots display item details and quantities. 11 | - Items have types, effects, and can be stacked based on type and effect. 12 | 13 | #### Interactive Game World 14 | - Items can be spawned in the game world. 15 | - Players interact with items to add them to their inventory. 16 | 17 | #### UI Integration 18 | - Inventory UI with grid layout for item slots. 19 | - Detailed view of item information on hover or selection. 20 | - Buttons for using or dropping items from the inventory. 21 | 22 | #### Player Interaction 23 | - Player character can move and interact with items. 24 | - Inventory access and item usage are linked to player actions. 25 | 26 | #### Global Management 27 | - Centralized management of inventory and player references. 28 | - Signals for updating UI when inventory changes. 29 | 30 | ## Inventory Preview 31 | ![image](https://github.com/christinec-dev/GodotInventorySystem/assets/87696858/d0c0023f-ce75-4e65-8d2b-93ce11953df3) 32 | ![image](https://github.com/christinec-dev/GodotInventorySystem/assets/87696858/6a63bf91-5dbb-4a6f-9b9a-2d1462ee521a) 33 | ![image](https://github.com/christinec-dev/GodotInventorySystem/assets/87696858/6b47e640-0f8c-4399-98b1-6c27abf3004b) 34 | ![image](https://github.com/christinec-dev/GodotInventorySystem/assets/87696858/a623b0b9-a55a-4da0-9449-9e425cfe46da) 35 | ![image](https://github.com/christinec-dev/GodotInventorySystem/assets/87696858/0615ede6-2af9-4a21-aaca-c41c87add9c2) 36 | 37 | ## Asset Creditations 38 | - [https://seliel-the-shaper.itch.io/character-base](https://seliel-the-shaper.itch.io/character-base) 39 | - [https://quintino-pixels.itch.io/assorted-icons](https://quintino-pixels.itch.io/assorted-icons) 40 | - [Sprout Lands - Asset Pack by Cup Nooble (itch.io)](https://cupnooble.itch.io/sprout-lands-asset-pack) 41 | -------------------------------------------------------------------------------- /Scenes/Inventory_Item.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=3 uid="uid://mfeavq58ovhk"] 2 | 3 | [ext_resource type="Script" path="res://Scripts/Inventory_Item.gd" id="1_ckp2a"] 4 | 5 | [sub_resource type="CircleShape2D" id="CircleShape2D_m1ro3"] 6 | 7 | [node name="Inventory_Item" type="Node2D" groups=["Items"]] 8 | script = ExtResource("1_ckp2a") 9 | 10 | [node name="Area2D" type="Area2D" parent="."] 11 | 12 | [node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"] 13 | shape = SubResource("CircleShape2D_m1ro3") 14 | 15 | [node name="Sprite2D" type="Sprite2D" parent="."] 16 | 17 | [connection signal="body_entered" from="Area2D" to="." method="_on_area_2d_body_entered"] 18 | [connection signal="body_exited" from="Area2D" to="." method="_on_area_2d_body_exited"] 19 | -------------------------------------------------------------------------------- /Scenes/Inventory_Slot.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=3 uid="uid://dqi854bvo43n5"] 2 | 3 | [ext_resource type="Script" path="res://Scripts/Inventory_Slot.gd" id="1_jht5t"] 4 | [ext_resource type="Texture2D" uid="uid://dswd2isskfmyr" path="res://Assets/Assets/Icons/icon10.png" id="2_4edl2"] 5 | [ext_resource type="FontFile" uid="uid://bi04iecmbt37l" path="res://Assets/Assets/Fonts/ARCADECLASSIC.TTF" id="3_kbu0m"] 6 | 7 | [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_kbdgs"] 8 | 9 | [node name="Inventory_Slot" type="Control"] 10 | custom_minimum_size = Vector2(150, 150) 11 | layout_mode = 3 12 | anchors_preset = 0 13 | offset_left = 10.0 14 | offset_top = 10.0 15 | offset_right = 160.0 16 | offset_bottom = 160.0 17 | script = ExtResource("1_jht5t") 18 | 19 | [node name="OuterBorder" type="ColorRect" parent="."] 20 | layout_mode = 1 21 | anchors_preset = 15 22 | anchor_right = 1.0 23 | anchor_bottom = 1.0 24 | grow_horizontal = 2 25 | grow_vertical = 2 26 | color = Color(0.596078, 0.933333, 0.8, 1) 27 | 28 | [node name="InnerBorder" type="ColorRect" parent="."] 29 | layout_mode = 1 30 | anchors_preset = 8 31 | anchor_left = 0.5 32 | anchor_top = 0.5 33 | anchor_right = 0.5 34 | anchor_bottom = 0.5 35 | offset_left = -70.0 36 | offset_top = -70.0 37 | offset_right = 70.0 38 | offset_bottom = 70.0 39 | grow_horizontal = 2 40 | grow_vertical = 2 41 | color = Color(0.611765, 0.603922, 0.584314, 1) 42 | 43 | [node name="ItemIcon" type="Sprite2D" parent="InnerBorder"] 44 | position = Vector2(70, 70) 45 | scale = Vector2(2.5, 2.5) 46 | texture = ExtResource("2_4edl2") 47 | 48 | [node name="ItemQuantity" type="Label" parent="InnerBorder"] 49 | layout_mode = 0 50 | offset_left = 5.0 51 | offset_right = 45.0 52 | offset_bottom = 54.0 53 | theme_override_colors/font_color = Color(0.0745098, 0.0745098, 0.0745098, 1) 54 | theme_override_fonts/font = ExtResource("3_kbu0m") 55 | theme_override_font_sizes/font_size = 50 56 | text = "1" 57 | 58 | [node name="ItemButton" type="Button" parent="."] 59 | layout_mode = 1 60 | anchors_preset = 15 61 | anchor_right = 1.0 62 | anchor_bottom = 1.0 63 | grow_horizontal = 2 64 | grow_vertical = 2 65 | theme_override_styles/normal = SubResource("StyleBoxEmpty_kbdgs") 66 | 67 | [node name="DetailsPanel" type="ColorRect" parent="."] 68 | visible = false 69 | layout_mode = 0 70 | offset_top = -135.0 71 | offset_right = 240.0 72 | offset_bottom = -5.0 73 | color = Color(0.596078, 0.933333, 0.8, 1) 74 | 75 | [node name="ItemName" type="Label" parent="DetailsPanel"] 76 | layout_mode = 1 77 | offset_left = 5.0 78 | offset_right = 45.0 79 | offset_bottom = 23.0 80 | theme_override_colors/font_color = Color(0.0745098, 0.0745098, 0.0745098, 1) 81 | theme_override_fonts/font = ExtResource("3_kbu0m") 82 | theme_override_font_sizes/font_size = 40 83 | text = "Name" 84 | 85 | [node name="ItemType" type="Label" parent="DetailsPanel"] 86 | layout_mode = 1 87 | anchors_preset = 4 88 | anchor_top = 0.5 89 | anchor_bottom = 0.5 90 | offset_left = 5.0 91 | offset_top = -11.5 92 | offset_right = 45.0 93 | offset_bottom = 11.5 94 | grow_vertical = 2 95 | theme_override_colors/font_color = Color(0.0745098, 0.0745098, 0.0745098, 0.784314) 96 | theme_override_fonts/font = ExtResource("3_kbu0m") 97 | theme_override_font_sizes/font_size = 40 98 | text = "Type" 99 | 100 | [node name="ItemEffect" type="Label" parent="DetailsPanel"] 101 | layout_mode = 1 102 | anchors_preset = 2 103 | anchor_top = 1.0 104 | anchor_bottom = 1.0 105 | offset_left = 5.0 106 | offset_top = -23.0 107 | offset_right = 45.0 108 | grow_vertical = 0 109 | theme_override_colors/font_color = Color(0.0745098, 0.0745098, 0.0745098, 0.588235) 110 | theme_override_fonts/font = ExtResource("3_kbu0m") 111 | theme_override_font_sizes/font_size = 40 112 | text = "Effect" 113 | 114 | [node name="UsagePanel" type="ColorRect" parent="."] 115 | visible = false 116 | layout_mode = 0 117 | offset_top = -135.0 118 | offset_right = 240.0 119 | offset_bottom = -5.0 120 | color = Color(0.596078, 0.933333, 0.8, 1) 121 | 122 | [node name="UseButton" type="Button" parent="UsagePanel"] 123 | layout_mode = 1 124 | anchors_preset = 5 125 | anchor_left = 0.5 126 | anchor_right = 0.5 127 | offset_left = -115.0 128 | offset_top = 10.0 129 | offset_right = 115.0 130 | offset_bottom = 53.0 131 | grow_horizontal = 2 132 | theme_override_fonts/font = ExtResource("3_kbu0m") 133 | theme_override_font_sizes/font_size = 40 134 | text = "Use" 135 | 136 | [node name="DropButton" type="Button" parent="UsagePanel"] 137 | layout_mode = 1 138 | anchors_preset = 7 139 | anchor_left = 0.5 140 | anchor_top = 1.0 141 | anchor_right = 0.5 142 | anchor_bottom = 1.0 143 | offset_left = -115.0 144 | offset_top = -59.0 145 | offset_right = 115.0 146 | offset_bottom = -16.0 147 | grow_horizontal = 2 148 | grow_vertical = 0 149 | theme_override_fonts/font = ExtResource("3_kbu0m") 150 | theme_override_font_sizes/font_size = 40 151 | text = "Drop" 152 | 153 | [connection signal="mouse_entered" from="ItemButton" to="." method="_on_item_button_mouse_entered"] 154 | [connection signal="mouse_exited" from="ItemButton" to="." method="_on_item_button_mouse_exited"] 155 | [connection signal="pressed" from="ItemButton" to="." method="_on_item_button_pressed"] 156 | [connection signal="pressed" from="UsagePanel/UseButton" to="." method="_on_use_button_pressed"] 157 | [connection signal="pressed" from="UsagePanel/DropButton" to="." method="_on_drop_button_pressed"] 158 | -------------------------------------------------------------------------------- /Scenes/Inventory_UI.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://bxbnos3drxhfp"] 2 | 3 | [ext_resource type="Script" path="res://Scripts/Inventory_UI.gd" id="1_ybuun"] 4 | 5 | [node name="InventoryUI" type="Control"] 6 | layout_mode = 3 7 | anchors_preset = 0 8 | size_flags_horizontal = 4 9 | size_flags_vertical = 4 10 | script = ExtResource("1_ybuun") 11 | 12 | [node name="GridContainer" type="GridContainer" parent="."] 13 | layout_mode = 0 14 | offset_left = 200.0 15 | offset_top = 200.0 16 | offset_right = 1000.0 17 | offset_bottom = 600.0 18 | size_flags_horizontal = 3 19 | size_flags_vertical = 3 20 | theme_override_constants/h_separation = 20 21 | theme_override_constants/v_separation = 20 22 | columns = 9 23 | -------------------------------------------------------------------------------- /Scenes/Player.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=32 format=3 uid="uid://b88ffk5acsfo6"] 2 | 3 | [ext_resource type="Script" path="res://Scripts/Player.gd" id="1_4m3h3"] 4 | [ext_resource type="Texture2D" uid="uid://0flrot5hrf4a" path="res://Assets/Assets/person.png" id="2_s0gdc"] 5 | [ext_resource type="FontFile" uid="uid://bi04iecmbt37l" path="res://Assets/Assets/Fonts/ARCADECLASSIC.TTF" id="3_ptwqw"] 6 | [ext_resource type="PackedScene" uid="uid://qna2th32kqo0" path="res://Inventory_UI.tscn" id="4_olh1u"] 7 | 8 | [sub_resource type="AtlasTexture" id="AtlasTexture_w4kwu"] 9 | atlas = ExtResource("2_s0gdc") 10 | region = Rect2(0, 0, 64, 64) 11 | 12 | [sub_resource type="AtlasTexture" id="AtlasTexture_sjyk4"] 13 | atlas = ExtResource("2_s0gdc") 14 | region = Rect2(0, 256, 64, 64) 15 | 16 | [sub_resource type="AtlasTexture" id="AtlasTexture_jrs1k"] 17 | atlas = ExtResource("2_s0gdc") 18 | region = Rect2(64, 256, 64, 64) 19 | 20 | [sub_resource type="AtlasTexture" id="AtlasTexture_ej72e"] 21 | atlas = ExtResource("2_s0gdc") 22 | region = Rect2(128, 256, 64, 64) 23 | 24 | [sub_resource type="AtlasTexture" id="AtlasTexture_4hqq7"] 25 | atlas = ExtResource("2_s0gdc") 26 | region = Rect2(192, 256, 64, 64) 27 | 28 | [sub_resource type="AtlasTexture" id="AtlasTexture_t3wl0"] 29 | atlas = ExtResource("2_s0gdc") 30 | region = Rect2(256, 256, 64, 64) 31 | 32 | [sub_resource type="AtlasTexture" id="AtlasTexture_fpvfo"] 33 | atlas = ExtResource("2_s0gdc") 34 | region = Rect2(320, 256, 64, 64) 35 | 36 | [sub_resource type="AtlasTexture" id="AtlasTexture_03lil"] 37 | atlas = ExtResource("2_s0gdc") 38 | region = Rect2(0, 448, 64, 64) 39 | 40 | [sub_resource type="AtlasTexture" id="AtlasTexture_850xf"] 41 | atlas = ExtResource("2_s0gdc") 42 | region = Rect2(64, 448, 64, 64) 43 | 44 | [sub_resource type="AtlasTexture" id="AtlasTexture_awha0"] 45 | atlas = ExtResource("2_s0gdc") 46 | region = Rect2(128, 448, 64, 64) 47 | 48 | [sub_resource type="AtlasTexture" id="AtlasTexture_h6qyj"] 49 | atlas = ExtResource("2_s0gdc") 50 | region = Rect2(192, 448, 64, 64) 51 | 52 | [sub_resource type="AtlasTexture" id="AtlasTexture_hn41f"] 53 | atlas = ExtResource("2_s0gdc") 54 | region = Rect2(256, 448, 64, 64) 55 | 56 | [sub_resource type="AtlasTexture" id="AtlasTexture_x33n0"] 57 | atlas = ExtResource("2_s0gdc") 58 | region = Rect2(320, 448, 64, 64) 59 | 60 | [sub_resource type="AtlasTexture" id="AtlasTexture_ipkyf"] 61 | atlas = ExtResource("2_s0gdc") 62 | region = Rect2(0, 384, 64, 64) 63 | 64 | [sub_resource type="AtlasTexture" id="AtlasTexture_tkxp8"] 65 | atlas = ExtResource("2_s0gdc") 66 | region = Rect2(64, 384, 64, 64) 67 | 68 | [sub_resource type="AtlasTexture" id="AtlasTexture_ip3qk"] 69 | atlas = ExtResource("2_s0gdc") 70 | region = Rect2(128, 384, 64, 64) 71 | 72 | [sub_resource type="AtlasTexture" id="AtlasTexture_cikjc"] 73 | atlas = ExtResource("2_s0gdc") 74 | region = Rect2(192, 384, 64, 64) 75 | 76 | [sub_resource type="AtlasTexture" id="AtlasTexture_rfbow"] 77 | atlas = ExtResource("2_s0gdc") 78 | region = Rect2(256, 384, 64, 64) 79 | 80 | [sub_resource type="AtlasTexture" id="AtlasTexture_2lodu"] 81 | atlas = ExtResource("2_s0gdc") 82 | region = Rect2(320, 384, 64, 64) 83 | 84 | [sub_resource type="AtlasTexture" id="AtlasTexture_tfqai"] 85 | atlas = ExtResource("2_s0gdc") 86 | region = Rect2(0, 320, 64, 64) 87 | 88 | [sub_resource type="AtlasTexture" id="AtlasTexture_6e3jh"] 89 | atlas = ExtResource("2_s0gdc") 90 | region = Rect2(64, 320, 64, 64) 91 | 92 | [sub_resource type="AtlasTexture" id="AtlasTexture_cbtob"] 93 | atlas = ExtResource("2_s0gdc") 94 | region = Rect2(128, 320, 64, 64) 95 | 96 | [sub_resource type="AtlasTexture" id="AtlasTexture_s3ior"] 97 | atlas = ExtResource("2_s0gdc") 98 | region = Rect2(192, 320, 64, 64) 99 | 100 | [sub_resource type="AtlasTexture" id="AtlasTexture_oy886"] 101 | atlas = ExtResource("2_s0gdc") 102 | region = Rect2(256, 320, 64, 64) 103 | 104 | [sub_resource type="AtlasTexture" id="AtlasTexture_ljlgn"] 105 | atlas = ExtResource("2_s0gdc") 106 | region = Rect2(320, 320, 64, 64) 107 | 108 | [sub_resource type="SpriteFrames" id="SpriteFrames_simk2"] 109 | animations = [{ 110 | "frames": [{ 111 | "duration": 1.0, 112 | "texture": SubResource("AtlasTexture_w4kwu") 113 | }], 114 | "loop": true, 115 | "name": &"idle", 116 | "speed": 5.0 117 | }, { 118 | "frames": [{ 119 | "duration": 1.0, 120 | "texture": SubResource("AtlasTexture_sjyk4") 121 | }, { 122 | "duration": 1.0, 123 | "texture": SubResource("AtlasTexture_jrs1k") 124 | }, { 125 | "duration": 1.0, 126 | "texture": SubResource("AtlasTexture_ej72e") 127 | }, { 128 | "duration": 1.0, 129 | "texture": SubResource("AtlasTexture_4hqq7") 130 | }, { 131 | "duration": 1.0, 132 | "texture": SubResource("AtlasTexture_t3wl0") 133 | }, { 134 | "duration": 1.0, 135 | "texture": SubResource("AtlasTexture_fpvfo") 136 | }], 137 | "loop": true, 138 | "name": &"walk_down", 139 | "speed": 5.0 140 | }, { 141 | "frames": [{ 142 | "duration": 1.0, 143 | "texture": SubResource("AtlasTexture_03lil") 144 | }, { 145 | "duration": 1.0, 146 | "texture": SubResource("AtlasTexture_850xf") 147 | }, { 148 | "duration": 1.0, 149 | "texture": SubResource("AtlasTexture_awha0") 150 | }, { 151 | "duration": 1.0, 152 | "texture": SubResource("AtlasTexture_h6qyj") 153 | }, { 154 | "duration": 1.0, 155 | "texture": SubResource("AtlasTexture_hn41f") 156 | }, { 157 | "duration": 1.0, 158 | "texture": SubResource("AtlasTexture_x33n0") 159 | }], 160 | "loop": true, 161 | "name": &"walk_left", 162 | "speed": 5.0 163 | }, { 164 | "frames": [{ 165 | "duration": 1.0, 166 | "texture": SubResource("AtlasTexture_ipkyf") 167 | }, { 168 | "duration": 1.0, 169 | "texture": SubResource("AtlasTexture_tkxp8") 170 | }, { 171 | "duration": 1.0, 172 | "texture": SubResource("AtlasTexture_ip3qk") 173 | }, { 174 | "duration": 1.0, 175 | "texture": SubResource("AtlasTexture_cikjc") 176 | }, { 177 | "duration": 1.0, 178 | "texture": SubResource("AtlasTexture_rfbow") 179 | }, { 180 | "duration": 1.0, 181 | "texture": SubResource("AtlasTexture_2lodu") 182 | }], 183 | "loop": true, 184 | "name": &"walk_right", 185 | "speed": 5.0 186 | }, { 187 | "frames": [{ 188 | "duration": 1.0, 189 | "texture": SubResource("AtlasTexture_tfqai") 190 | }, { 191 | "duration": 1.0, 192 | "texture": SubResource("AtlasTexture_6e3jh") 193 | }, { 194 | "duration": 1.0, 195 | "texture": SubResource("AtlasTexture_cbtob") 196 | }, { 197 | "duration": 1.0, 198 | "texture": SubResource("AtlasTexture_s3ior") 199 | }, { 200 | "duration": 1.0, 201 | "texture": SubResource("AtlasTexture_oy886") 202 | }, { 203 | "duration": 1.0, 204 | "texture": SubResource("AtlasTexture_ljlgn") 205 | }], 206 | "loop": true, 207 | "name": &"walk_up", 208 | "speed": 5.0 209 | }] 210 | 211 | [sub_resource type="CircleShape2D" id="CircleShape2D_ns28l"] 212 | 213 | [node name="Player" type="CharacterBody2D" groups=["Player"]] 214 | process_mode = 3 215 | script = ExtResource("1_4m3h3") 216 | 217 | [node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="."] 218 | sprite_frames = SubResource("SpriteFrames_simk2") 219 | animation = &"walk_down" 220 | 221 | [node name="CollisionShape2D" type="CollisionShape2D" parent="."] 222 | shape = SubResource("CircleShape2D_ns28l") 223 | 224 | [node name="Camera2D" type="Camera2D" parent="."] 225 | zoom = Vector2(3, 3) 226 | 227 | [node name="InteractUI" type="CanvasLayer" parent="."] 228 | visible = false 229 | 230 | [node name="ColorRect" type="ColorRect" parent="InteractUI"] 231 | anchors_preset = 3 232 | anchor_left = 1.0 233 | anchor_top = 1.0 234 | anchor_right = 1.0 235 | anchor_bottom = 1.0 236 | offset_left = -300.0 237 | offset_top = -50.0 238 | grow_horizontal = 0 239 | grow_vertical = 0 240 | color = Color(0.192157, 0.376471, 0.321569, 0.839216) 241 | 242 | [node name="Label" type="Label" parent="InteractUI/ColorRect"] 243 | layout_mode = 1 244 | anchors_preset = 8 245 | anchor_left = 0.5 246 | anchor_top = 0.5 247 | anchor_right = 0.5 248 | anchor_bottom = 0.5 249 | offset_left = -75.5 250 | offset_top = -13.0 251 | offset_right = 75.5 252 | offset_bottom = 13.0 253 | grow_horizontal = 2 254 | grow_vertical = 2 255 | theme_override_fonts/font = ExtResource("3_ptwqw") 256 | theme_override_font_sizes/font_size = 30 257 | text = "Press \"E\" to Pick Up" 258 | 259 | [node name="InventoryUI" type="CanvasLayer" parent="."] 260 | visible = false 261 | 262 | [node name="ColorRect" type="ColorRect" parent="InventoryUI"] 263 | anchors_preset = 15 264 | anchor_right = 1.0 265 | anchor_bottom = 1.0 266 | grow_horizontal = 2 267 | grow_vertical = 2 268 | color = Color(0.192157, 0.376471, 0.321569, 1) 269 | 270 | [node name="Label" type="Label" parent="InventoryUI/ColorRect"] 271 | layout_mode = 1 272 | anchors_preset = 5 273 | anchor_left = 0.5 274 | anchor_right = 0.5 275 | offset_left = -37.5 276 | offset_top = 50.0 277 | offset_right = 37.5 278 | offset_bottom = 76.0 279 | grow_horizontal = 2 280 | theme_override_fonts/font = ExtResource("3_ptwqw") 281 | theme_override_font_sizes/font_size = 60 282 | text = "Inventory" 283 | 284 | [node name="Inventory_UI" parent="InventoryUI/ColorRect" instance=ExtResource("4_olh1u")] 285 | -------------------------------------------------------------------------------- /Scripts/Global.gd: -------------------------------------------------------------------------------- 1 | ### Global.gd 2 | 3 | extends Node 4 | 5 | # Inventory items 6 | var inventory = [] 7 | 8 | # Custom signals 9 | signal inventory_updated 10 | var spawnable_items = [ 11 | {"type": "Consumable", "name": "Berry", "effect": "Health", "texture": preload("res://Assets/Assets/Icons/icon31.png")}, 12 | {"type": "Consumable", "name": "Water", "effect": "Stamina", "texture": preload("res://Assets/Assets/Icons/icon9.png")}, 13 | {"type": "Consumable", "name": "Mushroom", "effect": "Armor", "texture": preload("res://Assets/Assets/Icons/icon32.png")}, 14 | {"type": "Gift", "name": "Gemstone", "effect": "", "texture": preload("res://Assets/Assets/Icons/icon21.png")}, 15 | ] 16 | 17 | # Scene and node references 18 | var player_node: Node = null 19 | @onready var inventory_slot_scene = preload("res://Scenes/Inventory_Slot.tscn") 20 | 21 | func _ready(): 22 | # Initializes the inventory with 30 slots (spread over 9 blocks per row) 23 | inventory.resize(30) 24 | 25 | # Adds an item to the inventory, returns true if successful 26 | func add_item(item): 27 | for i in range(inventory.size()): 28 | # Check if the item exists in the inventory and matches both type and effect 29 | if inventory[i] != null and inventory[i]["type"] == item["type"] and inventory[i]["effect"] == item["effect"]: 30 | inventory[i]["quantity"] += item["quantity"] 31 | inventory_updated.emit() 32 | print("Item added", inventory) 33 | return true 34 | elif inventory[i] == null: 35 | inventory[i] = item 36 | inventory_updated.emit() 37 | print("Item added", inventory) 38 | return true 39 | return false 40 | 41 | # Removes an item from the inventory based on type and effect 42 | func remove_item(item_type, item_effect): 43 | for i in range(inventory.size()): 44 | if inventory[i] != null and inventory[i]["type"] == item_type and inventory[i]["effect"] == item_effect: 45 | inventory[i]["quantity"] -= 1 46 | if inventory[i]["quantity"] <= 0: 47 | inventory[i] = null 48 | inventory_updated.emit() 49 | return true 50 | return false 51 | 52 | # Increase inventory size dynamically 53 | func increase_inventory_size(extra_slots): 54 | inventory.resize(inventory.size() + extra_slots) 55 | inventory_updated.emit() 56 | 57 | # Sets the player reference for inventory interactions 58 | func set_player_reference(player): 59 | player_node = player 60 | 61 | # Adjusts the drop position to avoid overlapping with nearby items 62 | func adjust_drop_position(position): 63 | var radius = 100 64 | var nearby_items = get_tree().get_nodes_in_group("Items") 65 | for item in nearby_items: 66 | if item.global_position.distance_to(position) < radius: 67 | var random_offset = Vector2(randf_range(-radius, radius), randf_range(-radius, radius)) 68 | position += random_offset 69 | break 70 | return position 71 | 72 | # Drops an item at a specified position, adjusting for nearby items 73 | func drop_item(item_data, drop_position): 74 | var item_scene = load(item_data["scene_path"]) 75 | var item_instance = item_scene.instantiate() 76 | item_instance.set_item_data(item_data) 77 | drop_position = adjust_drop_position(drop_position) 78 | item_instance.global_position = drop_position 79 | get_tree().current_scene.add_child(item_instance) 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /Scripts/Inventory_Item.gd: -------------------------------------------------------------------------------- 1 | ### Inventory_Item.gd 2 | @tool 3 | extends Node2D 4 | 5 | # Item details for editor window 6 | @export var item_type = "" 7 | @export var item_name = "" 8 | @export var item_texture: Texture 9 | @export var item_effect = "" 10 | var scene_path: String = "res://Scenes/Inventory_Item.tscn" 11 | 12 | # Scene-Tree Node references 13 | @onready var icon_sprite = $Sprite2D 14 | 15 | # Variables 16 | var player_in_range = false 17 | 18 | func _ready(): 19 | # Set the texture to reflect in the game 20 | if not Engine.is_editor_hint(): 21 | icon_sprite.texture = item_texture 22 | 23 | func _process(_delta): 24 | # Set the texture to reflect in the editor 25 | if Engine.is_editor_hint(): 26 | icon_sprite.texture = item_texture 27 | # Add item to inventory if player presses "E" within range 28 | if player_in_range and Input.is_action_just_pressed("ui_add"): 29 | pickup_item() 30 | 31 | # Add item to inventory 32 | func pickup_item(): 33 | var item = { 34 | "quantity": 1, 35 | "type": item_type, 36 | "name": item_name, 37 | "effect": item_effect, 38 | "texture": item_texture, 39 | "scene_path": scene_path 40 | } 41 | if Global.player_node: 42 | Global.add_item(item) 43 | self.queue_free() 44 | 45 | # If player is in range, show UI and make item pickable 46 | func _on_area_2d_body_entered(body): 47 | if body.is_in_group("Player"): 48 | player_in_range = true 49 | body.interact_ui.visible = true 50 | 51 | # If player is in range, hide UI and don't make item pickable 52 | func _on_area_2d_body_exited(body): 53 | if body.is_in_group("Player"): 54 | player_in_range = false 55 | body.interact_ui.visible = false 56 | 57 | # Sets the item's dictionary data 58 | func set_item_data(data): 59 | item_type = data["type"] 60 | item_name = data["name"] 61 | item_effect = data["effect"] 62 | item_texture = data["texture"] 63 | 64 | # Set the items values for spawning 65 | func initiate_items(type, name, effect, texture): 66 | item_type = type 67 | item_name = name 68 | item_effect = effect 69 | item_texture = texture 70 | -------------------------------------------------------------------------------- /Scripts/Inventory_Slot.gd: -------------------------------------------------------------------------------- 1 | ### Inventory_Slot.gd 2 | 3 | extends Control 4 | 5 | # Scene-Tree Node references 6 | @onready var icon = $InnerBorder/ItemIcon 7 | @onready var quantity_label = $InnerBorder/ItemQuantity 8 | @onready var details_panel = $DetailsPanel 9 | @onready var item_name = $DetailsPanel/ItemName 10 | @onready var item_type = $DetailsPanel/ItemType 11 | @onready var item_effect = $DetailsPanel/ItemEffect 12 | @onready var usage_panel = $UsagePanel 13 | 14 | # Slot item 15 | var item = null 16 | 17 | # Show usage panel for player to use/remove item 18 | func _on_item_button_pressed(): 19 | if item != null: 20 | usage_panel.visible = !usage_panel.visible 21 | 22 | # Show item details on hover enter 23 | func _on_item_button_mouse_entered(): 24 | if item != null: 25 | usage_panel.visible = false 26 | details_panel.visible = true 27 | 28 | # Hide item details on hover exit 29 | func _on_item_button_mouse_exited(): 30 | details_panel.visible = false 31 | 32 | # Default empty slot 33 | func set_empty(): 34 | icon.texture = null 35 | quantity_label.text = "" 36 | 37 | # Set slot item with its values from the dictionary 38 | func set_item(new_item): 39 | item = new_item 40 | icon.texture = item["texture"] 41 | quantity_label.text = str(item["quantity"]) 42 | item_name.text = str(item["name"]) 43 | item_type.text = str(item["type"]) 44 | if item["effect"] != "": 45 | item_effect.text = str("+ ", item["effect"]) 46 | else: 47 | item_effect.text = "" 48 | 49 | # Remove item from inventory and drop it back into the world 50 | func _on_drop_button_pressed(): 51 | if item != null: 52 | var drop_position = Global.player_node.global_position 53 | var drop_offset = Vector2(0, 50) 54 | drop_offset = drop_offset.rotated(Global.player_node.rotation) 55 | Global.drop_item(item, drop_position + drop_offset) 56 | Global.remove_item(item["type"], item["effect"]) 57 | usage_panel.visible = false 58 | 59 | # Remove item from inventory, use it, and apply its effect (if possible) 60 | func _on_use_button_pressed(): 61 | usage_panel.visible = false 62 | if item != null and item["effect"] != "": 63 | if Global.player_node: 64 | Global.player_node.apply_item_effect(item) 65 | Global.remove_item(item["type"], item["effect"]) 66 | else: 67 | print("Player could not be found") 68 | -------------------------------------------------------------------------------- /Scripts/Inventory_UI.gd: -------------------------------------------------------------------------------- 1 | ### Inventory_UI.gd 2 | 3 | extends Control 4 | 5 | # Scene-Tree Node references 6 | @onready var grid_container = $GridContainer 7 | 8 | func _ready(): 9 | # Connect function to signal to update inventory UI 10 | Global.inventory_updated.connect(_on_inventory_updated) 11 | _on_inventory_updated() 12 | 13 | # Update inventory UI 14 | func _on_inventory_updated(): 15 | # Clear existing slots 16 | clear_grid_container() 17 | # Add slots for each inventory position 18 | for item in Global.inventory: 19 | var slot = Global.inventory_slot_scene.instantiate() 20 | grid_container.add_child(slot) 21 | if item != null: 22 | slot.set_item(item) 23 | else: 24 | slot.set_empty() 25 | 26 | # Clear inventory UI grid 27 | func clear_grid_container(): 28 | while grid_container.get_child_count() > 0: 29 | var child = grid_container.get_child(0) 30 | grid_container.remove_child(child) 31 | child.queue_free() 32 | -------------------------------------------------------------------------------- /Scripts/Main.gd: -------------------------------------------------------------------------------- 1 | ### Main.gd 2 | 3 | extends Node2D 4 | 5 | # Scene-Tree Node references 6 | @onready var items = $Items 7 | @onready var item_spawn_area = $ItemSpawnArea 8 | @onready var collision_shape = $ItemSpawnArea/CollisionShape2D 9 | 10 | # Called when the node enters the scene tree for the first time. 11 | func _ready(): 12 | spawn_random_items(10) 13 | 14 | # Get random position for item within the collision shape in spawn area 15 | func get_random_position(): 16 | var area_rect = collision_shape.shape.get_rect() 17 | var x = randf_range(0, area_rect.position.x) 18 | var y = randf_range(0, area_rect.position.y) 19 | return item_spawn_area.to_global(Vector2(x, y)) 20 | 21 | func spawn_random_items(count): 22 | var attempts = 0 23 | var spawned_count = 0 24 | while spawned_count < count and attempts < 100: 25 | var position = get_random_position() 26 | spawn_item(Global.spawnable_items[randi() % Global.spawnable_items.size()], position) 27 | spawned_count += 1 28 | attempts += 1 29 | 30 | # Create a physical instance of the Item scene on the map underneath /Items node 31 | func spawn_item(data, position): 32 | var item_scene = preload("res://Scenes/Inventory_Item.tscn") 33 | var item_instance = item_scene.instantiate() 34 | item_instance.initiate_items(data["type"], data["name"], data["effect"], data["texture"]) 35 | item_instance.global_position = position 36 | items.add_child(item_instance) 37 | -------------------------------------------------------------------------------- /Scripts/Player.gd: -------------------------------------------------------------------------------- 1 | ### Player.gd 2 | extends CharacterBody2D 3 | 4 | # Scene-Tree Node references 5 | @onready var animated_sprite = $AnimatedSprite2D 6 | @onready var interact_ui = $InteractUI 7 | @onready var inventory_ui = $InventoryUI 8 | 9 | # Variables 10 | @export var speed = 200 11 | 12 | func _ready(): 13 | # Set this node as the Player node 14 | Global.set_player_reference(self) 15 | 16 | # Input for movement 17 | func get_input(): 18 | var input_direction = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down") 19 | velocity = input_direction * speed 20 | 21 | # Movement & Animation 22 | func _physics_process(delta): 23 | get_input() 24 | move_and_slide() 25 | update_animation() 26 | 27 | # Animation 28 | func update_animation(): 29 | if velocity == Vector2.ZERO: 30 | animated_sprite.play("idle") 31 | else: 32 | if abs(velocity.x) > abs(velocity.y): 33 | if velocity.x > 0: 34 | animated_sprite.play("walk_right") 35 | else: 36 | animated_sprite.play("walk_left") 37 | else: 38 | if velocity.y > 0: 39 | animated_sprite.play("walk_down") 40 | else: 41 | animated_sprite.play("walk_up") 42 | 43 | # Show inventory menu on "I" pressed 44 | func _input(event): 45 | if event.is_action_pressed("ui_inventory"): 46 | inventory_ui.visible = !inventory_ui.visible 47 | get_tree().paused = !get_tree().paused 48 | 49 | # Apply the effect of the item (if possible) 50 | func apply_item_effect(item): 51 | match item["effect"]: 52 | "Stamina": 53 | speed += 50 54 | print("Speed increased to ", speed) 55 | "Slot Boost": 56 | Global.increase_inventory_size(5) 57 | print("Slots increased to ", Global.inventory.size()) 58 | _: 59 | print("There is no effect for this item") 60 | 61 | -------------------------------------------------------------------------------- /Sectional_Code/01 - Project and Player Setup/Scripts/Main.gd: -------------------------------------------------------------------------------- 1 | ### Main.gd 2 | extends Node 3 | 4 | 5 | -------------------------------------------------------------------------------- /Sectional_Code/01 - Project and Player Setup/Scripts/Player.gd: -------------------------------------------------------------------------------- 1 | ### Player.gd 2 | extends CharacterBody2D 3 | 4 | @onready var animated_sprite = $AnimatedSprite 5 | 6 | # Variables 7 | @export var speed = 200 8 | 9 | # Input for movement 10 | func get_input(): 11 | var input_direction = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down") 12 | velocity = input_direction * speed 13 | 14 | # Movement & Animation 15 | func _physics_process(delta): 16 | get_input() 17 | move_and_slide() 18 | update_animation() 19 | 20 | # Animation 21 | func update_animation(): 22 | if velocity == Vector2.ZERO: 23 | animated_sprite.play("idle") 24 | else: 25 | if abs(velocity.x) > abs(velocity.y): 26 | if velocity.x > 0: 27 | animated_sprite.play("walk_right") 28 | else: 29 | animated_sprite.play("walk_left") 30 | else: 31 | if velocity.y > 0: 32 | animated_sprite.play("walk_down") 33 | else: 34 | animated_sprite.play("walk_up") 35 | -------------------------------------------------------------------------------- /Sectional_Code/02 - Inventory Manager/Scripts/Global.gd: -------------------------------------------------------------------------------- 1 | ### Global.gd 2 | 3 | extends Node 4 | 5 | # Scene and node references 6 | var player_node: Node = null 7 | 8 | # Inventory items 9 | var inventory = [] 10 | 11 | # Custom signals 12 | signal inventory_updated 13 | 14 | func _ready(): 15 | # Initializes the inventory with 30 slots (spread over 9 blocks per row) 16 | inventory.resize(30) 17 | 18 | # Sets the player reference for inventory interactions 19 | func set_player_reference(player): 20 | player_node = player 21 | 22 | # Adds an item to the inventory, returns true if successful 23 | func add_item(): 24 | inventory_updated.emit() 25 | 26 | 27 | # Removes an item from the inventory based on type and effect 28 | func remove_item(): 29 | inventory_updated.emit() 30 | 31 | # Increase inventory size dynamically 32 | func increase_inventory_size(): 33 | inventory_updated.emit() 34 | -------------------------------------------------------------------------------- /Sectional_Code/02 - Inventory Manager/Scripts/Main.gd: -------------------------------------------------------------------------------- 1 | ### Main.gd 2 | extends Node 3 | -------------------------------------------------------------------------------- /Sectional_Code/02 - Inventory Manager/Scripts/Player.gd: -------------------------------------------------------------------------------- 1 | ### Player.gd 2 | extends CharacterBody2D 3 | 4 | # Scene-Tree Node references 5 | @onready var animated_sprite = $AnimatedSprite 6 | 7 | # Variables 8 | @export var speed = 200 9 | 10 | func _ready(): 11 | # Set this node as the Player node 12 | Global.set_player_reference(self) 13 | 14 | # Input for movement 15 | func get_input(): 16 | var input_direction = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down") 17 | velocity = input_direction * speed 18 | 19 | # Movement & Animation 20 | func _physics_process(delta): 21 | get_input() 22 | move_and_slide() 23 | update_animation() 24 | 25 | # Animation 26 | func update_animation(): 27 | if velocity == Vector2.ZERO: 28 | animated_sprite.play("idle") 29 | else: 30 | if abs(velocity.x) > abs(velocity.y): 31 | if velocity.x > 0: 32 | animated_sprite.play("walk_right") 33 | else: 34 | animated_sprite.play("walk_left") 35 | else: 36 | if velocity.y > 0: 37 | animated_sprite.play("walk_down") 38 | else: 39 | animated_sprite.play("walk_up") 40 | -------------------------------------------------------------------------------- /Sectional_Code/03 - Inventory Item - Part One/Scripts/Global.gd: -------------------------------------------------------------------------------- 1 | ### Global.gd 2 | 3 | extends Node 4 | 5 | # Scene and node references 6 | var player_node: Node = null 7 | 8 | # Inventory items 9 | var inventory = [] 10 | 11 | # Custom signals 12 | signal inventory_updated 13 | 14 | func _ready(): 15 | # Initializes the inventory with 30 slots (spread over 9 blocks per row) 16 | inventory.resize(30) 17 | 18 | # Sets the player reference for inventory interactions 19 | func set_player_reference(player): 20 | player_node = player 21 | 22 | # Adds an item to the inventory, returns true if successful 23 | func add_item(): 24 | inventory_updated.emit() 25 | 26 | # Removes an item from the inventory based on type and effect 27 | func remove_item(): 28 | inventory_updated.emit() 29 | 30 | # Increase inventory size dynamically 31 | func increase_inventory_size(): 32 | inventory_updated.emit() 33 | 34 | 35 | -------------------------------------------------------------------------------- /Sectional_Code/03 - Inventory Item - Part One/Scripts/Inventory_Item.gd: -------------------------------------------------------------------------------- 1 | ### Inventory_Item.gd 2 | @tool 3 | extends Node2D 4 | 5 | # Item details for editor window 6 | @export var item_type = "" 7 | @export var item_name = "" 8 | @export var item_texture: Texture 9 | @export var item_effect = "" 10 | var scene_path: String = "res://Scenes/Inventory_Item.tscn" 11 | 12 | # Scene-Tree Node references 13 | @onready var icon_sprite = $Sprite2D 14 | 15 | func _ready(): 16 | # Set the texture to reflect in the game 17 | if not Engine.is_editor_hint(): 18 | icon_sprite.texture = item_texture 19 | 20 | func _process(_delta): 21 | # Set the texture to reflect in the editor 22 | if Engine.is_editor_hint(): 23 | icon_sprite.texture = item_texture 24 | -------------------------------------------------------------------------------- /Sectional_Code/03 - Inventory Item - Part One/Scripts/Main.gd: -------------------------------------------------------------------------------- 1 | ### Main.gd 2 | extends Node 3 | -------------------------------------------------------------------------------- /Sectional_Code/03 - Inventory Item - Part One/Scripts/Player.gd: -------------------------------------------------------------------------------- 1 | ### Player.gd 2 | extends CharacterBody2D 3 | 4 | # Scene-Tree Node references 5 | @onready var animated_sprite = $AnimatedSprite 6 | 7 | # Variables 8 | @export var speed = 200 9 | 10 | func _ready(): 11 | # Set this node as the Player node 12 | Global.set_player_reference(self) 13 | 14 | # Input for movement 15 | func get_input(): 16 | var input_direction = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down") 17 | velocity = input_direction * speed 18 | 19 | # Movement & Animation 20 | func _physics_process(delta): 21 | get_input() 22 | move_and_slide() 23 | update_animation() 24 | 25 | # Animation 26 | func update_animation(): 27 | if velocity == Vector2.ZERO: 28 | animated_sprite.play("idle") 29 | else: 30 | if abs(velocity.x) > abs(velocity.y): 31 | if velocity.x > 0: 32 | animated_sprite.play("walk_right") 33 | else: 34 | animated_sprite.play("walk_left") 35 | else: 36 | if velocity.y > 0: 37 | animated_sprite.play("walk_down") 38 | else: 39 | animated_sprite.play("walk_up") 40 | -------------------------------------------------------------------------------- /Sectional_Code/04 - Inventory Item - Part Two/Scripts/Global.gd: -------------------------------------------------------------------------------- 1 | ### Global.gd 2 | 3 | extends Node 4 | 5 | # Scene and node references 6 | var player_node: Node = null 7 | 8 | # Inventory items 9 | var inventory = [] 10 | 11 | # Custom signals 12 | signal inventory_updated 13 | 14 | func _ready(): 15 | # Initializes the inventory with 30 slots (spread over 9 blocks per row) 16 | inventory.resize(30) 17 | 18 | # Sets the player reference for inventory interactions 19 | func set_player_reference(player): 20 | player_node = player 21 | 22 | # Adds an item to the inventory, returns true if successful 23 | func add_item(item): 24 | for i in range(inventory.size()): 25 | # Check if the item exists in the inventory and matches both type and effect 26 | if inventory[i] != null and inventory[i]["type"] == item["type"] and inventory[i]["effect"] == item["effect"]: 27 | inventory[i]["quantity"] += item["quantity"] 28 | inventory_updated.emit() 29 | print("Item added", inventory) 30 | return true 31 | elif inventory[i] == null: 32 | inventory[i] = item 33 | inventory_updated.emit() 34 | print("Item added", inventory) 35 | return true 36 | return false 37 | 38 | # Removes an item from the inventory based on type and effect 39 | func remove_item(): 40 | inventory_updated.emit() 41 | 42 | # Increase inventory size dynamically 43 | func increase_inventory_size(): 44 | inventory_updated.emit() 45 | 46 | 47 | -------------------------------------------------------------------------------- /Sectional_Code/04 - Inventory Item - Part Two/Scripts/Inventory_Item.gd: -------------------------------------------------------------------------------- 1 | ### Inventory_Item.gd 2 | @tool 3 | extends Node2D 4 | 5 | # Item details for editor window 6 | @export var item_type = "" 7 | @export var item_name = "" 8 | @export var item_texture: Texture 9 | @export var item_effect = "" 10 | var scene_path: String = "res://Scenes/Inventory_Item.tscn" 11 | 12 | # Scene-Tree Node references 13 | @onready var icon_sprite = $Sprite2D 14 | 15 | # Variables 16 | var player_in_range = false 17 | 18 | func _ready(): 19 | # Set the texture to reflect in the game 20 | if not Engine.is_editor_hint(): 21 | icon_sprite.texture = item_texture 22 | 23 | func _process(_delta): 24 | # Set the texture to reflect in the editor 25 | if Engine.is_editor_hint(): 26 | icon_sprite.texture = item_texture 27 | 28 | # Add item to inventory 29 | func pickup_item(): 30 | var item = { 31 | "quantity": 1, 32 | "type": item_type, 33 | "name": item_name, 34 | "effect": item_effect, 35 | "texture": item_texture, 36 | "scene_path": scene_path 37 | } 38 | if Global.player_node: 39 | Global.add_item(item) 40 | self.queue_free() 41 | 42 | # If player is in range, show UI and make item pickable 43 | func _on_area_2d_body_entered(body): 44 | if body.is_in_group("Player"): 45 | player_in_range = true 46 | body.interact_ui.visible = true 47 | 48 | # If player is in range, hide UI and don't make item pickable 49 | func _on_area_2d_body_exited(body): 50 | if body.is_in_group("Player"): 51 | player_in_range = false 52 | body.interact_ui.visible = false -------------------------------------------------------------------------------- /Sectional_Code/04 - Inventory Item - Part Two/Scripts/Main.gd: -------------------------------------------------------------------------------- 1 | ### Main.gd 2 | extends Node 3 | -------------------------------------------------------------------------------- /Sectional_Code/04 - Inventory Item - Part Two/Scripts/Player.gd: -------------------------------------------------------------------------------- 1 | ### Player.gd 2 | extends CharacterBody2D 3 | 4 | # Scene-Tree Node references 5 | @onready var interact_ui = $InteractUI 6 | @onready var animated_sprite = $AnimatedSprite 7 | # Variables 8 | @export var speed = 200 9 | 10 | func _ready(): 11 | # Set this node as the Player node 12 | Global.set_player_reference(self) 13 | 14 | # Input for movement 15 | func get_input(): 16 | var input_direction = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down") 17 | velocity = input_direction * speed 18 | 19 | # Movement & Animation 20 | func _physics_process(delta): 21 | get_input() 22 | move_and_slide() 23 | update_animation() 24 | 25 | # Animation 26 | func update_animation(): 27 | if velocity == Vector2.ZERO: 28 | animated_sprite.play("idle") 29 | else: 30 | if abs(velocity.x) > abs(velocity.y): 31 | if velocity.x > 0: 32 | animated_sprite.play("walk_right") 33 | else: 34 | animated_sprite.play("walk_left") 35 | else: 36 | if velocity.y > 0: 37 | animated_sprite.play("walk_down") 38 | else: 39 | animated_sprite.play("walk_up") 40 | -------------------------------------------------------------------------------- /Sectional_Code/05 - Inventory UI/Scripts/Global.gd: -------------------------------------------------------------------------------- 1 | ### Global.gd 2 | 3 | extends Node 4 | 5 | # Scene and node references 6 | var player_node: Node = null 7 | 8 | # Inventory items 9 | var inventory = [] 10 | 11 | # Custom signals 12 | signal inventory_updated 13 | 14 | func _ready(): 15 | # Initializes the inventory with 30 slots (spread over 9 blocks per row) 16 | inventory.resize(30) 17 | 18 | # Sets the player reference for inventory interactions 19 | func set_player_reference(player): 20 | player_node = player 21 | 22 | # Adds an item to the inventory, returns true if successful 23 | func add_item(item): 24 | for i in range(inventory.size()): 25 | # Check if the item exists in the inventory and matches both type and effect 26 | if inventory[i] != null and inventory[i]["type"] == item["type"] and inventory[i]["effect"] == item["effect"]: 27 | inventory[i]["quantity"] += item["quantity"] 28 | inventory_updated.emit() 29 | print("Item added", inventory) 30 | return true 31 | elif inventory[i] == null: 32 | inventory[i] = item 33 | inventory_updated.emit() 34 | print("Item added", inventory) 35 | return true 36 | return false 37 | 38 | # Removes an item from the inventory based on type and effect 39 | func remove_item(): 40 | inventory_updated.emit() 41 | 42 | # Increase inventory size dynamically 43 | func increase_inventory_size(): 44 | inventory_updated.emit() 45 | 46 | 47 | -------------------------------------------------------------------------------- /Sectional_Code/05 - Inventory UI/Scripts/Inventory_Item.gd: -------------------------------------------------------------------------------- 1 | ### Inventory_Item.gd 2 | @tool 3 | extends Node2D 4 | 5 | # Item details for editor window 6 | @export var item_type = "" 7 | @export var item_name = "" 8 | @export var item_texture: Texture 9 | @export var item_effect = "" 10 | var scene_path: String = "res://Scenes/Inventory_Item.tscn" 11 | 12 | # Scene-Tree Node references 13 | @onready var icon_sprite = $Sprite2D 14 | 15 | # Variables 16 | var player_in_range = false 17 | 18 | func _ready(): 19 | # Set the texture to reflect in the game 20 | if not Engine.is_editor_hint(): 21 | icon_sprite.texture = item_texture 22 | 23 | func _process(_delta): 24 | # Set the texture to reflect in the editor 25 | if Engine.is_editor_hint(): 26 | icon_sprite.texture = item_texture 27 | 28 | # Add item to inventory 29 | func pickup_item(): 30 | var item = { 31 | "quantity": 1, 32 | "type": item_type, 33 | "name": item_name, 34 | "effect": item_effect, 35 | "texture": item_texture, 36 | "scene_path": scene_path 37 | } 38 | if Global.player_node: 39 | Global.add_item(item) 40 | self.queue_free() 41 | 42 | # If player is in range, show UI and make item pickable 43 | func _on_area_2d_body_entered(body): 44 | if body.is_in_group("Player"): 45 | player_in_range = true 46 | body.interact_ui.visible = true 47 | 48 | # If player is in range, hide UI and don't make item pickable 49 | func _on_area_2d_body_exited(body): 50 | if body.is_in_group("Player"): 51 | player_in_range = false 52 | body.interact_ui.visible = false -------------------------------------------------------------------------------- /Sectional_Code/05 - Inventory UI/Scripts/Inventory_UI.gd: -------------------------------------------------------------------------------- 1 | ###Inventory_UI.gd 2 | extends Control 3 | 4 | # Scene-Tree Node references 5 | @onready var grid_container = $GridContainer 6 | 7 | func _ready(): 8 | # Connect function to signal to update inventory UI 9 | Global.inventory_updated.connect(_on_inventory_updated) 10 | _on_inventory_updated() 11 | 12 | # Update inventory U 13 | func _on_inventory_updated(): 14 | # Clear existing slots 15 | clear_grid_container() 16 | 17 | # Clear inventory UI grid 18 | func clear_grid_container(): 19 | while grid_container.get_child_count() > 0: 20 | var child = grid_container.get_child(0) 21 | grid_container.remove_child(child) 22 | child.queue_free() 23 | -------------------------------------------------------------------------------- /Sectional_Code/05 - Inventory UI/Scripts/Main.gd: -------------------------------------------------------------------------------- 1 | ### Main.gd 2 | extends Node 3 | -------------------------------------------------------------------------------- /Sectional_Code/05 - Inventory UI/Scripts/Player.gd: -------------------------------------------------------------------------------- 1 | ### Player.gd 2 | extends CharacterBody2D 3 | 4 | # Scene-Tree Node references 5 | @onready var inventory_ui = $InventoryUI 6 | @onready var interact_ui = $InteractUI 7 | @onready var animated_sprite = $AnimatedSprite 8 | 9 | # Variables 10 | @export var speed = 200 11 | 12 | func _ready(): 13 | # Set this node as the Player node 14 | Global.set_player_reference(self) 15 | 16 | # Input for movement 17 | func get_input(): 18 | var input_direction = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down") 19 | velocity = input_direction * speed 20 | 21 | # Movement & Animation 22 | func _physics_process(delta): 23 | get_input() 24 | move_and_slide() 25 | update_animation() 26 | 27 | # Animation 28 | func update_animation(): 29 | if velocity == Vector2.ZERO: 30 | animated_sprite.play("idle") 31 | else: 32 | if abs(velocity.x) > abs(velocity.y): 33 | if velocity.x > 0: 34 | animated_sprite.play("walk_right") 35 | else: 36 | animated_sprite.play("walk_left") 37 | else: 38 | if velocity.y > 0: 39 | animated_sprite.play("walk_down") 40 | else: 41 | animated_sprite.play("walk_up") 42 | 43 | # Show inventory menu on "I" pressed 44 | func _input(event): 45 | if event.is_action_pressed("ui_inventory"): 46 | inventory_ui.visible = !inventory_ui.visible 47 | get_tree().paused = !get_tree().paused 48 | -------------------------------------------------------------------------------- /Sectional_Code/06 - Inventory Slots (Creation)/Scripts/Global.gd: -------------------------------------------------------------------------------- 1 | ### Global.gd 2 | 3 | extends Node 4 | 5 | # Scene and node references 6 | var player_node: Node = null 7 | 8 | # Inventory items 9 | var inventory = [] 10 | 11 | # Custom signals 12 | signal inventory_updated 13 | 14 | func _ready(): 15 | # Initializes the inventory with 30 slots (spread over 9 blocks per row) 16 | inventory.resize(30) 17 | 18 | # Sets the player reference for inventory interactions 19 | func set_player_reference(player): 20 | player_node = player 21 | 22 | # Adds an item to the inventory, returns true if successful 23 | func add_item(item): 24 | for i in range(inventory.size()): 25 | # Check if the item exists in the inventory and matches both type and effect 26 | if inventory[i] != null and inventory[i]["type"] == item["type"] and inventory[i]["effect"] == item["effect"]: 27 | inventory[i]["quantity"] += item["quantity"] 28 | inventory_updated.emit() 29 | print("Item added", inventory) 30 | return true 31 | elif inventory[i] == null: 32 | inventory[i] = item 33 | inventory_updated.emit() 34 | print("Item added", inventory) 35 | return true 36 | return false 37 | 38 | # Removes an item from the inventory based on type and effect 39 | func remove_item(): 40 | inventory_updated.emit() 41 | 42 | # Increase inventory size dynamically 43 | func increase_inventory_size(): 44 | inventory_updated.emit() 45 | 46 | 47 | -------------------------------------------------------------------------------- /Sectional_Code/06 - Inventory Slots (Creation)/Scripts/Inventory_Item.gd: -------------------------------------------------------------------------------- 1 | ### Inventory_Item.gd 2 | @tool 3 | extends Node2D 4 | 5 | # Item details for editor window 6 | @export var item_type = "" 7 | @export var item_name = "" 8 | @export var item_texture: Texture 9 | @export var item_effect = "" 10 | var scene_path: String = "res://Scenes/Inventory_Item.tscn" 11 | 12 | # Scene-Tree Node references 13 | @onready var icon_sprite = $Sprite2D 14 | 15 | # Variables 16 | var player_in_range = false 17 | 18 | func _ready(): 19 | # Set the texture to reflect in the game 20 | if not Engine.is_editor_hint(): 21 | icon_sprite.texture = item_texture 22 | 23 | func _process(_delta): 24 | # Set the texture to reflect in the editor 25 | if Engine.is_editor_hint(): 26 | icon_sprite.texture = item_texture 27 | 28 | # Add item to inventory 29 | func pickup_item(): 30 | var item = { 31 | "quantity": 1, 32 | "type": item_type, 33 | "name": item_name, 34 | "effect": item_effect, 35 | "texture": item_texture, 36 | "scene_path": scene_path 37 | } 38 | if Global.player_node: 39 | Global.add_item(item) 40 | self.queue_free() 41 | 42 | # If player is in range, show UI and make item pickable 43 | func _on_area_2d_body_entered(body): 44 | if body.is_in_group("Player"): 45 | player_in_range = true 46 | body.interact_ui.visible = true 47 | 48 | # If player is in range, hide UI and don't make item pickable 49 | func _on_area_2d_body_exited(body): 50 | if body.is_in_group("Player"): 51 | player_in_range = false 52 | body.interact_ui.visible = false -------------------------------------------------------------------------------- /Sectional_Code/06 - Inventory Slots (Creation)/Scripts/Inventory_Slot.gd: -------------------------------------------------------------------------------- 1 | ##Inventory_Slot.gd 2 | 3 | # Show usage panel for player to use/remove item 4 | func _on_button_pressed(): 5 | pass 6 | 7 | # Show item details on hover enter 8 | func _on_button_mouse_entered(): 9 | pass 10 | 11 | # Hide item details on hover exit 12 | func _on_button_mouse_exited(): 13 | pass 14 | 15 | 16 | -------------------------------------------------------------------------------- /Sectional_Code/06 - Inventory Slots (Creation)/Scripts/Inventory_UI.gd: -------------------------------------------------------------------------------- 1 | ###Inventory_UI.gd 2 | extends Control 3 | 4 | # Scene-Tree Node references 5 | @onready var grid_container = $GridContainer 6 | 7 | func _ready(): 8 | # Connect function to signal to update inventory UI 9 | Global.inventory_updated.connect(_on_inventory_updated) 10 | _on_inventory_updated() 11 | 12 | # Update inventory U 13 | func _on_inventory_updated(): 14 | # Clear existing slots 15 | clear_grid_container() 16 | 17 | # Clear inventory UI grid 18 | func clear_grid_container(): 19 | while grid_container.get_child_count() > 0: 20 | var child = grid_container.get_child(0) 21 | grid_container.remove_child(child) 22 | child.queue_free() 23 | -------------------------------------------------------------------------------- /Sectional_Code/06 - Inventory Slots (Creation)/Scripts/Main.gd: -------------------------------------------------------------------------------- 1 | ### Main.gd 2 | extends Node 3 | -------------------------------------------------------------------------------- /Sectional_Code/06 - Inventory Slots (Creation)/Scripts/Player.gd: -------------------------------------------------------------------------------- 1 | ### Player.gd 2 | extends CharacterBody2D 3 | 4 | # Scene-Tree Node references 5 | @onready var inventory_ui = $InventoryUI 6 | @onready var interact_ui = $InteractUI 7 | @onready var animated_sprite = $AnimatedSprite 8 | 9 | # Variables 10 | @export var speed = 200 11 | 12 | func _ready(): 13 | # Set this node as the Player node 14 | Global.set_player_reference(self) 15 | 16 | # Input for movement 17 | func get_input(): 18 | var input_direction = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down") 19 | velocity = input_direction * speed 20 | 21 | # Movement & Animation 22 | func _physics_process(delta): 23 | get_input() 24 | move_and_slide() 25 | update_animation() 26 | 27 | # Animation 28 | func update_animation(): 29 | if velocity == Vector2.ZERO: 30 | animated_sprite.play("idle") 31 | else: 32 | if abs(velocity.x) > abs(velocity.y): 33 | if velocity.x > 0: 34 | animated_sprite.play("walk_right") 35 | else: 36 | animated_sprite.play("walk_left") 37 | else: 38 | if velocity.y > 0: 39 | animated_sprite.play("walk_down") 40 | else: 41 | animated_sprite.play("walk_up") 42 | 43 | # Show inventory menu on "I" pressed 44 | func _input(event): 45 | if event.is_action_pressed("ui_inventory"): 46 | inventory_ui.visible = !inventory_ui.visible 47 | get_tree().paused = !get_tree().paused 48 | -------------------------------------------------------------------------------- /Sectional_Code/07 - Inventory Slots (Adding Items)/Scripts/Global.gd: -------------------------------------------------------------------------------- 1 | ### Global.gd 2 | 3 | extends Node 4 | 5 | # Scene and node references 6 | @onready var inventory_slot_scene = preload("res://Scenes/Inventory_Slot.tscn") 7 | var player_node: Node = null 8 | 9 | # Inventory items 10 | var inventory = [] 11 | 12 | # Custom signals 13 | signal inventory_updated 14 | 15 | func _ready(): 16 | # Initializes the inventory with 30 slots (spread over 9 blocks per row) 17 | inventory.resize(30) 18 | 19 | # Sets the player reference for inventory interactions 20 | func set_player_reference(player): 21 | player_node = player 22 | 23 | # Adds an item to the inventory, returns true if successful 24 | func add_item(item): 25 | for i in range(inventory.size()): 26 | # Check if the item exists in the inventory and matches both type and effect 27 | if inventory[i] != null and inventory[i]["type"] == item["type"] and inventory[i]["effect"] == item["effect"]: 28 | inventory[i]["quantity"] += item["quantity"] 29 | inventory_updated.emit() 30 | print("Item added", inventory) 31 | return true 32 | elif inventory[i] == null: 33 | inventory[i] = item 34 | inventory_updated.emit() 35 | print("Item added", inventory) 36 | return true 37 | return false 38 | 39 | # Removes an item from the inventory based on type and effect 40 | func remove_item(): 41 | inventory_updated.emit() 42 | 43 | # Increase inventory size dynamically 44 | func increase_inventory_size(): 45 | inventory_updated.emit() 46 | 47 | 48 | -------------------------------------------------------------------------------- /Sectional_Code/07 - Inventory Slots (Adding Items)/Scripts/Inventory_Item.gd: -------------------------------------------------------------------------------- 1 | ### Inventory_Item.gd 2 | @tool 3 | extends Node2D 4 | 5 | # Item details for editor window 6 | @export var item_type = "" 7 | @export var item_name = "" 8 | @export var item_texture: Texture 9 | @export var item_effect = "" 10 | var scene_path: String = "res://Scenes/Inventory_Item.tscn" 11 | 12 | # Scene-Tree Node references 13 | @onready var icon_sprite = $Sprite2D 14 | 15 | # Variables 16 | var player_in_range = false 17 | 18 | func _ready(): 19 | # Set the texture to reflect in the game 20 | if not Engine.is_editor_hint(): 21 | icon_sprite.texture = item_texture 22 | 23 | func _process(_delta): 24 | # Set the texture to reflect in the editor 25 | if Engine.is_editor_hint(): 26 | icon_sprite.texture = item_texture 27 | 28 | # Add item to inventory 29 | func pickup_item(): 30 | var item = { 31 | "quantity": 1, 32 | "type": item_type, 33 | "name": item_name, 34 | "effect": item_effect, 35 | "texture": item_texture, 36 | "scene_path": scene_path 37 | } 38 | if Global.player_node: 39 | Global.add_item(item) 40 | self.queue_free() 41 | 42 | # If player is in range, show UI and make item pickable 43 | func _on_area_2d_body_entered(body): 44 | if body.is_in_group("Player"): 45 | player_in_range = true 46 | body.interact_ui.visible = true 47 | 48 | # If player is in range, hide UI and don't make item pickable 49 | func _on_area_2d_body_exited(body): 50 | if body.is_in_group("Player"): 51 | player_in_range = false 52 | body.interact_ui.visible = false -------------------------------------------------------------------------------- /Sectional_Code/07 - Inventory Slots (Adding Items)/Scripts/Inventory_Slot.gd: -------------------------------------------------------------------------------- 1 | ## Inventory_Slot.gd 2 | 3 | # Scene-Tree Node references 4 | @onready var icon = $InnerBorder/ItemIcon 5 | @onready var quantity_label = $InnerBorder/ItemQuantity 6 | @onready var details_panel = $DetailsPanel 7 | @onready var item_name = $DetailsPanel/ItemName 8 | @onready var item_type = $DetailsPanel/ItemType 9 | @onready var item_effect = $DetailsPanel/ItemEffect 10 | @onready var usage_panel = $UsagePanel 11 | 12 | # Slot Item 13 | var item = null 14 | 15 | # Show usage panel for player to use/remove item 16 | func _on_button_pressed(): 17 | if item != null: 18 | usage_panel.visible = !usage_panel.visible 19 | 20 | # Show item details on hover enter 21 | func _on_button_mouse_entered(): 22 | if item != null: 23 | usage_panel.visible = false 24 | details_panel.visible = true 25 | 26 | # Hide item details on hover exit 27 | func _on_button_mouse_exited(): 28 | details_panel.visible = false 29 | 30 | # Default empty slot 31 | func set_empty(): 32 | icon.texture = null 33 | quantity_label.text = "" 34 | 35 | # Set slot item with its values from the dictionary 36 | func set_item(new_item): 37 | item = new_item 38 | icon.texture = item["texture"] 39 | quantity_label.text = str(item["quantity"]) 40 | item_name.text = str(item["name"]) 41 | item_type.text = str(item["type"]) 42 | if item["effect"] != "": 43 | item_effect.text = str("+ ", item["effect"]) 44 | else: 45 | item_effect.text = "" -------------------------------------------------------------------------------- /Sectional_Code/07 - Inventory Slots (Adding Items)/Scripts/Inventory_UI.gd: -------------------------------------------------------------------------------- 1 | ###Inventory_UI.gd 2 | extends Control 3 | 4 | # Scene-Tree Node references 5 | @onready var grid_container = $GridContainer 6 | 7 | func _ready(): 8 | # Connect function to signal to update inventory UI 9 | Global.inventory_updated.connect(_on_inventory_updated) 10 | _on_inventory_updated() 11 | 12 | # Update inventory U 13 | func _on_inventory_updated(): 14 | # Clear existing slots 15 | clear_grid_container() 16 | # Add slots for each inventory position 17 | for item in Global.inventory: 18 | var slot = Global.inventory_slot_scene.instantiate() 19 | grid_container.add_child(slot) 20 | if item != null: 21 | slot.set_item(item) 22 | else: 23 | slot.set_empty() 24 | 25 | # Clear inventory UI grid 26 | func clear_grid_container(): 27 | while grid_container.get_child_count() > 0: 28 | var child = grid_container.get_child(0) 29 | grid_container.remove_child(child) 30 | child.queue_free() 31 | -------------------------------------------------------------------------------- /Sectional_Code/07 - Inventory Slots (Adding Items)/Scripts/Main.gd: -------------------------------------------------------------------------------- 1 | ### Main.gd 2 | extends Node 3 | -------------------------------------------------------------------------------- /Sectional_Code/07 - Inventory Slots (Adding Items)/Scripts/Player.gd: -------------------------------------------------------------------------------- 1 | ### Player.gd 2 | extends CharacterBody2D 3 | 4 | # Scene-Tree Node references 5 | @onready var inventory_ui = $InventoryUI 6 | @onready var interact_ui = $InteractUI 7 | @onready var animated_sprite = $AnimatedSprite 8 | 9 | # Variables 10 | @export var speed = 200 11 | 12 | func _ready(): 13 | # Set this node as the Player node 14 | Global.set_player_reference(self) 15 | 16 | # Input for movement 17 | func get_input(): 18 | var input_direction = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down") 19 | velocity = input_direction * speed 20 | 21 | # Movement & Animation 22 | func _physics_process(delta): 23 | get_input() 24 | move_and_slide() 25 | update_animation() 26 | 27 | # Animation 28 | func update_animation(): 29 | if velocity == Vector2.ZERO: 30 | animated_sprite.play("idle") 31 | else: 32 | if abs(velocity.x) > abs(velocity.y): 33 | if velocity.x > 0: 34 | animated_sprite.play("walk_right") 35 | else: 36 | animated_sprite.play("walk_left") 37 | else: 38 | if velocity.y > 0: 39 | animated_sprite.play("walk_down") 40 | else: 41 | animated_sprite.play("walk_up") 42 | 43 | # Show inventory menu on "I" pressed 44 | func _input(event): 45 | if event.is_action_pressed("ui_inventory"): 46 | inventory_ui.visible = !inventory_ui.visible 47 | get_tree().paused = !get_tree().paused 48 | -------------------------------------------------------------------------------- /Sectional_Code/08 - Inventory Slots (Dropping Items)/Scripts/Global.gd: -------------------------------------------------------------------------------- 1 | ### Global.gd 2 | 3 | extends Node 4 | 5 | # Scene and node references 6 | @onready var inventory_slot_scene = preload("res://Scenes/Inventory_Slot.tscn") 7 | var player_node: Node = null 8 | 9 | # Inventory items 10 | var inventory = [] 11 | 12 | # Custom signals 13 | signal inventory_updated 14 | 15 | func _ready(): 16 | # Initializes the inventory with 30 slots (spread over 9 blocks per row) 17 | inventory.resize(30) 18 | 19 | # Sets the player reference for inventory interactions 20 | func set_player_reference(player): 21 | player_node = player 22 | 23 | # Adds an item to the inventory, returns true if successful 24 | func add_item(item): 25 | for i in range(inventory.size()): 26 | # Check if the item exists in the inventory and matches both type and effect 27 | if inventory[i] != null and inventory[i]["type"] == item["type"] and inventory[i]["effect"] == item["effect"]: 28 | inventory[i]["quantity"] += item["quantity"] 29 | inventory_updated.emit() 30 | print("Item added", inventory) 31 | return true 32 | elif inventory[i] == null: 33 | inventory[i] = item 34 | inventory_updated.emit() 35 | print("Item added", inventory) 36 | return true 37 | return false 38 | 39 | # Removes an item from the inventory based on type and effect 40 | func remove_item(item_type, item_effect): 41 | for i in range(inventory.size()): 42 | if inventory[i] != null and inventory[i]["type"] == item_type and inventory[i]["effect"] == item_effect: 43 | inventory[i]["quantity"] -= 1 44 | if inventory[i]["quantity"] <= 0: 45 | inventory[i] = null 46 | inventory_updated.emit() 47 | return true 48 | return false 49 | 50 | # Increase inventory size dynamically 51 | func increase_inventory_size(): 52 | inventory_updated.emit() 53 | 54 | # Drops an item at a specified position, adjusting for nearby items 55 | func drop_item(item_data, drop_position): 56 | var item_scene = load(item_data["scene_path"]) 57 | var item_instance = item_scene.instantiate() 58 | item_instance.set_item_data(item_data) 59 | drop_position = adjust_drop_position(drop_position) 60 | item_instance.global_position = drop_position 61 | get_tree().current_scene.add_child(item_instance) 62 | 63 | # Adjusts the drop position to avoid overlapping with nearby items 64 | func adjust_drop_position(position): 65 | var radius = 100 66 | var nearby_items = get_tree().get_nodes_in_group("Items") 67 | for item in nearby_items: 68 | if item.global_position.distance_to(position) < radius: 69 | var random_offset = Vector2(randf_range(-radius, radius), randf_range(-radius, radius)) 70 | position += random_offset 71 | break 72 | return position -------------------------------------------------------------------------------- /Sectional_Code/08 - Inventory Slots (Dropping Items)/Scripts/Inventory_Item.gd: -------------------------------------------------------------------------------- 1 | ### Inventory_Item.gd 2 | @tool 3 | extends Node2D 4 | 5 | # Item details for editor window 6 | @export var item_type = "" 7 | @export var item_name = "" 8 | @export var item_texture: Texture 9 | @export var item_effect = "" 10 | var scene_path: String = "res://Scenes/Inventory_Item.tscn" 11 | 12 | # Scene-Tree Node references 13 | @onready var icon_sprite = $Sprite2D 14 | 15 | # Variables 16 | var player_in_range = false 17 | 18 | func _ready(): 19 | # Set the texture to reflect in the game 20 | if not Engine.is_editor_hint(): 21 | icon_sprite.texture = item_texture 22 | 23 | func _process(_delta): 24 | # Set the texture to reflect in the editor 25 | if Engine.is_editor_hint(): 26 | icon_sprite.texture = item_texture 27 | 28 | # Add item to inventory 29 | func pickup_item(): 30 | var item = { 31 | "quantity": 1, 32 | "type": item_type, 33 | "name": item_name, 34 | "effect": item_effect, 35 | "texture": item_texture, 36 | "scene_path": scene_path 37 | } 38 | if Global.player_node: 39 | Global.add_item(item) 40 | self.queue_free() 41 | 42 | # If player is in range, show UI and make item pickable 43 | func _on_area_2d_body_entered(body): 44 | if body.is_in_group("Player"): 45 | player_in_range = true 46 | body.interact_ui.visible = true 47 | 48 | # If player is in range, hide UI and don't make item pickable 49 | func _on_area_2d_body_exited(body): 50 | if body.is_in_group("Player"): 51 | player_in_range = false 52 | body.interact_ui.visible = false 53 | 54 | # Sets the item's dictionary data 55 | func set_item_data(data): 56 | item_type = data["type"] 57 | item_name = data["name"] 58 | item_effect = data["effect"] 59 | item_texture = data["texture"] -------------------------------------------------------------------------------- /Sectional_Code/08 - Inventory Slots (Dropping Items)/Scripts/Inventory_Slot.gd: -------------------------------------------------------------------------------- 1 | ## Inventory_Slot.gd 2 | 3 | # Scene-Tree Node references 4 | @onready var icon = $InnerBorder/ItemIcon 5 | @onready var quantity_label = $InnerBorder/ItemQuantity 6 | @onready var details_panel = $DetailsPanel 7 | @onready var item_name = $DetailsPanel/ItemName 8 | @onready var item_type = $DetailsPanel/ItemType 9 | @onready var item_effect = $DetailsPanel/ItemEffect 10 | @onready var usage_panel = $UsagePanel 11 | 12 | # Slot Item 13 | var item = null 14 | 15 | # Show usage panel for player to use/remove item 16 | func _on_button_pressed(): 17 | if item != null: 18 | usage_panel.visible = !usage_panel.visible 19 | 20 | # Show item details on hover enter 21 | func _on_button_mouse_entered(): 22 | if item != null: 23 | usage_panel.visible = false 24 | details_panel.visible = true 25 | 26 | # Hide item details on hover exit 27 | func _on_button_mouse_exited(): 28 | details_panel.visible = false 29 | 30 | # Remove item from inventory and drop it back into the world 31 | func _on_drop_button_pressed(): 32 | if item != null: 33 | var drop_position = Global.player_node.global_position 34 | var drop_offset = Vector2(50, 0) 35 | drop_offset = drop_offset.rotated(Global.player_node.rotation) 36 | Global.drop_item(item, drop_position + drop_offset) 37 | Global.remove_item(item["type"], item["effect"]) 38 | usage_panel.visible = false 39 | 40 | # Default empty slot 41 | func set_empty(): 42 | icon.texture = null 43 | quantity_label.text = "" 44 | 45 | # Set slot item with its values from the dictionary 46 | func set_item(new_item): 47 | item = new_item 48 | icon.texture = item["texture"] 49 | quantity_label.text = str(item["quantity"]) 50 | item_name.text = str(item["name"]) 51 | item_type.text = str(item["type"]) 52 | if item["effect"] != "": 53 | item_effect.text = str("+ ", item["effect"]) 54 | else: 55 | item_effect.text = "" -------------------------------------------------------------------------------- /Sectional_Code/08 - Inventory Slots (Dropping Items)/Scripts/Inventory_UI.gd: -------------------------------------------------------------------------------- 1 | ###Inventory_UI.gd 2 | extends Control 3 | 4 | # Scene-Tree Node references 5 | @onready var grid_container = $GridContainer 6 | 7 | func _ready(): 8 | # Connect function to signal to update inventory UI 9 | Global.inventory_updated.connect(_on_inventory_updated) 10 | _on_inventory_updated() 11 | 12 | # Update inventory U 13 | func _on_inventory_updated(): 14 | # Clear existing slots 15 | clear_grid_container() 16 | # Add slots for each inventory position 17 | for item in Global.inventory: 18 | var slot = Global.inventory_slot_scene.instantiate() 19 | grid_container.add_child(slot) 20 | if item != null: 21 | slot.set_item(item) 22 | else: 23 | slot.set_empty() 24 | 25 | # Clear inventory UI grid 26 | func clear_grid_container(): 27 | while grid_container.get_child_count() > 0: 28 | var child = grid_container.get_child(0) 29 | grid_container.remove_child(child) 30 | child.queue_free() 31 | -------------------------------------------------------------------------------- /Sectional_Code/08 - Inventory Slots (Dropping Items)/Scripts/Main.gd: -------------------------------------------------------------------------------- 1 | ### Main.gd 2 | extends Node 3 | -------------------------------------------------------------------------------- /Sectional_Code/08 - Inventory Slots (Dropping Items)/Scripts/Player.gd: -------------------------------------------------------------------------------- 1 | ### Player.gd 2 | extends CharacterBody2D 3 | 4 | # Scene-Tree Node references 5 | @onready var inventory_ui = $InventoryUI 6 | @onready var interact_ui = $InteractUI 7 | @onready var animated_sprite = $AnimatedSprite 8 | 9 | # Variables 10 | @export var speed = 200 11 | 12 | func _ready(): 13 | # Set this node as the Player node 14 | Global.set_player_reference(self) 15 | 16 | # Input for movement 17 | func get_input(): 18 | var input_direction = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down") 19 | velocity = input_direction * speed 20 | 21 | # Movement & Animation 22 | func _physics_process(delta): 23 | get_input() 24 | move_and_slide() 25 | update_animation() 26 | 27 | # Animation 28 | func update_animation(): 29 | if velocity == Vector2.ZERO: 30 | animated_sprite.play("idle") 31 | else: 32 | if abs(velocity.x) > abs(velocity.y): 33 | if velocity.x > 0: 34 | animated_sprite.play("walk_right") 35 | else: 36 | animated_sprite.play("walk_left") 37 | else: 38 | if velocity.y > 0: 39 | animated_sprite.play("walk_down") 40 | else: 41 | animated_sprite.play("walk_up") 42 | 43 | # Show inventory menu on "I" pressed 44 | func _input(event): 45 | if event.is_action_pressed("ui_inventory"): 46 | inventory_ui.visible = !inventory_ui.visible 47 | get_tree().paused = !get_tree().paused 48 | -------------------------------------------------------------------------------- /Sectional_Code/09 - Using Inventory Items/Scripts/Global.gd: -------------------------------------------------------------------------------- 1 | ### Global.gd 2 | 3 | extends Node 4 | 5 | # Inventory items 6 | var inventory = [] 7 | 8 | # Custom signals 9 | signal inventory_updated 10 | 11 | # Scene and node references 12 | var player_node: Node = null 13 | @onready var inventory_slot_scene = preload("res://Scenes/Inventory_Slot.tscn") 14 | 15 | func _ready(): 16 | # Initializes the inventory with 30 slots (spread over 9 blocks per row) 17 | inventory.resize(30) 18 | 19 | # Adds an item to the inventory, returns true if successful 20 | func add_item(item): 21 | for i in range(inventory.size()): 22 | # Check if the item exists in the inventory and matches both type and effect 23 | if inventory[i] != null and inventory[i]["type"] == item["type"] and inventory[i]["effect"] == item["effect"]: 24 | inventory[i]["quantity"] += item["quantity"] 25 | inventory_updated.emit() 26 | print("Item added", inventory) 27 | return true 28 | elif inventory[i] == null: 29 | inventory[i] = item 30 | inventory_updated.emit() 31 | print("Item added", inventory) 32 | return true 33 | return false 34 | 35 | # Removes an item from the inventory based on type and effect 36 | func remove_item(item_type, item_effect): 37 | for i in range(inventory.size()): 38 | if inventory[i] != null and inventory[i]["type"] == item_type and inventory[i]["effect"] == item_effect: 39 | inventory[i]["quantity"] -= 1 40 | if inventory[i]["quantity"] <= 0: 41 | inventory[i] = null 42 | inventory_updated.emit() 43 | return true 44 | return false 45 | 46 | # Increase inventory size dynamically 47 | func increase_inventory_size(extra_slots): 48 | inventory.resize(inventory.size() + extra_slots) 49 | inventory_updated.emit() 50 | 51 | # Sets the player reference for inventory interactions 52 | func set_player_reference(player): 53 | player_node = player 54 | 55 | # Adjusts the drop position to avoid overlapping with nearby items 56 | func adjust_drop_position(position): 57 | var radius = 100 58 | var nearby_items = get_tree().get_nodes_in_group("Items") 59 | for item in nearby_items: 60 | if item.global_position.distance_to(position) < radius: 61 | var random_offset = Vector2(randf_range(-radius, radius), randf_range(-radius, radius)) 62 | position += random_offset 63 | break 64 | return position 65 | 66 | # Drops an item at a specified position, adjusting for nearby items 67 | func drop_item(item_data, drop_position): 68 | var item_scene = load(item_data["scene_path"]) 69 | var item_instance = item_scene.instantiate() 70 | item_instance.set_item_data(item_data) 71 | drop_position = adjust_drop_position(drop_position) 72 | item_instance.global_position = drop_position 73 | get_tree().current_scene.add_child(item_instance) 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /Sectional_Code/09 - Using Inventory Items/Scripts/Inventory_Item.gd: -------------------------------------------------------------------------------- 1 | ### Inventory_Item.gd 2 | @tool 3 | extends Node2D 4 | 5 | # Item details for editor window 6 | @export var item_type = "" 7 | @export var item_name = "" 8 | @export var item_texture: Texture 9 | @export var item_effect = "" 10 | var scene_path: String = "res://Scenes/Inventory_Item.tscn" 11 | 12 | # Scene-Tree Node references 13 | @onready var icon_sprite = $Sprite2D 14 | 15 | # Variables 16 | var player_in_range = false 17 | 18 | func _ready(): 19 | # Set the texture to reflect in the game 20 | if not Engine.is_editor_hint(): 21 | icon_sprite.texture = item_texture 22 | 23 | func _process(_delta): 24 | # Set the texture to reflect in the editor 25 | if Engine.is_editor_hint(): 26 | icon_sprite.texture = item_texture 27 | # Add item to inventory if player presses "E" within range 28 | if player_in_range and Input.is_action_just_pressed("ui_add"): 29 | pickup_item() 30 | 31 | # Add item to inventory 32 | func pickup_item(): 33 | var item = { 34 | "quantity": 1, 35 | "type": item_type, 36 | "name": item_name, 37 | "effect": item_effect, 38 | "texture": item_texture, 39 | "scene_path": scene_path 40 | } 41 | if Global.player_node: 42 | Global.add_item(item) 43 | self.queue_free() 44 | 45 | # If player is in range, show UI and make item pickable 46 | func _on_area_2d_body_entered(body): 47 | if body.is_in_group("Player"): 48 | player_in_range = true 49 | body.interact_ui.visible = true 50 | 51 | # If player is in range, hide UI and don't make item pickable 52 | func _on_area_2d_body_exited(body): 53 | if body.is_in_group("Player"): 54 | player_in_range = false 55 | body.interact_ui.visible = false 56 | 57 | # Sets the item's dictionary data 58 | func set_item_data(data): 59 | item_type = data["type"] 60 | item_name = data["name"] 61 | item_effect = data["effect"] 62 | item_texture = data["texture"] 63 | -------------------------------------------------------------------------------- /Sectional_Code/09 - Using Inventory Items/Scripts/Inventory_Slot.gd: -------------------------------------------------------------------------------- 1 | ### Inventory_Slot.gd 2 | 3 | extends Control 4 | 5 | # Scene-Tree Node references 6 | @onready var icon = $InnerBorder/ItemIcon 7 | @onready var quantity_label = $InnerBorder/ItemQuantity 8 | @onready var details_panel = $DetailsPanel 9 | @onready var item_name = $DetailsPanel/ItemName 10 | @onready var item_type = $DetailsPanel/ItemType 11 | @onready var item_effect = $DetailsPanel/ItemEffect 12 | @onready var usage_panel = $UsagePanel 13 | 14 | # Slot item 15 | var item = null 16 | 17 | # Show usage panel for player to use/remove item 18 | func _on_item_button_pressed(): 19 | if item != null: 20 | usage_panel.visible = !usage_panel.visible 21 | 22 | # Show item details on hover enter 23 | func _on_item_button_mouse_entered(): 24 | if item != null: 25 | usage_panel.visible = false 26 | details_panel.visible = true 27 | 28 | # Hide item details on hover exit 29 | func _on_item_button_mouse_exited(): 30 | details_panel.visible = false 31 | 32 | # Default empty slot 33 | func set_empty(): 34 | icon.texture = null 35 | quantity_label.text = "" 36 | 37 | # Set slot item with its values from the dictionary 38 | func set_item(new_item): 39 | item = new_item 40 | icon.texture = item["texture"] 41 | quantity_label.text = str(item["quantity"]) 42 | item_name.text = str(item["name"]) 43 | item_type.text = str(item["type"]) 44 | if item["effect"] != "": 45 | item_effect.text = str("+ ", item["effect"]) 46 | else: 47 | item_effect.text = "" 48 | 49 | # Remove item from inventory and drop it back into the world 50 | func _on_drop_button_pressed(): 51 | if item != null: 52 | var drop_position = Global.player_node.global_position 53 | var drop_offset = Vector2(0, 50) 54 | drop_offset = drop_offset.rotated(Global.player_node.rotation) 55 | Global.drop_item(item, drop_position + drop_offset) 56 | Global.remove_item(item["type"], item["effect"]) 57 | usage_panel.visible = false 58 | 59 | # Remove item from inventory, use it, and apply its effect (if possible) 60 | func _on_use_button_pressed(): 61 | usage_panel.visible = false 62 | if item != null and item["effect"] != "": 63 | if Global.player_node: 64 | Global.player_node.apply_item_effect(item) 65 | Global.remove_item(item["type"], item["effect"]) 66 | else: 67 | print("Player could not be found") 68 | -------------------------------------------------------------------------------- /Sectional_Code/09 - Using Inventory Items/Scripts/Inventory_UI.gd: -------------------------------------------------------------------------------- 1 | ### Inventory_UI.gd 2 | 3 | extends Control 4 | 5 | # Scene-Tree Node references 6 | @onready var grid_container = $GridContainer 7 | 8 | func _ready(): 9 | # Connect function to signal to update inventory UI 10 | Global.inventory_updated.connect(_on_inventory_updated) 11 | _on_inventory_updated() 12 | 13 | # Update inventory UI 14 | func _on_inventory_updated(): 15 | # Clear existing slots 16 | clear_grid_container() 17 | # Add slots for each inventory position 18 | for item in Global.inventory: 19 | var slot = Global.inventory_slot_scene.instantiate() 20 | grid_container.add_child(slot) 21 | if item != null: 22 | slot.set_item(item) 23 | else: 24 | slot.set_empty() 25 | 26 | # Clear inventory UI grid 27 | func clear_grid_container(): 28 | while grid_container.get_child_count() > 0: 29 | var child = grid_container.get_child(0) 30 | grid_container.remove_child(child) 31 | child.queue_free() 32 | -------------------------------------------------------------------------------- /Sectional_Code/09 - Using Inventory Items/Scripts/Main.gd: -------------------------------------------------------------------------------- 1 | ### Main.gd 2 | 3 | extends Node2D 4 | 5 | # Called when the node enters the scene tree for the first time. 6 | func _ready(): 7 | pass # Replace with function body. 8 | 9 | 10 | # Called every frame. 'delta' is the elapsed time since the previous frame. 11 | func _process(delta): 12 | pass 13 | -------------------------------------------------------------------------------- /Sectional_Code/09 - Using Inventory Items/Scripts/Player.gd: -------------------------------------------------------------------------------- 1 | ### Player.gd 2 | extends CharacterBody2D 3 | 4 | # Scene-Tree Node references 5 | @onready var animated_sprite = $AnimatedSprite2D 6 | @onready var interact_ui = $InteractUI 7 | @onready var inventory_ui = $InventoryUI 8 | 9 | # Variables 10 | @export var speed = 200 11 | 12 | func _ready(): 13 | # Set this node as the Player node 14 | Global.set_player_reference(self) 15 | 16 | # Input for movement 17 | func get_input(): 18 | var input_direction = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down") 19 | velocity = input_direction * speed 20 | 21 | # Movement & Animation 22 | func _physics_process(delta): 23 | get_input() 24 | move_and_slide() 25 | update_animation() 26 | 27 | # Animation 28 | func update_animation(): 29 | if velocity == Vector2.ZERO: 30 | animated_sprite.play("idle") 31 | else: 32 | if abs(velocity.x) > abs(velocity.y): 33 | if velocity.x > 0: 34 | animated_sprite.play("walk_right") 35 | else: 36 | animated_sprite.play("walk_left") 37 | else: 38 | if velocity.y > 0: 39 | animated_sprite.play("walk_down") 40 | else: 41 | animated_sprite.play("walk_up") 42 | 43 | # Show inventory menu on "I" pressed 44 | func _input(event): 45 | if event.is_action_pressed("ui_inventory"): 46 | inventory_ui.visible = !inventory_ui.visible 47 | get_tree().paused = !get_tree().paused 48 | 49 | # Apply the effect of the item (if possible) 50 | func apply_item_effect(item): 51 | match item["effect"]: 52 | "Stamina": 53 | speed += 50 54 | print("Speed increased to ", speed) 55 | "Slot Boost": 56 | Global.increase_inventory_size(5) 57 | print("Slots increased to ", Global.inventory.size()) 58 | _: 59 | print("There is no effect for this item") 60 | 61 | -------------------------------------------------------------------------------- /Sectional_Code/10 - Spawning Items/Scripts/Global.gd: -------------------------------------------------------------------------------- 1 | ### Global.gd 2 | 3 | extends Node 4 | 5 | # Inventory items 6 | var inventory = [] 7 | 8 | # Custom signals 9 | signal inventory_updated 10 | var spawnable_items = [ 11 | {"type": "Consumable", "name": "Berry", "effect": "Health", "texture": preload("res://Assets/Assets/Icons/icon31.png")}, 12 | {"type": "Consumable", "name": "Water", "effect": "Stamina", "texture": preload("res://Assets/Assets/Icons/icon9.png")}, 13 | {"type": "Consumable", "name": "Mushroom", "effect": "Armor", "texture": preload("res://Assets/Assets/Icons/icon32.png")}, 14 | {"type": "Gift", "name": "Gemstone", "effect": "", "texture": preload("res://Assets/Assets/Icons/icon21.png")}, 15 | ] 16 | 17 | # Scene and node references 18 | var player_node: Node = null 19 | @onready var inventory_slot_scene = preload("res://Scenes/Inventory_Slot.tscn") 20 | 21 | func _ready(): 22 | # Initializes the inventory with 30 slots (spread over 9 blocks per row) 23 | inventory.resize(30) 24 | 25 | # Adds an item to the inventory, returns true if successful 26 | func add_item(item): 27 | for i in range(inventory.size()): 28 | # Check if the item exists in the inventory and matches both type and effect 29 | if inventory[i] != null and inventory[i]["type"] == item["type"] and inventory[i]["effect"] == item["effect"]: 30 | inventory[i]["quantity"] += item["quantity"] 31 | inventory_updated.emit() 32 | print("Item added", inventory) 33 | return true 34 | elif inventory[i] == null: 35 | inventory[i] = item 36 | inventory_updated.emit() 37 | print("Item added", inventory) 38 | return true 39 | return false 40 | 41 | # Removes an item from the inventory based on type and effect 42 | func remove_item(item_type, item_effect): 43 | for i in range(inventory.size()): 44 | if inventory[i] != null and inventory[i]["type"] == item_type and inventory[i]["effect"] == item_effect: 45 | inventory[i]["quantity"] -= 1 46 | if inventory[i]["quantity"] <= 0: 47 | inventory[i] = null 48 | inventory_updated.emit() 49 | return true 50 | return false 51 | 52 | # Increase inventory size dynamically 53 | func increase_inventory_size(extra_slots): 54 | inventory.resize(inventory.size() + extra_slots) 55 | inventory_updated.emit() 56 | 57 | # Sets the player reference for inventory interactions 58 | func set_player_reference(player): 59 | player_node = player 60 | 61 | # Adjusts the drop position to avoid overlapping with nearby items 62 | func adjust_drop_position(position): 63 | var radius = 100 64 | var nearby_items = get_tree().get_nodes_in_group("Items") 65 | for item in nearby_items: 66 | if item.global_position.distance_to(position) < radius: 67 | var random_offset = Vector2(randf_range(-radius, radius), randf_range(-radius, radius)) 68 | position += random_offset 69 | break 70 | return position 71 | 72 | # Drops an item at a specified position, adjusting for nearby items 73 | func drop_item(item_data, drop_position): 74 | var item_scene = load(item_data["scene_path"]) 75 | var item_instance = item_scene.instantiate() 76 | item_instance.set_item_data(item_data) 77 | drop_position = adjust_drop_position(drop_position) 78 | item_instance.global_position = drop_position 79 | get_tree().current_scene.add_child(item_instance) 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /Sectional_Code/10 - Spawning Items/Scripts/Inventory_Item.gd: -------------------------------------------------------------------------------- 1 | ### Inventory_Item.gd 2 | @tool 3 | extends Node2D 4 | 5 | # Item details for editor window 6 | @export var item_type = "" 7 | @export var item_name = "" 8 | @export var item_texture: Texture 9 | @export var item_effect = "" 10 | var scene_path: String = "res://Scenes/Inventory_Item.tscn" 11 | 12 | # Scene-Tree Node references 13 | @onready var icon_sprite = $Sprite2D 14 | 15 | # Variables 16 | var player_in_range = false 17 | 18 | func _ready(): 19 | # Set the texture to reflect in the game 20 | if not Engine.is_editor_hint(): 21 | icon_sprite.texture = item_texture 22 | 23 | func _process(_delta): 24 | # Set the texture to reflect in the editor 25 | if Engine.is_editor_hint(): 26 | icon_sprite.texture = item_texture 27 | # Add item to inventory if player presses "E" within range 28 | if player_in_range and Input.is_action_just_pressed("ui_add"): 29 | pickup_item() 30 | 31 | # Add item to inventory 32 | func pickup_item(): 33 | var item = { 34 | "quantity": 1, 35 | "type": item_type, 36 | "name": item_name, 37 | "effect": item_effect, 38 | "texture": item_texture, 39 | "scene_path": scene_path 40 | } 41 | if Global.player_node: 42 | Global.add_item(item) 43 | self.queue_free() 44 | 45 | # If player is in range, show UI and make item pickable 46 | func _on_area_2d_body_entered(body): 47 | if body.is_in_group("Player"): 48 | player_in_range = true 49 | body.interact_ui.visible = true 50 | 51 | # If player is in range, hide UI and don't make item pickable 52 | func _on_area_2d_body_exited(body): 53 | if body.is_in_group("Player"): 54 | player_in_range = false 55 | body.interact_ui.visible = false 56 | 57 | # Sets the item's dictionary data 58 | func set_item_data(data): 59 | item_type = data["type"] 60 | item_name = data["name"] 61 | item_effect = data["effect"] 62 | item_texture = data["texture"] 63 | 64 | # Set the items values for spawning 65 | func initiate_items(type, name, effect, texture): 66 | item_type = type 67 | item_name = name 68 | item_effect = effect 69 | item_texture = texture 70 | -------------------------------------------------------------------------------- /Sectional_Code/10 - Spawning Items/Scripts/Inventory_Slot.gd: -------------------------------------------------------------------------------- 1 | ### Inventory_Slot.gd 2 | 3 | extends Control 4 | 5 | # Scene-Tree Node references 6 | @onready var icon = $InnerBorder/ItemIcon 7 | @onready var quantity_label = $InnerBorder/ItemQuantity 8 | @onready var details_panel = $DetailsPanel 9 | @onready var item_name = $DetailsPanel/ItemName 10 | @onready var item_type = $DetailsPanel/ItemType 11 | @onready var item_effect = $DetailsPanel/ItemEffect 12 | @onready var usage_panel = $UsagePanel 13 | 14 | # Slot item 15 | var item = null 16 | 17 | # Show usage panel for player to use/remove item 18 | func _on_item_button_pressed(): 19 | if item != null: 20 | usage_panel.visible = !usage_panel.visible 21 | 22 | # Show item details on hover enter 23 | func _on_item_button_mouse_entered(): 24 | if item != null: 25 | usage_panel.visible = false 26 | details_panel.visible = true 27 | 28 | # Hide item details on hover exit 29 | func _on_item_button_mouse_exited(): 30 | details_panel.visible = false 31 | 32 | # Default empty slot 33 | func set_empty(): 34 | icon.texture = null 35 | quantity_label.text = "" 36 | 37 | # Set slot item with its values from the dictionary 38 | func set_item(new_item): 39 | item = new_item 40 | icon.texture = item["texture"] 41 | quantity_label.text = str(item["quantity"]) 42 | item_name.text = str(item["name"]) 43 | item_type.text = str(item["type"]) 44 | if item["effect"] != "": 45 | item_effect.text = str("+ ", item["effect"]) 46 | else: 47 | item_effect.text = "" 48 | 49 | # Remove item from inventory and drop it back into the world 50 | func _on_drop_button_pressed(): 51 | if item != null: 52 | var drop_position = Global.player_node.global_position 53 | var drop_offset = Vector2(0, 50) 54 | drop_offset = drop_offset.rotated(Global.player_node.rotation) 55 | Global.drop_item(item, drop_position + drop_offset) 56 | Global.remove_item(item["type"], item["effect"]) 57 | usage_panel.visible = false 58 | 59 | # Remove item from inventory, use it, and apply its effect (if possible) 60 | func _on_use_button_pressed(): 61 | usage_panel.visible = false 62 | if item != null and item["effect"] != "": 63 | if Global.player_node: 64 | Global.player_node.apply_item_effect(item) 65 | Global.remove_item(item["type"], item["effect"]) 66 | else: 67 | print("Player could not be found") 68 | -------------------------------------------------------------------------------- /Sectional_Code/10 - Spawning Items/Scripts/Inventory_UI.gd: -------------------------------------------------------------------------------- 1 | ### Inventory_UI.gd 2 | 3 | extends Control 4 | 5 | # Scene-Tree Node references 6 | @onready var grid_container = $GridContainer 7 | 8 | func _ready(): 9 | # Connect function to signal to update inventory UI 10 | Global.inventory_updated.connect(_on_inventory_updated) 11 | _on_inventory_updated() 12 | 13 | # Update inventory UI 14 | func _on_inventory_updated(): 15 | # Clear existing slots 16 | clear_grid_container() 17 | # Add slots for each inventory position 18 | for item in Global.inventory: 19 | var slot = Global.inventory_slot_scene.instantiate() 20 | grid_container.add_child(slot) 21 | if item != null: 22 | slot.set_item(item) 23 | else: 24 | slot.set_empty() 25 | 26 | # Clear inventory UI grid 27 | func clear_grid_container(): 28 | while grid_container.get_child_count() > 0: 29 | var child = grid_container.get_child(0) 30 | grid_container.remove_child(child) 31 | child.queue_free() 32 | -------------------------------------------------------------------------------- /Sectional_Code/10 - Spawning Items/Scripts/Main.gd: -------------------------------------------------------------------------------- 1 | ### Main.gd 2 | 3 | extends Node2D 4 | 5 | # Scene-Tree Node references 6 | @onready var items = $Items 7 | @onready var item_spawn_area = $ItemSpawnArea 8 | @onready var collision_shape = $ItemSpawnArea/CollisionShape2D 9 | 10 | # Called when the node enters the scene tree for the first time. 11 | func _ready(): 12 | spawn_random_items(10) 13 | 14 | # Get random position for item within the collision shape in spawn area 15 | func get_random_position(): 16 | var area_rect = collision_shape.shape.get_rect() 17 | var x = randf_range(0, area_rect.position.x) 18 | var y = randf_range(0, area_rect.position.y) 19 | return item_spawn_area.to_global(Vector2(x, y)) 20 | 21 | func spawn_random_items(count): 22 | var attempts = 0 23 | var spawned_count = 0 24 | while spawned_count < count and attempts < 100: 25 | var position = get_random_position() 26 | spawn_item(Global.spawnable_items[randi() % Global.spawnable_items.size()], position) 27 | spawned_count += 1 28 | attempts += 1 29 | 30 | # Create a physical instance of the Item scene on the map underneath /Items node 31 | func spawn_item(data, position): 32 | var item_scene = preload("res://Scenes/Inventory_Item.tscn") 33 | var item_instance = item_scene.instantiate() 34 | item_instance.initiate_items(data["type"], data["name"], data["effect"], data["texture"]) 35 | item_instance.global_position = position 36 | items.add_child(item_instance) 37 | -------------------------------------------------------------------------------- /Sectional_Code/10 - Spawning Items/Scripts/Player.gd: -------------------------------------------------------------------------------- 1 | ### Player.gd 2 | extends CharacterBody2D 3 | 4 | # Scene-Tree Node references 5 | @onready var animated_sprite = $AnimatedSprite2D 6 | @onready var interact_ui = $InteractUI 7 | @onready var inventory_ui = $InventoryUI 8 | 9 | # Variables 10 | @export var speed = 200 11 | 12 | func _ready(): 13 | # Set this node as the Player node 14 | Global.set_player_reference(self) 15 | 16 | # Input for movement 17 | func get_input(): 18 | var input_direction = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down") 19 | velocity = input_direction * speed 20 | 21 | # Movement & Animation 22 | func _physics_process(delta): 23 | get_input() 24 | move_and_slide() 25 | update_animation() 26 | 27 | # Animation 28 | func update_animation(): 29 | if velocity == Vector2.ZERO: 30 | animated_sprite.play("idle") 31 | else: 32 | if abs(velocity.x) > abs(velocity.y): 33 | if velocity.x > 0: 34 | animated_sprite.play("walk_right") 35 | else: 36 | animated_sprite.play("walk_left") 37 | else: 38 | if velocity.y > 0: 39 | animated_sprite.play("walk_down") 40 | else: 41 | animated_sprite.play("walk_up") 42 | 43 | # Show inventory menu on "I" pressed 44 | func _input(event): 45 | if event.is_action_pressed("ui_inventory"): 46 | inventory_ui.visible = !inventory_ui.visible 47 | get_tree().paused = !get_tree().paused 48 | 49 | # Apply the effect of the item (if possible) 50 | func apply_item_effect(item): 51 | match item["effect"]: 52 | "Stamina": 53 | speed += 50 54 | print("Speed increased to ", speed) 55 | "Slot Boost": 56 | Global.increase_inventory_size(5) 57 | print("Slots increased to ", Global.inventory.size()) 58 | _: 59 | print("There is no effect for this item") 60 | 61 | -------------------------------------------------------------------------------- /Sectional_Code/11 - Hotbar - Part 1/Scripts/Global.gd: -------------------------------------------------------------------------------- 1 | ### Global.gd 2 | 3 | extends Node 4 | 5 | # Scene and node references 6 | @onready var inventory_slot_scene = preload("res://Scenes/Inventory_Slot.tscn") 7 | var player_node: Node = null 8 | 9 | # Inventory items 10 | var inventory = [] 11 | var spawnable_items = [ 12 | {"type": "Consumable", "name": "Berry", "effect": "Health", "texture": preload("res://Assets/Icons/icon31.png")}, 13 | {"type": "Consumable", "name": "Water", "effect": "Stamina", "texture": preload("res://Assets/Icons/icon9.png")}, 14 | {"type": "Consumable", "name": "Mushroom", "effect": "Armor", "texture": preload("res://Assets/Icons/icon32.png")}, 15 | {"type": "Gift", "name": "Gemstone", "effect": "", "texture": preload("res://Assets/Icons/icon21.png")}, 16 | ] 17 | 18 | # Custom signals 19 | signal inventory_updated 20 | 21 | # Hotbar items 22 | var hotbar_size = 5 23 | var hotbar_inventory = [] 24 | 25 | func _ready(): 26 | # Initializes the inventory with 30 slots (spread over 9 blocks per row) 27 | inventory.resize(30) 28 | # Hotbar size 29 | hotbar_inventory.resize(hotbar_size) 30 | 31 | # Sets the player reference for inventory interactions 32 | func set_player_reference(player): 33 | player_node = player 34 | 35 | # Adds an item to the inventory, returns true if successful 36 | func add_item(item, to_hotbar = false): 37 | var added_to_hotbar = false 38 | if to_hotbar: 39 | added_to_hotbar = add_hotbar_item(item) 40 | inventory_updated.emit() 41 | if not added_to_hotbar: 42 | for i in range(inventory.size()): 43 | # Check if the item exists in the inventory and matches both type and effect 44 | if inventory[i] != null and inventory[i]["type"] == item["type"] and inventory[i]["effect"] == item["effect"]: 45 | inventory[i]["quantity"] += item["quantity"] 46 | inventory_updated.emit() 47 | print("Item added", inventory) 48 | return true 49 | elif inventory[i] == null: 50 | inventory[i] = item 51 | inventory_updated.emit() 52 | print("Item added", inventory) 53 | return true 54 | return false 55 | 56 | # Removes an item from the inventory based on type and effect 57 | func remove_item(item_type, item_effect): 58 | # Inventory removal 59 | for i in range(inventory.size()): 60 | if inventory[i] != null and inventory[i]["type"] == item_type and inventory[i]["effect"] == item_effect: 61 | inventory[i]["quantity"] -= 1 62 | if inventory[i]["quantity"] <= 0: 63 | inventory[i] = null 64 | inventory_updated.emit() 65 | return true 66 | return false 67 | 68 | # Increase inventory size dynamically 69 | func increase_inventory_size(extra_slots): 70 | inventory.resize(inventory.size() + extra_slots) 71 | inventory_updated.emit() 72 | 73 | # Drops an item at a specified position, adjusting for nearby items 74 | func drop_item(item_data, drop_position): 75 | var item_scene = load(item_data["scene_path"]) 76 | var item_instance = item_scene.instantiate() 77 | item_instance.set_item_data(item_data) 78 | drop_position = adjust_drop_position(drop_position) 79 | item_instance.global_position = drop_position 80 | get_tree().current_scene.add_child(item_instance) 81 | 82 | # Adjusts the drop position to avoid overlapping with nearby items 83 | func adjust_drop_position(position): 84 | var radius = 100 85 | var nearby_items = get_tree().get_nodes_in_group("Items") 86 | for item in nearby_items: 87 | if item.global_position.distance_to(position) < radius: 88 | var random_offset = Vector2(randf_range(-radius, radius), randf_range(-radius, radius)) 89 | position += random_offset 90 | break 91 | return position 92 | 93 | # Try adding to hotbar 94 | func add_hotbar_item(item): 95 | for i in range(hotbar_size): 96 | if hotbar_inventory[i] == null: 97 | hotbar_inventory[i] = item 98 | return true 99 | return false 100 | 101 | # Removes an item from the hotbar 102 | func remove_hotbar_item(item_type, item_effect): 103 | for i in range(hotbar_inventory.size()): 104 | if hotbar_inventory[i] != null and hotbar_inventory[i]["type"] == item_type and hotbar_inventory[i]["effect"] == item_effect: 105 | if hotbar_inventory[i]["quantity"] <= 0: 106 | hotbar_inventory[i] = null 107 | inventory_updated.emit() 108 | return true 109 | return false 110 | 111 | # Unassigns an item from the hotbar 112 | func unassign_hotbar_item(item_type, item_effect): 113 | for i in range(hotbar_inventory.size()): 114 | if hotbar_inventory[i] != null and hotbar_inventory[i]["type"] == item_type and hotbar_inventory[i]["effect"] == item_effect: 115 | hotbar_inventory[i] = null 116 | inventory_updated.emit() 117 | return true 118 | return false -------------------------------------------------------------------------------- /Sectional_Code/11 - Hotbar - Part 1/Scripts/Inventory_Hotbar.gd: -------------------------------------------------------------------------------- 1 | ### Inventory_Hotbar.gd 2 | 3 | extends Control 4 | 5 | # Scene-Tree Node references 6 | @onready var hotbar_container = $HBoxContainer 7 | 8 | func _ready(): 9 | Global.inventory_updated.connect(_update_hotbar) 10 | _update_hotbar() 11 | 12 | # Create the hotbar slots 13 | func _update_hotbar(): 14 | clear_hotbar_container() 15 | for i in range(Global.hotbar_size): 16 | var item = Global.hotbar_inventory[i] 17 | var slot = Global.inventory_slot_scene.instantiate() 18 | slot.set_slot_index(i) # Set the index here 19 | hotbar_container.add_child(slot) 20 | if item != null: 21 | slot.set_item(item) 22 | else: 23 | slot.set_empty() 24 | 25 | # Clear hotbar slots 26 | func clear_hotbar_container(): 27 | while hotbar_container.get_child_count() > 0: 28 | var child = hotbar_container.get_child(0) 29 | hotbar_container.remove_child(child) 30 | child.queue_free() 31 | -------------------------------------------------------------------------------- /Sectional_Code/11 - Hotbar - Part 1/Scripts/Inventory_Item.gd: -------------------------------------------------------------------------------- 1 | ### Inventory_Item.gd 2 | @tool 3 | extends Node2D 4 | 5 | # Item details for editor window 6 | @export var item_type = "" 7 | @export var item_name = "" 8 | @export var item_texture: Texture 9 | @export var item_effect = "" 10 | var scene_path: String = "res://Scenes/Inventory_Item.tscn" 11 | 12 | # Scene-Tree Node references 13 | @onready var icon_sprite = $Sprite2D 14 | 15 | # Variables 16 | var player_in_range = false 17 | 18 | func _ready(): 19 | # Set the texture to reflect in the game 20 | if not Engine.is_editor_hint(): 21 | icon_sprite.texture = item_texture 22 | 23 | func _process(_delta): 24 | # Set the texture to reflect in the editor 25 | if Engine.is_editor_hint(): 26 | icon_sprite.texture = item_texture 27 | # Add item to inventory if player presses "E" within range 28 | if player_in_range and Input.is_action_just_pressed("ui_add"): 29 | pickup_item() 30 | 31 | # Add item to inventory 32 | func pickup_item(): 33 | var item = { 34 | "quantity": 1, 35 | "type": item_type, 36 | "name": item_name, 37 | "effect": item_effect, 38 | "texture": item_texture, 39 | "scene_path": scene_path 40 | } 41 | if Global.player_node: 42 | Global.add_item(item, false) 43 | self.queue_free() 44 | 45 | # If player is in range, show UI and make item pickable 46 | func _on_area_2d_body_entered(body): 47 | if body.is_in_group("Player"): 48 | player_in_range = true 49 | body.interact_ui.visible = true 50 | 51 | # If player is in range, hide UI and don't make item pickable 52 | func _on_area_2d_body_exited(body): 53 | if body.is_in_group("Player"): 54 | player_in_range = false 55 | body.interact_ui.visible = false 56 | 57 | # Set the items values for spawning 58 | func initiate_items(type, name, effect, texture): 59 | item_type = type 60 | item_name = name 61 | item_effect = effect 62 | item_texture = texture 63 | 64 | # Sets the item's dictionary data 65 | func set_item_data(data): 66 | item_type = data["type"] 67 | item_name = data["name"] 68 | item_effect = data["effect"] 69 | item_texture = data["texture"] 70 | -------------------------------------------------------------------------------- /Sectional_Code/11 - Hotbar - Part 1/Scripts/Inventory_Slot.gd: -------------------------------------------------------------------------------- 1 | ##Inventory_Slot.gd 2 | 3 | extends Control 4 | 5 | # Scene-Tree Node references 6 | @onready var icon = $InnerBorder/ItemIcon 7 | @onready var quantity_label = $InnerBorder/ItemQuantity 8 | @onready var details_panel = $DetailsPanel 9 | @onready var item_name = $DetailsPanel/ItemName 10 | @onready var item_type = $DetailsPanel/ItemType 11 | @onready var item_effect = $DetailsPanel/ItemEffect 12 | @onready var usage_panel = $UsagePanel 13 | @onready var assign_button = $UsagePanel/AssignButton 14 | 15 | # Slot Item 16 | var item = null 17 | var slot_index = -1 # Default to an invalid index 18 | 19 | # Setting slot index 20 | func set_slot_index(new_index): 21 | slot_index = new_index 22 | 23 | # Default empty slot 24 | func set_empty(): 25 | icon.texture = null 26 | quantity_label.text = "" 27 | 28 | # Set slot item with its values from the dictionary 29 | func set_item(new_item): 30 | item = new_item 31 | icon.texture = item["texture"] 32 | quantity_label.text = str(item["quantity"]) 33 | item_name.text = str(item["name"]) 34 | item_type.text = str(item["type"]) 35 | if item["effect"] != "": 36 | item_effect.text = str("+ ", item["effect"]) 37 | else: 38 | item_effect.text = "" 39 | 40 | # Show usage panel for player to use/remove item 41 | func _on_button_pressed(): 42 | if item != null: 43 | usage_panel.visible = !usage_panel.visible 44 | 45 | # Show item details on hover enter 46 | func _on_button_mouse_entered(): 47 | if item != null: 48 | usage_panel.visible = false 49 | details_panel.visible = true 50 | 51 | # Hide item details on hover exit 52 | func _on_button_mouse_exited(): 53 | details_panel.visible = false 54 | 55 | # Remove item from inventory, use it, and apply its effect (if possible) 56 | func _on_use_button_pressed(): 57 | usage_panel.visible = false 58 | if item != null: 59 | if Global.player_node: 60 | Global.player_node.apply_item_effect(item) 61 | Global.remove_item(item["type"], item["effect"]) 62 | Global.remove_hotbar_item(item["type"], item["effect"]) 63 | else: 64 | print("Player node not found") 65 | 66 | # Remove item from inventory and drop it back into the world 67 | func _on_drop_button_pressed(): 68 | if item != null: 69 | var drop_position = Global.player_node.global_position 70 | var drop_offset = Vector2(50, 0) 71 | drop_offset = drop_offset.rotated(Global.player_node.rotation) 72 | Global.drop_item(item, drop_position + drop_offset) 73 | Global.remove_item(item["type"], item["effect"]) 74 | Global.remove_hotbar_item(item["type"], item["effect"]) 75 | usage_panel.visible = false 76 | 77 | # Assigns item to hotbar 78 | func _on_assign_button_pressed(): 79 | pass -------------------------------------------------------------------------------- /Sectional_Code/11 - Hotbar - Part 1/Scripts/Inventory_UI.gd: -------------------------------------------------------------------------------- 1 | ###Inventory_UI.gd 2 | extends Control 3 | 4 | # Scene-Tree Node references 5 | @onready var grid_container = $GridContainer 6 | 7 | func _ready(): 8 | # Connect function to signal to update inventory UI 9 | Global.inventory_updated.connect(_on_inventory_updated) 10 | _on_inventory_updated() 11 | 12 | # Update inventory UI 13 | func _on_inventory_updated(): 14 | # Clear existing slots 15 | clear_grid_container() 16 | # Add slots for each inventory position 17 | for item in Global.inventory: 18 | var slot = Global.inventory_slot_scene.instantiate() 19 | grid_container.add_child(slot) 20 | if item != null: 21 | slot.set_item(item) 22 | else: 23 | slot.set_empty() 24 | 25 | # Clear inventory UI grid 26 | func clear_grid_container(): 27 | while grid_container.get_child_count() > 0: 28 | var child = grid_container.get_child(0) 29 | grid_container.remove_child(child) 30 | child.queue_free() 31 | -------------------------------------------------------------------------------- /Sectional_Code/11 - Hotbar - Part 1/Scripts/Main.gd: -------------------------------------------------------------------------------- 1 | ### Main.gd 2 | extends Node 3 | 4 | # Scene-Tree Node references 5 | @onready var items = $Items 6 | @onready var item_spawn_area = $ItemSpawnArea 7 | @onready var collision_shape = $ItemSpawnArea/CollisionShape2D 8 | 9 | # When the game loads spawn 10 pickup items in the spawn area 10 | func _ready(): 11 | spawn_random_items(10) 12 | 13 | # Get random position for item within the collision shape in spawn area 14 | func get_random_position(): 15 | var area_rect = collision_shape.shape.get_rect() 16 | var x = randf_range(0, area_rect.position.x) 17 | var y = randf_range(0, area_rect.position.y) 18 | return item_spawn_area.to_global(Vector2(x, y)) 19 | 20 | # Spawn random items from the Global list up until the max amount (10) has been reached 21 | func spawn_random_items(count): 22 | var attempts = 0 23 | var spawned_count = 0 24 | while spawned_count < count and attempts < 100: 25 | var position = get_random_position() 26 | spawn_item(Global.spawnable_items[randi() % Global.spawnable_items.size()], position) 27 | spawned_count += 1 28 | attempts += 1 29 | 30 | # Create a physical instance of the Item scene on the map underneath /Items node 31 | func spawn_item(data, position): 32 | var item_scene = preload("res://Scenes/Inventory_Item.tscn") 33 | var item_instance = item_scene.instantiate() 34 | item_instance.initiate_items(data["type"], data["name"], data["effect"], data["texture"]) 35 | item_instance.global_position = position 36 | items.add_child(item_instance) 37 | -------------------------------------------------------------------------------- /Sectional_Code/11 - Hotbar - Part 1/Scripts/Player.gd: -------------------------------------------------------------------------------- 1 | ### Player.gd 2 | extends CharacterBody2D 3 | 4 | # Scene-Tree Node references 5 | @onready var inventory_ui = $InventoryUI 6 | @onready var interact_ui = $InteractUI 7 | @onready var animated_sprite = $AnimatedSprite 8 | @onready var hotbar_ui = $InventoryHotbar 9 | 10 | # Variables 11 | @export var speed = 200 12 | 13 | func _ready(): 14 | # Set this node as the Player node 15 | Global.set_player_reference(self) 16 | 17 | # Input for movement 18 | func get_input(): 19 | var input_direction = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down") 20 | velocity = input_direction * speed 21 | 22 | # Movement & Animation 23 | func _physics_process(delta): 24 | get_input() 25 | move_and_slide() 26 | update_animation() 27 | 28 | # Animation 29 | func update_animation(): 30 | if velocity == Vector2.ZERO: 31 | animated_sprite.play("idle") 32 | else: 33 | if abs(velocity.x) > abs(velocity.y): 34 | if velocity.x > 0: 35 | animated_sprite.play("walk_right") 36 | else: 37 | animated_sprite.play("walk_left") 38 | else: 39 | if velocity.y > 0: 40 | animated_sprite.play("walk_down") 41 | else: 42 | animated_sprite.play("walk_up") 43 | 44 | # Show inventory menu on "I" pressed 45 | func _input(event): 46 | if event.is_action_pressed("ui_inventory"): 47 | inventory_ui.visible = !inventory_ui.visible 48 | get_tree().paused = !get_tree().paused 49 | hotbar_ui.visible = !hotbar_ui.visible 50 | 51 | # Apply the effect of the item (if possible) 52 | func apply_item_effect(item): 53 | match item["effect"]: 54 | "Stamina": 55 | speed += 50 56 | print("Speed increased to ", speed) 57 | "Slot Boost": 58 | Global.increase_inventory_size(5) 59 | print("Inventory increased to ", Global.inventory.size()) 60 | _: 61 | print("No effect for this item") 62 | -------------------------------------------------------------------------------- /Sectional_Code/12 - Hotbar - Part 2/Scenes/Inv21E0.tmp: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=3 uid="uid://bxbnos3drxhfp"] 2 | 3 | [ext_resource type="Script" path="res://Scripts/Inventory_UI.gd" id="1_ybuun"] 4 | [ext_resource type="PackedScene" uid="uid://xp38ekmolgts" path="res://Scenes/Inventory_Hotbar.tscn" id="2_v4gxy"] 5 | 6 | [node name="InventoryUI" type="Control"] 7 | layout_mode = 3 8 | anchors_preset = 0 9 | size_flags_horizontal = 4 10 | size_flags_vertical = 4 11 | script = ExtResource("1_ybuun") 12 | 13 | [node name="GridContainer" type="GridContainer" parent="."] 14 | layout_mode = 0 15 | offset_left = 200.0 16 | offset_top = 200.0 17 | offset_right = 1000.0 18 | offset_bottom = 600.0 19 | size_flags_horizontal = 3 20 | size_flags_vertical = 3 21 | theme_override_constants/h_separation = 20 22 | theme_override_constants/v_separation = 20 23 | columns = 9 24 | 25 | [node name="Inventory_Hotbar" parent="." instance=ExtResource("2_v4gxy")] 26 | layout_mode = 1 27 | -------------------------------------------------------------------------------- /Sectional_Code/12 - Hotbar - Part 2/Scenes/Inventory_Hotbar.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://xp38ekmolgts"] 2 | 3 | [ext_resource type="Script" path="res://Scripts/Inventory_Hotbar.gd" id="1_frtqr"] 4 | 5 | [node name="Inventory_Hotbar" type="Control"] 6 | layout_mode = 3 7 | anchors_preset = 12 8 | anchor_top = 1.0 9 | anchor_right = 1.0 10 | anchor_bottom = 1.0 11 | grow_horizontal = 2 12 | grow_vertical = 0 13 | script = ExtResource("1_frtqr") 14 | 15 | [node name="HBoxContainer" type="HBoxContainer" parent="."] 16 | layout_mode = 1 17 | anchors_preset = 7 18 | anchor_left = 0.5 19 | anchor_top = 1.0 20 | anchor_right = 0.5 21 | anchor_bottom = 1.0 22 | offset_top = -10.0 23 | offset_bottom = -10.0 24 | grow_horizontal = 2 25 | grow_vertical = 0 26 | theme_override_constants/separation = 10 27 | alignment = 1 28 | -------------------------------------------------------------------------------- /Sectional_Code/12 - Hotbar - Part 2/Scenes/Inventory_Item.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=3 uid="uid://dmqra368itmb1"] 2 | 3 | [ext_resource type="Script" path="res://Scripts/Inventory_Item.gd" id="1_xchys"] 4 | [ext_resource type="Texture2D" uid="uid://cpsjaebpas6w4" path="res://Assets/Icons/icon1.png" id="2_k6yw0"] 5 | 6 | [sub_resource type="CircleShape2D" id="CircleShape2D_t7t2y"] 7 | 8 | [node name="Item" type="Node2D" groups=["Items"]] 9 | script = ExtResource("1_xchys") 10 | item_type = "None" 11 | item_name = "None" 12 | item_texture = ExtResource("2_k6yw0") 13 | item_effect = "None" 14 | 15 | [node name="Area2D" type="Area2D" parent="."] 16 | 17 | [node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"] 18 | shape = SubResource("CircleShape2D_t7t2y") 19 | 20 | [node name="Sprite2D" type="Sprite2D" parent="."] 21 | texture = ExtResource("2_k6yw0") 22 | 23 | [connection signal="body_entered" from="Area2D" to="." method="_on_area_2d_body_entered"] 24 | [connection signal="body_exited" from="Area2D" to="." method="_on_area_2d_body_exited"] 25 | -------------------------------------------------------------------------------- /Sectional_Code/12 - Hotbar - Part 2/Scenes/Inventory_Slot.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=6 format=3 uid="uid://m7ynpurmto7y"] 2 | 3 | [ext_resource type="Script" path="res://Scripts/Inventory_Slot.gd" id="1_2p61u"] 4 | [ext_resource type="Texture2D" uid="uid://vrb1ndxsqx7k" path="res://Assets/Icons/icon3.png" id="2_bj1on"] 5 | [ext_resource type="FontFile" uid="uid://bi04iecmbt37l" path="res://Assets/Fonts/ARCADECLASSIC.TTF" id="3_y3fau"] 6 | 7 | [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_th8tt"] 8 | 9 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_7s3e5"] 10 | bg_color = Color(0.192157, 0.376471, 0.321569, 0.384314) 11 | 12 | [node name="Inventory_Slot" type="Control"] 13 | custom_minimum_size = Vector2(150, 150) 14 | layout_mode = 3 15 | anchors_preset = 0 16 | offset_left = 10.0 17 | offset_top = 10.0 18 | offset_right = 160.0 19 | offset_bottom = 160.0 20 | script = ExtResource("1_2p61u") 21 | 22 | [node name="OuterBorder" type="ColorRect" parent="."] 23 | layout_mode = 1 24 | anchors_preset = 15 25 | anchor_right = 1.0 26 | anchor_bottom = 1.0 27 | grow_horizontal = 2 28 | grow_vertical = 2 29 | color = Color(0.596078, 0.933333, 0.8, 1) 30 | 31 | [node name="InnerBorder" type="ColorRect" parent="."] 32 | layout_mode = 1 33 | anchors_preset = 8 34 | anchor_left = 0.5 35 | anchor_top = 0.5 36 | anchor_right = 0.5 37 | anchor_bottom = 0.5 38 | offset_left = -70.0 39 | offset_top = -70.0 40 | offset_right = 70.0 41 | offset_bottom = 70.0 42 | grow_horizontal = 2 43 | grow_vertical = 2 44 | color = Color(0.611765, 0.603922, 0.584314, 1) 45 | 46 | [node name="ItemIcon" type="Sprite2D" parent="InnerBorder"] 47 | position = Vector2(70, 70) 48 | scale = Vector2(2.5, 2.5) 49 | texture = ExtResource("2_bj1on") 50 | 51 | [node name="ItemQuantity" type="Label" parent="InnerBorder"] 52 | layout_mode = 1 53 | offset_left = 5.0 54 | offset_right = 38.0 55 | offset_bottom = 64.0 56 | theme_override_colors/font_color = Color(0.0745098, 0.0745098, 0.0745098, 1) 57 | theme_override_fonts/font = ExtResource("3_y3fau") 58 | theme_override_font_sizes/font_size = 50 59 | text = "1" 60 | 61 | [node name="ItemButton" type="Button" parent="."] 62 | layout_mode = 1 63 | anchors_preset = 15 64 | anchor_right = 1.0 65 | anchor_bottom = 1.0 66 | grow_horizontal = 2 67 | grow_vertical = 2 68 | theme_override_styles/normal = SubResource("StyleBoxEmpty_th8tt") 69 | theme_override_styles/hover = SubResource("StyleBoxFlat_7s3e5") 70 | 71 | [node name="DetailsPanel" type="ColorRect" parent="."] 72 | visible = false 73 | layout_mode = 0 74 | offset_top = -135.0 75 | offset_right = 240.0 76 | offset_bottom = -5.0 77 | color = Color(0.596078, 0.933333, 0.8, 1) 78 | 79 | [node name="ItemName" type="Label" parent="DetailsPanel"] 80 | layout_mode = 1 81 | offset_left = 5.0 82 | offset_right = 73.0 83 | offset_bottom = 19.0 84 | theme_override_colors/font_color = Color(0.0745098, 0.0745098, 0.0745098, 1) 85 | theme_override_fonts/font = ExtResource("3_y3fau") 86 | theme_override_font_sizes/font_size = 40 87 | text = "Item Name" 88 | 89 | [node name="ItemType" type="Label" parent="DetailsPanel"] 90 | layout_mode = 1 91 | anchors_preset = 4 92 | anchor_top = 0.5 93 | anchor_bottom = 0.5 94 | offset_left = 5.0 95 | offset_top = -9.5 96 | offset_right = 73.0 97 | offset_bottom = 9.5 98 | grow_vertical = 2 99 | theme_override_colors/font_color = Color(0.0745098, 0.0745098, 0.0745098, 0.784314) 100 | theme_override_fonts/font = ExtResource("3_y3fau") 101 | theme_override_font_sizes/font_size = 40 102 | text = "Item Type" 103 | 104 | [node name="ItemEffect" type="Label" parent="DetailsPanel"] 105 | layout_mode = 1 106 | anchors_preset = 2 107 | anchor_top = 1.0 108 | anchor_bottom = 1.0 109 | offset_left = 5.0 110 | offset_top = -19.0 111 | offset_right = 90.0 112 | grow_vertical = 0 113 | theme_override_colors/font_color = Color(0.0745098, 0.0745098, 0.0745098, 0.588235) 114 | theme_override_fonts/font = ExtResource("3_y3fau") 115 | theme_override_font_sizes/font_size = 40 116 | text = "Item Effect" 117 | 118 | [node name="UsagePanel" type="ColorRect" parent="."] 119 | visible = false 120 | layout_mode = 0 121 | offset_top = -193.0 122 | offset_right = 240.0 123 | offset_bottom = -3.0 124 | color = Color(0.596078, 0.933333, 0.8, 1) 125 | 126 | [node name="UseButton" type="Button" parent="UsagePanel"] 127 | layout_mode = 1 128 | anchors_preset = 5 129 | anchor_left = 0.5 130 | anchor_right = 0.5 131 | offset_left = -115.0 132 | offset_top = 10.0 133 | offset_right = 115.0 134 | offset_bottom = 59.0 135 | grow_horizontal = 2 136 | theme_override_colors/font_color = Color(0.0745098, 0.0745098, 0.0745098, 1) 137 | theme_override_fonts/font = ExtResource("3_y3fau") 138 | theme_override_font_sizes/font_size = 40 139 | text = "Use" 140 | 141 | [node name="DropButton" type="Button" parent="UsagePanel"] 142 | layout_mode = 1 143 | anchors_preset = 7 144 | anchor_left = 0.5 145 | anchor_top = 1.0 146 | anchor_right = 0.5 147 | anchor_bottom = 1.0 148 | offset_left = -115.0 149 | offset_top = -59.0 150 | offset_right = 115.0 151 | offset_bottom = -10.0 152 | grow_horizontal = 2 153 | grow_vertical = 0 154 | theme_override_colors/font_color = Color(0.0745098, 0.0745098, 0.0745098, 1) 155 | theme_override_fonts/font = ExtResource("3_y3fau") 156 | theme_override_font_sizes/font_size = 40 157 | text = "Drop" 158 | 159 | [node name="AssignButton" type="Button" parent="UsagePanel"] 160 | layout_mode = 1 161 | anchors_preset = 4 162 | anchor_top = 0.5 163 | anchor_bottom = 0.5 164 | offset_left = 5.0 165 | offset_top = -24.5 166 | offset_right = 235.0 167 | offset_bottom = 24.5 168 | grow_vertical = 2 169 | theme_override_colors/font_color = Color(0.0745098, 0.0745098, 0.0745098, 1) 170 | theme_override_fonts/font = ExtResource("3_y3fau") 171 | theme_override_font_sizes/font_size = 40 172 | text = "ASSIGN" 173 | 174 | [connection signal="mouse_entered" from="ItemButton" to="." method="_on_button_mouse_entered"] 175 | [connection signal="mouse_exited" from="ItemButton" to="." method="_on_button_mouse_exited"] 176 | [connection signal="pressed" from="ItemButton" to="." method="_on_button_pressed"] 177 | [connection signal="pressed" from="UsagePanel/UseButton" to="." method="_on_use_button_pressed"] 178 | [connection signal="pressed" from="UsagePanel/DropButton" to="." method="_on_drop_button_pressed"] 179 | [connection signal="pressed" from="UsagePanel/AssignButton" to="." method="_on_assign_button_pressed"] 180 | -------------------------------------------------------------------------------- /Sectional_Code/12 - Hotbar - Part 2/Scenes/Inventory_UI.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://bxbnos3drxhfp"] 2 | 3 | [ext_resource type="Script" path="res://Scripts/Inventory_UI.gd" id="1_ybuun"] 4 | 5 | [node name="InventoryUI" type="Control"] 6 | layout_mode = 3 7 | anchors_preset = 0 8 | size_flags_horizontal = 4 9 | size_flags_vertical = 4 10 | script = ExtResource("1_ybuun") 11 | 12 | [node name="GridContainer" type="GridContainer" parent="."] 13 | layout_mode = 0 14 | offset_left = 196.0 15 | offset_top = 196.0 16 | offset_right = 996.0 17 | offset_bottom = 596.0 18 | size_flags_horizontal = 3 19 | size_flags_vertical = 3 20 | theme_override_constants/h_separation = 20 21 | theme_override_constants/v_separation = 20 22 | columns = 9 23 | -------------------------------------------------------------------------------- /Sectional_Code/12 - Hotbar - Part 2/Scenes/Player.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=33 format=3 uid="uid://ceybwx01k7cpj"] 2 | 3 | [ext_resource type="Script" path="res://Scripts/Player.gd" id="1_ff6u3"] 4 | [ext_resource type="Texture2D" uid="uid://0flrot5hrf4a" path="res://Assets/person.png" id="2_8ia3g"] 5 | [ext_resource type="PackedScene" uid="uid://bxbnos3drxhfp" path="res://Scenes/Inventory_UI.tscn" id="3_nouor"] 6 | [ext_resource type="FontFile" uid="uid://bi04iecmbt37l" path="res://Assets/Fonts/ARCADECLASSIC.TTF" id="4_fpcyg"] 7 | [ext_resource type="PackedScene" uid="uid://xp38ekmolgts" path="res://Scenes/Inventory_Hotbar.tscn" id="5_fs4tt"] 8 | 9 | [sub_resource type="CircleShape2D" id="CircleShape2D_1i7oq"] 10 | 11 | [sub_resource type="AtlasTexture" id="AtlasTexture_rhofu"] 12 | atlas = ExtResource("2_8ia3g") 13 | region = Rect2(0, 0, 64, 64) 14 | 15 | [sub_resource type="AtlasTexture" id="AtlasTexture_oavyr"] 16 | atlas = ExtResource("2_8ia3g") 17 | region = Rect2(0, 256, 64, 64) 18 | 19 | [sub_resource type="AtlasTexture" id="AtlasTexture_dxf4e"] 20 | atlas = ExtResource("2_8ia3g") 21 | region = Rect2(64, 256, 64, 64) 22 | 23 | [sub_resource type="AtlasTexture" id="AtlasTexture_wmyu6"] 24 | atlas = ExtResource("2_8ia3g") 25 | region = Rect2(128, 256, 64, 64) 26 | 27 | [sub_resource type="AtlasTexture" id="AtlasTexture_o80ip"] 28 | atlas = ExtResource("2_8ia3g") 29 | region = Rect2(192, 256, 64, 64) 30 | 31 | [sub_resource type="AtlasTexture" id="AtlasTexture_gyi7f"] 32 | atlas = ExtResource("2_8ia3g") 33 | region = Rect2(256, 256, 64, 64) 34 | 35 | [sub_resource type="AtlasTexture" id="AtlasTexture_6bhyg"] 36 | atlas = ExtResource("2_8ia3g") 37 | region = Rect2(320, 256, 64, 64) 38 | 39 | [sub_resource type="AtlasTexture" id="AtlasTexture_8tosd"] 40 | atlas = ExtResource("2_8ia3g") 41 | region = Rect2(0, 448, 64, 64) 42 | 43 | [sub_resource type="AtlasTexture" id="AtlasTexture_stlph"] 44 | atlas = ExtResource("2_8ia3g") 45 | region = Rect2(64, 448, 64, 64) 46 | 47 | [sub_resource type="AtlasTexture" id="AtlasTexture_1orm7"] 48 | atlas = ExtResource("2_8ia3g") 49 | region = Rect2(128, 448, 64, 64) 50 | 51 | [sub_resource type="AtlasTexture" id="AtlasTexture_scpxb"] 52 | atlas = ExtResource("2_8ia3g") 53 | region = Rect2(192, 448, 64, 64) 54 | 55 | [sub_resource type="AtlasTexture" id="AtlasTexture_blhop"] 56 | atlas = ExtResource("2_8ia3g") 57 | region = Rect2(256, 448, 64, 64) 58 | 59 | [sub_resource type="AtlasTexture" id="AtlasTexture_imqr8"] 60 | atlas = ExtResource("2_8ia3g") 61 | region = Rect2(320, 448, 64, 64) 62 | 63 | [sub_resource type="AtlasTexture" id="AtlasTexture_banpt"] 64 | atlas = ExtResource("2_8ia3g") 65 | region = Rect2(0, 384, 64, 64) 66 | 67 | [sub_resource type="AtlasTexture" id="AtlasTexture_0ljlp"] 68 | atlas = ExtResource("2_8ia3g") 69 | region = Rect2(64, 384, 64, 64) 70 | 71 | [sub_resource type="AtlasTexture" id="AtlasTexture_eojdw"] 72 | atlas = ExtResource("2_8ia3g") 73 | region = Rect2(128, 384, 64, 64) 74 | 75 | [sub_resource type="AtlasTexture" id="AtlasTexture_fhvk6"] 76 | atlas = ExtResource("2_8ia3g") 77 | region = Rect2(192, 384, 64, 64) 78 | 79 | [sub_resource type="AtlasTexture" id="AtlasTexture_ifkow"] 80 | atlas = ExtResource("2_8ia3g") 81 | region = Rect2(256, 384, 64, 64) 82 | 83 | [sub_resource type="AtlasTexture" id="AtlasTexture_rletn"] 84 | atlas = ExtResource("2_8ia3g") 85 | region = Rect2(320, 384, 64, 64) 86 | 87 | [sub_resource type="AtlasTexture" id="AtlasTexture_oqulu"] 88 | atlas = ExtResource("2_8ia3g") 89 | region = Rect2(0, 320, 64, 64) 90 | 91 | [sub_resource type="AtlasTexture" id="AtlasTexture_mxthr"] 92 | atlas = ExtResource("2_8ia3g") 93 | region = Rect2(64, 320, 64, 64) 94 | 95 | [sub_resource type="AtlasTexture" id="AtlasTexture_hfa0w"] 96 | atlas = ExtResource("2_8ia3g") 97 | region = Rect2(128, 320, 64, 64) 98 | 99 | [sub_resource type="AtlasTexture" id="AtlasTexture_x4pxg"] 100 | atlas = ExtResource("2_8ia3g") 101 | region = Rect2(192, 320, 64, 64) 102 | 103 | [sub_resource type="AtlasTexture" id="AtlasTexture_0y2d6"] 104 | atlas = ExtResource("2_8ia3g") 105 | region = Rect2(256, 320, 64, 64) 106 | 107 | [sub_resource type="AtlasTexture" id="AtlasTexture_kybak"] 108 | atlas = ExtResource("2_8ia3g") 109 | region = Rect2(320, 320, 64, 64) 110 | 111 | [sub_resource type="SpriteFrames" id="SpriteFrames_y1i4q"] 112 | animations = [{ 113 | "frames": [{ 114 | "duration": 1.0, 115 | "texture": SubResource("AtlasTexture_rhofu") 116 | }], 117 | "loop": true, 118 | "name": &"idle", 119 | "speed": 5.0 120 | }, { 121 | "frames": [{ 122 | "duration": 1.0, 123 | "texture": SubResource("AtlasTexture_oavyr") 124 | }, { 125 | "duration": 1.0, 126 | "texture": SubResource("AtlasTexture_dxf4e") 127 | }, { 128 | "duration": 1.0, 129 | "texture": SubResource("AtlasTexture_wmyu6") 130 | }, { 131 | "duration": 1.0, 132 | "texture": SubResource("AtlasTexture_o80ip") 133 | }, { 134 | "duration": 1.0, 135 | "texture": SubResource("AtlasTexture_gyi7f") 136 | }, { 137 | "duration": 1.0, 138 | "texture": SubResource("AtlasTexture_6bhyg") 139 | }], 140 | "loop": true, 141 | "name": &"walk_down", 142 | "speed": 5.0 143 | }, { 144 | "frames": [{ 145 | "duration": 1.0, 146 | "texture": SubResource("AtlasTexture_8tosd") 147 | }, { 148 | "duration": 1.0, 149 | "texture": SubResource("AtlasTexture_stlph") 150 | }, { 151 | "duration": 1.0, 152 | "texture": SubResource("AtlasTexture_1orm7") 153 | }, { 154 | "duration": 1.0, 155 | "texture": SubResource("AtlasTexture_scpxb") 156 | }, { 157 | "duration": 1.0, 158 | "texture": SubResource("AtlasTexture_blhop") 159 | }, { 160 | "duration": 1.0, 161 | "texture": SubResource("AtlasTexture_imqr8") 162 | }], 163 | "loop": true, 164 | "name": &"walk_left", 165 | "speed": 5.0 166 | }, { 167 | "frames": [{ 168 | "duration": 1.0, 169 | "texture": SubResource("AtlasTexture_banpt") 170 | }, { 171 | "duration": 1.0, 172 | "texture": SubResource("AtlasTexture_0ljlp") 173 | }, { 174 | "duration": 1.0, 175 | "texture": SubResource("AtlasTexture_eojdw") 176 | }, { 177 | "duration": 1.0, 178 | "texture": SubResource("AtlasTexture_fhvk6") 179 | }, { 180 | "duration": 1.0, 181 | "texture": SubResource("AtlasTexture_ifkow") 182 | }, { 183 | "duration": 1.0, 184 | "texture": SubResource("AtlasTexture_rletn") 185 | }], 186 | "loop": true, 187 | "name": &"walk_right", 188 | "speed": 5.0 189 | }, { 190 | "frames": [{ 191 | "duration": 1.0, 192 | "texture": SubResource("AtlasTexture_oqulu") 193 | }, { 194 | "duration": 1.0, 195 | "texture": SubResource("AtlasTexture_mxthr") 196 | }, { 197 | "duration": 1.0, 198 | "texture": SubResource("AtlasTexture_hfa0w") 199 | }, { 200 | "duration": 1.0, 201 | "texture": SubResource("AtlasTexture_x4pxg") 202 | }, { 203 | "duration": 1.0, 204 | "texture": SubResource("AtlasTexture_0y2d6") 205 | }, { 206 | "duration": 1.0, 207 | "texture": SubResource("AtlasTexture_kybak") 208 | }], 209 | "loop": true, 210 | "name": &"walk_up", 211 | "speed": 5.0 212 | }] 213 | 214 | [node name="Player" type="CharacterBody2D" groups=["Player"]] 215 | process_mode = 3 216 | script = ExtResource("1_ff6u3") 217 | 218 | [node name="CollisionShape2D" type="CollisionShape2D" parent="."] 219 | shape = SubResource("CircleShape2D_1i7oq") 220 | 221 | [node name="AnimatedSprite" type="AnimatedSprite2D" parent="."] 222 | sprite_frames = SubResource("SpriteFrames_y1i4q") 223 | animation = &"walk_down" 224 | autoplay = "idle" 225 | 226 | [node name="Camera2D" type="Camera2D" parent="."] 227 | zoom = Vector2(3, 3) 228 | 229 | [node name="InteractUI" type="CanvasLayer" parent="."] 230 | visible = false 231 | 232 | [node name="ColorRect" type="ColorRect" parent="InteractUI"] 233 | anchors_preset = 3 234 | anchor_left = 1.0 235 | anchor_top = 1.0 236 | anchor_right = 1.0 237 | anchor_bottom = 1.0 238 | offset_left = -307.0 239 | offset_top = -58.0 240 | offset_right = -7.0 241 | offset_bottom = -8.0 242 | grow_horizontal = 0 243 | grow_vertical = 0 244 | color = Color(0.192157, 0.376471, 0.321569, 0.839216) 245 | 246 | [node name="Label" type="Label" parent="InteractUI/ColorRect"] 247 | layout_mode = 1 248 | anchors_preset = 8 249 | anchor_left = 0.5 250 | anchor_top = 0.5 251 | anchor_right = 0.5 252 | anchor_bottom = 0.5 253 | offset_left = -75.5 254 | offset_top = -13.0 255 | offset_right = 75.5 256 | offset_bottom = 13.0 257 | grow_horizontal = 2 258 | grow_vertical = 2 259 | theme_override_fonts/font = ExtResource("4_fpcyg") 260 | theme_override_font_sizes/font_size = 30 261 | text = "Press \"E\" to Pick Up" 262 | 263 | [node name="InventoryUI" type="CanvasLayer" parent="."] 264 | visible = false 265 | 266 | [node name="Background" type="ColorRect" parent="InventoryUI"] 267 | anchors_preset = 15 268 | anchor_right = 1.0 269 | anchor_bottom = 1.0 270 | grow_horizontal = 2 271 | grow_vertical = 2 272 | color = Color(0.192157, 0.376471, 0.321569, 1) 273 | 274 | [node name="Label" type="Label" parent="InventoryUI/Background"] 275 | layout_mode = 1 276 | anchors_preset = 5 277 | anchor_left = 0.5 278 | anchor_right = 0.5 279 | offset_left = -148.5 280 | offset_top = 50.0 281 | offset_right = 148.5 282 | offset_bottom = 114.0 283 | grow_horizontal = 2 284 | theme_override_fonts/font = ExtResource("4_fpcyg") 285 | theme_override_font_sizes/font_size = 60 286 | text = "Inventory" 287 | 288 | [node name="InventoryUI" parent="InventoryUI/Background" instance=ExtResource("3_nouor")] 289 | layout_mode = 1 290 | 291 | [node name="InventoryHotbar" type="CanvasLayer" parent="."] 292 | 293 | [node name="Inventory_Hotbar" parent="InventoryHotbar" instance=ExtResource("5_fs4tt")] 294 | -------------------------------------------------------------------------------- /Sectional_Code/12 - Hotbar - Part 2/Scripts/Global.gd: -------------------------------------------------------------------------------- 1 | ### Global.gd 2 | 3 | extends Node 4 | 5 | # Scene and node references 6 | @onready var inventory_slot_scene = preload("res://Scenes/Inventory_Slot.tscn") 7 | var player_node: Node = null 8 | 9 | # Inventory items 10 | var inventory = [] 11 | var spawnable_items = [ 12 | {"type": "Consumable", "name": "Berry", "effect": "Health", "texture": preload("res://Assets/Icons/icon31.png")}, 13 | {"type": "Consumable", "name": "Water", "effect": "Stamina", "texture": preload("res://Assets/Icons/icon9.png")}, 14 | {"type": "Consumable", "name": "Mushroom", "effect": "Armor", "texture": preload("res://Assets/Icons/icon32.png")}, 15 | {"type": "Gift", "name": "Gemstone", "effect": "", "texture": preload("res://Assets/Icons/icon21.png")}, 16 | ] 17 | 18 | # Custom signals 19 | signal inventory_updated 20 | 21 | # Hotbar items 22 | var hotbar_size = 5 23 | var hotbar_inventory = [] 24 | 25 | func _ready(): 26 | # Initializes the inventory with 30 slots (spread over 9 blocks per row) 27 | inventory.resize(30) 28 | # Hotbar size 29 | hotbar_inventory.resize(hotbar_size) 30 | 31 | # Sets the player reference for inventory interactions 32 | func set_player_reference(player): 33 | player_node = player 34 | 35 | # Adds an item to the inventory, returns true if successful 36 | func add_item(item, to_hotbar = false): 37 | var added_to_hotbar = false 38 | if to_hotbar: 39 | added_to_hotbar = add_hotbar_item(item) 40 | inventory_updated.emit() 41 | if not added_to_hotbar: 42 | for i in range(inventory.size()): 43 | # Check if the item exists in the inventory and matches both type and effect 44 | if inventory[i] != null and inventory[i]["type"] == item["type"] and inventory[i]["effect"] == item["effect"]: 45 | inventory[i]["quantity"] += item["quantity"] 46 | inventory_updated.emit() 47 | print("Item added", inventory) 48 | return true 49 | elif inventory[i] == null: 50 | inventory[i] = item 51 | inventory_updated.emit() 52 | print("Item added", inventory) 53 | return true 54 | return false 55 | 56 | # Removes an item from the inventory based on type and effect 57 | func remove_item(item_type, item_effect): 58 | # Inventory removal 59 | for i in range(inventory.size()): 60 | if inventory[i] != null and inventory[i]["type"] == item_type and inventory[i]["effect"] == item_effect: 61 | inventory[i]["quantity"] -= 1 62 | if inventory[i]["quantity"] <= 0: 63 | inventory[i] = null 64 | inventory_updated.emit() 65 | return true 66 | return false 67 | 68 | # Increase inventory size dynamically 69 | func increase_inventory_size(extra_slots): 70 | inventory.resize(inventory.size() + extra_slots) 71 | inventory_updated.emit() 72 | 73 | # Drops an item at a specified position, adjusting for nearby items 74 | func drop_item(item_data, drop_position): 75 | var item_scene = load(item_data["scene_path"]) 76 | var item_instance = item_scene.instantiate() 77 | item_instance.set_item_data(item_data) 78 | drop_position = adjust_drop_position(drop_position) 79 | item_instance.global_position = drop_position 80 | get_tree().current_scene.add_child(item_instance) 81 | 82 | # Adjusts the drop position to avoid overlapping with nearby items 83 | func adjust_drop_position(position): 84 | var radius = 100 85 | var nearby_items = get_tree().get_nodes_in_group("Items") 86 | for item in nearby_items: 87 | if item.global_position.distance_to(position) < radius: 88 | var random_offset = Vector2(randf_range(-radius, radius), randf_range(-radius, radius)) 89 | position += random_offset 90 | break 91 | return position 92 | 93 | # Try adding to hotbar 94 | func add_hotbar_item(item): 95 | for i in range(hotbar_size): 96 | if hotbar_inventory[i] == null: 97 | hotbar_inventory[i] = item 98 | return true 99 | return false 100 | 101 | # Removes an item from the hotbar 102 | func remove_hotbar_item(item_type, item_effect): 103 | for i in range(hotbar_inventory.size()): 104 | if hotbar_inventory[i] != null and hotbar_inventory[i]["type"] == item_type and hotbar_inventory[i]["effect"] == item_effect: 105 | if hotbar_inventory[i]["quantity"] <= 0: 106 | hotbar_inventory[i] = null 107 | inventory_updated.emit() 108 | return true 109 | return false 110 | 111 | # Unassigns an item from the hotbar 112 | func unassign_hotbar_item(item_type, item_effect): 113 | for i in range(hotbar_inventory.size()): 114 | if hotbar_inventory[i] != null and hotbar_inventory[i]["type"] == item_type and hotbar_inventory[i]["effect"] == item_effect: 115 | hotbar_inventory[i] = null 116 | inventory_updated.emit() 117 | return true 118 | return false 119 | 120 | # Prevents duplicate item assignment 121 | func is_item_assigned_to_hotbar(item_to_check): 122 | return item_to_check in hotbar_inventory 123 | 124 | -------------------------------------------------------------------------------- /Sectional_Code/12 - Hotbar - Part 2/Scripts/Inventory_Hotbar.gd: -------------------------------------------------------------------------------- 1 | ### Inventory_Hotbar.gd 2 | 3 | extends Control 4 | 5 | # Scene-Tree Node references 6 | @onready var hotbar_container = $HBoxContainer 7 | 8 | func _ready(): 9 | Global.inventory_updated.connect(_update_hotbar) 10 | _update_hotbar() 11 | 12 | # Create the hotbar slots 13 | func _update_hotbar(): 14 | clear_hotbar_container() 15 | for i in range(Global.hotbar_size): 16 | var item = Global.hotbar_inventory[i] 17 | var slot = Global.inventory_slot_scene.instantiate() 18 | slot.set_slot_index(i) # Set the index here 19 | hotbar_container.add_child(slot) 20 | if item != null: 21 | slot.set_item(item) 22 | else: 23 | slot.set_empty() 24 | slot.update_assignment_status() 25 | 26 | # Clear hotbar slots 27 | func clear_hotbar_container(): 28 | while hotbar_container.get_child_count() > 0: 29 | var child = hotbar_container.get_child(0) 30 | hotbar_container.remove_child(child) 31 | child.queue_free() 32 | -------------------------------------------------------------------------------- /Sectional_Code/12 - Hotbar - Part 2/Scripts/Inventory_Item.gd: -------------------------------------------------------------------------------- 1 | ### Inventory_Item.gd 2 | @tool 3 | extends Node2D 4 | 5 | # Item details for editor window 6 | @export var item_type = "" 7 | @export var item_name = "" 8 | @export var item_texture: Texture 9 | @export var item_effect = "" 10 | var scene_path: String = "res://Scenes/Inventory_Item.tscn" 11 | 12 | # Scene-Tree Node references 13 | @onready var icon_sprite = $Sprite2D 14 | 15 | # Variables 16 | var player_in_range = false 17 | 18 | func _ready(): 19 | # Set the texture to reflect in the game 20 | if not Engine.is_editor_hint(): 21 | icon_sprite.texture = item_texture 22 | 23 | func _process(_delta): 24 | # Set the texture to reflect in the editor 25 | if Engine.is_editor_hint(): 26 | icon_sprite.texture = item_texture 27 | # Add item to inventory if player presses "E" within range 28 | if player_in_range and Input.is_action_just_pressed("ui_add"): 29 | pickup_item() 30 | 31 | # Add item to inventory 32 | func pickup_item(): 33 | var item = { 34 | "quantity": 1, 35 | "type": item_type, 36 | "name": item_name, 37 | "effect": item_effect, 38 | "texture": item_texture, 39 | "scene_path": scene_path 40 | } 41 | if Global.player_node: 42 | Global.add_item(item, false) 43 | self.queue_free() 44 | 45 | # If player is in range, show UI and make item pickable 46 | func _on_area_2d_body_entered(body): 47 | if body.is_in_group("Player"): 48 | player_in_range = true 49 | body.interact_ui.visible = true 50 | 51 | # If player is in range, hide UI and don't make item pickable 52 | func _on_area_2d_body_exited(body): 53 | if body.is_in_group("Player"): 54 | player_in_range = false 55 | body.interact_ui.visible = false 56 | 57 | # Set the items values for spawning 58 | func initiate_items(type, name, effect, texture): 59 | item_type = type 60 | item_name = name 61 | item_effect = effect 62 | item_texture = texture 63 | 64 | # Sets the item's dictionary data 65 | func set_item_data(data): 66 | item_type = data["type"] 67 | item_name = data["name"] 68 | item_effect = data["effect"] 69 | item_texture = data["texture"] 70 | -------------------------------------------------------------------------------- /Sectional_Code/12 - Hotbar - Part 2/Scripts/Inventory_Slot.gd: -------------------------------------------------------------------------------- 1 | ##Inventory_Slot.gd 2 | 3 | extends Control 4 | 5 | # Scene-Tree Node references 6 | @onready var icon = $InnerBorder/ItemIcon 7 | @onready var quantity_label = $InnerBorder/ItemQuantity 8 | @onready var details_panel = $DetailsPanel 9 | @onready var item_name = $DetailsPanel/ItemName 10 | @onready var item_type = $DetailsPanel/ItemType 11 | @onready var item_effect = $DetailsPanel/ItemEffect 12 | @onready var usage_panel = $UsagePanel 13 | @onready var assign_button = $UsagePanel/AssignButton 14 | 15 | # Slot Item 16 | var item = null 17 | var slot_index = -1 # Default to an invalid index 18 | var is_assigned = false 19 | 20 | # Setting slot index 21 | func set_slot_index(new_index): 22 | slot_index = new_index 23 | 24 | # Default empty slot 25 | func set_empty(): 26 | icon.texture = null 27 | quantity_label.text = "" 28 | 29 | # Set slot item with its values from the dictionary 30 | func set_item(new_item): 31 | item = new_item 32 | icon.texture = item["texture"] 33 | quantity_label.text = str(item["quantity"]) 34 | item_name.text = str(item["name"]) 35 | item_type.text = str(item["type"]) 36 | if item["effect"] != "": 37 | item_effect.text = str("+ ", item["effect"]) 38 | else: 39 | item_effect.text = "" 40 | update_assignment_status() 41 | 42 | # Show usage panel for player to use/remove item 43 | func _on_button_pressed(): 44 | if item != null: 45 | usage_panel.visible = !usage_panel.visible 46 | 47 | # Show item details on hover enter 48 | func _on_button_mouse_entered(): 49 | if item != null: 50 | usage_panel.visible = false 51 | details_panel.visible = true 52 | 53 | # Hide item details on hover exit 54 | func _on_button_mouse_exited(): 55 | details_panel.visible = false 56 | 57 | # Remove item from inventory, use it, and apply its effect (if possible) 58 | func _on_use_button_pressed(): 59 | usage_panel.visible = false 60 | if item != null: 61 | if Global.player_node: 62 | Global.player_node.apply_item_effect(item) 63 | Global.remove_item(item["type"], item["effect"]) 64 | Global.remove_hotbar_item(item["type"], item["effect"]) 65 | else: 66 | print("Player node not found") 67 | 68 | # Remove item from inventory and drop it back into the world 69 | func _on_drop_button_pressed(): 70 | if item != null: 71 | var drop_position = Global.player_node.global_position 72 | var drop_offset = Vector2(50, 0) 73 | drop_offset = drop_offset.rotated(Global.player_node.rotation) 74 | Global.drop_item(item, drop_position + drop_offset) 75 | Global.remove_item(item["type"], item["effect"]) 76 | Global.remove_hotbar_item(item["type"], item["effect"]) 77 | usage_panel.visible = false 78 | 79 | # Assigns item to hotbar 80 | func _on_assign_button_pressed(): 81 | if item != null: 82 | if is_assigned: 83 | Global.remove_hotbar_item(item["type"], item["effect"]) 84 | is_assigned = false 85 | else: 86 | Global.add_item(item, true) 87 | is_assigned = true 88 | update_assignment_status() 89 | 90 | # Updates assignment status 91 | func update_assignment_status(): 92 | is_assigned = Global.is_item_assigned_to_hotbar(item) 93 | if is_assigned: 94 | assign_button.text = "Unassign" 95 | else: 96 | assign_button.text = "Assign" 97 | -------------------------------------------------------------------------------- /Sectional_Code/12 - Hotbar - Part 2/Scripts/Inventory_UI.gd: -------------------------------------------------------------------------------- 1 | ###Inventory_UI.gd 2 | extends Control 3 | 4 | # Scene-Tree Node references 5 | @onready var grid_container = $GridContainer 6 | 7 | func _ready(): 8 | # Connect function to signal to update inventory UI 9 | Global.inventory_updated.connect(_on_inventory_updated) 10 | _on_inventory_updated() 11 | 12 | # Update inventory UI 13 | func _on_inventory_updated(): 14 | # Clear existing slots 15 | clear_grid_container() 16 | # Add slots for each inventory position 17 | for item in Global.inventory: 18 | var slot = Global.inventory_slot_scene.instantiate() 19 | grid_container.add_child(slot) 20 | if item != null: 21 | slot.set_item(item) 22 | else: 23 | slot.set_empty() 24 | 25 | # Clear inventory UI grid 26 | func clear_grid_container(): 27 | while grid_container.get_child_count() > 0: 28 | var child = grid_container.get_child(0) 29 | grid_container.remove_child(child) 30 | child.queue_free() 31 | -------------------------------------------------------------------------------- /Sectional_Code/12 - Hotbar - Part 2/Scripts/Main.gd: -------------------------------------------------------------------------------- 1 | ### Main.gd 2 | extends Node 3 | 4 | # Scene-Tree Node references 5 | @onready var items = $Items 6 | @onready var item_spawn_area = $ItemSpawnArea 7 | @onready var collision_shape = $ItemSpawnArea/CollisionShape2D 8 | 9 | # When the game loads spawn 10 pickup items in the spawn area 10 | func _ready(): 11 | spawn_random_items(10) 12 | 13 | # Get random position for item within the collision shape in spawn area 14 | func get_random_position(): 15 | var area_rect = collision_shape.shape.get_rect() 16 | var x = randf_range(0, area_rect.position.x) 17 | var y = randf_range(0, area_rect.position.y) 18 | return item_spawn_area.to_global(Vector2(x, y)) 19 | 20 | # Spawn random items from the Global list up until the max amount (10) has been reached 21 | func spawn_random_items(count): 22 | var attempts = 0 23 | var spawned_count = 0 24 | while spawned_count < count and attempts < 100: 25 | var position = get_random_position() 26 | spawn_item(Global.spawnable_items[randi() % Global.spawnable_items.size()], position) 27 | spawned_count += 1 28 | attempts += 1 29 | 30 | # Create a physical instance of the Item scene on the map underneath /Items node 31 | func spawn_item(data, position): 32 | var item_scene = preload("res://Scenes/Inventory_Item.tscn") 33 | var item_instance = item_scene.instantiate() 34 | item_instance.initiate_items(data["type"], data["name"], data["effect"], data["texture"]) 35 | item_instance.global_position = position 36 | items.add_child(item_instance) 37 | -------------------------------------------------------------------------------- /Sectional_Code/12 - Hotbar - Part 2/Scripts/Player.gd: -------------------------------------------------------------------------------- 1 | ### Player.gd 2 | extends CharacterBody2D 3 | 4 | # Scene-Tree Node references 5 | @onready var inventory_ui = $InventoryUI 6 | @onready var interact_ui = $InteractUI 7 | @onready var animated_sprite = $AnimatedSprite 8 | @onready var hotbar_ui = $InventoryHotbar 9 | 10 | # Variables 11 | @export var speed = 200 12 | 13 | func _ready(): 14 | # Set this node as the Player node 15 | Global.set_player_reference(self) 16 | 17 | # Input for movement 18 | func get_input(): 19 | var input_direction = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down") 20 | velocity = input_direction * speed 21 | 22 | # Movement & Animation 23 | func _physics_process(delta): 24 | get_input() 25 | move_and_slide() 26 | update_animation() 27 | 28 | # Animation 29 | func update_animation(): 30 | if velocity == Vector2.ZERO: 31 | animated_sprite.play("idle") 32 | else: 33 | if abs(velocity.x) > abs(velocity.y): 34 | if velocity.x > 0: 35 | animated_sprite.play("walk_right") 36 | else: 37 | animated_sprite.play("walk_left") 38 | else: 39 | if velocity.y > 0: 40 | animated_sprite.play("walk_down") 41 | else: 42 | animated_sprite.play("walk_up") 43 | 44 | # Show inventory menu on "I" pressed 45 | func _input(event): 46 | if event.is_action_pressed("ui_inventory"): 47 | inventory_ui.visible = !inventory_ui.visible 48 | get_tree().paused = !get_tree().paused 49 | hotbar_ui.visible = !hotbar_ui.visible 50 | 51 | # Apply the effect of the item (if possible) 52 | func apply_item_effect(item): 53 | match item["effect"]: 54 | "Stamina": 55 | speed += 50 56 | print("Speed increased to ", speed) 57 | "Slot Boost": 58 | Global.increase_inventory_size(5) 59 | print("Inventory increased to ", Global.inventory.size()) 60 | _: 61 | print("No effect for this item") 62 | 63 | # Use hotbar items on key 1 - 5 press 64 | func use_hotbar_item(slot_index): 65 | if slot_index < Global.hotbar_inventory.size(): 66 | var item = Global.hotbar_inventory[slot_index] 67 | if item != null: 68 | # Use item 69 | apply_item_effect(item) 70 | # Remove item 71 | item["quantity"] -= 1 72 | if item["quantity"] <= 0: 73 | Global.hotbar_inventory[slot_index] = null 74 | Global.remove_item(item["type"], item["effect"]) 75 | Global.inventory_updated.emit() 76 | 77 | # Hotbar shortcuts 78 | func _unhandled_input(event): 79 | if event is InputEventKey and event.pressed: 80 | # Then check for specific keys 81 | for i in range(Global.hotbar_size): 82 | # Assuming keys 1-5 are mapped to actions "hotbar_1" to "hotbar_5" in the Input Map 83 | if Input.is_action_just_pressed("hotbar_" + str(i + 1)): 84 | use_hotbar_item(i) 85 | break 86 | 87 | 88 | -------------------------------------------------------------------------------- /Sectional_Code/13 - Draggable Inventory/Scripts/Global.gd: -------------------------------------------------------------------------------- 1 | ### Global.gd 2 | 3 | extends Node 4 | 5 | # Scene and node references 6 | @onready var inventory_slot_scene = preload("res://Scenes/Inventory_Slot.tscn") 7 | var player_node: Node = null 8 | 9 | # Inventory items 10 | var inventory = [] 11 | var spawnable_items = [ 12 | {"type": "Consumable", "name": "Berry", "effect": "Health", "texture": preload("res://Assets/Icons/icon31.png")}, 13 | {"type": "Consumable", "name": "Water", "effect": "Stamina", "texture": preload("res://Assets/Icons/icon9.png")}, 14 | {"type": "Consumable", "name": "Mushroom", "effect": "Armor", "texture": preload("res://Assets/Icons/icon32.png")}, 15 | {"type": "Gift", "name": "Gemstone", "effect": "", "texture": preload("res://Assets/Icons/icon21.png")}, 16 | ] 17 | 18 | # Custom signals 19 | signal inventory_updated 20 | 21 | # Hotbar items 22 | var hotbar_size = 5 23 | var hotbar_inventory = [] 24 | 25 | func _ready(): 26 | # Initializes the inventory with 30 slots (spread over 9 blocks per row) 27 | inventory.resize(30) 28 | # Hotbar size 29 | hotbar_inventory.resize(hotbar_size) 30 | 31 | # Sets the player reference for inventory interactions 32 | func set_player_reference(player): 33 | player_node = player 34 | 35 | # Adds an item to the inventory, returns true if successful 36 | func add_item(item, to_hotbar = false): 37 | var added_to_hotbar = false 38 | if to_hotbar: 39 | added_to_hotbar = add_hotbar_item(item) 40 | inventory_updated.emit() 41 | if not added_to_hotbar: 42 | for i in range(inventory.size()): 43 | # Check if the item exists in the inventory and matches both type and effect 44 | if inventory[i] != null and inventory[i]["type"] == item["type"] and inventory[i]["effect"] == item["effect"]: 45 | inventory[i]["quantity"] += item["quantity"] 46 | inventory_updated.emit() 47 | print("Item added", inventory) 48 | return true 49 | elif inventory[i] == null: 50 | inventory[i] = item 51 | inventory_updated.emit() 52 | print("Item added", inventory) 53 | return true 54 | return false 55 | 56 | # Removes an item from the inventory based on type and effect 57 | func remove_item(item_type, item_effect): 58 | # Inventory removal 59 | for i in range(inventory.size()): 60 | if inventory[i] != null and inventory[i]["type"] == item_type and inventory[i]["effect"] == item_effect: 61 | inventory[i]["quantity"] -= 1 62 | if inventory[i]["quantity"] <= 0: 63 | inventory[i] = null 64 | inventory_updated.emit() 65 | return true 66 | return false 67 | 68 | # Increase inventory size dynamically 69 | func increase_inventory_size(extra_slots): 70 | inventory.resize(inventory.size() + extra_slots) 71 | inventory_updated.emit() 72 | 73 | # Drops an item at a specified position, adjusting for nearby items 74 | func drop_item(item_data, drop_position): 75 | var item_scene = load(item_data["scene_path"]) 76 | var item_instance = item_scene.instantiate() 77 | item_instance.set_item_data(item_data) 78 | drop_position = adjust_drop_position(drop_position) 79 | item_instance.global_position = drop_position 80 | get_tree().current_scene.add_child(item_instance) 81 | 82 | # Adjusts the drop position to avoid overlapping with nearby items 83 | func adjust_drop_position(position): 84 | var radius = 100 85 | var nearby_items = get_tree().get_nodes_in_group("Items") 86 | for item in nearby_items: 87 | if item.global_position.distance_to(position) < radius: 88 | var random_offset = Vector2(randf_range(-radius, radius), randf_range(-radius, radius)) 89 | position += random_offset 90 | break 91 | return position 92 | 93 | # Try adding to hotbar 94 | func add_hotbar_item(item): 95 | for i in range(hotbar_size): 96 | if hotbar_inventory[i] == null: 97 | hotbar_inventory[i] = item 98 | return true 99 | return false 100 | 101 | # Removes an item from the hotbar 102 | func remove_hotbar_item(item_type, item_effect): 103 | for i in range(hotbar_inventory.size()): 104 | if hotbar_inventory[i] != null and hotbar_inventory[i]["type"] == item_type and hotbar_inventory[i]["effect"] == item_effect: 105 | if hotbar_inventory[i]["quantity"] <= 0: 106 | hotbar_inventory[i] = null 107 | inventory_updated.emit() 108 | return true 109 | return false 110 | 111 | # Unassigns an item from the hotbar 112 | func unassign_hotbar_item(item_type, item_effect): 113 | for i in range(hotbar_inventory.size()): 114 | if hotbar_inventory[i] != null and hotbar_inventory[i]["type"] == item_type and hotbar_inventory[i]["effect"] == item_effect: 115 | hotbar_inventory[i] = null 116 | inventory_updated.emit() 117 | return true 118 | return false 119 | 120 | # Prevents duplicate item assignment 121 | func is_item_assigned_to_hotbar(item_to_check): 122 | return item_to_check in hotbar_inventory 123 | 124 | # Swaps items in the inventory based on their indices 125 | func swap_inventory_items(index1, index2): 126 | if index1 < 0 or index1 >= inventory.size() or index2 < 0 or index2 >= inventory.size(): 127 | return false 128 | var temp = inventory[index1] 129 | inventory[index1] = inventory[index2] 130 | inventory[index2] = temp 131 | inventory_updated.emit() 132 | return true 133 | 134 | -------------------------------------------------------------------------------- /Sectional_Code/13 - Draggable Inventory/Scripts/Inventory_Hotbar.gd: -------------------------------------------------------------------------------- 1 | ### Inventory_Hotbar.gd 2 | 3 | extends Control 4 | 5 | # Scene-Tree Node references 6 | @onready var hotbar_container = $HBoxContainer 7 | 8 | func _ready(): 9 | Global.inventory_updated.connect(_update_hotbar) 10 | _update_hotbar() 11 | 12 | # Create the hotbar slots 13 | func _update_hotbar(): 14 | clear_hotbar_container() 15 | for i in range(Global.hotbar_size): 16 | var slot = Global.inventory_slot_scene.instantiate() 17 | slot.set_slot_index(i) 18 | hotbar_container.add_child(slot) 19 | if Global.hotbar_inventory[i] != null: 20 | slot.set_item(Global.hotbar_inventory[i]) 21 | else: 22 | slot.set_empty() 23 | slot.update_assignment_status() 24 | 25 | 26 | # Clear hotbar slots 27 | func clear_hotbar_container(): 28 | while hotbar_container.get_child_count() > 0: 29 | var child = hotbar_container.get_child(0) 30 | hotbar_container.remove_child(child) 31 | child.queue_free() 32 | -------------------------------------------------------------------------------- /Sectional_Code/13 - Draggable Inventory/Scripts/Inventory_Item.gd: -------------------------------------------------------------------------------- 1 | ### Inventory_Item.gd 2 | @tool 3 | extends Node2D 4 | 5 | # Item details for editor window 6 | @export var item_type = "" 7 | @export var item_name = "" 8 | @export var item_texture: Texture 9 | @export var item_effect = "" 10 | var scene_path: String = "res://Scenes/Inventory_Item.tscn" 11 | 12 | # Scene-Tree Node references 13 | @onready var icon_sprite = $Sprite2D 14 | 15 | # Variables 16 | var player_in_range = false 17 | 18 | func _ready(): 19 | # Set the texture to reflect in the game 20 | if not Engine.is_editor_hint(): 21 | icon_sprite.texture = item_texture 22 | 23 | func _process(_delta): 24 | # Set the texture to reflect in the editor 25 | if Engine.is_editor_hint(): 26 | icon_sprite.texture = item_texture 27 | # Add item to inventory if player presses "E" within range 28 | if player_in_range and Input.is_action_just_pressed("ui_add"): 29 | pickup_item() 30 | 31 | # Add item to inventory 32 | func pickup_item(): 33 | var item = { 34 | "quantity": 1, 35 | "type": item_type, 36 | "name": item_name, 37 | "effect": item_effect, 38 | "texture": item_texture, 39 | "scene_path": scene_path 40 | } 41 | if Global.player_node: 42 | Global.add_item(item, false) 43 | self.queue_free() 44 | 45 | # If player is in range, show UI and make item pickable 46 | func _on_area_2d_body_entered(body): 47 | if body.is_in_group("Player"): 48 | player_in_range = true 49 | body.interact_ui.visible = true 50 | 51 | # If player is in range, hide UI and don't make item pickable 52 | func _on_area_2d_body_exited(body): 53 | if body.is_in_group("Player"): 54 | player_in_range = false 55 | body.interact_ui.visible = false 56 | 57 | # Set the items values for spawning 58 | func initiate_items(type, name, effect, texture): 59 | item_type = type 60 | item_name = name 61 | item_effect = effect 62 | item_texture = texture 63 | 64 | # Sets the item's dictionary data 65 | func set_item_data(data): 66 | item_type = data["type"] 67 | item_name = data["name"] 68 | item_effect = data["effect"] 69 | item_texture = data["texture"] 70 | -------------------------------------------------------------------------------- /Sectional_Code/13 - Draggable Inventory/Scripts/Inventory_Slot.gd: -------------------------------------------------------------------------------- 1 | ##Inventory_Slot.gd 2 | 3 | extends Control 4 | 5 | # Scene-Tree Node references 6 | @onready var icon = $InnerBorder/ItemIcon 7 | @onready var quantity_label = $InnerBorder/ItemQuantity 8 | @onready var details_panel = $DetailsPanel 9 | @onready var item_name = $DetailsPanel/ItemName 10 | @onready var item_type = $DetailsPanel/ItemType 11 | @onready var item_effect = $DetailsPanel/ItemEffect 12 | @onready var usage_panel = $UsagePanel 13 | @onready var assign_button = $UsagePanel/AssignButton 14 | @onready var outer_border = $OuterBorder 15 | 16 | # Slot Item 17 | var item = null 18 | var slot_index = -1 # Default to an invalid index 19 | var is_assigned = false 20 | 21 | # Signals 22 | signal drag_start(slot) 23 | signal drag_end() 24 | 25 | # Setting slot index 26 | func set_slot_index(new_index): 27 | slot_index = new_index 28 | 29 | # Default empty slot 30 | func set_empty(): 31 | icon.texture = null 32 | quantity_label.text = "" 33 | 34 | # Set slot item with its values from the dictionary 35 | func set_item(new_item): 36 | item = new_item 37 | icon.texture = item["texture"] 38 | quantity_label.text = str(item["quantity"]) 39 | item_name.text = str(item["name"]) 40 | item_type.text = str(item["type"]) 41 | if item["effect"] != "": 42 | item_effect.text = str("+ ", item["effect"]) 43 | else: 44 | item_effect.text = "" 45 | update_assignment_status() 46 | 47 | # Show item details on hover enter 48 | func _on_button_mouse_entered(): 49 | if item != null: 50 | usage_panel.visible = false 51 | details_panel.visible = true 52 | 53 | # Hide item details on hover exit 54 | func _on_button_mouse_exited(): 55 | details_panel.visible = false 56 | 57 | # Remove item from inventory, use it, and apply its effect (if possible) 58 | func _on_use_button_pressed(): 59 | usage_panel.visible = false 60 | if item != null: 61 | if Global.player_node: 62 | Global.player_node.apply_item_effect(item) 63 | Global.remove_item(item["type"], item["effect"]) 64 | Global.remove_hotbar_item(item["type"], item["effect"]) 65 | else: 66 | print("Player node not found") 67 | 68 | # Remove item from inventory and drop it back into the world 69 | func _on_drop_button_pressed(): 70 | if item != null: 71 | var drop_position = Global.player_node.global_position 72 | var drop_offset = Vector2(50, 0) 73 | drop_offset = drop_offset.rotated(Global.player_node.rotation) 74 | Global.drop_item(item, drop_position + drop_offset) 75 | Global.remove_item(item["type"], item["effect"]) 76 | Global.remove_hotbar_item(item["type"], item["effect"]) 77 | usage_panel.visible = false 78 | 79 | # Assigns item to hotbar 80 | func _on_assign_button_pressed(): 81 | if item != null: 82 | if is_assigned: 83 | Global.remove_hotbar_item(item["type"], item["effect"]) 84 | is_assigned = false 85 | else: 86 | Global.add_item(item, true) 87 | is_assigned = true 88 | update_assignment_status() 89 | 90 | # Updates assignment status 91 | func update_assignment_status(): 92 | is_assigned = Global.is_item_assigned_to_hotbar(item) 93 | if is_assigned: 94 | assign_button.text = "Unassign" 95 | else: 96 | assign_button.text = "Assign" 97 | 98 | # ItemButtons pressed eventss 99 | func _on_item_button_gui_input(event): 100 | if event is InputEventMouseButton: 101 | if event.button_index == MOUSE_BUTTON_LEFT and event.is_pressed(): 102 | if item != null: 103 | usage_panel.visible = !usage_panel.visible 104 | # Handle right mouse button for drag 105 | if event.button_index == MOUSE_BUTTON_RIGHT: 106 | if event.pressed: 107 | outer_border.modulate = Color(1, 1, 0) 108 | drag_start.emit(self) 109 | else: 110 | outer_border.modulate = Color(1, 1, 1) 111 | drag_end.emit() 112 | -------------------------------------------------------------------------------- /Sectional_Code/13 - Draggable Inventory/Scripts/Inventory_UI.gd: -------------------------------------------------------------------------------- 1 | ###Inventory_UI.gd 2 | extends Control 3 | 4 | # Scene-Tree Node references 5 | @onready var grid_container = $GridContainer 6 | 7 | # Currently dragged item 8 | var dragged_slot = null 9 | 10 | func _ready(): 11 | # Connect function to signal to update inventory UI 12 | Global.inventory_updated.connect(_on_inventory_updated) 13 | _on_inventory_updated() 14 | 15 | # Update inventory UI 16 | func _on_inventory_updated(): 17 | # Clear existing slots 18 | clear_grid_container() 19 | # Add slot items 20 | for item in Global.inventory: 21 | var slot = Global.inventory_slot_scene.instantiate() 22 | slot.drag_start.connect(_on_drag_start) 23 | slot.drag_end.connect(_on_drag_end) 24 | grid_container.add_child(slot) 25 | if item != null: 26 | slot.set_item(item) 27 | else: 28 | slot.set_empty() 29 | 30 | # Clear inventory UI grid 31 | func clear_grid_container(): 32 | while grid_container.get_child_count() > 0: 33 | var child = grid_container.get_child(0) 34 | grid_container.remove_child(child) 35 | child.queue_free() 36 | 37 | # Store dragged slot reference 38 | func _on_drag_start(slot_control: Control): 39 | dragged_slot = slot_control 40 | print("Drag started for slot:", slot_control) 41 | 42 | # Drops slot at new location 43 | func _on_drag_end(): 44 | var target_slot = get_slot_under_mouse() 45 | if target_slot and dragged_slot != target_slot: 46 | drop_slot(dragged_slot, target_slot) 47 | dragged_slot = null 48 | 49 | # Get the current mouse position in the grid_container's coordinate system 50 | func get_slot_under_mouse() -> Control: 51 | var mouse_position = get_global_mouse_position() 52 | for slot in grid_container.get_children(): 53 | var slot_rect = Rect2(slot.global_position, slot.size) 54 | if slot_rect.has_point(mouse_position): 55 | return slot 56 | return null 57 | 58 | # Find the index of a slot 59 | func get_slot_index(slot: Control) -> int: 60 | for i in range(grid_container.get_child_count()): 61 | if grid_container.get_child(i) == slot: 62 | # Valid slot 63 | return i 64 | # Invalid slot 65 | return -1 66 | 67 | # Drop slots 68 | func drop_slot(slot1: Control, slot2: Control): 69 | var slot1_index = get_slot_index(slot1) 70 | var slot2_index = get_slot_index(slot2) 71 | if slot1_index == -1 or slot2_index == -1: 72 | return 73 | else: 74 | if Global.swap_inventory_items(slot1_index, slot2_index): 75 | _on_inventory_updated() 76 | print("Dropping slots:", slot1_index, slot2_index) 77 | -------------------------------------------------------------------------------- /Sectional_Code/13 - Draggable Inventory/Scripts/Main.gd: -------------------------------------------------------------------------------- 1 | ### Main.gd 2 | extends Node 3 | 4 | # Scene-Tree Node references 5 | @onready var items = $Items 6 | @onready var item_spawn_area = $ItemSpawnArea 7 | @onready var collision_shape = $ItemSpawnArea/CollisionShape2D 8 | 9 | # When the game loads spawn 10 pickup items in the spawn area 10 | func _ready(): 11 | spawn_random_items(10) 12 | 13 | # Get random position for item within the collision shape in spawn area 14 | func get_random_position(): 15 | var area_rect = collision_shape.shape.get_rect() 16 | var x = randf_range(0, area_rect.position.x) 17 | var y = randf_range(0, area_rect.position.y) 18 | return item_spawn_area.to_global(Vector2(x, y)) 19 | 20 | # Spawn random items from the Global list up until the max amount (10) has been reached 21 | func spawn_random_items(count): 22 | var attempts = 0 23 | var spawned_count = 0 24 | while spawned_count < count and attempts < 100: 25 | var position = get_random_position() 26 | spawn_item(Global.spawnable_items[randi() % Global.spawnable_items.size()], position) 27 | spawned_count += 1 28 | attempts += 1 29 | 30 | # Create a physical instance of the Item scene on the map underneath /Items node 31 | func spawn_item(data, position): 32 | var item_scene = preload("res://Scenes/Inventory_Item.tscn") 33 | var item_instance = item_scene.instantiate() 34 | item_instance.initiate_items(data["type"], data["name"], data["effect"], data["texture"]) 35 | item_instance.global_position = position 36 | items.add_child(item_instance) 37 | -------------------------------------------------------------------------------- /Sectional_Code/13 - Draggable Inventory/Scripts/Player.gd: -------------------------------------------------------------------------------- 1 | ### Player.gd 2 | extends CharacterBody2D 3 | 4 | # Scene-Tree Node references 5 | @onready var inventory_ui = $InventoryUI 6 | @onready var interact_ui = $InteractUI 7 | @onready var animated_sprite = $AnimatedSprite 8 | @onready var hotbar_ui = $InventoryHotbar 9 | 10 | # Variables 11 | @export var speed = 200 12 | 13 | func _ready(): 14 | # Set this node as the Player node 15 | Global.set_player_reference(self) 16 | 17 | # Input for movement 18 | func get_input(): 19 | var input_direction = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down") 20 | velocity = input_direction * speed 21 | 22 | # Movement & Animation 23 | func _physics_process(delta): 24 | get_input() 25 | move_and_slide() 26 | update_animation() 27 | 28 | # Animation 29 | func update_animation(): 30 | if velocity == Vector2.ZERO: 31 | animated_sprite.play("idle") 32 | else: 33 | if abs(velocity.x) > abs(velocity.y): 34 | if velocity.x > 0: 35 | animated_sprite.play("walk_right") 36 | else: 37 | animated_sprite.play("walk_left") 38 | else: 39 | if velocity.y > 0: 40 | animated_sprite.play("walk_down") 41 | else: 42 | animated_sprite.play("walk_up") 43 | 44 | # Show inventory menu on "I" pressed 45 | func _input(event): 46 | if event.is_action_pressed("ui_inventory"): 47 | inventory_ui.visible = !inventory_ui.visible 48 | get_tree().paused = !get_tree().paused 49 | hotbar_ui.visible = !hotbar_ui.visible 50 | 51 | # Apply the effect of the item (if possible) 52 | func apply_item_effect(item): 53 | match item["effect"]: 54 | "Stamina": 55 | speed += 50 56 | print("Speed increased to ", speed) 57 | "Slot Boost": 58 | Global.increase_inventory_size(5) 59 | print("Inventory increased to ", Global.inventory.size()) 60 | _: 61 | print("No effect for this item") 62 | 63 | # Use hotbar items on key 1 - 5 press 64 | func use_hotbar_item(slot_index): 65 | if slot_index < Global.hotbar_inventory.size(): 66 | var item = Global.hotbar_inventory[slot_index] 67 | if item != null: 68 | # Use item 69 | apply_item_effect(item) 70 | # Remove item 71 | item["quantity"] -= 1 72 | if item["quantity"] <= 0: 73 | Global.hotbar_inventory[slot_index] = null 74 | Global.remove_item(item["type"], item["effect"]) 75 | Global.inventory_updated.emit() 76 | 77 | # Hotbar shortcuts 78 | func _unhandled_input(event): 79 | if event is InputEventKey and event.pressed: 80 | # Then check for specific keys 81 | for i in range(Global.hotbar_size): 82 | # Assuming keys 1-5 are mapped to actions "hotbar_1" to "hotbar_5" in the Input Map 83 | if Input.is_action_just_pressed("hotbar_" + str(i + 1)): 84 | use_hotbar_item(i) 85 | break 86 | 87 | 88 | -------------------------------------------------------------------------------- /Sectional_Code/14 - Draggable Hotbar/Scripts/Global.gd: -------------------------------------------------------------------------------- 1 | ### Global.gd 2 | 3 | extends Node 4 | 5 | # Scene and node references 6 | @onready var inventory_slot_scene = preload("res://Scenes/Inventory_Slot.tscn") 7 | var player_node: Node = null 8 | 9 | # Inventory items 10 | var inventory = [] 11 | var spawnable_items = [ 12 | {"type": "Consumable", "name": "Berry", "effect": "Health", "texture": preload("res://Assets/Icons/icon31.png")}, 13 | {"type": "Consumable", "name": "Water", "effect": "Stamina", "texture": preload("res://Assets/Icons/icon9.png")}, 14 | {"type": "Consumable", "name": "Mushroom", "effect": "Armor", "texture": preload("res://Assets/Icons/icon32.png")}, 15 | {"type": "Gift", "name": "Gemstone", "effect": "", "texture": preload("res://Assets/Icons/icon21.png")}, 16 | ] 17 | 18 | # Custom signals 19 | signal inventory_updated 20 | 21 | # Hotbar items 22 | var hotbar_size = 5 23 | var hotbar_inventory = [] 24 | 25 | func _ready(): 26 | # Initializes the inventory with 30 slots (spread over 9 blocks per row) 27 | inventory.resize(30) 28 | # Hotbar size 29 | hotbar_inventory.resize(hotbar_size) 30 | 31 | # Sets the player reference for inventory interactions 32 | func set_player_reference(player): 33 | player_node = player 34 | 35 | # Adds an item to the inventory, returns true if successful 36 | func add_item(item, to_hotbar = false): 37 | var added_to_hotbar = false 38 | if to_hotbar: 39 | added_to_hotbar = add_hotbar_item(item) 40 | inventory_updated.emit() 41 | if not added_to_hotbar: 42 | for i in range(inventory.size()): 43 | # Check if the item exists in the inventory and matches both type and effect 44 | if inventory[i] != null and inventory[i]["type"] == item["type"] and inventory[i]["effect"] == item["effect"]: 45 | inventory[i]["quantity"] += item["quantity"] 46 | inventory_updated.emit() 47 | print("Item added", inventory) 48 | return true 49 | elif inventory[i] == null: 50 | inventory[i] = item 51 | inventory_updated.emit() 52 | print("Item added", inventory) 53 | return true 54 | return false 55 | 56 | # Removes an item from the inventory based on type and effect 57 | func remove_item(item_type, item_effect): 58 | # Inventory removal 59 | for i in range(inventory.size()): 60 | if inventory[i] != null and inventory[i]["type"] == item_type and inventory[i]["effect"] == item_effect: 61 | inventory[i]["quantity"] -= 1 62 | if inventory[i]["quantity"] <= 0: 63 | inventory[i] = null 64 | inventory_updated.emit() 65 | return true 66 | return false 67 | 68 | # Increase inventory size dynamically 69 | func increase_inventory_size(extra_slots): 70 | inventory.resize(inventory.size() + extra_slots) 71 | inventory_updated.emit() 72 | 73 | # Drops an item at a specified position, adjusting for nearby items 74 | func drop_item(item_data, drop_position): 75 | var item_scene = load(item_data["scene_path"]) 76 | var item_instance = item_scene.instantiate() 77 | item_instance.set_item_data(item_data) 78 | drop_position = adjust_drop_position(drop_position) 79 | item_instance.global_position = drop_position 80 | get_tree().current_scene.add_child(item_instance) 81 | 82 | # Adjusts the drop position to avoid overlapping with nearby items 83 | func adjust_drop_position(position): 84 | var radius = 100 85 | var nearby_items = get_tree().get_nodes_in_group("Items") 86 | for item in nearby_items: 87 | if item.global_position.distance_to(position) < radius: 88 | var random_offset = Vector2(randf_range(-radius, radius), randf_range(-radius, radius)) 89 | position += random_offset 90 | break 91 | return position 92 | 93 | # Try adding to hotbar 94 | func add_hotbar_item(item): 95 | for i in range(hotbar_size): 96 | if hotbar_inventory[i] == null: 97 | hotbar_inventory[i] = item 98 | return true 99 | return false 100 | 101 | # Removes an item from the hotbar 102 | func remove_hotbar_item(item_type, item_effect): 103 | for i in range(hotbar_inventory.size()): 104 | if hotbar_inventory[i] != null and hotbar_inventory[i]["type"] == item_type and hotbar_inventory[i]["effect"] == item_effect: 105 | if hotbar_inventory[i]["quantity"] <= 0: 106 | hotbar_inventory[i] = null 107 | inventory_updated.emit() 108 | return true 109 | return false 110 | 111 | # Unassigns an item from the hotbar 112 | func unassign_hotbar_item(item_type, item_effect): 113 | for i in range(hotbar_inventory.size()): 114 | if hotbar_inventory[i] != null and hotbar_inventory[i]["type"] == item_type and hotbar_inventory[i]["effect"] == item_effect: 115 | hotbar_inventory[i] = null 116 | inventory_updated.emit() 117 | return true 118 | return false 119 | 120 | # Prevents duplicate item assignment 121 | func is_item_assigned_to_hotbar(item_to_check): 122 | return item_to_check in hotbar_inventory 123 | 124 | # Swaps items in the inventory based on their indices 125 | func swap_inventory_items(index1, index2): 126 | if index1 < 0 or index1 >= inventory.size() or index2 < 0 or index2 >= inventory.size(): 127 | return false 128 | var temp = inventory[index1] 129 | inventory[index1] = inventory[index2] 130 | inventory[index2] = temp 131 | inventory_updated.emit() 132 | return true 133 | 134 | # Swaps items in the hotbar inventory based on their indices 135 | func swap_hotbar_items(index1, index2): 136 | if index1 < 0 or index1 >= hotbar_inventory.size() or index2 < 0 or index2 >= hotbar_inventory.size(): 137 | return false 138 | var temp = hotbar_inventory[index1] 139 | hotbar_inventory[index1] = hotbar_inventory[index2] 140 | hotbar_inventory[index2] = temp 141 | inventory_updated.emit() 142 | return true 143 | -------------------------------------------------------------------------------- /Sectional_Code/14 - Draggable Hotbar/Scripts/Inventory_Hotbar.gd: -------------------------------------------------------------------------------- 1 | ### Inventory_Hotbar.gd 2 | 3 | extends Control 4 | 5 | @onready var hotbar_container = $HBoxContainer 6 | 7 | # Drag/Drop 8 | var dragged_slot = null 9 | 10 | # Called when the node enters the scene tree for the first time. 11 | func _ready(): 12 | Global.inventory_updated.connect(_update_hotbar_ui) 13 | _update_hotbar_ui() 14 | 15 | # Create the hotbar slots 16 | func _update_hotbar_ui(): 17 | clear_hotbar_container() 18 | for i in range(Global.hotbar_size): 19 | var slot = Global.inventory_slot_scene.instantiate() 20 | slot.set_slot_index(i) 21 | 22 | slot.drag_start.connect(_on_drag_start) 23 | slot.drag_end.connect(_on_drag_end) 24 | 25 | hotbar_container.add_child(slot) 26 | if Global.hotbar_inventory[i] != null: 27 | slot.set_item(Global.hotbar_inventory[i]) 28 | else: 29 | slot.set_empty() 30 | slot.update_assignment_status() 31 | 32 | # Clear hotbar slots 33 | func clear_hotbar_container(): 34 | while hotbar_container.get_child_count() > 0: 35 | var child = hotbar_container.get_child(0) 36 | hotbar_container.remove_child(child) 37 | child.queue_free() 38 | 39 | # Store dragged slot reference 40 | func _on_drag_start(slot_control : Control): 41 | dragged_slot = slot_control 42 | print("Drag started fro slot: ", dragged_slot) 43 | 44 | func _on_drag_end(): 45 | var target_slot = get_slot_under_mouse() 46 | if target_slot and dragged_slot != target_slot: 47 | drop_slot(dragged_slot, target_slot) 48 | dragged_slot = null 49 | 50 | # Get the current mouse position in the hotbar_container's coordinate system 51 | func get_slot_under_mouse() -> Control: 52 | var mouse_position = get_global_mouse_position() 53 | for slot in hotbar_container.get_children(): 54 | var slot_rect = Rect2(slot.global_position, slot.size) 55 | if slot_rect.has_point(mouse_position): 56 | return slot 57 | return null 58 | 59 | # Find the index of a slot 60 | func get_slot_index(slot: Control) -> int: 61 | for i in range(hotbar_container.get_child_count()): 62 | if hotbar_container.get_child(i) == slot: 63 | # Valid slot found 64 | return i 65 | # Invalid slot 66 | return -1 67 | 68 | # Drop slots 69 | func drop_slot(slot1: Control, slot2: Control): 70 | var slot1_index = get_slot_index(slot1) 71 | var slot2_index = get_slot_index(slot2) 72 | if slot1_index == -1 or slot2_index == -1: 73 | print("Invalid slots found") 74 | return 75 | else: 76 | if Global.swap_hotbar_items(slot1_index, slot2_index): 77 | print("Drpping slot items: ", slot1, slot2_index) 78 | _update_hotbar_ui() 79 | 80 | -------------------------------------------------------------------------------- /Sectional_Code/14 - Draggable Hotbar/Scripts/Inventory_Item.gd: -------------------------------------------------------------------------------- 1 | ### Inventory_Item.gd 2 | @tool 3 | extends Node2D 4 | 5 | # Item details for editor window 6 | @export var item_type = "" 7 | @export var item_name = "" 8 | @export var item_texture: Texture 9 | @export var item_effect = "" 10 | var scene_path: String = "res://Scenes/Inventory_Item.tscn" 11 | 12 | # Scene-Tree Node references 13 | @onready var icon_sprite = $Sprite2D 14 | 15 | # Variables 16 | var player_in_range = false 17 | 18 | func _ready(): 19 | # Set the texture to reflect in the game 20 | if not Engine.is_editor_hint(): 21 | icon_sprite.texture = item_texture 22 | 23 | func _process(_delta): 24 | # Set the texture to reflect in the editor 25 | if Engine.is_editor_hint(): 26 | icon_sprite.texture = item_texture 27 | # Add item to inventory if player presses "E" within range 28 | if player_in_range and Input.is_action_just_pressed("ui_add"): 29 | pickup_item() 30 | 31 | # Add item to inventory 32 | func pickup_item(): 33 | var item = { 34 | "quantity": 1, 35 | "type": item_type, 36 | "name": item_name, 37 | "effect": item_effect, 38 | "texture": item_texture, 39 | "scene_path": scene_path 40 | } 41 | if Global.player_node: 42 | Global.add_item(item, false) 43 | self.queue_free() 44 | 45 | # If player is in range, show UI and make item pickable 46 | func _on_area_2d_body_entered(body): 47 | if body.is_in_group("Player"): 48 | player_in_range = true 49 | body.interact_ui.visible = true 50 | 51 | # If player is in range, hide UI and don't make item pickable 52 | func _on_area_2d_body_exited(body): 53 | if body.is_in_group("Player"): 54 | player_in_range = false 55 | body.interact_ui.visible = false 56 | 57 | # Sets the item's dictionary data 58 | func set_item_data(data): 59 | item_type = data["type"] 60 | item_name = data["name"] 61 | item_effect = data["effect"] 62 | item_texture = data["texture"] 63 | 64 | # Set the items values for spawning 65 | func initiate_items(type, name, effect, texture): 66 | item_type = type 67 | item_name = name 68 | item_effect = effect 69 | item_texture = texture 70 | -------------------------------------------------------------------------------- /Sectional_Code/14 - Draggable Hotbar/Scripts/Inventory_Slot.gd: -------------------------------------------------------------------------------- 1 | ### Inventory_Slot.gd 2 | 3 | extends Control 4 | 5 | # Scene-Tree Node references 6 | @onready var icon = $InnerBorder/ItemIcon 7 | @onready var quantity_label = $InnerBorder/ItemQuantity 8 | @onready var details_panel = $DetailsPanel 9 | @onready var item_name = $DetailsPanel/ItemName 10 | @onready var item_type = $DetailsPanel/ItemType 11 | @onready var item_effect = $DetailsPanel/ItemEffect 12 | @onready var usage_panel = $UsagePanel 13 | @onready var assign_button = $UsagePanel/AssignButton 14 | @onready var outer_border = $OuterBorder 15 | 16 | # Signals 17 | signal drag_start(slot) 18 | signal drag_end() 19 | 20 | # Slot item 21 | var item = null 22 | var slot_index = -1 23 | var is_assigned = false 24 | 25 | # Set index 26 | func set_slot_index(new_index): 27 | slot_index = new_index 28 | 29 | # Show item details on hover enter 30 | func _on_item_button_mouse_entered(): 31 | if item != null: 32 | usage_panel.visible = false 33 | details_panel.visible = true 34 | 35 | # Hide item details on hover exit 36 | func _on_item_button_mouse_exited(): 37 | details_panel.visible = false 38 | 39 | # Default empty slot 40 | func set_empty(): 41 | icon.texture = null 42 | quantity_label.text = "" 43 | 44 | # Set slot item with its values from the dictionary 45 | func set_item(new_item): 46 | item = new_item 47 | icon.texture = item["texture"] 48 | quantity_label.text = str(item["quantity"]) 49 | item_name.text = str(item["name"]) 50 | item_type.text = str(item["type"]) 51 | if item["effect"] != "": 52 | item_effect.text = str("+ ", item["effect"]) 53 | else: 54 | item_effect.text = "" 55 | update_assignment_status() 56 | 57 | # Remove item from inventory and drop it back into the world 58 | func _on_drop_button_pressed(): 59 | if item != null: 60 | var drop_position = Global.player_node.global_position 61 | var drop_offset = Vector2(0, 50) 62 | drop_offset = drop_offset.rotated(Global.player_node.rotation) 63 | Global.drop_item(item, drop_position + drop_offset) 64 | Global.remove_item(item["type"], item["effect"]) 65 | Global.remove_hotbar_item(item["type"], item["effect"]) 66 | usage_panel.visible = false 67 | 68 | # Remove item from inventory, use it, and apply its effect (if possible) 69 | func _on_use_button_pressed(): 70 | usage_panel.visible = false 71 | if item != null and item["effect"] != "": 72 | if Global.player_node: 73 | Global.player_node.apply_item_effect(item) 74 | Global.remove_item(item["type"], item["effect"]) 75 | Global.remove_hotbar_item(item["type"], item["effect"]) 76 | else: 77 | print("Player could not be found") 78 | 79 | # Updates hotbar assignment status 80 | func update_assignment_status(): 81 | is_assigned = Global.is_item_assigned_to_hotbar(item) 82 | if is_assigned: 83 | assign_button.text = "Unassign" 84 | else: 85 | assign_button.text = "Assign" 86 | 87 | # Assigns/Unassigns hotbar item 88 | func _on_assign_button_pressed(): 89 | if item != null: 90 | if is_assigned: 91 | Global.unassign_hotbar_item(item["type"], item["effect"]) 92 | is_assigned = false 93 | else: 94 | Global.add_item(item, true) 95 | is_assigned = true 96 | update_assignment_status() 97 | 98 | # ItemButtons pressed events 99 | func _on_item_button_gui_input(event): 100 | if event is InputEventMouseButton: 101 | # Usage panel 102 | if event.button_index == MOUSE_BUTTON_LEFT and event.is_pressed(): 103 | if item != null: 104 | usage_panel.visible = !usage_panel.visible 105 | # Dragging item 106 | if event.button_index == MOUSE_BUTTON_RIGHT: 107 | if event.is_pressed(): 108 | outer_border.modulate = Color(1, 1, 0) 109 | drag_start.emit(self) 110 | else: 111 | outer_border.modulate = Color(1, 1, 1) 112 | drag_end.emit() 113 | 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /Sectional_Code/14 - Draggable Hotbar/Scripts/Inventory_UI.gd: -------------------------------------------------------------------------------- 1 | ### Inventory_UI.gd 2 | 3 | extends Control 4 | 5 | # Scene-Tree Node references 6 | @onready var grid_container = $GridContainer 7 | 8 | # Drag/Drop 9 | var dragged_slot = null 10 | 11 | func _ready(): 12 | # Connect function to signal to update inventory UI 13 | Global.inventory_updated.connect(_on_inventory_updated) 14 | _on_inventory_updated() 15 | 16 | # Update inventory UI 17 | func _on_inventory_updated(): 18 | # Clear existing slots 19 | clear_grid_container() 20 | # Add slots for each inventory position 21 | for item in Global.inventory: 22 | var slot = Global.inventory_slot_scene.instantiate() 23 | 24 | slot.drag_start.connect(_on_drag_start) 25 | slot.drag_end.connect(_on_drag_end) 26 | 27 | grid_container.add_child(slot) 28 | if item != null: 29 | slot.set_item(item) 30 | else: 31 | slot.set_empty() 32 | 33 | # Clear inventory UI grid 34 | func clear_grid_container(): 35 | while grid_container.get_child_count() > 0: 36 | var child = grid_container.get_child(0) 37 | grid_container.remove_child(child) 38 | child.queue_free() 39 | 40 | # Store dragged slot reference 41 | func _on_drag_start(slot_control : Control): 42 | dragged_slot = slot_control 43 | print("Drag started fro slot: ", dragged_slot) 44 | 45 | func _on_drag_end(): 46 | var target_slot = get_slot_under_mouse() 47 | if target_slot and dragged_slot != target_slot: 48 | drop_slot(dragged_slot, target_slot) 49 | dragged_slot = null 50 | 51 | # Get the current mouse position in the grid_container's coordinate system 52 | func get_slot_under_mouse() -> Control: 53 | var mouse_position = get_global_mouse_position() 54 | for slot in grid_container.get_children(): 55 | var slot_rect = Rect2(slot.global_position, slot.size) 56 | if slot_rect.has_point(mouse_position): 57 | return slot 58 | return null 59 | 60 | # Find the index of a slot 61 | func get_slot_index(slot: Control) -> int: 62 | for i in range(grid_container.get_child_count()): 63 | if grid_container.get_child(i) == slot: 64 | # Valid slot found 65 | return i 66 | # Invalid slot 67 | return -1 68 | 69 | # Drop slots 70 | func drop_slot(slot1: Control, slot2: Control): 71 | var slot1_index = get_slot_index(slot1) 72 | var slot2_index = get_slot_index(slot2) 73 | if slot1_index == -1 or slot2_index == -1: 74 | print("Invalid slots found") 75 | return 76 | else: 77 | if Global.swap_inventory_items(slot1_index, slot2_index): 78 | print("Drpping slot items: ", slot1, slot2_index) 79 | _on_inventory_updated() 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /Sectional_Code/14 - Draggable Hotbar/Scripts/Main.gd: -------------------------------------------------------------------------------- 1 | ### Main.gd 2 | 3 | extends Node2D 4 | 5 | # Scene-Tree Node references 6 | @onready var items = $Items 7 | @onready var item_spawn_area = $ItemSpawnArea 8 | @onready var collision_shape = $ItemSpawnArea/CollisionShape2D 9 | 10 | # Called when the node enters the scene tree for the first time. 11 | func _ready(): 12 | spawn_random_items(10) 13 | 14 | # Get random position for item within the collision shape in spawn area 15 | func get_random_position(): 16 | var area_rect = collision_shape.shape.get_rect() 17 | var x = randf_range(0, area_rect.position.x) 18 | var y = randf_range(0, area_rect.position.y) 19 | return item_spawn_area.to_global(Vector2(x, y)) 20 | 21 | func spawn_random_items(count): 22 | var attempts = 0 23 | var spawned_count = 0 24 | while spawned_count < count and attempts < 100: 25 | var position = get_random_position() 26 | spawn_item(Global.spawnable_items[randi() % Global.spawnable_items.size()], position) 27 | spawned_count += 1 28 | attempts += 1 29 | 30 | # Create a physical instance of the Item scene on the map underneath /Items node 31 | func spawn_item(data, position): 32 | var item_scene = preload("res://Scenes/Inventory_Item.tscn") 33 | var item_instance = item_scene.instantiate() 34 | item_instance.initiate_items(data["type"], data["name"], data["effect"], data["texture"]) 35 | item_instance.global_position = position 36 | items.add_child(item_instance) 37 | -------------------------------------------------------------------------------- /Sectional_Code/14 - Draggable Hotbar/Scripts/Player.gd: -------------------------------------------------------------------------------- 1 | ### Player.gd 2 | extends CharacterBody2D 3 | 4 | # Scene-Tree Node references 5 | @onready var animated_sprite = $AnimatedSprite2D 6 | @onready var interact_ui = $InteractUI 7 | @onready var inventory_ui = $InventoryUI 8 | @onready var inventory_hotbar = $InventoryHotbar 9 | 10 | # Variables 11 | @export var speed = 200 12 | 13 | func _ready(): 14 | # Set this node as the Player node 15 | Global.set_player_reference(self) 16 | 17 | # Input for movement 18 | func get_input(): 19 | var input_direction = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down") 20 | velocity = input_direction * speed 21 | 22 | # Movement & Animation 23 | func _physics_process(delta): 24 | get_input() 25 | move_and_slide() 26 | update_animation() 27 | 28 | # Animation 29 | func update_animation(): 30 | if velocity == Vector2.ZERO: 31 | animated_sprite.play("idle") 32 | else: 33 | if abs(velocity.x) > abs(velocity.y): 34 | if velocity.x > 0: 35 | animated_sprite.play("walk_right") 36 | else: 37 | animated_sprite.play("walk_left") 38 | else: 39 | if velocity.y > 0: 40 | animated_sprite.play("walk_down") 41 | else: 42 | animated_sprite.play("walk_up") 43 | 44 | # Show inventory menu on "I" pressed 45 | func _input(event): 46 | if event.is_action_pressed("ui_inventory"): 47 | inventory_ui.visible = !inventory_ui.visible 48 | get_tree().paused = !get_tree().paused 49 | inventory_hotbar.visible = !inventory_hotbar.visible 50 | 51 | # Apply the effect of the item (if possible) 52 | func apply_item_effect(item): 53 | match item["effect"]: 54 | "Stamina": 55 | speed += 50 56 | print("Speed increased to ", speed) 57 | "Slot Boost": 58 | Global.increase_inventory_size(5) 59 | print("Slots increased to ", Global.inventory.size()) 60 | _: 61 | print("There is no effect for this item") 62 | 63 | 64 | # Hotbar shotcut keys 65 | func use_hotbar_item(slot_index): 66 | if slot_index < Global.hotbar_inventory.size(): 67 | var item = Global.hotbar_inventory[slot_index] 68 | if item != null: 69 | # Use item at slot 70 | apply_item_effect(item) 71 | # Remove item 72 | item["quantity"] -= 1 73 | if item["quantity"] <= 0: 74 | Global.hotbar_inventory[slot_index] = null 75 | Global.remove_item(item["type"], item["effect"]) 76 | Global.inventory_updated.emit() 77 | 78 | # Hotbar shortcuts usage 79 | func _unhandled_input(event): 80 | if event is InputEventKey and event.pressed: 81 | for i in range(Global.hotbar_size): 82 | if Input.is_action_just_pressed("hotbar_" + str(i + 1)): 83 | use_hotbar_item(i) 84 | break 85 | 86 | 87 | 88 | 89 | --------------------------------------------------------------------------------