├── .gitignore ├── Assets ├── Blue.png ├── Blue.png.import ├── Border.png ├── Border.png.import ├── Cyan.png ├── Cyan.png.import ├── Ghost.png ├── Ghost.png.import ├── Green.png ├── Green.png.import ├── Grid.png ├── Grid.png.import ├── Orange.png ├── Orange.png.import ├── Purple.png ├── Purple.png.import ├── Red.png ├── Red.png.import ├── Yellow.png ├── Yellow.png.import ├── icon.svg └── icon.svg.import ├── Resources ├── i_piece_data.tres ├── j_piece_data.tres ├── l_piece_data.tres ├── o_piece_data.tres ├── s_piece_data.tres ├── t_piece_data.tres └── z_piece_data.tres ├── Scenes ├── ghost_tetromino.tscn ├── line.tscn ├── main.tscn ├── piece.tscn ├── tetromino.tscn └── ui.tscn ├── Scripts ├── board.gd ├── ghost_tetromino.gd ├── line.gd ├── piece.gd ├── piece_data.gd ├── piece_spawner.gd ├── shared.gd ├── tetromino.gd └── ui.gd └── project.godot /.gitignore: -------------------------------------------------------------------------------- 1 | # Godot 4+ specific ignores 2 | .godot/ 3 | 4 | # Godot-specific ignores 5 | .import/ 6 | export.cfg 7 | export_presets.cfg 8 | 9 | # Imported translations (automatically generated from CSV files) 10 | *.translation 11 | 12 | # Mono-specific ignores 13 | .mono/ 14 | data_*/ 15 | mono_crash.*.json -------------------------------------------------------------------------------- /Assets/Blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wojciech-bilicki/TetrisTutorial/910b0ce661ce24e4293cdec9f8dad82e2a8fffb8/Assets/Blue.png -------------------------------------------------------------------------------- /Assets/Blue.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://u5huhvhxg2bo" 6 | path="res://.godot/imported/Blue.png-7d44080c477d302cd4d04cf4d7e48fd0.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://Assets/Blue.png" 14 | dest_files=["res://.godot/imported/Blue.png-7d44080c477d302cd4d04cf4d7e48fd0.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /Assets/Border.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wojciech-bilicki/TetrisTutorial/910b0ce661ce24e4293cdec9f8dad82e2a8fffb8/Assets/Border.png -------------------------------------------------------------------------------- /Assets/Border.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://dj1olp7v7y623" 6 | path="res://.godot/imported/Border.png-a28cad03bbcf48870e769e774d8aa370.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://Assets/Border.png" 14 | dest_files=["res://.godot/imported/Border.png-a28cad03bbcf48870e769e774d8aa370.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /Assets/Cyan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wojciech-bilicki/TetrisTutorial/910b0ce661ce24e4293cdec9f8dad82e2a8fffb8/Assets/Cyan.png -------------------------------------------------------------------------------- /Assets/Cyan.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://bvhiy4egr6qkq" 6 | path="res://.godot/imported/Cyan.png-93cfe51a913c97141257e6898bf95a28.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://Assets/Cyan.png" 14 | dest_files=["res://.godot/imported/Cyan.png-93cfe51a913c97141257e6898bf95a28.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /Assets/Ghost.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wojciech-bilicki/TetrisTutorial/910b0ce661ce24e4293cdec9f8dad82e2a8fffb8/Assets/Ghost.png -------------------------------------------------------------------------------- /Assets/Ghost.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://csgei4g8xvkbb" 6 | path="res://.godot/imported/Ghost.png-c37d60734710ecd616e37cb581037c8f.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://Assets/Ghost.png" 14 | dest_files=["res://.godot/imported/Ghost.png-c37d60734710ecd616e37cb581037c8f.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /Assets/Green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wojciech-bilicki/TetrisTutorial/910b0ce661ce24e4293cdec9f8dad82e2a8fffb8/Assets/Green.png -------------------------------------------------------------------------------- /Assets/Green.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://dmsufpu70xvxu" 6 | path="res://.godot/imported/Green.png-da7f67f6082979dfa8c8eb879e6e026f.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://Assets/Green.png" 14 | dest_files=["res://.godot/imported/Green.png-da7f67f6082979dfa8c8eb879e6e026f.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /Assets/Grid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wojciech-bilicki/TetrisTutorial/910b0ce661ce24e4293cdec9f8dad82e2a8fffb8/Assets/Grid.png -------------------------------------------------------------------------------- /Assets/Grid.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://dddenph2txf1h" 6 | path="res://.godot/imported/Grid.png-7cb94410da10419a5f895fdff80711bb.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://Assets/Grid.png" 14 | dest_files=["res://.godot/imported/Grid.png-7cb94410da10419a5f895fdff80711bb.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /Assets/Orange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wojciech-bilicki/TetrisTutorial/910b0ce661ce24e4293cdec9f8dad82e2a8fffb8/Assets/Orange.png -------------------------------------------------------------------------------- /Assets/Orange.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://dopu8p8nw1nn8" 6 | path="res://.godot/imported/Orange.png-123a6548a40c64eaecd4da7b0ff7748e.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://Assets/Orange.png" 14 | dest_files=["res://.godot/imported/Orange.png-123a6548a40c64eaecd4da7b0ff7748e.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /Assets/Purple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wojciech-bilicki/TetrisTutorial/910b0ce661ce24e4293cdec9f8dad82e2a8fffb8/Assets/Purple.png -------------------------------------------------------------------------------- /Assets/Purple.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://d4lhgw2colkdv" 6 | path="res://.godot/imported/Purple.png-72b93608b1468bcab6367f291daf922e.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://Assets/Purple.png" 14 | dest_files=["res://.godot/imported/Purple.png-72b93608b1468bcab6367f291daf922e.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /Assets/Red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wojciech-bilicki/TetrisTutorial/910b0ce661ce24e4293cdec9f8dad82e2a8fffb8/Assets/Red.png -------------------------------------------------------------------------------- /Assets/Red.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://dofvojmuljtjf" 6 | path="res://.godot/imported/Red.png-b794f9e636417b513efdcf96cb3fc673.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://Assets/Red.png" 14 | dest_files=["res://.godot/imported/Red.png-b794f9e636417b513efdcf96cb3fc673.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /Assets/Yellow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wojciech-bilicki/TetrisTutorial/910b0ce661ce24e4293cdec9f8dad82e2a8fffb8/Assets/Yellow.png -------------------------------------------------------------------------------- /Assets/Yellow.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://bjf3jiap1gfg7" 6 | path="res://.godot/imported/Yellow.png-75bc20b052908a3e549c2d0229e1066c.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://Assets/Yellow.png" 14 | dest_files=["res://.godot/imported/Yellow.png-75bc20b052908a3e549c2d0229e1066c.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /Assets/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Assets/icon.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://dque8rl2wia34" 6 | path="res://.godot/imported/icon.svg-8193eb3d66a1b5143b8bb4c28c1dc139.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://Assets/icon.svg" 14 | dest_files=["res://.godot/imported/icon.svg-8193eb3d66a1b5143b8bb4c28c1dc139.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=1.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /Resources/i_piece_data.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" load_steps=3 format=3 uid="uid://cyd43r7tkl62f"] 2 | 3 | [ext_resource type="Texture2D" uid="uid://bvhiy4egr6qkq" path="res://Assets/Cyan.png" id="1_runxs"] 4 | [ext_resource type="Script" path="res://Scripts/piece_data.gd" id="2_4n53t"] 5 | 6 | [resource] 7 | script = ExtResource("2_4n53t") 8 | piece_texture = ExtResource("1_runxs") 9 | tetromino_type = 0 10 | spawn_position = Vector2(-24, -456) 11 | -------------------------------------------------------------------------------- /Resources/j_piece_data.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" load_steps=3 format=3 uid="uid://bkhihfbdmqdx7"] 2 | 3 | [ext_resource type="Texture2D" uid="uid://u5huhvhxg2bo" path="res://Assets/Blue.png" id="1_sy12j"] 4 | [ext_resource type="Script" path="res://Scripts/piece_data.gd" id="2_eoafq"] 5 | 6 | [resource] 7 | script = ExtResource("2_eoafq") 8 | piece_texture = ExtResource("1_sy12j") 9 | tetromino_type = 3 10 | spawn_position = Vector2(-24, -456) 11 | -------------------------------------------------------------------------------- /Resources/l_piece_data.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" load_steps=3 format=3 uid="uid://kfbkpv1oga5"] 2 | 3 | [ext_resource type="Texture2D" uid="uid://bjf3jiap1gfg7" path="res://Assets/Yellow.png" id="1_g1fxq"] 4 | [ext_resource type="Script" path="res://Scripts/piece_data.gd" id="2_bcqf2"] 5 | 6 | [resource] 7 | script = ExtResource("2_bcqf2") 8 | piece_texture = ExtResource("1_g1fxq") 9 | tetromino_type = 1 10 | spawn_position = Vector2(-24, -456) 11 | -------------------------------------------------------------------------------- /Resources/o_piece_data.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" load_steps=3 format=3 uid="uid://d2dvraldfgmbd"] 2 | 3 | [ext_resource type="Texture2D" uid="uid://dopu8p8nw1nn8" path="res://Assets/Orange.png" id="1_5so7u"] 4 | [ext_resource type="Script" path="res://Scripts/piece_data.gd" id="2_jiahi"] 5 | 6 | [resource] 7 | script = ExtResource("2_jiahi") 8 | piece_texture = ExtResource("1_5so7u") 9 | tetromino_type = 4 10 | spawn_position = Vector2(-24, -456) 11 | -------------------------------------------------------------------------------- /Resources/s_piece_data.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" load_steps=3 format=3 uid="uid://dqp43ebvupj36"] 2 | 3 | [ext_resource type="Texture2D" uid="uid://dmsufpu70xvxu" path="res://Assets/Green.png" id="1_wnvma"] 4 | [ext_resource type="Script" path="res://Scripts/piece_data.gd" id="2_vfxql"] 5 | 6 | [resource] 7 | script = ExtResource("2_vfxql") 8 | piece_texture = ExtResource("1_wnvma") 9 | tetromino_type = 5 10 | spawn_position = Vector2(24, -456) 11 | -------------------------------------------------------------------------------- /Resources/t_piece_data.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" load_steps=3 format=3 uid="uid://cxivocmfljq0l"] 2 | 3 | [ext_resource type="Texture2D" uid="uid://dofvojmuljtjf" path="res://Assets/Red.png" id="1_f8pdg"] 4 | [ext_resource type="Script" path="res://Scripts/piece_data.gd" id="2_75svq"] 5 | 6 | [resource] 7 | script = ExtResource("2_75svq") 8 | piece_texture = ExtResource("1_f8pdg") 9 | tetromino_type = 6 10 | spawn_position = Vector2(-24, -456) 11 | -------------------------------------------------------------------------------- /Resources/z_piece_data.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Resource" load_steps=3 format=3 uid="uid://b5ynowy668do0"] 2 | 3 | [ext_resource type="Texture2D" uid="uid://d4lhgw2colkdv" path="res://Assets/Purple.png" id="1_jbaxo"] 4 | [ext_resource type="Script" path="res://Scripts/piece_data.gd" id="2_6y2px"] 5 | 6 | [resource] 7 | script = ExtResource("2_6y2px") 8 | piece_texture = ExtResource("1_jbaxo") 9 | tetromino_type = 2 10 | spawn_position = Vector2(-24, -456) 11 | -------------------------------------------------------------------------------- /Scenes/ghost_tetromino.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://peeyd3oo0tsh"] 2 | 3 | [ext_resource type="Script" path="res://Scripts/ghost_tetromino.gd" id="1_5m71h"] 4 | 5 | [node name="ghost_tetromino" type="Node2D"] 6 | script = ExtResource("1_5m71h") 7 | -------------------------------------------------------------------------------- /Scenes/line.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://ca8nh034fytl5"] 2 | 3 | [ext_resource type="Script" path="res://Scripts/line.gd" id="1_gj086"] 4 | 5 | [node name="Line" type="Node2D"] 6 | script = ExtResource("1_gj086") 7 | -------------------------------------------------------------------------------- /Scenes/main.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=7 format=3 uid="uid://cjshm244ivhhy"] 2 | 3 | [ext_resource type="Texture2D" uid="uid://dj1olp7v7y623" path="res://Assets/Border.png" id="1_2kdh7"] 4 | [ext_resource type="Texture2D" uid="uid://dddenph2txf1h" path="res://Assets/Grid.png" id="2_7mxh0"] 5 | [ext_resource type="Script" path="res://Scripts/piece_spawner.gd" id="3_ygpth"] 6 | [ext_resource type="Script" path="res://Scripts/board.gd" id="4_yatxc"] 7 | [ext_resource type="PackedScene" uid="uid://c4j05v6wfo823" path="res://Scenes/tetromino.tscn" id="5_j0sar"] 8 | [ext_resource type="PackedScene" uid="uid://ct2meksk8huhw" path="res://Scenes/ui.tscn" id="6_5ie2u"] 9 | 10 | [node name="main" type="Node"] 11 | 12 | [node name="Camera2D" type="Camera2D" parent="."] 13 | zoom = Vector2(0.5, 0.5) 14 | 15 | [node name="Border" type="TextureRect" parent="."] 16 | offset_left = -256.0 17 | offset_top = -496.0 18 | offset_right = 1794.0 19 | offset_bottom = 3474.0 20 | scale = Vector2(0.25, 0.25) 21 | texture = ExtResource("1_2kdh7") 22 | 23 | [node name="GridTexture" type="TextureRect" parent="Border"] 24 | layout_mode = 1 25 | anchors_preset = 8 26 | anchor_left = 0.5 27 | anchor_top = 0.5 28 | anchor_right = 0.5 29 | anchor_bottom = 0.5 30 | offset_left = -961.0 31 | offset_top = -1921.0 32 | offset_right = 959.0 33 | offset_bottom = 1928.0 34 | grow_horizontal = 2 35 | grow_vertical = 2 36 | texture = ExtResource("2_7mxh0") 37 | stretch_mode = 1 38 | 39 | [node name="Board" type="Node" parent="."] 40 | script = ExtResource("4_yatxc") 41 | tetromino_scene = ExtResource("5_j0sar") 42 | 43 | [node name="PanelContainer" type="PanelContainer" parent="."] 44 | custom_minimum_size = Vector2(200, 100) 45 | offset_left = -100.0 46 | offset_top = -631.0 47 | offset_right = 100.0 48 | offset_bottom = -531.0 49 | 50 | [node name="Label" type="Label" parent="PanelContainer"] 51 | layout_mode = 2 52 | size_flags_vertical = 0 53 | text = "NEXT TETROMINO:" 54 | horizontal_alignment = 1 55 | 56 | [node name="PieceSpawner" type="Node" parent="."] 57 | script = ExtResource("3_ygpth") 58 | 59 | [node name="UI" parent="." instance=ExtResource("6_5ie2u")] 60 | -------------------------------------------------------------------------------- /Scenes/piece.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=3 uid="uid://ohv2dbvddn45"] 2 | 3 | [ext_resource type="Script" path="res://Scripts/piece.gd" id="1_4v0be"] 4 | [ext_resource type="Texture2D" uid="uid://bjf3jiap1gfg7" path="res://Assets/Yellow.png" id="2_d3cui"] 5 | 6 | [sub_resource type="RectangleShape2D" id="RectangleShape2D_jmyax"] 7 | size = Vector2(48, 48) 8 | 9 | [node name="Piece" type="Area2D"] 10 | script = ExtResource("1_4v0be") 11 | 12 | [node name="Sprite2D" type="Sprite2D" parent="."] 13 | scale = Vector2(0.25, 0.25) 14 | texture = ExtResource("2_d3cui") 15 | 16 | [node name="CollisionShape2D" type="CollisionShape2D" parent="."] 17 | shape = SubResource("RectangleShape2D_jmyax") 18 | -------------------------------------------------------------------------------- /Scenes/tetromino.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://c4j05v6wfo823"] 2 | 3 | [ext_resource type="Script" path="res://Scripts/tetromino.gd" id="1_egcr8"] 4 | 5 | [node name="Tetromino" type="Node2D"] 6 | script = ExtResource("1_egcr8") 7 | 8 | [node name="Timer" type="Timer" parent="."] 9 | autostart = true 10 | 11 | [connection signal="timeout" from="Timer" to="." method="_on_timer_timeout"] 12 | -------------------------------------------------------------------------------- /Scenes/ui.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://ct2meksk8huhw"] 2 | 3 | [ext_resource type="Script" path="res://Scripts/ui.gd" id="1_j3a81"] 4 | 5 | [node name="UI" type="CanvasLayer"] 6 | script = ExtResource("1_j3a81") 7 | 8 | [node name="CenterContainer" type="CenterContainer" parent="."] 9 | visible = false 10 | anchors_preset = 15 11 | anchor_right = 1.0 12 | anchor_bottom = 1.0 13 | grow_horizontal = 2 14 | grow_vertical = 2 15 | 16 | [node name="PanelContainer" type="PanelContainer" parent="CenterContainer"] 17 | layout_mode = 2 18 | 19 | [node name="MarginContainer" type="MarginContainer" parent="CenterContainer/PanelContainer"] 20 | layout_mode = 2 21 | theme_override_constants/margin_left = 16 22 | theme_override_constants/margin_top = 16 23 | theme_override_constants/margin_right = 16 24 | theme_override_constants/margin_bottom = 16 25 | 26 | [node name="VBoxContainer" type="VBoxContainer" parent="CenterContainer/PanelContainer/MarginContainer"] 27 | layout_mode = 2 28 | 29 | [node name="Label" type="Label" parent="CenterContainer/PanelContainer/MarginContainer/VBoxContainer"] 30 | layout_mode = 2 31 | text = "GAME OVER" 32 | 33 | [node name="Button" type="Button" parent="CenterContainer/PanelContainer/MarginContainer/VBoxContainer"] 34 | layout_mode = 2 35 | text = "RESTART" 36 | 37 | [connection signal="pressed" from="CenterContainer/PanelContainer/MarginContainer/VBoxContainer/Button" to="." method="_on_button_pressed"] 38 | -------------------------------------------------------------------------------- /Scripts/board.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | class_name Board 4 | 5 | signal tetromino_locked 6 | signal game_over 7 | 8 | @onready var panel_container = $"../PanelContainer" 9 | 10 | @onready var line_scene = preload("res://Scenes/line.tscn") 11 | 12 | 13 | const ROW_COUNT = 20 14 | const COLUMN_COUNT = 10 15 | var next_tetromino 16 | var tetrominos: Array[Tetromino] = [] 17 | @export var tetromino_scene: PackedScene 18 | 19 | func spawn_tetromino(type: Shared.Tetromino, is_next_piece, spawn_position): 20 | var tetromino_data = Shared.data[type] 21 | var tetromino = tetromino_scene.instantiate() as Tetromino 22 | 23 | tetromino.tetromino_data = tetromino_data 24 | tetromino.is_next_piece = is_next_piece 25 | 26 | if is_next_piece == false: 27 | var other_pieces = get_all_pieces() 28 | tetromino.position = tetromino_data.spawn_position 29 | tetromino.other_tetrominoes_pieces = other_pieces 30 | add_child(tetromino) 31 | tetromino.lock_tetromino.connect(on_tetromino_locked) 32 | else: 33 | tetromino.scale = Vector2(0.5, 0.5) 34 | panel_container.add_child(tetromino) 35 | tetromino.set_position(spawn_position) 36 | next_tetromino = tetromino 37 | 38 | 39 | func on_tetromino_locked(tetromino: Tetromino): 40 | next_tetromino.queue_free() 41 | tetrominos.append(tetromino) 42 | add_tetromino_to_lines(tetromino) 43 | remove_full_lines() 44 | tetromino_locked.emit() 45 | check_game_over() 46 | 47 | 48 | func check_game_over(): 49 | for piece in get_all_pieces(): 50 | var y_location = piece.global_position.y 51 | if y_location == -456: 52 | game_over.emit() 53 | 54 | func add_tetromino_to_lines(tetromino: Tetromino): 55 | var tetromino_pieces = tetromino.get_children().filter(func (c): return c is Piece) 56 | 57 | for piece in tetromino_pieces: 58 | var y_position = piece.global_position.y 59 | var does_line_for_piece_exists = false 60 | 61 | for line in get_lines(): 62 | 63 | if line.global_position.y == y_position: 64 | piece.reparent(line) 65 | does_line_for_piece_exists = true 66 | 67 | if !does_line_for_piece_exists: 68 | var piece_line = line_scene.instantiate() as Line 69 | piece_line.global_position = Vector2(0, y_position) 70 | add_child(piece_line) 71 | piece.reparent(piece_line) 72 | 73 | func get_lines(): 74 | return get_children().filter(func (c): return c is Line) 75 | 76 | func remove_full_lines(): 77 | for line in get_lines(): 78 | if line.is_line_full(COLUMN_COUNT): 79 | move_lines_down(line.global_position.y) 80 | line.free() 81 | 82 | func move_lines_down(y_position): 83 | for line in get_lines(): 84 | if line.global_position.y < y_position: 85 | line.global_position.y += 48 86 | 87 | func get_all_pieces(): 88 | var pieces = [] 89 | for line in get_lines(): 90 | pieces.append_array(line.get_children()) 91 | return pieces 92 | -------------------------------------------------------------------------------- /Scripts/ghost_tetromino.gd: -------------------------------------------------------------------------------- 1 | extends Node2D 2 | 3 | class_name GhostTetromino 4 | 5 | @onready var piece_scene = preload("res://Scenes/piece.tscn") 6 | @onready var ghost_texture = preload("res://Assets/Ghost.png") 7 | 8 | var tetromino_data: Resource 9 | 10 | func _ready(): 11 | var tetromino_cells = Shared.cells[tetromino_data.tetromino_type] 12 | 13 | for cell in tetromino_cells: 14 | var piece = piece_scene.instantiate() as Piece 15 | add_child(piece) 16 | piece.set_texture(ghost_texture) 17 | piece.position = cell * piece.get_size() 18 | 19 | func set_ghost_tetromino(new_position: Vector2, pieces_position): 20 | global_position = new_position 21 | 22 | var pieces = get_children() 23 | for i in pieces.size(): 24 | pieces[i].position = pieces_position[i] 25 | -------------------------------------------------------------------------------- /Scripts/line.gd: -------------------------------------------------------------------------------- 1 | extends Node2D 2 | 3 | class_name Line 4 | 5 | 6 | func is_line_full(max_count): 7 | return max_count == get_child_count() 8 | -------------------------------------------------------------------------------- /Scripts/piece.gd: -------------------------------------------------------------------------------- 1 | extends Area2D 2 | 3 | class_name Piece 4 | 5 | @onready var sprite_2d = $Sprite2D 6 | @onready var collision_shape_2d = $CollisionShape2D 7 | 8 | func set_texture(texture: Texture2D): 9 | sprite_2d.texture = texture 10 | 11 | func get_size(): 12 | return collision_shape_2d.shape.get_rect().size 13 | -------------------------------------------------------------------------------- /Scripts/piece_data.gd: -------------------------------------------------------------------------------- 1 | extends Resource 2 | 3 | @export var piece_texture: Texture 4 | @export var tetromino_type: Shared.Tetromino 5 | @export var spawn_position: Vector2 6 | -------------------------------------------------------------------------------- /Scripts/piece_spawner.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | var current_tetromino 4 | var next_tetromino 5 | 6 | @onready var board = $"../Board" as Board 7 | @onready var ui = $"../UI" as UI 8 | var is_game_over = false 9 | 10 | func _ready(): 11 | current_tetromino = Shared.Tetromino.values().pick_random() 12 | next_tetromino = Shared.Tetromino.values().pick_random() 13 | board.spawn_tetromino(current_tetromino, false, null) 14 | board.spawn_tetromino(next_tetromino, true, Vector2(100, 50)) 15 | board.tetromino_locked.connect(on_tetromino_locked) 16 | board.game_over.connect(on_game_over) 17 | 18 | func on_tetromino_locked(): 19 | if is_game_over: 20 | return 21 | current_tetromino = next_tetromino 22 | next_tetromino = Shared.Tetromino.values().pick_random() 23 | board.spawn_tetromino(current_tetromino, false, null) 24 | board.spawn_tetromino(next_tetromino, true, Vector2(100, 50)) 25 | 26 | func on_game_over(): 27 | is_game_over = true 28 | ui.show_game_over() 29 | -------------------------------------------------------------------------------- /Scripts/shared.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | enum Tetromino { 4 | I,O, T, J, L, S, Z 5 | } 6 | 7 | var cells = { 8 | Tetromino.I: [Vector2(-1, 0), Vector2(0, 0), Vector2(1, 0), Vector2(2, 0)], 9 | #------------------------------------------------------------------- 10 | Tetromino.J: [Vector2(-1, 1), Vector2(-1, 0), Vector2(0,0), Vector2(1, 0 )], 11 | #------------------------------------------------------------------- 12 | Tetromino.L: [Vector2(1,1), Vector2(-1, 0), Vector2(0,0), Vector2(1,0)], 13 | #------------------------------------------------------------------- 14 | Tetromino.O: [Vector2(0,1), Vector2(1,1), Vector2(0,0), Vector2(1,0)], 15 | #------------------------------------------------------------------- 16 | Tetromino.S: [Vector2(0,1), Vector2(1,1), Vector2(-1, 0), Vector2(0,0)], 17 | #------------------------------------------------------------------- 18 | Tetromino.T: [Vector2(0,1), Vector2(-1, 0), Vector2(0,0), Vector2(1,0)], 19 | #------------------------------------------------------------------- 20 | Tetromino.Z: [Vector2(-1, 1), Vector2(0, 1), Vector2(0,0), Vector2(1, 0)] 21 | } 22 | 23 | var wall_kicks_i = [ 24 | [Vector2(0,0), Vector2(-2,0), Vector2(1,0), Vector2(-2,-1), Vector2(1,2)], 25 | [Vector2(0,0), Vector2(2,0), Vector2(-1, 0), Vector2(2,1), Vector2(-1, -2)], 26 | [Vector2(0,0), Vector2(-1, 0), Vector2(2,0), Vector2(-1,2), Vector2(2, -1)], 27 | [Vector2(0,0), Vector2(1,0), Vector2(-2, 0), Vector2(1, -2), Vector2(-2, 1)], 28 | [Vector2(0,0), Vector2(2,0), Vector2(-1, 0), Vector2(2,1), Vector2(-1, -2)], 29 | [Vector2(0,0), Vector2(-2,0), Vector2(1, 0), Vector2(-2, -1), Vector2(1, 2)], 30 | [Vector2(0,0), Vector2(1,0), Vector2(-2,0), Vector2(1, -2), Vector2(-2,1)], 31 | [Vector2(0,0), Vector2(-1, 0), Vector2(2, 0), Vector2(-1,2), Vector2(2, -1)] 32 | ] 33 | 34 | var wall_kicks_jlostz = [ 35 | [Vector2(0,0), Vector2(-1,0), Vector2(-1,1), Vector2(0,-2), Vector2(-1, -2)], 36 | [Vector2(0,0), Vector2(1,0), Vector2(1, -1), Vector2(0,2), Vector2(1, 2)], 37 | [Vector2(0,0), Vector2(1, 0), Vector2(1,-1), Vector2(0,2), Vector2(1, 2)], 38 | [Vector2(0,0), Vector2(-1,0), Vector2(-1, 1), Vector2(0, -2), Vector2(-1, -2)], 39 | [Vector2(0,0), Vector2(1,0), Vector2(1, 1), Vector2(0,-2), Vector2(1, -2)], 40 | [Vector2(0,0), Vector2(-1,0), Vector2(-1, -1), Vector2(0, 2), Vector2(-1, 2)], 41 | [Vector2(0,0), Vector2(-1,0), Vector2(-1,-1), Vector2(0, 2), Vector2(-1, 2)], 42 | [Vector2(0,0), Vector2(1, 0), Vector2(1, 1), Vector2(0,-2), Vector2(1, -2)] 43 | ] 44 | 45 | var data = { 46 | Tetromino.I: preload("res://Resources/i_piece_data.tres"), 47 | Tetromino.J: preload("res://Resources/j_piece_data.tres"), 48 | Tetromino.L: preload("res://Resources/l_piece_data.tres"), 49 | Tetromino.O: preload("res://Resources/o_piece_data.tres"), 50 | Tetromino.S: preload("res://Resources/s_piece_data.tres"), 51 | Tetromino.T: preload("res://Resources/t_piece_data.tres"), 52 | Tetromino.Z: preload("res://Resources/z_piece_data.tres") 53 | } 54 | 55 | var clockwise_rotation_matrix = [Vector2(0, -1), Vector2(1, 0)] 56 | var counter_clockwise_rotation_matrix = [Vector2(0,1), Vector2(-1, 0)] 57 | 58 | -------------------------------------------------------------------------------- /Scripts/tetromino.gd: -------------------------------------------------------------------------------- 1 | extends Node2D 2 | 3 | class_name Tetromino 4 | 5 | signal lock_tetromino(tetromino: Tetromino) 6 | 7 | var bounds = { 8 | "min_x": -216, 9 | "max_x": 216, 10 | "max_y": 457 11 | } 12 | 13 | var rotation_index = 0 14 | var wall_kicks 15 | var tetromino_data 16 | var is_next_piece 17 | var pieces = [] 18 | var other_tetrominoes_pieces = [] 19 | var ghost_tetromino 20 | 21 | @onready var timer = $Timer 22 | @onready var piece_scene = preload("res://Scenes/piece.tscn") 23 | @onready var ghost_tetromino_scene = preload("res://Scenes/ghost_tetromino.tscn") 24 | 25 | var tetromino_cells 26 | func _ready(): 27 | tetromino_cells = Shared.cells[tetromino_data.tetromino_type] 28 | 29 | for cell in tetromino_cells: 30 | var piece = piece_scene.instantiate() as Piece 31 | pieces.append(piece) 32 | add_child(piece) 33 | piece.set_texture(tetromino_data.piece_texture) 34 | piece.position = cell * piece.get_size() 35 | 36 | if is_next_piece == false: 37 | position = tetromino_data.spawn_position 38 | wall_kicks = Shared.wall_kicks_i if tetromino_data.tetromino_type == Shared.Tetromino.I else Shared.wall_kicks_jlostz 39 | ghost_tetromino = ghost_tetromino_scene.instantiate() as GhostTetromino 40 | ghost_tetromino.tetromino_data = tetromino_data 41 | get_tree().root.add_child.call_deferred(ghost_tetromino) 42 | hard_drop_ghost.call_deferred() 43 | else: 44 | timer.stop() 45 | set_process_input(false) 46 | 47 | 48 | func hard_drop_ghost(): 49 | var final_hard_drop_position 50 | var ghost_position_update = calculate_global_position(Vector2.DOWN, global_position) 51 | 52 | while ghost_position_update != null: 53 | ghost_position_update = calculate_global_position(Vector2.DOWN, ghost_position_update) 54 | if ghost_position_update != null: 55 | final_hard_drop_position = ghost_position_update 56 | 57 | if final_hard_drop_position != null: 58 | var children = get_children().filter(func (c): return c is Piece) 59 | 60 | var pieces_position = [] 61 | 62 | for i in children.size(): 63 | var piece_position = children[i].position 64 | pieces_position.append(piece_position) 65 | 66 | ghost_tetromino.set_ghost_tetromino(final_hard_drop_position, pieces_position) 67 | 68 | return final_hard_drop_position 69 | 70 | 71 | func _input(_event): 72 | if Input.is_action_just_pressed("left"): 73 | move(Vector2.LEFT) 74 | elif Input.is_action_just_pressed("right"): 75 | move(Vector2.RIGHT) 76 | elif Input.is_action_just_pressed("down"): 77 | move(Vector2.DOWN) 78 | elif Input.is_action_just_pressed("hard_drop"): 79 | hard_drop() 80 | elif Input.is_action_just_pressed("rotate_left"): 81 | rotate_tetromino(-1) 82 | elif Input.is_action_just_pressed("rotate_right"): 83 | rotate_tetromino(1) 84 | 85 | func move(direction: Vector2) -> bool: 86 | 87 | var new_position = calculate_global_position(direction, global_position) 88 | if new_position: 89 | global_position = new_position 90 | if direction != Vector2.DOWN: 91 | hard_drop_ghost.call_deferred() 92 | return true 93 | return false 94 | 95 | func calculate_global_position(direction: Vector2, starting_global_position: Vector2): 96 | #TODO: check for collision with other tetrominos 97 | print_debug(is_colliding_with_other_tetrominos(direction, starting_global_position)) 98 | if is_colliding_with_other_tetrominos(direction, starting_global_position): 99 | return null 100 | #TODO: check for collision with game bounds 101 | if !is_within_game_bounds(direction, starting_global_position): 102 | return null 103 | return starting_global_position + direction * pieces[0].get_size().x 104 | 105 | func is_within_game_bounds(direction: Vector2, starting_global_position: Vector2): 106 | for piece in pieces: 107 | var new_position = piece.position + starting_global_position + direction * piece.get_size() 108 | if new_position.x < bounds.get("min_x") || new_position.x > bounds.get("max_x") || new_position.y >= bounds.get("max_y"): 109 | return false 110 | return true 111 | 112 | func is_colliding_with_other_tetrominos(direction: Vector2, starting_global_position: Vector2): 113 | for tetromino_piece in other_tetrominoes_pieces: 114 | for piece in pieces: 115 | if starting_global_position + piece.position + direction * piece.get_size() == tetromino_piece.global_position: 116 | return true 117 | return false 118 | 119 | func rotate_tetromino(direction: int): 120 | var original_rotation_index = rotation_index 121 | if tetromino_data.tetromino_type == Shared.Tetromino.O: 122 | return 123 | 124 | apply_rotation(direction) 125 | 126 | rotation_index = wrap(rotation_index + direction, 0, 4) 127 | 128 | if !test_wall_kicks(rotation_index, direction): 129 | rotation_index = original_rotation_index 130 | apply_rotation(-direction) 131 | 132 | hard_drop_ghost.call_deferred() 133 | 134 | 135 | func test_wall_kicks(rotation_index: int, rotation_direction: int): 136 | var wall_kick_index = get_wall_kick_index(rotation_index, rotation_direction) 137 | 138 | for i in wall_kicks[0].size(): 139 | var translation = wall_kicks[wall_kick_index][i] 140 | if move(translation): 141 | return true 142 | return false 143 | 144 | func get_wall_kick_index(rotation_index: int, rotation_direction): 145 | var wall_kick_index = rotation_index * 2 146 | if rotation_direction < 0: 147 | wall_kick_index -= 1 148 | 149 | return wrap(wall_kick_index, 0 , wall_kicks.size()) 150 | 151 | func apply_rotation(direction: int): 152 | var rotation_matrix = Shared.clockwise_rotation_matrix if direction == 1 else Shared.counter_clockwise_rotation_matrix 153 | 154 | var tetromino_cells = Shared.cells[tetromino_data.tetromino_type] 155 | 156 | for i in tetromino_cells.size(): 157 | var cell = tetromino_cells[i] 158 | 159 | var coordinates = rotation_matrix[0] * cell.x + rotation_matrix[1]* cell.y 160 | tetromino_cells[i] = coordinates 161 | 162 | for i in pieces.size(): 163 | var piece = pieces[i] 164 | piece.position = tetromino_cells[i] * piece.get_size() 165 | 166 | 167 | 168 | func hard_drop(): 169 | while(move(Vector2.DOWN)): 170 | continue 171 | lock() 172 | 173 | func lock(): 174 | timer.stop() 175 | lock_tetromino.emit(self) 176 | set_process_input(false) 177 | ghost_tetromino.queue_free() 178 | 179 | 180 | func _on_timer_timeout(): 181 | var should_lock = !move(Vector2.DOWN) 182 | if should_lock: 183 | lock() 184 | -------------------------------------------------------------------------------- /Scripts/ui.gd: -------------------------------------------------------------------------------- 1 | extends CanvasLayer 2 | 3 | class_name UI 4 | 5 | @onready var center_container = $CenterContainer 6 | 7 | func show_game_over(): 8 | center_container.show() 9 | 10 | 11 | func _on_button_pressed(): 12 | get_tree().reload_current_scene() 13 | -------------------------------------------------------------------------------- /project.godot: -------------------------------------------------------------------------------- 1 | ; Engine configuration file. 2 | ; It's best edited using the editor UI and not directly, 3 | ; since the parameters that go here are not all obvious. 4 | ; 5 | ; Format: 6 | ; [section] ; section goes between [] 7 | ; param=value ; assign values to parameters 8 | 9 | config_version=5 10 | 11 | [application] 12 | 13 | config/name="TetrisTutorial" 14 | run/main_scene="res://Scenes/main.tscn" 15 | config/features=PackedStringArray("4.1", "Forward Plus") 16 | config/icon="res://Assets/icon.svg" 17 | 18 | [autoload] 19 | 20 | Shared="*res://Scripts/shared.gd" 21 | 22 | [display] 23 | 24 | window/size/viewport_width=324 25 | window/stretch/mode="canvas_items" 26 | 27 | [input] 28 | 29 | left={ 30 | "deadzone": 0.5, 31 | "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"echo":false,"script":null) 32 | ] 33 | } 34 | right={ 35 | "deadzone": 0.5, 36 | "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"echo":false,"script":null) 37 | ] 38 | } 39 | down={ 40 | "deadzone": 0.5, 41 | "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"echo":false,"script":null) 42 | ] 43 | } 44 | hard_drop={ 45 | "deadzone": 0.5, 46 | "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"key_label":0,"unicode":32,"echo":false,"script":null) 47 | ] 48 | } 49 | rotate_left={ 50 | "deadzone": 0.5, 51 | "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":81,"key_label":0,"unicode":113,"echo":false,"script":null) 52 | ] 53 | } 54 | rotate_right={ 55 | "deadzone": 0.5, 56 | "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":69,"key_label":0,"unicode":101,"echo":false,"script":null) 57 | ] 58 | } 59 | 60 | [rendering] 61 | 62 | environment/defaults/default_clear_color=Color(0.0941176, 0.266667, 0.419608, 1) 63 | --------------------------------------------------------------------------------