Browse Source

Merge pull request #851 from jtnicholl/2d_platformer

Update, clean up, and reorganize the 2D platformer
Rémi Verschelde 2 years ago
parent
commit
20d2e6ed2f
100 changed files with 1942 additions and 878 deletions
  1. 14 19
      2d/platformer/README.md
  2. BIN
      2d/platformer/assets/art/background/cloud_1.png
  3. BIN
      2d/platformer/assets/art/background/cloud_2.png
  4. BIN
      2d/platformer/assets/art/background/cloud_3.png
  5. BIN
      2d/platformer/assets/art/background/distant_platforms_1.png
  6. BIN
      2d/platformer/assets/art/background/distant_platforms_2.png
  7. BIN
      2d/platformer/assets/art/background/sky.png
  8. BIN
      2d/platformer/assets/art/coin/coin.png
  9. BIN
      2d/platformer/assets/art/enemy/enemy.png
  10. BIN
      2d/platformer/assets/art/platforms/moving_platform.png
  11. BIN
      2d/platformer/assets/art/platforms/one_way_platform.png
  12. BIN
      2d/platformer/assets/art/player/bullet/bullet.png
  13. BIN
      2d/platformer/assets/art/player/robot_demo.png
  14. BIN
      2d/platformer/assets/art/tileset/tiles_demo.png
  15. 0 335
      2d/platformer/assets/art/tileset/tileset.tres
  16. BIN
      2d/platformer/assets/art/ui/touch_button_fire.png
  17. BIN
      2d/platformer/assets/art/ui/touch_button_jump.png
  18. BIN
      2d/platformer/assets/art/ui/touch_button_left.png
  19. BIN
      2d/platformer/assets/art/ui/touch_button_right.png
  20. 0 19
      2d/platformer/assets/audio/music/music.ogg.import
  21. 0 5
      2d/platformer/assets/theme/fonts/kenney_mini_square.tres
  22. 59 0
      2d/platformer/enemy/enemy.gd
  23. 147 99
      2d/platformer/enemy/enemy.tscn
  24. BIN
      2d/platformer/enemy/enemy.webp
  25. 5 5
      2d/platformer/enemy/enemy.webp.import
  26. 0 0
      2d/platformer/enemy/explode.wav
  27. 3 3
      2d/platformer/enemy/explode.wav.import
  28. 0 0
      2d/platformer/enemy/hit.wav
  29. 3 3
      2d/platformer/enemy/hit.wav.import
  30. 24 0
      2d/platformer/game.gd
  31. 25 0
      2d/platformer/game_singleplayer.tscn
  32. 10 0
      2d/platformer/game_splitscreen.gd
  33. 82 0
      2d/platformer/game_splitscreen.tscn
  34. 16 0
      2d/platformer/gui/coins_counter.gd
  35. 70 0
      2d/platformer/gui/coins_counter.tscn
  36. 0 0
      2d/platformer/gui/kenney_mini_square.ttf
  37. 4 3
      2d/platformer/gui/kenney_mini_square.ttf.import
  38. 77 0
      2d/platformer/gui/pause_menu.gd
  39. 16 32
      2d/platformer/gui/pause_menu.tscn
  40. 11 0
      2d/platformer/gui/pause_menu_singleplayer.tscn
  41. 11 0
      2d/platformer/gui/pause_menu_splitscreen.tscn
  42. 2 2
      2d/platformer/gui/theme.tres
  43. BIN
      2d/platformer/gui/touch_button_fire.webp
  44. 4 4
      2d/platformer/gui/touch_button_fire.webp.import
  45. BIN
      2d/platformer/gui/touch_button_jump.webp
  46. 4 4
      2d/platformer/gui/touch_button_jump.webp.import
  47. BIN
      2d/platformer/gui/touch_button_left.webp
  48. 4 4
      2d/platformer/gui/touch_button_left.webp.import
  49. BIN
      2d/platformer/gui/touch_button_right.webp
  50. 4 4
      2d/platformer/gui/touch_button_right.webp.import
  51. BIN
      2d/platformer/icon.png
  52. BIN
      2d/platformer/icon.webp
  53. 4 4
      2d/platformer/icon.webp.import
  54. BIN
      2d/platformer/level/cloud_1.webp
  55. 4 4
      2d/platformer/level/cloud_1.webp.import
  56. BIN
      2d/platformer/level/cloud_2.webp
  57. 4 4
      2d/platformer/level/cloud_2.webp.import
  58. BIN
      2d/platformer/level/cloud_3.webp
  59. 4 4
      2d/platformer/level/cloud_3.webp.import
  60. 10 0
      2d/platformer/level/coin.gd
  61. 112 53
      2d/platformer/level/coin.tscn
  62. BIN
      2d/platformer/level/coin.webp
  63. 4 4
      2d/platformer/level/coin.webp.import
  64. BIN
      2d/platformer/level/distant_platforms_1.webp
  65. 4 4
      2d/platformer/level/distant_platforms_1.webp.import
  66. BIN
      2d/platformer/level/distant_platforms_2.webp
  67. 4 4
      2d/platformer/level/distant_platforms_2.webp.import
  68. 61 0
      2d/platformer/level/level.tscn
  69. BIN
      2d/platformer/level/moving_platform.webp
  70. 4 4
      2d/platformer/level/moving_platform.webp.import
  71. 4 4
      2d/platformer/level/one_way_platform.import
  72. BIN
      2d/platformer/level/one_way_platform.webp
  73. 34 0
      2d/platformer/level/one_way_platform.webp.import
  74. 38 34
      2d/platformer/level/parallax_background.tscn
  75. 19 0
      2d/platformer/level/platform.tscn
  76. BIN
      2d/platformer/level/sky.webp
  77. 4 4
      2d/platformer/level/sky.webp.import
  78. BIN
      2d/platformer/level/tiles.webp
  79. 4 4
      2d/platformer/level/tiles.webp.import
  80. 729 0
      2d/platformer/level/tileset.tres
  81. 0 0
      2d/platformer/music.ogg
  82. 19 0
      2d/platformer/music.ogg.import
  83. 8 0
      2d/platformer/music.tscn
  84. 13 0
      2d/platformer/player/bullet.gd
  85. 32 27
      2d/platformer/player/bullet.tscn
  86. BIN
      2d/platformer/player/bullet.webp
  87. 4 4
      2d/platformer/player/bullet.webp.import
  88. 0 0
      2d/platformer/player/coin_pickup.wav
  89. 3 3
      2d/platformer/player/coin_pickup.wav.import
  90. 25 0
      2d/platformer/player/gun.gd
  91. 0 0
      2d/platformer/player/jump.wav
  92. 3 3
      2d/platformer/player/jump.wav.import
  93. 88 0
      2d/platformer/player/player.gd
  94. 72 83
      2d/platformer/player/player.tscn
  95. BIN
      2d/platformer/player/player.webp
  96. 4 4
      2d/platformer/player/player.webp.import
  97. 0 0
      2d/platformer/player/shoot.wav
  98. 3 3
      2d/platformer/player/shoot.wav.import
  99. 26 79
      2d/platformer/project.godot
  100. BIN
      2d/platformer/screenshots/layout.png

+ 14 - 19
2d/platformer/README.md

@@ -1,46 +1,41 @@
 # 2D Platformer
 
-This demo is a pixel art 2D platformer with graphics and sound.
+This demo is a pixel art 2D platformer with single-player
+and two player splitscreen multiplayer.
 
-It shows you how to code characters and physics-based objects
+It demonstrates how to code characters and physics-based objects
 in a real game context. This is a relatively complete demo
 where the player can jump, walk on slopes, fire bullets,
-interact with enemies, and more. It contains one closed
-level, and the player is invincible, unlike the enemies.
-
-You will find most of the demo’s content in the `Level.tscn` scene.
-You can open it from the default `Game.tscn` scene, or double
-click on `Level.tscn` in the `src/Level/` directory.
-
-We invite you to open the demo's GDScript files in the editor as
-they contain a lot of comments that explain how each class works.
+interact with enemies, and collect items. It contains one
+level. The player is invincible, unlike the enemies.
 
 Language: GDScript
 
-Renderer: GLES 2
+Renderer: Forward Plus
 
 Check out this demo on the asset library: https://godotengine.org/asset-library/asset/120
 
 ## Features
 
-- Side-scrolling player controller using [`KinematicBody2D`](https://docs.godotengine.org/en/latest/classes/class_kinematicbody2d.html).
-    - Can walk on and snap to slopes.
-    - Can shoot, including while jumping.
+- Side-scrolling player controller using [`CharacterBody2D`](https://docs.godotengine.org/en/latest/classes/class_characterbody2d.html).
+	- Can walk smoothly up and down slopes.
+	- Can shoot, including while jumping.
+	- Has a double jump that provides a horizontal momentum boost.
 - Enemies that crawl on the floor and change direction when they encounter an obstacle.
 - Camera that stays within the level’s bounds.
-- Supports keyboard and gamepad controls.
+- Keyboard and gamepad control support.
 - Platforms that can move in any direction.
 - Gun that shoots bullets with rigid body (natural) physics.
 - Collectible coins.
-- Pause and pause menu.
+- Pausing and a pause menu.
 - Pixel art visuals.
 - Sound effects and music.
 
 ## Screenshots
 
-![Player shooting in the direction of an enemy](screenshots/shoot.png)
+![Player shooting in the direction of an enemy](screenshots/shoot.webp)
 
-![The entire level layout viewed in the editor](screenshots/layout.png)
+![The entire level layout viewed in the editor](screenshots/layout.webp)
 
 ## Music
 

BIN
2d/platformer/assets/art/background/cloud_1.png


BIN
2d/platformer/assets/art/background/cloud_2.png


BIN
2d/platformer/assets/art/background/cloud_3.png


BIN
2d/platformer/assets/art/background/distant_platforms_1.png


BIN
2d/platformer/assets/art/background/distant_platforms_2.png


BIN
2d/platformer/assets/art/background/sky.png


BIN
2d/platformer/assets/art/coin/coin.png


BIN
2d/platformer/assets/art/enemy/enemy.png


BIN
2d/platformer/assets/art/platforms/moving_platform.png


BIN
2d/platformer/assets/art/platforms/one_way_platform.png


BIN
2d/platformer/assets/art/player/bullet/bullet.png


BIN
2d/platformer/assets/art/player/robot_demo.png


BIN
2d/platformer/assets/art/tileset/tiles_demo.png


+ 0 - 335
2d/platformer/assets/art/tileset/tileset.tres

@@ -1,335 +0,0 @@
-[gd_resource type="TileSet" load_steps=14 format=2]
-
-[ext_resource path="res://assets/art/tileset/tiles_demo.png" type="Texture2D" id=1]
-
-[sub_resource type="ConvexPolygonShape2D" id=1]
-points = PackedVector2Array( 0, 6, 32, 6, 32, 32, 0, 32 )
-
-[sub_resource type="ConvexPolygonShape2D" id=2]
-points = PackedVector2Array( 0, 6, 28, 6, 28, 32, 0, 32 )
-
-[sub_resource type="ConvexPolygonShape2D" id=3]
-points = PackedVector2Array( 0, 0, 32, 0, 32, 32, 0, 32 )
-
-[sub_resource type="ConvexPolygonShape2D" id=4]
-points = PackedVector2Array( 0, 6, 32, 6, 32, 32, 0, 32 )
-
-[sub_resource type="ConvexPolygonShape2D" id=5]
-points = PackedVector2Array( 32, 38, 32, 64, 0, 64, 0, 6 )
-
-[sub_resource type="ConvexPolygonShape2D" id=6]
-points = PackedVector2Array( 0, 0, 28, 0, 28, 32, 0, 32 )
-
-[sub_resource type="ConvexPolygonShape2D" id=7]
-points = PackedVector2Array( 28, 6, 32, 6, 32, 32, 0, 32, 0, 0, 28, 0 )
-
-[sub_resource type="ConvexPolygonShape2D" id=8]
-points = PackedVector2Array( 0, 6, 32, 6, 32, 32, 0, 32 )
-
-[sub_resource type="ConvexPolygonShape2D" id=9]
-points = PackedVector2Array( 0, 6, 28, 6, 28, 32, 0, 32 )
-
-[sub_resource type="ConvexPolygonShape2D" id=10]
-points = PackedVector2Array( 0, 0, 32, 0, 32, 32, 0, 32 )
-
-[sub_resource type="ConvexPolygonShape2D" id=11]
-points = PackedVector2Array( 0, 0, 32, 0, 32, 24, 0, 24 )
-
-[sub_resource type="ConvexPolygonShape2D" id=12]
-points = PackedVector2Array( 0, 0, 28, 0, 28, 24, 0, 24 )
-
-[resource]
-0/name = "ground"
-0/texture = ExtResource( 1 )
-0/tex_offset = Vector2( 0, 0 )
-0/modulate = Color( 1, 1, 1, 1 )
-0/region = Rect2( 0, 0, 32, 32 )
-0/tile_mode = 0
-0/occluder_offset = Vector2( 0, 0 )
-0/navigation_offset = Vector2( 0, 0 )
-0/shape_offset = Vector2( 0, 0 )
-0/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
-0/shape = SubResource( 1 )
-0/shape_one_way = false
-0/shape_one_way_margin = 1.0
-0/shapes = [ {
-"autotile_coord": Vector2( 0, 0 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 1 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-} ]
-0/z_index = 0
-1/name = "ground_end"
-1/texture = ExtResource( 1 )
-1/tex_offset = Vector2( 0, 0 )
-1/modulate = Color( 1, 1, 1, 1 )
-1/region = Rect2( 32, 0, 32, 32 )
-1/tile_mode = 0
-1/occluder_offset = Vector2( 0, 0 )
-1/navigation_offset = Vector2( 0, 0 )
-1/shape_offset = Vector2( 0, 0 )
-1/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
-1/shape = SubResource( 2 )
-1/shape_one_way = false
-1/shape_one_way_margin = 1.0
-1/shapes = [ {
-"autotile_coord": Vector2( 0, 0 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 2 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-} ]
-1/z_index = 0
-2/name = "slope"
-2/texture = ExtResource( 1 )
-2/tex_offset = Vector2( 0, 0 )
-2/modulate = Color( 1, 1, 1, 1 )
-2/region = Rect2( 64, 64, 32, 64 )
-2/tile_mode = 0
-2/occluder_offset = Vector2( 0, 0 )
-2/navigation_offset = Vector2( 0, 0 )
-2/shape_offset = Vector2( 0, 0 )
-2/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
-2/shape = SubResource( 5 )
-2/shape_one_way = false
-2/shape_one_way_margin = 1.0
-2/shapes = [ {
-"autotile_coord": Vector2( 0, 0 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 5 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-} ]
-2/z_index = 0
-3/name = "wall"
-3/texture = ExtResource( 1 )
-3/tex_offset = Vector2( 0, 0 )
-3/modulate = Color( 1, 1, 1, 1 )
-3/region = Rect2( 32, 32, 32, 32 )
-3/tile_mode = 0
-3/occluder_offset = Vector2( 0, 0 )
-3/navigation_offset = Vector2( 0, 0 )
-3/shape_offset = Vector2( 0, 0 )
-3/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
-3/shape = SubResource( 6 )
-3/shape_one_way = false
-3/shape_one_way_margin = 1.0
-3/shapes = [ {
-"autotile_coord": Vector2( 0, 0 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 6 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-} ]
-3/z_index = 0
-4/name = "slope_top"
-4/texture = ExtResource( 1 )
-4/tex_offset = Vector2( 0, 0 )
-4/modulate = Color( 1, 1, 1, 1 )
-4/region = Rect2( 32, 64, 32, 32 )
-4/tile_mode = 0
-4/occluder_offset = Vector2( 0, 0 )
-4/navigation_offset = Vector2( 0, 0 )
-4/shape_offset = Vector2( 0, 0 )
-4/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
-4/shape = SubResource( 7 )
-4/shape_one_way = false
-4/shape_one_way_margin = 1.0
-4/shapes = [ {
-"autotile_coord": Vector2( 0, 0 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 7 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-} ]
-4/z_index = 0
-5/name = "one_way"
-5/texture = ExtResource( 1 )
-5/tex_offset = Vector2( 0, 0 )
-5/modulate = Color( 1, 1, 1, 1 )
-5/region = Rect2( 64, 0, 32, 32 )
-5/tile_mode = 0
-5/occluder_offset = Vector2( 0, 0 )
-5/navigation_offset = Vector2( 0, 0 )
-5/shape_offset = Vector2( 0, 0 )
-5/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
-5/shape = SubResource( 8 )
-5/shape_one_way = true
-5/shape_one_way_margin = 1.0
-5/shapes = [ {
-"autotile_coord": Vector2( 0, 0 ),
-"one_way": true,
-"one_way_margin": 1.0,
-"shape": SubResource( 8 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-} ]
-5/z_index = 0
-6/name = "one_way_end"
-6/texture = ExtResource( 1 )
-6/tex_offset = Vector2( 0, 0 )
-6/modulate = Color( 1, 1, 1, 1 )
-6/region = Rect2( 96, 0, 32, 32 )
-6/tile_mode = 0
-6/occluder_offset = Vector2( 0, 0 )
-6/navigation_offset = Vector2( 0, 0 )
-6/shape_offset = Vector2( 0, 0 )
-6/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
-6/shape = SubResource( 9 )
-6/shape_one_way = true
-6/shape_one_way_margin = 1.0
-6/shapes = [ {
-"autotile_coord": Vector2( 0, 0 ),
-"one_way": true,
-"one_way_margin": 1.0,
-"shape": SubResource( 9 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-} ]
-6/z_index = 0
-7/name = "rock"
-7/texture = ExtResource( 1 )
-7/tex_offset = Vector2( 0, 0 )
-7/modulate = Color( 1, 1, 1, 1 )
-7/region = Rect2( 0, 32, 32, 32 )
-7/tile_mode = 0
-7/occluder_offset = Vector2( 0, 0 )
-7/navigation_offset = Vector2( 0, 0 )
-7/shape_offset = Vector2( 0, 0 )
-7/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
-7/shape = SubResource( 10 )
-7/shape_one_way = false
-7/shape_one_way_margin = 1.0
-7/shapes = [ {
-"autotile_coord": Vector2( 0, 0 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 10 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-} ]
-7/z_index = 0
-8/name = "bottom"
-8/texture = ExtResource( 1 )
-8/tex_offset = Vector2( 0, 0 )
-8/modulate = Color( 1, 1, 1, 1 )
-8/region = Rect2( 192, 32, 32, 32 )
-8/tile_mode = 0
-8/occluder_offset = Vector2( 0, 0 )
-8/navigation_offset = Vector2( 0, 0 )
-8/shape_offset = Vector2( 0, 0 )
-8/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
-8/shape = SubResource( 11 )
-8/shape_one_way = false
-8/shape_one_way_margin = 1.0
-8/shapes = [ {
-"autotile_coord": Vector2( 0, 0 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 11 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-} ]
-8/z_index = 0
-9/name = "bottom_end"
-9/texture = ExtResource( 1 )
-9/tex_offset = Vector2( 0, 0 )
-9/modulate = Color( 1, 1, 1, 1 )
-9/region = Rect2( 224, 32, 32, 32 )
-9/tile_mode = 0
-9/occluder_offset = Vector2( 0, 0 )
-9/navigation_offset = Vector2( 0, 0 )
-9/shape_offset = Vector2( 0, 0 )
-9/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
-9/shape = SubResource( 12 )
-9/shape_one_way = false
-9/shape_one_way_margin = 1.0
-9/shapes = [ {
-"autotile_coord": Vector2( 0, 0 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 12 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-} ]
-9/z_index = 0
-10/name = "bottom_corner"
-10/texture = ExtResource( 1 )
-10/tex_offset = Vector2( 0, 0 )
-10/modulate = Color( 1, 1, 1, 1 )
-10/region = Rect2( 160, 32, 32, 32 )
-10/tile_mode = 0
-10/occluder_offset = Vector2( 0, 0 )
-10/navigation_offset = Vector2( 0, 0 )
-10/shape_offset = Vector2( 0, 0 )
-10/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
-10/shape = SubResource( 3 )
-10/shape_one_way = false
-10/shape_one_way_margin = 1.0
-10/shapes = [ {
-"autotile_coord": Vector2( 0, 0 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 3 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-} ]
-10/z_index = 0
-11/name = "tree_trunk_0"
-11/texture = ExtResource( 1 )
-11/tex_offset = Vector2( 0, 0 )
-11/modulate = Color( 1, 1, 1, 1 )
-11/region = Rect2( 128, 64, 32, 32 )
-11/tile_mode = 0
-11/occluder_offset = Vector2( 0, 0 )
-11/navigation_offset = Vector2( 0, 0 )
-11/shape_offset = Vector2( 0, 0 )
-11/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
-11/shape_one_way = false
-11/shape_one_way_margin = 0.0
-11/shapes = [  ]
-11/z_index = 0
-12/name = "tree_trunk_1"
-12/texture = ExtResource( 1 )
-12/tex_offset = Vector2( 0, 0 )
-12/modulate = Color( 1, 1, 1, 1 )
-12/region = Rect2( 128, 32, 32, 32 )
-12/tile_mode = 0
-12/occluder_offset = Vector2( 0, 0 )
-12/navigation_offset = Vector2( 0, 0 )
-12/shape_offset = Vector2( 0, 0 )
-12/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
-12/shape_one_way = false
-12/shape_one_way_margin = 0.0
-12/shapes = [  ]
-12/z_index = 0
-13/name = "tree_base"
-13/texture = ExtResource( 1 )
-13/tex_offset = Vector2( 0, 0 )
-13/modulate = Color( 1, 1, 1, 1 )
-13/region = Rect2( 128, 96, 32, 32 )
-13/tile_mode = 0
-13/occluder_offset = Vector2( 0, 0 )
-13/navigation_offset = Vector2( 0, 0 )
-13/shape_offset = Vector2( 0, 0 )
-13/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
-13/shape = SubResource( 4 )
-13/shape_one_way = false
-13/shape_one_way_margin = 1.0
-13/shapes = [ {
-"autotile_coord": Vector2( 0, 0 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 4 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-} ]
-13/z_index = 0
-14/name = "tree_top"
-14/texture = ExtResource( 1 )
-14/tex_offset = Vector2( 0, 0 )
-14/modulate = Color( 1, 1, 1, 1 )
-14/region = Rect2( 128, 0, 32, 32 )
-14/tile_mode = 0
-14/occluder_offset = Vector2( 0, 0 )
-14/navigation_offset = Vector2( 0, 0 )
-14/shape_offset = Vector2( 0, 0 )
-14/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
-14/shape_one_way = false
-14/shape_one_way_margin = 0.0
-14/shapes = [  ]
-14/z_index = 0

BIN
2d/platformer/assets/art/ui/touch_button_fire.png


BIN
2d/platformer/assets/art/ui/touch_button_jump.png


BIN
2d/platformer/assets/art/ui/touch_button_left.png


BIN
2d/platformer/assets/art/ui/touch_button_right.png


+ 0 - 19
2d/platformer/assets/audio/music/music.ogg.import

@@ -1,19 +0,0 @@
-[remap]
-
-importer="oggvorbisstr"
-type="AudioStreamOggVorbis"
-uid="uid://cx6hrmvjvhkt5"
-path="res://.godot/imported/music.ogg-e27216112531ea490cdad574860a53a5.oggvorbisstr"
-
-[deps]
-
-source_file="res://assets/audio/music/music.ogg"
-dest_files=["res://.godot/imported/music.ogg-e27216112531ea490cdad574860a53a5.oggvorbisstr"]
-
-[params]
-
-loop=true
-loop_offset=0
-bpm=0
-beat_count=0
-bar_beats=4

+ 0 - 5
2d/platformer/assets/theme/fonts/kenney_mini_square.tres

@@ -1,5 +0,0 @@
-[gd_resource type="FontData" format=2]
-
-[resource]
-antialiased = false
-font_path = "res://assets/theme/fonts/kenney_mini_square.ttf"

+ 59 - 0
2d/platformer/enemy/enemy.gd

@@ -0,0 +1,59 @@
+class_name Enemy extends CharacterBody2D
+
+
+enum State {
+	WALKING,
+	DEAD,
+}
+
+const WALK_SPEED = 100.0
+
+var _state := State.WALKING
+
+@onready var gravity: int = ProjectSettings.get("physics/2d/default_gravity")
+@onready var platform_detector := $PlatformDetector as RayCast2D
+@onready var floor_detector_left := $FloorDetectorLeft as RayCast2D
+@onready var floor_detector_right := $FloorDetectorRight as RayCast2D
+@onready var sprite := $Sprite2D as Sprite2D
+@onready var animation_player := $AnimationPlayer as AnimationPlayer
+
+
+func _physics_process(delta: float) -> void:
+	if _state == State.WALKING and velocity.is_zero_approx():
+		velocity.x = WALK_SPEED
+	velocity.y += gravity * delta
+	if not floor_detector_left.is_colliding():
+		velocity.x = WALK_SPEED
+	elif not floor_detector_right.is_colliding():
+		velocity.x = -WALK_SPEED
+
+	if is_on_wall():
+		velocity.x = -velocity.x
+
+	move_and_slide()
+
+	if velocity.x > 0.0:
+		sprite.scale.x = 1.0
+	elif velocity.x < 0.0:
+		sprite.scale.x = -1.0
+
+	var animation := get_new_animation()
+	if animation != animation_player.current_animation:
+		animation_player.play(animation)
+
+
+func destroy() -> void:
+	_state = State.DEAD
+	velocity = Vector2.ZERO
+
+
+func get_new_animation() -> StringName:
+	var animation_new: StringName
+	if _state == State.WALKING:
+		if velocity.x == 0:
+			animation_new = &"idle"
+		else:
+			animation_new = &"walk"
+	else:
+		animation_new = &"destroy"
+	return animation_new

+ 147 - 99
2d/platformer/src/Actors/Enemy.tscn → 2d/platformer/enemy/enemy.tscn

@@ -1,22 +1,85 @@
-[gd_scene load_steps=13 format=2]
+[gd_scene load_steps=15 format=3 uid="uid://bd478yrtijbfn"]
 
-[ext_resource path="res://assets/art/player/bullet/bullet.png" type="Texture2D" id=1]
-[ext_resource path="res://assets/audio/sfx/explode.wav" type="AudioStream" id=2]
-[ext_resource path="res://assets/audio/sfx/hit.wav" type="AudioStream" id=3]
-[ext_resource path="res://assets/art/enemy/enemy.png" type="Texture2D" id=4]
-[ext_resource path="res://src/Actors/Enemy.gd" type="Script" id=5]
+[ext_resource type="Texture2D" uid="uid://c2aisfmq85suf" path="res://player/bullet.webp" id="1"]
+[ext_resource type="AudioStream" uid="uid://bbxjxs8sms61b" path="res://enemy/explode.wav" id="2"]
+[ext_resource type="AudioStream" uid="uid://brtn51vs7jaet" path="res://enemy/hit.wav" id="3"]
+[ext_resource type="Texture2D" uid="uid://cdy6gikv8wka7" path="res://enemy/enemy.webp" id="4"]
+[ext_resource type="Script" path="res://enemy/enemy.gd" id="5"]
 
-[sub_resource type="CanvasItemMaterial" id=1]
+[sub_resource type="CanvasItemMaterial" id="1"]
 
-[sub_resource type="Animation" id=2]
+[sub_resource type="Animation" id="Animation_67t2c"]
+length = 0.001
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:collision_layer")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 1,
+"values": [2]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath("Sprite2D:frame")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 1,
+"values": [0]
+}
+tracks/2/type = "value"
+tracks/2/imported = false
+tracks/2/enabled = true
+tracks/2/path = NodePath("Sprite2D:position")
+tracks/2/interp = 1
+tracks/2/loop_wrap = true
+tracks/2/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [Vector2(0, 0)]
+}
+tracks/3/type = "value"
+tracks/3/imported = false
+tracks/3/enabled = true
+tracks/3/path = NodePath("Sprite2D:rotation")
+tracks/3/interp = 1
+tracks/3/loop_wrap = true
+tracks/3/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [0.0]
+}
+tracks/4/type = "value"
+tracks/4/imported = false
+tracks/4/enabled = true
+tracks/4/path = NodePath("Sprite2D:self_modulate")
+tracks/4/interp = 1
+tracks/4/loop_wrap = true
+tracks/4/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [Color(1, 1, 1, 1)]
+}
+
+[sub_resource type="Animation" id="2"]
 resource_name = "destroy"
 length = 1.5
 tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
 tracks/0/path = NodePath("Sprite2D:frame")
 tracks/0/interp = 1
 tracks/0/loop_wrap = true
-tracks/0/imported = false
-tracks/0/enabled = true
 tracks/0/keys = {
 "times": PackedFloat32Array(0),
 "transitions": PackedFloat32Array(1),
@@ -24,11 +87,11 @@ tracks/0/keys = {
 "values": [7]
 }
 tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
 tracks/1/path = NodePath("Sprite2D:rotation_degrees")
 tracks/1/interp = 1
 tracks/1/loop_wrap = true
-tracks/1/imported = false
-tracks/1/enabled = true
 tracks/1/keys = {
 "times": PackedFloat32Array(0, 0.8),
 "transitions": PackedFloat32Array(0.0796601, 1),
@@ -36,23 +99,23 @@ tracks/1/keys = {
 "values": [0.0, 180.0]
 }
 tracks/2/type = "value"
+tracks/2/imported = false
+tracks/2/enabled = true
 tracks/2/path = NodePath("Sprite2D:self_modulate")
 tracks/2/interp = 1
 tracks/2/loop_wrap = true
-tracks/2/imported = false
-tracks/2/enabled = true
 tracks/2/keys = {
-"times": PackedFloat32Array(0, 0.5, 1.1),
+"times": PackedFloat32Array(0, 0.9, 1.3),
 "transitions": PackedFloat32Array(1, 1, 1),
 "update": 0,
 "values": [Color(1, 1, 1, 1), Color(1, 1, 1, 1), Color(1, 1, 1, 0)]
 }
 tracks/3/type = "value"
+tracks/3/imported = false
+tracks/3/enabled = true
 tracks/3/path = NodePath("Explosion:emitting")
 tracks/3/interp = 1
 tracks/3/loop_wrap = true
-tracks/3/imported = false
-tracks/3/enabled = true
 tracks/3/keys = {
 "times": PackedFloat32Array(0, 1),
 "transitions": PackedFloat32Array(1, 1),
@@ -60,90 +123,77 @@ tracks/3/keys = {
 "values": [false, true]
 }
 tracks/4/type = "value"
-tracks/4/path = NodePath("Explosion:process_material:scale")
-tracks/4/interp = 1
-tracks/4/loop_wrap = true
 tracks/4/imported = false
 tracks/4/enabled = true
+tracks/4/path = NodePath("Hit:playing")
+tracks/4/interp = 1
+tracks/4/loop_wrap = true
 tracks/4/keys = {
-"times": PackedFloat32Array(0.6, 1),
-"transitions": PackedFloat32Array(1, 1),
-"update": 0,
-"values": [1.0, 4.0]
+"times": PackedFloat32Array(0.00999999),
+"transitions": PackedFloat32Array(1),
+"update": 1,
+"values": [true]
 }
 tracks/5/type = "value"
-tracks/5/path = NodePath("Hit:playing")
-tracks/5/interp = 1
-tracks/5/loop_wrap = true
 tracks/5/imported = false
 tracks/5/enabled = true
+tracks/5/path = NodePath("Explode:playing")
+tracks/5/interp = 1
+tracks/5/loop_wrap = true
 tracks/5/keys = {
-"times": PackedFloat32Array(0.00999999),
+"times": PackedFloat32Array(0.8),
 "transitions": PackedFloat32Array(1),
 "update": 1,
 "values": [true]
 }
-tracks/6/type = "value"
-tracks/6/path = NodePath("Explode:playing")
-tracks/6/interp = 1
-tracks/6/loop_wrap = true
+tracks/6/type = "method"
 tracks/6/imported = false
 tracks/6/enabled = true
+tracks/6/path = NodePath(".")
+tracks/6/interp = 1
+tracks/6/loop_wrap = true
 tracks/6/keys = {
-"times": PackedFloat32Array(0.8),
-"transitions": PackedFloat32Array(1),
-"update": 1,
-"values": [true]
-}
-tracks/7/type = "method"
-tracks/7/path = NodePath(".")
-tracks/7/interp = 1
-tracks/7/loop_wrap = true
-tracks/7/imported = false
-tracks/7/enabled = true
-tracks/7/keys = {
 "times": PackedFloat32Array(1.5),
 "transitions": PackedFloat32Array(1),
 "values": [{
 "args": [],
-"method": "queue_free"
+"method": &"queue_free"
 }]
 }
-tracks/8/type = "value"
-tracks/8/path = NodePath(".:collision_layer")
-tracks/8/interp = 1
-tracks/8/loop_wrap = true
-tracks/8/imported = false
-tracks/8/enabled = true
-tracks/8/keys = {
+tracks/7/type = "value"
+tracks/7/imported = false
+tracks/7/enabled = true
+tracks/7/path = NodePath(".:collision_layer")
+tracks/7/interp = 1
+tracks/7/loop_wrap = true
+tracks/7/keys = {
 "times": PackedFloat32Array(0),
 "transitions": PackedFloat32Array(1),
 "update": 1,
 "values": [0]
 }
-tracks/9/type = "value"
-tracks/9/path = NodePath("Sprite2D:position")
-tracks/9/interp = 1
-tracks/9/loop_wrap = true
-tracks/9/imported = false
-tracks/9/enabled = true
-tracks/9/keys = {
+tracks/8/type = "value"
+tracks/8/imported = false
+tracks/8/enabled = true
+tracks/8/path = NodePath("Sprite2D:position")
+tracks/8/interp = 1
+tracks/8/loop_wrap = true
+tracks/8/keys = {
 "times": PackedFloat32Array(0, 0.2, 0.4),
 "transitions": PackedFloat32Array(2.2974, 0.183011, 1),
 "update": 0,
 "values": [Vector2(0, 0), Vector2(0, -32), Vector2(0, 0)]
 }
 
-[sub_resource type="Animation" id=3]
+[sub_resource type="Animation" id="3"]
 length = 6.75
-loop = true
 step = 0.25
 tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
 tracks/0/path = NodePath("Sprite2D:frame")
 tracks/0/interp = 1
 tracks/0/loop_wrap = true
-tracks/0/imported = false
-tracks/0/enabled = true
 tracks/0/keys = {
 "times": PackedFloat32Array(0, 0.75, 1.5, 2.25, 3, 3.75, 4.5, 5.25, 6, 6.75),
 "transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
@@ -151,16 +201,15 @@ tracks/0/keys = {
 "values": [5, 6, 5, 6, 5, 6, 7, 6, 7, 5]
 }
 
-[sub_resource type="Animation" id=4]
+[sub_resource type="Animation" id="4"]
 length = 1.25
-loop = true
 step = 0.25
 tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
 tracks/0/path = NodePath("Sprite2D:frame")
 tracks/0/interp = 1
 tracks/0/loop_wrap = true
-tracks/0/imported = false
-tracks/0/enabled = true
 tracks/0/keys = {
 "times": PackedFloat32Array(0, 0.25, 0.5, 0.75, 1, 1.25),
 "transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1),
@@ -168,60 +217,61 @@ tracks/0/keys = {
 "values": [0, 1, 2, 3, 4, 0]
 }
 
-[sub_resource type="CapsuleShape2D" id=5]
-radius = 11.0
-height = 7.0
+[sub_resource type="AnimationLibrary" id="AnimationLibrary_nnb1f"]
+_data = {
+"RESET": SubResource("Animation_67t2c"),
+"destroy": SubResource("2"),
+"idle": SubResource("3"),
+"walk": SubResource("4")
+}
 
-[sub_resource type="CanvasItemMaterial" id=6]
+[sub_resource type="CapsuleShape2D" id="5"]
+radius = 8.0
+height = 22.0
+
+[sub_resource type="CanvasItemMaterial" id="6"]
 blend_mode = 1
 
-[sub_resource type="Gradient" id=7]
+[sub_resource type="Gradient" id="7"]
 offsets = PackedFloat32Array(0.5, 1)
 colors = PackedColorArray(1, 1, 1, 1, 0, 0, 0, 1)
 
 [node name="Enemy" type="CharacterBody2D"]
 collision_layer = 2
-collision_mask = 24
-script = ExtResource( 5 )
-speed = Vector2(75, 250)
+collision_mask = 26
+collision_priority = 2.0
+script = ExtResource("5")
 
 [node name="PlatformDetector" type="RayCast2D" parent="."]
 position = Vector2(0, 6)
-enabled = true
-cast_to = Vector2(0, 8)
 collision_mask = 8
 
 [node name="FloorDetectorLeft" type="RayCast2D" parent="."]
 position = Vector2(-15, -4)
-enabled = true
-cast_to = Vector2(0, 35)
 collision_mask = 24
 
 [node name="FloorDetectorRight" type="RayCast2D" parent="."]
 position = Vector2(15.5, -3)
-enabled = true
-cast_to = Vector2(0, 35)
 collision_mask = 24
 
 [node name="Sprite2D" type="Sprite2D" parent="."]
-material = SubResource( 1 )
-texture = ExtResource( 4 )
+material = SubResource("1")
+texture = ExtResource("4")
 flip_h = true
 hframes = 8
-frame = 7
 
 [node name="AnimationPlayer" type="AnimationPlayer" parent="."]
-anims/destroy = SubResource( 2 )
-anims/idle = SubResource( 3 )
-anims/walk = SubResource( 4 )
+libraries = {
+"": SubResource("AnimationLibrary_nnb1f")
+}
 
 [node name="CollisionShape2D" type="CollisionShape2D" parent="."]
 rotation = -1.5708
-shape = SubResource( 5 )
+shape = SubResource("5")
 
 [node name="Explosion" type="CPUParticles2D" parent="."]
 self_modulate = Color(1, 1, 1, 0.12)
-material = SubResource( 6 )
+material = SubResource("6")
 emitting = false
 amount = 32
 lifetime = 0.5
@@ -229,21 +279,19 @@ one_shot = true
 speed_scale = 1.2
 explosiveness = 0.76
 draw_order = 215832976
-texture = ExtResource( 1 )
+texture = ExtResource("1")
 emission_shape = 1
 emission_sphere_radius = 8.0
 spread = 180.0
 gravity = Vector2(0, 250)
-initial_velocity = 120.0
-initial_velocity_random = 0.5
-angle_random = 1.0
-scale_amount_random = 1.0
-color_ramp = SubResource( 7 )
-hue_variation = 0.05
-hue_variation_random = 0.46
+initial_velocity_min = 25.0
+initial_velocity_max = 80.0
+angular_velocity_max = 45.0
+scale_amount_max = 1.2
+color_ramp = SubResource("7")
 
 [node name="Hit" type="AudioStreamPlayer2D" parent="."]
-stream = ExtResource( 3 )
+stream = ExtResource("3")
 
 [node name="Explode" type="AudioStreamPlayer2D" parent="."]
-stream = ExtResource( 2 )
+stream = ExtResource("2")

BIN
2d/platformer/enemy/enemy.webp


+ 5 - 5
2d/platformer/assets/art/enemy/enemy.png.import → 2d/platformer/enemy/enemy.webp.import

@@ -2,23 +2,23 @@
 
 importer="texture"
 type="CompressedTexture2D"
-uid="uid://dq7svs8qmf7h6"
-path="res://.godot/imported/enemy.png-c2f48b2558d3b68a547452306041a310.ctex"
+uid="uid://cdy6gikv8wka7"
+path="res://.godot/imported/enemy.webp-c5e00d5c5f64233c41f70dc392999636.ctex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://assets/art/enemy/enemy.png"
-dest_files=["res://.godot/imported/enemy.png-c2f48b2558d3b68a547452306041a310.ctex"]
+source_file="res://enemy/enemy.webp"
+dest_files=["res://.godot/imported/enemy.webp-c5e00d5c5f64233c41f70dc392999636.ctex"]
 
 [params]
 
 compress/mode=0
+compress/high_quality=false
 compress/lossy_quality=0.7
 compress/hdr_compression=1
-compress/bptc_ldr=0
 compress/normal_map=0
 compress/channel_pack=0
 mipmaps/generate=false

+ 0 - 0
2d/platformer/assets/audio/sfx/explode.wav → 2d/platformer/enemy/explode.wav


+ 3 - 3
2d/platformer/assets/audio/sfx/explode.wav.import → 2d/platformer/enemy/explode.wav.import

@@ -3,12 +3,12 @@
 importer="wav"
 type="AudioStreamWAV"
 uid="uid://bbxjxs8sms61b"
-path="res://.godot/imported/explode.wav-302a3de6d016432bf47477d337a4d553.sample"
+path="res://.godot/imported/explode.wav-2389d0cf62710ef336bf397194eae82e.sample"
 
 [deps]
 
-source_file="res://assets/audio/sfx/explode.wav"
-dest_files=["res://.godot/imported/explode.wav-302a3de6d016432bf47477d337a4d553.sample"]
+source_file="res://enemy/explode.wav"
+dest_files=["res://.godot/imported/explode.wav-2389d0cf62710ef336bf397194eae82e.sample"]
 
 [params]
 

+ 0 - 0
2d/platformer/assets/audio/sfx/hit.wav → 2d/platformer/enemy/hit.wav


+ 3 - 3
2d/platformer/assets/audio/sfx/hit.wav.import → 2d/platformer/enemy/hit.wav.import

@@ -3,12 +3,12 @@
 importer="wav"
 type="AudioStreamWAV"
 uid="uid://brtn51vs7jaet"
-path="res://.godot/imported/hit.wav-27e178036f6cee6545e9f025a3865a36.sample"
+path="res://.godot/imported/hit.wav-02ea2b331eef4f150ed1e5cb9477122b.sample"
 
 [deps]
 
-source_file="res://assets/audio/sfx/hit.wav"
-dest_files=["res://.godot/imported/hit.wav-27e178036f6cee6545e9f025a3865a36.sample"]
+source_file="res://enemy/hit.wav"
+dest_files=["res://.godot/imported/hit.wav-02ea2b331eef4f150ed1e5cb9477122b.sample"]
 
 [params]
 

+ 24 - 0
2d/platformer/game.gd

@@ -0,0 +1,24 @@
+class_name Game extends Node
+
+
+@onready var _pause_menu := $InterfaceLayer/PauseMenu as PauseMenu
+
+
+func _unhandled_input(event: InputEvent) -> void:
+	if event.is_action_pressed(&"toggle_fullscreen"):
+		var mode := DisplayServer.window_get_mode()
+		if mode == DisplayServer.WINDOW_MODE_FULLSCREEN or \
+				mode == DisplayServer.WINDOW_MODE_EXCLUSIVE_FULLSCREEN:
+			DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
+		else:
+			DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)
+		get_tree().root.set_input_as_handled()
+
+	elif event.is_action_pressed(&"toggle_pause"):
+		var tree := get_tree()
+		tree.paused = not tree.paused
+		if tree.paused:
+			_pause_menu.open()
+		else:
+			_pause_menu.close()
+		get_tree().root.set_input_as_handled()

+ 25 - 0
2d/platformer/game_singleplayer.tscn

@@ -0,0 +1,25 @@
+[gd_scene load_steps=6 format=3 uid="uid://bf3wnwihk7ymg"]
+
+[ext_resource type="Script" path="res://game.gd" id="2"]
+[ext_resource type="PackedScene" uid="uid://dr2p70jo7e4kn" path="res://level/level.tscn" id="3"]
+[ext_resource type="PackedScene" uid="uid://d0ni64ucb3ym2" path="res://player/player.tscn" id="4"]
+[ext_resource type="PackedScene" uid="uid://c7ai4bigaryci" path="res://gui/pause_menu_singleplayer.tscn" id="4_x6l06"]
+[ext_resource type="PackedScene" uid="uid://do7htx4sqmcnh" path="res://music.tscn" id="5_rkna2"]
+
+[node name="Game" type="Node"]
+process_mode = 3
+script = ExtResource("2")
+
+[node name="Level" parent="." instance=ExtResource("3")]
+
+[node name="Player" parent="Level" instance=ExtResource("4")]
+position = Vector2(90, 546)
+
+[node name="InterfaceLayer" type="CanvasLayer" parent="."]
+layer = 100
+
+[node name="PauseMenu" parent="InterfaceLayer" instance=ExtResource("4_x6l06")]
+
+[node name="Music" parent="." instance=ExtResource("5_rkna2")]
+
+[connection signal="coin_collected" from="Level/Player" to="InterfaceLayer/PauseMenu" method="_on_coin_collected"]

+ 10 - 0
2d/platformer/game_splitscreen.gd

@@ -0,0 +1,10 @@
+extends Game
+
+
+func _ready() -> void:
+	var player_2 := %Player2 as Player
+	var viewport_1 := %Viewport1 as SubViewport
+	var viewport_2 := %Viewport2 as SubViewport
+	viewport_2.world_2d = viewport_1.world_2d
+	player_2.camera.custom_viewport = viewport_2
+	player_2.camera.make_current()

+ 82 - 0
2d/platformer/game_splitscreen.tscn

@@ -0,0 +1,82 @@
+[gd_scene load_steps=7 format=3 uid="uid://2elur2m0il32"]
+
+[ext_resource type="Script" path="res://game_splitscreen.gd" id="1_60qgt"]
+[ext_resource type="PackedScene" uid="uid://dggactv0aho4p" path="res://gui/pause_menu_splitscreen.tscn" id="2_xkexm"]
+[ext_resource type="PackedScene" uid="uid://dr2p70jo7e4kn" path="res://level/level.tscn" id="3_e0nyr"]
+[ext_resource type="PackedScene" uid="uid://d0ni64ucb3ym2" path="res://player/player.tscn" id="4_8j0va"]
+[ext_resource type="PackedScene" uid="uid://bkyw3e13rupar" path="res://level/parallax_background.tscn" id="5_47vt4"]
+[ext_resource type="PackedScene" uid="uid://do7htx4sqmcnh" path="res://music.tscn" id="6_q2yet"]
+
+[node name="GameSplitscreen" type="Node"]
+process_mode = 3
+script = ExtResource("1_60qgt")
+
+[node name="Black" type="ColorRect" parent="."]
+process_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+offset_right = 6.10352e-05
+offset_bottom = 3.05176e-05
+color = Color(0, 0, 0, 1)
+
+[node name="SplitContainer" type="HSplitContainer" parent="Black"]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+dragger_visibility = 1
+
+[node name="ViewportContainer1" type="SubViewportContainer" parent="Black/SplitContainer"]
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+stretch = true
+
+[node name="Viewport1" type="SubViewport" parent="Black/SplitContainer/ViewportContainer1"]
+unique_name_in_owner = true
+handle_input_locally = false
+canvas_item_default_texture_filter = 0
+audio_listener_enable_2d = true
+size = Vector2i(394, 480)
+render_target_update_mode = 4
+
+[node name="Level" parent="Black/SplitContainer/ViewportContainer1/Viewport1" instance=ExtResource("3_e0nyr")]
+
+[node name="Player1" parent="Black/SplitContainer/ViewportContainer1/Viewport1" instance=ExtResource("4_8j0va")]
+unique_name_in_owner = true
+position = Vector2(90, 546)
+action_suffix = "_p1"
+
+[node name="Player2" parent="Black/SplitContainer/ViewportContainer1/Viewport1" instance=ExtResource("4_8j0va")]
+unique_name_in_owner = true
+position = Vector2(120, 546)
+action_suffix = "_p2"
+
+[node name="ViewportContainer2" type="SubViewportContainer" parent="Black/SplitContainer"]
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+stretch = true
+
+[node name="Viewport2" type="SubViewport" parent="Black/SplitContainer/ViewportContainer2"]
+unique_name_in_owner = true
+handle_input_locally = false
+canvas_item_default_texture_filter = 0
+audio_listener_enable_2d = true
+size = Vector2i(394, 480)
+render_target_update_mode = 4
+
+[node name="ParallaxBackground" parent="Black/SplitContainer/ViewportContainer2/Viewport2" instance=ExtResource("5_47vt4")]
+
+[node name="InterfaceLayer" type="CanvasLayer" parent="."]
+layer = 100
+
+[node name="PauseMenu" parent="InterfaceLayer" instance=ExtResource("2_xkexm")]
+
+[node name="Music" parent="." instance=ExtResource("6_q2yet")]
+
+[connection signal="coin_collected" from="Black/SplitContainer/ViewportContainer1/Viewport1/Player1" to="InterfaceLayer/PauseMenu" method="_on_coin_collected"]
+[connection signal="coin_collected" from="Black/SplitContainer/ViewportContainer1/Viewport1/Player2" to="InterfaceLayer/PauseMenu" method="_on_coin_collected"]

+ 16 - 0
2d/platformer/gui/coins_counter.gd

@@ -0,0 +1,16 @@
+class_name CoinsCounter extends Panel
+
+
+var _coins_collected: int = 0
+
+@onready var _coins_label := $Label as Label
+
+
+func _ready() -> void:
+	_coins_label.set_text(str(_coins_collected))
+	($AnimatedSprite2D as AnimatedSprite2D).play()
+
+
+func collect_coin() -> void:
+	_coins_collected += 1
+	_coins_label.set_text(str(_coins_collected))

+ 70 - 0
2d/platformer/gui/coins_counter.tscn

@@ -0,0 +1,70 @@
+[gd_scene load_steps=9 format=3 uid="uid://bsyqg6eh3wl5i"]
+
+[ext_resource type="Theme" uid="uid://da4noqsij73it" path="res://gui/theme.tres" id="1"]
+[ext_resource type="Texture2D" uid="uid://l42us5qso8v4" path="res://level/coin.webp" id="2"]
+[ext_resource type="Script" path="res://gui/coins_counter.gd" id="3"]
+
+[sub_resource type="AtlasTexture" id="2"]
+atlas = ExtResource("2")
+region = Rect2(0, 0, 8, 8)
+
+[sub_resource type="AtlasTexture" id="3"]
+atlas = ExtResource("2")
+region = Rect2(8, 0, 8, 8)
+
+[sub_resource type="AtlasTexture" id="4"]
+atlas = ExtResource("2")
+region = Rect2(16, 0, 8, 8)
+
+[sub_resource type="AtlasTexture" id="5"]
+atlas = ExtResource("2")
+region = Rect2(24, 0, 8, 8)
+
+[sub_resource type="SpriteFrames" id="6"]
+animations = [{
+"frames": [{
+"duration": 1.0,
+"texture": SubResource("2")
+}, {
+"duration": 1.0,
+"texture": SubResource("3")
+}, {
+"duration": 1.0,
+"texture": SubResource("4")
+}, {
+"duration": 1.0,
+"texture": SubResource("5")
+}, {
+"duration": 1.0,
+"texture": SubResource("4")
+}, {
+"duration": 1.0,
+"texture": SubResource("3")
+}],
+"loop": true,
+"name": &"coin_spinning",
+"speed": 6.5
+}]
+
+[node name="CoinsCounter" type="Panel"]
+offset_left = 5.0
+offset_top = 5.0
+offset_right = 100.0
+offset_bottom = 45.0
+theme = ExtResource("1")
+script = ExtResource("3")
+
+[node name="Label" type="Label" parent="."]
+layout_mode = 0
+anchor_right = 1.0
+anchor_bottom = 1.0
+offset_right = -8.0
+text = "100"
+horizontal_alignment = 2
+vertical_alignment = 1
+
+[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="."]
+position = Vector2(21.5, 22.5)
+scale = Vector2(4.375, 4.375)
+sprite_frames = SubResource("6")
+animation = &"coin_spinning"

+ 0 - 0
2d/platformer/assets/theme/fonts/kenney_mini_square.ttf → 2d/platformer/gui/kenney_mini_square.ttf


+ 4 - 3
2d/platformer/assets/theme/fonts/kenney_mini_square.ttf.import → 2d/platformer/gui/kenney_mini_square.ttf.import

@@ -3,12 +3,12 @@
 importer="font_data_dynamic"
 type="FontFile"
 uid="uid://bk80b6owsrioj"
-path="res://.godot/imported/kenney_mini_square.ttf-d79fb84878832e276f7b282a10aa19c8.fontdata"
+path="res://.godot/imported/kenney_mini_square.ttf-14b0a28a89225c31efd7626f5228f467.fontdata"
 
 [deps]
 
-source_file="res://assets/theme/fonts/kenney_mini_square.ttf"
-dest_files=["res://.godot/imported/kenney_mini_square.ttf-d79fb84878832e276f7b282a10aa19c8.fontdata"]
+source_file="res://gui/kenney_mini_square.ttf"
+dest_files=["res://.godot/imported/kenney_mini_square.ttf-14b0a28a89225c31efd7626f5228f467.fontdata"]
 
 [params]
 
@@ -18,6 +18,7 @@ generate_mipmaps=false
 multichannel_signed_distance_field=false
 msdf_pixel_range=8
 msdf_size=48
+allow_system_fallback=true
 force_autohinter=false
 hinting=1
 subpixel_positioning=1

+ 77 - 0
2d/platformer/gui/pause_menu.gd

@@ -0,0 +1,77 @@
+class_name PauseMenu extends Control
+
+
+@export var fade_in_duration := 0.3
+@export var fade_out_duration := 0.2
+
+@onready var center_cont := $ColorRect/CenterContainer as CenterContainer
+@onready var resume_button := center_cont.get_node(^"VBoxContainer/ResumeButton") as Button
+@onready var coins_counter := $ColorRect/CoinsCounter as CoinsCounter
+
+
+func _ready():
+	hide()
+
+
+func close():
+	var tween := create_tween()
+	get_tree().paused = false
+	tween.tween_property(
+		self,
+		^"modulate:a",
+		0.0,
+		fade_out_duration
+	).set_trans(Tween.TRANS_LINEAR).set_ease(Tween.EASE_OUT)
+	tween.parallel().tween_property(
+		center_cont,
+		^"anchor_bottom",
+		0.5,
+		fade_out_duration
+	).set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_OUT)
+	tween.tween_callback(hide)
+
+
+func open():
+	show()
+	resume_button.grab_focus()
+
+	modulate.a = 0.0
+	center_cont.anchor_bottom = 0.5
+	var tween := create_tween()
+	tween.tween_property(
+		self,
+		^"modulate:a",
+		1.0,
+		fade_in_duration
+	).set_trans(Tween.TRANS_LINEAR).set_ease(Tween.EASE_IN)
+	tween.parallel().tween_property(
+		center_cont,
+		^"anchor_bottom",
+		1.0,
+		fade_out_duration
+	).set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_OUT)
+
+
+func _on_coin_collected() -> void:
+	coins_counter.collect_coin()
+
+
+func _on_resume_button_pressed():
+	close()
+
+
+func _on_singleplayer_button_pressed() -> void:
+	if visible:
+		get_tree().paused = false
+		get_tree().change_scene_to_file("res://game_singleplayer.tscn")
+
+
+func _on_splitscreen_button_pressed() -> void:
+	if visible:
+		get_tree().paused = false
+		get_tree().change_scene_to_file("res://game_splitscreen.tscn")
+
+
+func _on_quit_button_pressed():
+	if visible:
+		get_tree().quit()

+ 16 - 32
2d/platformer/src/UserInterface/PauseMenu.tscn → 2d/platformer/gui/pause_menu.tscn

@@ -1,8 +1,8 @@
-[gd_scene load_steps=4 format=3 uid="uid://0oqbyhiw1abi"]
+[gd_scene load_steps=4 format=3 uid="uid://dh71g61cm8k44"]
 
-[ext_resource type="Theme" uid="uid://chubprkmexsng" path="res://assets/theme/user_interface.tres" id="1"]
-[ext_resource type="Script" path="res://src/UserInterface/PauseMenu.gd" id="2"]
-[ext_resource type="PackedScene" path="res://src/UserInterface/CoinsCounter.tscn" id="4"]
+[ext_resource type="Theme" uid="uid://da4noqsij73it" path="res://gui/theme.tres" id="1"]
+[ext_resource type="Script" path="res://gui/pause_menu.gd" id="2"]
+[ext_resource type="PackedScene" uid="uid://bsyqg6eh3wl5i" path="res://gui/coins_counter.tscn" id="4"]
 
 [node name="PauseMenu" type="Control"]
 process_mode = 3
@@ -10,6 +10,8 @@ layout_mode = 3
 anchors_preset = 15
 anchor_right = 1.0
 anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
 theme = ExtResource("1")
 script = ExtResource("2")
 
@@ -18,64 +20,46 @@ layout_mode = 1
 anchors_preset = 15
 anchor_right = 1.0
 anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
 color = Color(0, 0, 0, 0.294118)
 
 [node name="CenterContainer" type="CenterContainer" parent="ColorRect"]
 layout_mode = 1
-anchors_preset = 15
+anchors_preset = -1
 anchor_right = 1.0
 anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
 
 [node name="VBoxContainer" type="VBoxContainer" parent="ColorRect/CenterContainer"]
 layout_mode = 2
-offset_left = 347.0
-offset_top = 194.0
-offset_right = 453.0
-offset_bottom = 285.0
 alignment = 1
 
 [node name="Label" type="Label" parent="ColorRect/CenterContainer/VBoxContainer"]
 layout_mode = 2
-offset_right = 106.0
-offset_bottom = 23.0
 text = "Game Paused"
+horizontal_alignment = 1
 
 [node name="MarginContainer" type="MarginContainer" parent="ColorRect/CenterContainer/VBoxContainer"]
 layout_mode = 2
-offset_top = 27.0
-offset_right = 106.0
-offset_bottom = 27.0
 
 [node name="ResumeButton" type="Button" parent="ColorRect/CenterContainer/VBoxContainer"]
 layout_mode = 2
-offset_left = 16.0
-offset_top = 31.0
-offset_right = 90.0
-offset_bottom = 59.0
 size_flags_horizontal = 4
 text = "Resume"
 
 [node name="QuitButton" type="Button" parent="ColorRect/CenterContainer/VBoxContainer"]
 layout_mode = 2
-offset_left = 31.0
-offset_top = 63.0
-offset_right = 75.0
-offset_bottom = 91.0
 size_flags_horizontal = 4
 text = "Quit"
 
 [node name="CoinsCounter" parent="ColorRect" instance=ExtResource("4")]
 layout_mode = 0
+offset_left = 0.0
+offset_top = 0.0
 offset_right = 105.0
 offset_bottom = 50.0
 
-[node name="Tween" type="Tween" parent="."]
-_import_path = NodePath("")
-unique_name_in_owner = false
-process_mode = 0
-process_priority = 0
-editor_description = ""
-script = null
-
-[connection signal="pressed" from="ColorRect/CenterContainer/VBoxContainer/ResumeButton" to="." method="_on_ResumeButton_pressed"]
-[connection signal="pressed" from="ColorRect/CenterContainer/VBoxContainer/QuitButton" to="." method="_on_QuitButton_pressed"]
+[connection signal="pressed" from="ColorRect/CenterContainer/VBoxContainer/ResumeButton" to="." method="_on_resume_button_pressed"]
+[connection signal="pressed" from="ColorRect/CenterContainer/VBoxContainer/QuitButton" to="." method="_on_quit_button_pressed"]

+ 11 - 0
2d/platformer/gui/pause_menu_singleplayer.tscn

@@ -0,0 +1,11 @@
+[gd_scene load_steps=2 format=3 uid="uid://c7ai4bigaryci"]
+
+[ext_resource type="PackedScene" uid="uid://dh71g61cm8k44" path="res://gui/pause_menu.tscn" id="1_pwe1t"]
+
+[node name="PauseMenu" instance=ExtResource("1_pwe1t")]
+
+[node name="SplitscreenButton" type="Button" parent="ColorRect/CenterContainer/VBoxContainer" index="3"]
+layout_mode = 2
+text = "Change to 2-Player"
+
+[connection signal="pressed" from="ColorRect/CenterContainer/VBoxContainer/SplitscreenButton" to="." method="_on_splitscreen_button_pressed"]

+ 11 - 0
2d/platformer/gui/pause_menu_splitscreen.tscn

@@ -0,0 +1,11 @@
+[gd_scene load_steps=2 format=3 uid="uid://dggactv0aho4p"]
+
+[ext_resource type="PackedScene" uid="uid://dh71g61cm8k44" path="res://gui/pause_menu.tscn" id="1_x3hgi"]
+
+[node name="PauseMenu" instance=ExtResource("1_x3hgi")]
+
+[node name="SingleplayerButton" type="Button" parent="ColorRect/CenterContainer/VBoxContainer" index="3"]
+layout_mode = 2
+text = "Change to 1-player"
+
+[connection signal="pressed" from="ColorRect/CenterContainer/VBoxContainer/SingleplayerButton" to="." method="_on_singleplayer_button_pressed"]

+ 2 - 2
2d/platformer/assets/theme/user_interface.tres → 2d/platformer/gui/theme.tres

@@ -1,6 +1,6 @@
-[gd_resource type="Theme" load_steps=7 format=3 uid="uid://chubprkmexsng"]
+[gd_resource type="Theme" load_steps=7 format=3 uid="uid://da4noqsij73it"]
 
-[ext_resource type="FontFile" uid="uid://bk80b6owsrioj" path="res://assets/theme/fonts/kenney_mini_square.ttf" id="1_f0sjs"]
+[ext_resource type="FontFile" uid="uid://bk80b6owsrioj" path="res://gui/kenney_mini_square.ttf" id="1_f0sjs"]
 
 [sub_resource type="StyleBoxFlat" id="1"]
 content_margin_left = 6.0

BIN
2d/platformer/gui/touch_button_fire.webp


+ 4 - 4
2d/platformer/assets/art/ui/touch_button_fire.png.import → 2d/platformer/gui/touch_button_fire.webp.import

@@ -3,22 +3,22 @@
 importer="texture"
 type="CompressedTexture2D"
 uid="uid://dkvmtr3ieug3l"
-path="res://.godot/imported/touch_button_fire.png-8b72c42a8cb252207ce8948d4b623690.ctex"
+path="res://.godot/imported/touch_button_fire.webp-dccf84dcf0f617f42794a4bab6e5b347.ctex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://assets/art/ui/touch_button_fire.png"
-dest_files=["res://.godot/imported/touch_button_fire.png-8b72c42a8cb252207ce8948d4b623690.ctex"]
+source_file="res://gui/touch_button_fire.webp"
+dest_files=["res://.godot/imported/touch_button_fire.webp-dccf84dcf0f617f42794a4bab6e5b347.ctex"]
 
 [params]
 
 compress/mode=0
+compress/high_quality=false
 compress/lossy_quality=0.7
 compress/hdr_compression=1
-compress/bptc_ldr=0
 compress/normal_map=0
 compress/channel_pack=0
 mipmaps/generate=false

BIN
2d/platformer/gui/touch_button_jump.webp


+ 4 - 4
2d/platformer/assets/art/ui/touch_button_jump.png.import → 2d/platformer/gui/touch_button_jump.webp.import

@@ -3,22 +3,22 @@
 importer="texture"
 type="CompressedTexture2D"
 uid="uid://xbywv0ti1u0h"
-path="res://.godot/imported/touch_button_jump.png-f72afeb370538aa951853dbc52052250.ctex"
+path="res://.godot/imported/touch_button_jump.webp-72d09f543801d684298fbadf893197c2.ctex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://assets/art/ui/touch_button_jump.png"
-dest_files=["res://.godot/imported/touch_button_jump.png-f72afeb370538aa951853dbc52052250.ctex"]
+source_file="res://gui/touch_button_jump.webp"
+dest_files=["res://.godot/imported/touch_button_jump.webp-72d09f543801d684298fbadf893197c2.ctex"]
 
 [params]
 
 compress/mode=0
+compress/high_quality=false
 compress/lossy_quality=0.7
 compress/hdr_compression=1
-compress/bptc_ldr=0
 compress/normal_map=0
 compress/channel_pack=0
 mipmaps/generate=false

BIN
2d/platformer/gui/touch_button_left.webp


+ 4 - 4
2d/platformer/assets/art/ui/touch_button_left.png.import → 2d/platformer/gui/touch_button_left.webp.import

@@ -3,22 +3,22 @@
 importer="texture"
 type="CompressedTexture2D"
 uid="uid://byv1xhmnegdap"
-path="res://.godot/imported/touch_button_left.png-e48f16cfdaae98fdc92a21f20c157c53.ctex"
+path="res://.godot/imported/touch_button_left.webp-f44154539d59fd4f5b3597e8703bbc6a.ctex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://assets/art/ui/touch_button_left.png"
-dest_files=["res://.godot/imported/touch_button_left.png-e48f16cfdaae98fdc92a21f20c157c53.ctex"]
+source_file="res://gui/touch_button_left.webp"
+dest_files=["res://.godot/imported/touch_button_left.webp-f44154539d59fd4f5b3597e8703bbc6a.ctex"]
 
 [params]
 
 compress/mode=0
+compress/high_quality=false
 compress/lossy_quality=0.7
 compress/hdr_compression=1
-compress/bptc_ldr=0
 compress/normal_map=0
 compress/channel_pack=0
 mipmaps/generate=false

BIN
2d/platformer/gui/touch_button_right.webp


+ 4 - 4
2d/platformer/assets/art/ui/touch_button_right.png.import → 2d/platformer/gui/touch_button_right.webp.import

@@ -3,22 +3,22 @@
 importer="texture"
 type="CompressedTexture2D"
 uid="uid://byg0psif5h7ak"
-path="res://.godot/imported/touch_button_right.png-74bf87a3a0fa663fbb3574844de31372.ctex"
+path="res://.godot/imported/touch_button_right.webp-ec9f97ce35fcf0bf570ff19f4fcaecc8.ctex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://assets/art/ui/touch_button_right.png"
-dest_files=["res://.godot/imported/touch_button_right.png-74bf87a3a0fa663fbb3574844de31372.ctex"]
+source_file="res://gui/touch_button_right.webp"
+dest_files=["res://.godot/imported/touch_button_right.webp-ec9f97ce35fcf0bf570ff19f4fcaecc8.ctex"]
 
 [params]
 
 compress/mode=0
+compress/high_quality=false
 compress/lossy_quality=0.7
 compress/hdr_compression=1
-compress/bptc_ldr=0
 compress/normal_map=0
 compress/channel_pack=0
 mipmaps/generate=false

BIN
2d/platformer/icon.png


BIN
2d/platformer/icon.webp


+ 4 - 4
2d/platformer/icon.png.import → 2d/platformer/icon.webp.import

@@ -3,22 +3,22 @@
 importer="texture"
 type="CompressedTexture2D"
 uid="uid://dpxlcfssx0etu"
-path="res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex"
+path="res://.godot/imported/icon.webp-e94f9a68b0f625a567a797079e4d325f.ctex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://icon.png"
-dest_files=["res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex"]
+source_file="res://icon.webp"
+dest_files=["res://.godot/imported/icon.webp-e94f9a68b0f625a567a797079e4d325f.ctex"]
 
 [params]
 
 compress/mode=0
+compress/high_quality=false
 compress/lossy_quality=0.7
 compress/hdr_compression=1
-compress/bptc_ldr=0
 compress/normal_map=0
 compress/channel_pack=0
 mipmaps/generate=false

BIN
2d/platformer/level/cloud_1.webp


+ 4 - 4
2d/platformer/assets/art/background/cloud_1.png.import → 2d/platformer/level/cloud_1.webp.import

@@ -3,22 +3,22 @@
 importer="texture"
 type="CompressedTexture2D"
 uid="uid://b4n7s65t0qoep"
-path="res://.godot/imported/cloud_1.png-03c0ad8be397b731df0dd38fa3c87727.ctex"
+path="res://.godot/imported/cloud_1.webp-d4440f8a56714fd63d83c7074d20ace3.ctex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://assets/art/background/cloud_1.png"
-dest_files=["res://.godot/imported/cloud_1.png-03c0ad8be397b731df0dd38fa3c87727.ctex"]
+source_file="res://level/cloud_1.webp"
+dest_files=["res://.godot/imported/cloud_1.webp-d4440f8a56714fd63d83c7074d20ace3.ctex"]
 
 [params]
 
 compress/mode=0
+compress/high_quality=false
 compress/lossy_quality=0.7
 compress/hdr_compression=1
-compress/bptc_ldr=0
 compress/normal_map=0
 compress/channel_pack=0
 mipmaps/generate=false

BIN
2d/platformer/level/cloud_2.webp


+ 4 - 4
2d/platformer/assets/art/background/cloud_2.png.import → 2d/platformer/level/cloud_2.webp.import

@@ -3,22 +3,22 @@
 importer="texture"
 type="CompressedTexture2D"
 uid="uid://cubkvnu4fdwki"
-path="res://.godot/imported/cloud_2.png-4ddf8c5bceca4aa07a8bc86d7d788e02.ctex"
+path="res://.godot/imported/cloud_2.webp-6870de4e2ed6536e37af4c22aa731ad1.ctex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://assets/art/background/cloud_2.png"
-dest_files=["res://.godot/imported/cloud_2.png-4ddf8c5bceca4aa07a8bc86d7d788e02.ctex"]
+source_file="res://level/cloud_2.webp"
+dest_files=["res://.godot/imported/cloud_2.webp-6870de4e2ed6536e37af4c22aa731ad1.ctex"]
 
 [params]
 
 compress/mode=0
+compress/high_quality=false
 compress/lossy_quality=0.7
 compress/hdr_compression=1
-compress/bptc_ldr=0
 compress/normal_map=0
 compress/channel_pack=0
 mipmaps/generate=false

BIN
2d/platformer/level/cloud_3.webp


+ 4 - 4
2d/platformer/assets/art/background/cloud_3.png.import → 2d/platformer/level/cloud_3.webp.import

@@ -3,22 +3,22 @@
 importer="texture"
 type="CompressedTexture2D"
 uid="uid://5tho6j8r4eam"
-path="res://.godot/imported/cloud_3.png-a1b7dc71aa84bea9cb4f78f585dcc65d.ctex"
+path="res://.godot/imported/cloud_3.webp-a303ee6af47d3df137be263a98a9fa7d.ctex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://assets/art/background/cloud_3.png"
-dest_files=["res://.godot/imported/cloud_3.png-a1b7dc71aa84bea9cb4f78f585dcc65d.ctex"]
+source_file="res://level/cloud_3.webp"
+dest_files=["res://.godot/imported/cloud_3.webp-a303ee6af47d3df137be263a98a9fa7d.ctex"]
 
 [params]
 
 compress/mode=0
+compress/high_quality=false
 compress/lossy_quality=0.7
 compress/hdr_compression=1
-compress/bptc_ldr=0
 compress/normal_map=0
 compress/channel_pack=0
 mipmaps/generate=false

+ 10 - 0
2d/platformer/level/coin.gd

@@ -0,0 +1,10 @@
+class_name Coin extends Area2D
+## Collectible that disappears when the player touches it.
+
+
+@onready var animation_player := $AnimationPlayer as AnimationPlayer
+
+
+func _on_body_entered(body: Node2D) -> void:
+	animation_player.play(&"picked")
+	(body as Player).coin_collected.emit()

+ 112 - 53
2d/platformer/src/Objects/Coin.tscn → 2d/platformer/level/coin.tscn

@@ -1,19 +1,71 @@
-[gd_scene load_steps=7 format=2]
+[gd_scene load_steps=9 format=3 uid="uid://b2xsfn7h7komw"]
 
-[ext_resource path="res://assets/art/coin/coin.png" type="Texture2D" id=2]
-[ext_resource path="res://assets/audio/sfx/coin_pickup.wav" type="AudioStream" id=3]
-[ext_resource path="res://src/Objects/Coin.gd" type="Script" id=4]
+[ext_resource type="Texture2D" uid="uid://l42us5qso8v4" path="res://level/coin.webp" id="2"]
+[ext_resource type="AudioStream" uid="uid://bw67pgdlhpqd0" path="res://player/coin_pickup.wav" id="3"]
+[ext_resource type="Script" path="res://level/coin.gd" id="4"]
 
-[sub_resource type="Animation" id=1]
+[sub_resource type="Animation" id="Animation_mfug7"]
+resource_name = "RESET"
+length = 0.01
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:monitoring")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 1,
+"values": [true]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath("Sprite2D:position")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [Vector2(0, 0)]
+}
+tracks/2/type = "value"
+tracks/2/imported = false
+tracks/2/enabled = true
+tracks/2/path = NodePath("Sprite2D:frame")
+tracks/2/interp = 1
+tracks/2/loop_wrap = true
+tracks/2/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 1,
+"values": [0]
+}
+tracks/3/type = "value"
+tracks/3/imported = false
+tracks/3/enabled = true
+tracks/3/path = NodePath("Sprite2D:self_modulate")
+tracks/3/interp = 1
+tracks/3/loop_wrap = true
+tracks/3/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [Color(1, 1, 1, 1)]
+}
+
+[sub_resource type="Animation" id="1"]
 resource_name = "picked"
 length = 1.5
 step = 0.25
 tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
 tracks/0/path = NodePath("Sprite2D:frame")
 tracks/0/interp = 1
 tracks/0/loop_wrap = true
-tracks/0/imported = false
-tracks/0/enabled = true
 tracks/0/keys = {
 "times": PackedFloat32Array(0),
 "transitions": PackedFloat32Array(1),
@@ -21,25 +73,25 @@ tracks/0/keys = {
 "values": [0]
 }
 tracks/1/type = "method"
+tracks/1/imported = false
+tracks/1/enabled = true
 tracks/1/path = NodePath(".")
 tracks/1/interp = 1
 tracks/1/loop_wrap = true
-tracks/1/imported = false
-tracks/1/enabled = true
 tracks/1/keys = {
-"times": PackedFloat32Array(1),
+"times": PackedFloat32Array(1.5),
 "transitions": PackedFloat32Array(1),
 "values": [{
 "args": [],
-"method": "queue_free"
+"method": &"queue_free"
 }]
 }
 tracks/2/type = "value"
+tracks/2/imported = false
+tracks/2/enabled = true
 tracks/2/path = NodePath("Sprite2D:self_modulate")
 tracks/2/interp = 1
 tracks/2/loop_wrap = true
-tracks/2/imported = false
-tracks/2/enabled = true
 tracks/2/keys = {
 "times": PackedFloat32Array(0.25, 1.25),
 "transitions": PackedFloat32Array(1, 1),
@@ -47,52 +99,55 @@ tracks/2/keys = {
 "values": [Color(1, 1, 1, 1), Color(1, 1, 1, 0)]
 }
 tracks/3/type = "value"
-tracks/3/path = NodePath("Pickup:playing")
-tracks/3/interp = 1
-tracks/3/loop_wrap = true
 tracks/3/imported = false
 tracks/3/enabled = true
+tracks/3/path = NodePath(".:monitoring")
+tracks/3/interp = 1
+tracks/3/loop_wrap = true
 tracks/3/keys = {
 "times": PackedFloat32Array(0),
 "transitions": PackedFloat32Array(1),
-"update": 2,
-"values": [true]
+"update": 1,
+"values": [false]
 }
 tracks/4/type = "value"
-tracks/4/path = NodePath(".:monitoring")
-tracks/4/interp = 1
-tracks/4/loop_wrap = true
 tracks/4/imported = false
 tracks/4/enabled = true
+tracks/4/path = NodePath("Sprite2D:position")
+tracks/4/interp = 1
+tracks/4/loop_wrap = true
 tracks/4/keys = {
-"times": PackedFloat32Array(0),
-"transitions": PackedFloat32Array(1),
-"update": 1,
-"values": [false]
-}
-tracks/5/type = "value"
-tracks/5/path = NodePath("Sprite2D:position")
-tracks/5/interp = 1
-tracks/5/loop_wrap = true
-tracks/5/imported = false
-tracks/5/enabled = true
-tracks/5/keys = {
 "times": PackedFloat32Array(0, 1.5),
 "transitions": PackedFloat32Array(1, 1),
 "update": 0,
 "values": [Vector2(0, 0), Vector2(0, -42)]
 }
+tracks/5/type = "audio"
+tracks/5/imported = false
+tracks/5/enabled = true
+tracks/5/path = NodePath("Pickup")
+tracks/5/interp = 1
+tracks/5/loop_wrap = true
+tracks/5/keys = {
+"clips": [{
+"end_offset": 0.0,
+"start_offset": 0.0,
+"stream": ExtResource("3")
+}],
+"times": PackedFloat32Array(0)
+}
+tracks/5/use_blend = true
 
-[sub_resource type="Animation" id=2]
+[sub_resource type="Animation" id="2"]
 length = 1.5
-loop = true
+loop_mode = 1
 step = 0.25
 tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
 tracks/0/path = NodePath("Sprite2D:frame")
 tracks/0/interp = 1
 tracks/0/loop_wrap = true
-tracks/0/imported = false
-tracks/0/enabled = true
 tracks/0/keys = {
 "times": PackedFloat32Array(0, 0.25, 0.5, 0.75, 1, 1.25, 1.5),
 "transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1),
@@ -100,11 +155,11 @@ tracks/0/keys = {
 "values": [0, 1, 2, 3, 2, 1, 0]
 }
 tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
 tracks/1/path = NodePath("Sprite2D:position")
 tracks/1/interp = 1
 tracks/1/loop_wrap = true
-tracks/1/imported = false
-tracks/1/enabled = true
 tracks/1/keys = {
 "times": PackedFloat32Array(0),
 "transitions": PackedFloat32Array(1),
@@ -112,11 +167,11 @@ tracks/1/keys = {
 "values": [Vector2(0, 0)]
 }
 tracks/2/type = "value"
+tracks/2/imported = false
+tracks/2/enabled = true
 tracks/2/path = NodePath("Sprite2D:self_modulate")
 tracks/2/interp = 1
 tracks/2/loop_wrap = true
-tracks/2/imported = false
-tracks/2/enabled = true
 tracks/2/keys = {
 "times": PackedFloat32Array(0),
 "transitions": PackedFloat32Array(1),
@@ -124,11 +179,11 @@ tracks/2/keys = {
 "values": [Color(1, 1, 1, 1)]
 }
 tracks/3/type = "value"
+tracks/3/imported = false
+tracks/3/enabled = true
 tracks/3/path = NodePath(".:monitoring")
 tracks/3/interp = 1
 tracks/3/loop_wrap = true
-tracks/3/imported = false
-tracks/3/enabled = true
 tracks/3/keys = {
 "times": PackedFloat32Array(0),
 "transitions": PackedFloat32Array(1),
@@ -136,29 +191,33 @@ tracks/3/keys = {
 "values": [true]
 }
 
-[sub_resource type="CircleShape2D" id=3]
+[sub_resource type="AnimationLibrary" id="AnimationLibrary_fwb0h"]
+_data = {
+"RESET": SubResource("Animation_mfug7"),
+"picked": SubResource("1"),
+"spinning": SubResource("2")
+}
+
+[sub_resource type="CircleShape2D" id="3"]
 radius = 5.0
 
 [node name="Coin" type="Area2D"]
 collision_layer = 0
-monitoring = false
-monitorable = false
-script = ExtResource( 4 )
+script = ExtResource("4")
 
 [node name="Sprite2D" type="Sprite2D" parent="."]
-texture = ExtResource( 2 )
+texture = ExtResource("2")
 hframes = 4
 
 [node name="AnimationPlayer" type="AnimationPlayer" parent="."]
 autoplay = "spinning"
-playback_speed = 1.5
-anims/picked = SubResource( 1 )
-anims/spinning = SubResource( 2 )
+libraries = {
+"": SubResource("AnimationLibrary_fwb0h")
+}
 
 [node name="CollisionShape2D" type="CollisionShape2D" parent="."]
-shape = SubResource( 3 )
+shape = SubResource("3")
 
 [node name="Pickup" type="AudioStreamPlayer2D" parent="."]
-stream = ExtResource( 3 )
 
 [connection signal="body_entered" from="." to="." method="_on_body_entered"]

BIN
2d/platformer/level/coin.webp


+ 4 - 4
2d/platformer/assets/art/coin/coin.png.import → 2d/platformer/level/coin.webp.import

@@ -3,22 +3,22 @@
 importer="texture"
 type="CompressedTexture2D"
 uid="uid://l42us5qso8v4"
-path="res://.godot/imported/coin.png-87689993f83db6056500d4fa153313d8.ctex"
+path="res://.godot/imported/coin.webp-1d50c095672512acb2df6e9dbf7e85c6.ctex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://assets/art/coin/coin.png"
-dest_files=["res://.godot/imported/coin.png-87689993f83db6056500d4fa153313d8.ctex"]
+source_file="res://level/coin.webp"
+dest_files=["res://.godot/imported/coin.webp-1d50c095672512acb2df6e9dbf7e85c6.ctex"]
 
 [params]
 
 compress/mode=0
+compress/high_quality=false
 compress/lossy_quality=0.7
 compress/hdr_compression=1
-compress/bptc_ldr=0
 compress/normal_map=0
 compress/channel_pack=0
 mipmaps/generate=false

BIN
2d/platformer/level/distant_platforms_1.webp


+ 4 - 4
2d/platformer/assets/art/background/distant_platforms_1.png.import → 2d/platformer/level/distant_platforms_1.webp.import

@@ -3,22 +3,22 @@
 importer="texture"
 type="CompressedTexture2D"
 uid="uid://smxp1wviat8"
-path="res://.godot/imported/distant_platforms_1.png-7286fe6c8587b96abbbe0bc4a8cbc510.ctex"
+path="res://.godot/imported/distant_platforms_1.webp-3e434db11cd91084f2225ce02ba95102.ctex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://assets/art/background/distant_platforms_1.png"
-dest_files=["res://.godot/imported/distant_platforms_1.png-7286fe6c8587b96abbbe0bc4a8cbc510.ctex"]
+source_file="res://level/distant_platforms_1.webp"
+dest_files=["res://.godot/imported/distant_platforms_1.webp-3e434db11cd91084f2225ce02ba95102.ctex"]
 
 [params]
 
 compress/mode=0
+compress/high_quality=false
 compress/lossy_quality=0.7
 compress/hdr_compression=1
-compress/bptc_ldr=0
 compress/normal_map=0
 compress/channel_pack=0
 mipmaps/generate=false

BIN
2d/platformer/level/distant_platforms_2.webp


+ 4 - 4
2d/platformer/assets/art/background/distant_platforms_2.png.import → 2d/platformer/level/distant_platforms_2.webp.import

@@ -3,22 +3,22 @@
 importer="texture"
 type="CompressedTexture2D"
 uid="uid://d003shl6ntver"
-path="res://.godot/imported/distant_platforms_2.png-ba010b30987da6d74062ce964ab450ef.ctex"
+path="res://.godot/imported/distant_platforms_2.webp-cfb64fd24d51633ea9b69670abc2c765.ctex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://assets/art/background/distant_platforms_2.png"
-dest_files=["res://.godot/imported/distant_platforms_2.png-ba010b30987da6d74062ce964ab450ef.ctex"]
+source_file="res://level/distant_platforms_2.webp"
+dest_files=["res://.godot/imported/distant_platforms_2.webp-cfb64fd24d51633ea9b69670abc2c765.ctex"]
 
 [params]
 
 compress/mode=0
+compress/high_quality=false
 compress/lossy_quality=0.7
 compress/hdr_compression=1
-compress/bptc_ldr=0
 compress/normal_map=0
 compress/channel_pack=0
 mipmaps/generate=false

File diff suppressed because it is too large
+ 61 - 0
2d/platformer/level/level.tscn


BIN
2d/platformer/level/moving_platform.webp


+ 4 - 4
2d/platformer/assets/art/platforms/moving_platform.png.import → 2d/platformer/level/moving_platform.webp.import

@@ -3,22 +3,22 @@
 importer="texture"
 type="CompressedTexture2D"
 uid="uid://8p65ui1ydnff"
-path="res://.godot/imported/moving_platform.png-479aa8f802d1a4964b138893ada8d372.ctex"
+path="res://.godot/imported/moving_platform.webp-dd4a79a18c99da84f4c06de09878b0a4.ctex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://assets/art/platforms/moving_platform.png"
-dest_files=["res://.godot/imported/moving_platform.png-479aa8f802d1a4964b138893ada8d372.ctex"]
+source_file="res://level/moving_platform.webp"
+dest_files=["res://.godot/imported/moving_platform.webp-dd4a79a18c99da84f4c06de09878b0a4.ctex"]
 
 [params]
 
 compress/mode=0
+compress/high_quality=false
 compress/lossy_quality=0.7
 compress/hdr_compression=1
-compress/bptc_ldr=0
 compress/normal_map=0
 compress/channel_pack=0
 mipmaps/generate=false

+ 4 - 4
2d/platformer/assets/art/platforms/one_way_platform.png.import → 2d/platformer/level/one_way_platform.import

@@ -3,22 +3,22 @@
 importer="texture"
 type="CompressedTexture2D"
 uid="uid://dpdd5ioofxcur"
-path="res://.godot/imported/one_way_platform.png-aaf0179c7171228f27cb489e99e339bd.ctex"
+path="res://.godot/imported/one_way_platform.png-ff82db5f4cf9bbd816ae5115d1b41cf7.ctex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://assets/art/platforms/one_way_platform.png"
-dest_files=["res://.godot/imported/one_way_platform.png-aaf0179c7171228f27cb489e99e339bd.ctex"]
+source_file="res://level/one_way_platform.png"
+dest_files=["res://.godot/imported/one_way_platform.png-ff82db5f4cf9bbd816ae5115d1b41cf7.ctex"]
 
 [params]
 
 compress/mode=0
+compress/high_quality=false
 compress/lossy_quality=0.7
 compress/hdr_compression=1
-compress/bptc_ldr=0
 compress/normal_map=0
 compress/channel_pack=0
 mipmaps/generate=false

BIN
2d/platformer/level/one_way_platform.webp


+ 34 - 0
2d/platformer/level/one_way_platform.webp.import

@@ -0,0 +1,34 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://db21c324q8p5n"
+path="res://.godot/imported/one_way_platform.webp-184fac31b4e1b4bd4c4e6085ce99357a.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://level/one_way_platform.webp"
+dest_files=["res://.godot/imported/one_way_platform.webp-184fac31b4e1b4bd4c4e6085ce99357a.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1

+ 38 - 34
2d/platformer/src/Level/ParallaxBackground.tscn → 2d/platformer/level/parallax_background.tscn

@@ -1,11 +1,11 @@
-[gd_scene load_steps=7 format=2]
+[gd_scene load_steps=7 format=3 uid="uid://bkyw3e13rupar"]
 
-[ext_resource path="res://assets/art/background/distant_platforms_2.png" type="Texture2D" id=1]
-[ext_resource path="res://assets/art/background/sky.png" type="Texture2D" id=2]
-[ext_resource path="res://assets/art/background/cloud_1.png" type="Texture2D" id=3]
-[ext_resource path="res://assets/art/background/cloud_2.png" type="Texture2D" id=4]
-[ext_resource path="res://assets/art/background/cloud_3.png" type="Texture2D" id=5]
-[ext_resource path="res://assets/art/background/distant_platforms_1.png" type="Texture2D" id=6]
+[ext_resource type="Texture2D" uid="uid://d003shl6ntver" path="res://level/distant_platforms_2.webp" id="1"]
+[ext_resource type="Texture2D" uid="uid://cnxf4hsvrcgka" path="res://level/sky.webp" id="2"]
+[ext_resource type="Texture2D" uid="uid://b4n7s65t0qoep" path="res://level/cloud_1.webp" id="3"]
+[ext_resource type="Texture2D" uid="uid://cubkvnu4fdwki" path="res://level/cloud_2.webp" id="4"]
+[ext_resource type="Texture2D" uid="uid://5tho6j8r4eam" path="res://level/cloud_3.webp" id="5"]
+[ext_resource type="Texture2D" uid="uid://smxp1wviat8" path="res://level/distant_platforms_1.webp" id="6"]
 
 [node name="ParallaxBackground" type="ParallaxBackground"]
 scroll_base_scale = Vector2(0.4, 0)
@@ -15,7 +15,7 @@ motion_mirroring = Vector2(400, 0)
 
 [node name="Sprite2D" type="Sprite2D" parent="Sky"]
 scale = Vector2(64, 0.94)
-texture = ExtResource( 2 )
+texture = ExtResource("2")
 centered = false
 
 [node name="Clouds" type="ParallaxLayer" parent="."]
@@ -27,64 +27,64 @@ position = Vector2(-780, 0)
 
 [node name="Sprite1" type="Sprite2D" parent="Clouds/CloudGroup1"]
 position = Vector2(-200, 120)
-texture = ExtResource( 3 )
+texture = ExtResource("3")
 centered = false
 
 [node name="Sprite2" type="Sprite2D" parent="Clouds/CloudGroup1"]
 position = Vector2(100, 10)
-texture = ExtResource( 3 )
+texture = ExtResource("3")
 centered = false
 
 [node name="Sprite3" type="Sprite2D" parent="Clouds/CloudGroup1"]
 position = Vector2(-60, 40)
-texture = ExtResource( 4 )
+texture = ExtResource("4")
 centered = false
 
 [node name="Sprite4" type="Sprite2D" parent="Clouds/CloudGroup1"]
 position = Vector2(150, 65)
-texture = ExtResource( 4 )
+texture = ExtResource("4")
 centered = false
 
 [node name="Sprite5" type="Sprite2D" parent="Clouds/CloudGroup1"]
 position = Vector2(15, 75)
-texture = ExtResource( 5 )
+texture = ExtResource("5")
 centered = false
 
 [node name="Sprite6" type="Sprite2D" parent="Clouds/CloudGroup1"]
 position = Vector2(225, 35)
-texture = ExtResource( 5 )
+texture = ExtResource("5")
 centered = false
 
 [node name="CloudGroup2" type="Node2D" parent="Clouds"]
 
 [node name="Sprite1" type="Sprite2D" parent="Clouds/CloudGroup2"]
 position = Vector2(-200, 120)
-texture = ExtResource( 3 )
+texture = ExtResource("3")
 centered = false
 
 [node name="Sprite2" type="Sprite2D" parent="Clouds/CloudGroup2"]
 position = Vector2(100, 10)
-texture = ExtResource( 3 )
+texture = ExtResource("3")
 centered = false
 
 [node name="Sprite3" type="Sprite2D" parent="Clouds/CloudGroup2"]
 position = Vector2(-60, 40)
-texture = ExtResource( 4 )
+texture = ExtResource("4")
 centered = false
 
 [node name="Sprite4" type="Sprite2D" parent="Clouds/CloudGroup2"]
 position = Vector2(150, 65)
-texture = ExtResource( 4 )
+texture = ExtResource("4")
 centered = false
 
 [node name="Sprite5" type="Sprite2D" parent="Clouds/CloudGroup2"]
 position = Vector2(15, 75)
-texture = ExtResource( 5 )
+texture = ExtResource("5")
 centered = false
 
 [node name="Sprite6" type="Sprite2D" parent="Clouds/CloudGroup2"]
 position = Vector2(225, 35)
-texture = ExtResource( 5 )
+texture = ExtResource("5")
 centered = false
 
 [node name="CloudGroup3" type="Node2D" parent="Clouds"]
@@ -92,32 +92,32 @@ position = Vector2(390, 0)
 
 [node name="Sprite1" type="Sprite2D" parent="Clouds/CloudGroup3"]
 position = Vector2(-200, 120)
-texture = ExtResource( 3 )
+texture = ExtResource("3")
 centered = false
 
 [node name="Sprite2" type="Sprite2D" parent="Clouds/CloudGroup3"]
 position = Vector2(100, 10)
-texture = ExtResource( 3 )
+texture = ExtResource("3")
 centered = false
 
 [node name="Sprite3" type="Sprite2D" parent="Clouds/CloudGroup3"]
 position = Vector2(-60, 40)
-texture = ExtResource( 4 )
+texture = ExtResource("4")
 centered = false
 
 [node name="Sprite4" type="Sprite2D" parent="Clouds/CloudGroup3"]
 position = Vector2(150, 65)
-texture = ExtResource( 4 )
+texture = ExtResource("4")
 centered = false
 
 [node name="Sprite5" type="Sprite2D" parent="Clouds/CloudGroup3"]
 position = Vector2(15, 75)
-texture = ExtResource( 5 )
+texture = ExtResource("5")
 centered = false
 
 [node name="Sprite6" type="Sprite2D" parent="Clouds/CloudGroup3"]
 position = Vector2(225, 35)
-texture = ExtResource( 5 )
+texture = ExtResource("5")
 centered = false
 
 [node name="CloudGroup4" type="Node2D" parent="Clouds"]
@@ -125,32 +125,32 @@ position = Vector2(780, 0)
 
 [node name="Sprite1" type="Sprite2D" parent="Clouds/CloudGroup4"]
 position = Vector2(-200, 120)
-texture = ExtResource( 3 )
+texture = ExtResource("3")
 centered = false
 
 [node name="Sprite2" type="Sprite2D" parent="Clouds/CloudGroup4"]
 position = Vector2(100, 10)
-texture = ExtResource( 3 )
+texture = ExtResource("3")
 centered = false
 
 [node name="Sprite3" type="Sprite2D" parent="Clouds/CloudGroup4"]
 position = Vector2(-60, 40)
-texture = ExtResource( 4 )
+texture = ExtResource("4")
 centered = false
 
 [node name="Sprite4" type="Sprite2D" parent="Clouds/CloudGroup4"]
 position = Vector2(150, 65)
-texture = ExtResource( 4 )
+texture = ExtResource("4")
 centered = false
 
 [node name="Sprite5" type="Sprite2D" parent="Clouds/CloudGroup4"]
 position = Vector2(15, 75)
-texture = ExtResource( 5 )
+texture = ExtResource("5")
 centered = false
 
 [node name="Sprite6" type="Sprite2D" parent="Clouds/CloudGroup4"]
 position = Vector2(225, 35)
-texture = ExtResource( 5 )
+texture = ExtResource("5")
 centered = false
 
 [node name="Mountains2" type="ParallaxLayer" parent="."]
@@ -159,7 +159,9 @@ motion_scale = Vector2(0.2, 1)
 
 [node name="Sprite2D" type="Sprite2D" parent="Mountains2"]
 position = Vector2(0, -64)
-texture = ExtResource( 1 )
+texture = ExtResource("1")
+centered = false
+offset = Vector2(0, -64)
 region_enabled = true
 region_rect = Rect2(0, 0, 2048, 128)
 
@@ -169,6 +171,8 @@ motion_scale = Vector2(0.4, 1)
 
 [node name="Sprite2D" type="Sprite2D" parent="Mountains1"]
 position = Vector2(0, -64)
-texture = ExtResource( 6 )
+texture = ExtResource("6")
+centered = false
+offset = Vector2(0, -64)
 region_enabled = true
 region_rect = Rect2(0, 0, 2048, 128)

+ 19 - 0
2d/platformer/level/platform.tscn

@@ -0,0 +1,19 @@
+[gd_scene load_steps=3 format=3 uid="uid://bfylfwu4pwywv"]
+
+[ext_resource type="Texture2D" uid="uid://8p65ui1ydnff" path="res://level/moving_platform.webp" id="2"]
+
+[sub_resource type="RectangleShape2D" id="1"]
+size = Vector2(94, 12)
+
+[node name="Platform" type="CharacterBody2D"]
+z_index = -1
+collision_layer = 8
+collision_mask = 0
+
+[node name="Sprite2D" type="Sprite2D" parent="."]
+texture = ExtResource("2")
+
+[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
+position = Vector2(0, -4)
+shape = SubResource("1")
+one_way_collision = true

BIN
2d/platformer/level/sky.webp


+ 4 - 4
2d/platformer/assets/art/background/sky.png.import → 2d/platformer/level/sky.webp.import

@@ -3,22 +3,22 @@
 importer="texture"
 type="CompressedTexture2D"
 uid="uid://cnxf4hsvrcgka"
-path="res://.godot/imported/sky.png-c175b712c46edc17f2b5fc55b9de3c49.ctex"
+path="res://.godot/imported/sky.webp-378e3d4469ee1943579600be36d5a9f5.ctex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://assets/art/background/sky.png"
-dest_files=["res://.godot/imported/sky.png-c175b712c46edc17f2b5fc55b9de3c49.ctex"]
+source_file="res://level/sky.webp"
+dest_files=["res://.godot/imported/sky.webp-378e3d4469ee1943579600be36d5a9f5.ctex"]
 
 [params]
 
 compress/mode=0
+compress/high_quality=false
 compress/lossy_quality=0.7
 compress/hdr_compression=1
-compress/bptc_ldr=0
 compress/normal_map=0
 compress/channel_pack=0
 mipmaps/generate=false

BIN
2d/platformer/level/tiles.webp


+ 4 - 4
2d/platformer/assets/art/tileset/tiles_demo.png.import → 2d/platformer/level/tiles.webp.import

@@ -3,22 +3,22 @@
 importer="texture"
 type="CompressedTexture2D"
 uid="uid://c1hixfwf86y2q"
-path="res://.godot/imported/tiles_demo.png-f720a7de2b60b01f690cfa3cb881996b.ctex"
+path="res://.godot/imported/tiles.webp-4f56cd8ea452f8ba920d65a0b9099010.ctex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://assets/art/tileset/tiles_demo.png"
-dest_files=["res://.godot/imported/tiles_demo.png-f720a7de2b60b01f690cfa3cb881996b.ctex"]
+source_file="res://level/tiles.webp"
+dest_files=["res://.godot/imported/tiles.webp-4f56cd8ea452f8ba920d65a0b9099010.ctex"]
 
 [params]
 
 compress/mode=0
+compress/high_quality=false
 compress/lossy_quality=0.7
 compress/hdr_compression=1
-compress/bptc_ldr=0
 compress/normal_map=0
 compress/channel_pack=0
 mipmaps/generate=false

+ 729 - 0
2d/platformer/level/tileset.tres

@@ -0,0 +1,729 @@
+[gd_resource type="TileSet" load_steps=17 format=3 uid="uid://dmpguegs1kkkl"]
+
+[ext_resource type="Texture2D" uid="uid://c1hixfwf86y2q" path="res://level/tiles.webp" id="1"]
+
+[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_24d4o"]
+texture = ExtResource("1")
+texture_region_size = Vector2i(32, 32)
+0:0/next_alternative_id = 8
+0:0/0 = 0
+0:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/0/physics_layer_0/angular_velocity = 0.0
+0:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -10, 16, -10, 16, 16, -16, 16)
+0:0/1 = 1
+0:0/1/flip_h = true
+0:0/1/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/1/physics_layer_0/angular_velocity = 0.0
+0:0/1/physics_layer_0/polygon_0/points = PackedVector2Array(16, -10, -16, -10, -16, 16, 16, 16)
+0:0/2 = 2
+0:0/2/flip_v = true
+0:0/2/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/2/physics_layer_0/angular_velocity = 0.0
+0:0/2/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 10, 16, 10, 16, -16, -16, -16)
+0:0/3 = 3
+0:0/3/flip_h = true
+0:0/3/flip_v = true
+0:0/3/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/3/physics_layer_0/angular_velocity = 0.0
+0:0/3/physics_layer_0/polygon_0/points = PackedVector2Array(16, 10, -16, 10, -16, -16, 16, -16)
+0:0/4 = 4
+0:0/4/transpose = true
+0:0/4/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/4/physics_layer_0/angular_velocity = 0.0
+0:0/4/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -10, 16, -10, 16, 16, -16, 16)
+0:0/5 = 5
+0:0/5/flip_h = true
+0:0/5/transpose = true
+0:0/5/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/5/physics_layer_0/angular_velocity = 0.0
+0:0/5/physics_layer_0/polygon_0/points = PackedVector2Array(16, -10, -16, -10, -16, 16, 16, 16)
+0:0/6 = 6
+0:0/6/flip_v = true
+0:0/6/transpose = true
+0:0/6/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/6/physics_layer_0/angular_velocity = 0.0
+0:0/6/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 10, 16, 10, 16, -16, -16, -16)
+0:0/7 = 7
+0:0/7/flip_h = true
+0:0/7/flip_v = true
+0:0/7/transpose = true
+0:0/7/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/7/physics_layer_0/angular_velocity = 0.0
+0:0/7/physics_layer_0/polygon_0/points = PackedVector2Array(16, 10, -16, 10, -16, -16, 16, -16)
+
+[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_opo1u"]
+texture = ExtResource("1")
+margins = Vector2i(32, 0)
+texture_region_size = Vector2i(32, 32)
+0:0/next_alternative_id = 8
+0:0/0 = 0
+0:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/0/physics_layer_0/angular_velocity = 0.0
+0:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -10, 12, -10, 12, 16, -16, 16)
+0:0/1 = 1
+0:0/1/flip_h = true
+0:0/1/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/1/physics_layer_0/angular_velocity = 0.0
+0:0/1/physics_layer_0/polygon_0/points = PackedVector2Array(16, -10, -12, -10, -12, 16, 16, 16)
+0:0/2 = 2
+0:0/2/flip_v = true
+0:0/2/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/2/physics_layer_0/angular_velocity = 0.0
+0:0/2/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 10, 12, 10, 12, -16, -16, -16)
+0:0/3 = 3
+0:0/3/flip_h = true
+0:0/3/flip_v = true
+0:0/3/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/3/physics_layer_0/angular_velocity = 0.0
+0:0/3/physics_layer_0/polygon_0/points = PackedVector2Array(16, 10, -12, 10, -12, -16, 16, -16)
+0:0/4 = 4
+0:0/4/transpose = true
+0:0/4/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/4/physics_layer_0/angular_velocity = 0.0
+0:0/4/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -10, 12, -10, 12, 16, -16, 16)
+0:0/5 = 5
+0:0/5/flip_h = true
+0:0/5/transpose = true
+0:0/5/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/5/physics_layer_0/angular_velocity = 0.0
+0:0/5/physics_layer_0/polygon_0/points = PackedVector2Array(16, -10, -12, -10, -12, 16, 16, 16)
+0:0/6 = 6
+0:0/6/flip_v = true
+0:0/6/transpose = true
+0:0/6/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/6/physics_layer_0/angular_velocity = 0.0
+0:0/6/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 10, 12, 10, 12, -16, -16, -16)
+0:0/7 = 7
+0:0/7/flip_h = true
+0:0/7/flip_v = true
+0:0/7/transpose = true
+0:0/7/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/7/physics_layer_0/angular_velocity = 0.0
+0:0/7/physics_layer_0/polygon_0/points = PackedVector2Array(16, 10, -12, 10, -12, -16, 16, -16)
+
+[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_val0e"]
+texture = ExtResource("1")
+margins = Vector2i(160, 32)
+texture_region_size = Vector2i(32, 32)
+0:0/next_alternative_id = 8
+0:0/0 = 0
+0:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/0/physics_layer_0/angular_velocity = 0.0
+0:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16)
+0:0/1 = 1
+0:0/1/flip_h = true
+0:0/1/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/1/physics_layer_0/angular_velocity = 0.0
+0:0/1/physics_layer_0/polygon_0/points = PackedVector2Array(16, -16, -16, -16, -16, 16, 16, 16)
+0:0/2 = 2
+0:0/2/flip_v = true
+0:0/2/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/2/physics_layer_0/angular_velocity = 0.0
+0:0/2/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 16, 16, 16, 16, -16, -16, -16)
+0:0/3 = 3
+0:0/3/flip_h = true
+0:0/3/flip_v = true
+0:0/3/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/3/physics_layer_0/angular_velocity = 0.0
+0:0/3/physics_layer_0/polygon_0/points = PackedVector2Array(16, 16, -16, 16, -16, -16, 16, -16)
+0:0/4 = 4
+0:0/4/transpose = true
+0:0/4/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/4/physics_layer_0/angular_velocity = 0.0
+0:0/4/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16)
+0:0/5 = 5
+0:0/5/flip_h = true
+0:0/5/transpose = true
+0:0/5/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/5/physics_layer_0/angular_velocity = 0.0
+0:0/5/physics_layer_0/polygon_0/points = PackedVector2Array(16, -16, -16, -16, -16, 16, 16, 16)
+0:0/6 = 6
+0:0/6/flip_v = true
+0:0/6/transpose = true
+0:0/6/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/6/physics_layer_0/angular_velocity = 0.0
+0:0/6/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 16, 16, 16, 16, -16, -16, -16)
+0:0/7 = 7
+0:0/7/flip_h = true
+0:0/7/flip_v = true
+0:0/7/transpose = true
+0:0/7/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/7/physics_layer_0/angular_velocity = 0.0
+0:0/7/physics_layer_0/polygon_0/points = PackedVector2Array(16, 16, -16, 16, -16, -16, 16, -16)
+
+[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_vw3dp"]
+texture = ExtResource("1")
+margins = Vector2i(128, 64)
+texture_region_size = Vector2i(32, 32)
+0:0/next_alternative_id = 8
+0:0/0 = 0
+0:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/0/physics_layer_0/angular_velocity = 0.0
+0:0/1 = 1
+0:0/1/flip_h = true
+0:0/1/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/1/physics_layer_0/angular_velocity = 0.0
+0:0/2 = 2
+0:0/2/flip_v = true
+0:0/2/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/2/physics_layer_0/angular_velocity = 0.0
+0:0/3 = 3
+0:0/3/flip_h = true
+0:0/3/flip_v = true
+0:0/3/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/3/physics_layer_0/angular_velocity = 0.0
+0:0/4 = 4
+0:0/4/transpose = true
+0:0/4/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/4/physics_layer_0/angular_velocity = 0.0
+0:0/5 = 5
+0:0/5/flip_h = true
+0:0/5/transpose = true
+0:0/5/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/5/physics_layer_0/angular_velocity = 0.0
+0:0/6 = 6
+0:0/6/flip_v = true
+0:0/6/transpose = true
+0:0/6/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/6/physics_layer_0/angular_velocity = 0.0
+0:0/7 = 7
+0:0/7/flip_h = true
+0:0/7/flip_v = true
+0:0/7/transpose = true
+0:0/7/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/7/physics_layer_0/angular_velocity = 0.0
+
+[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_ofvgn"]
+texture = ExtResource("1")
+margins = Vector2i(128, 32)
+texture_region_size = Vector2i(32, 32)
+0:0/next_alternative_id = 8
+0:0/0 = 0
+0:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/0/physics_layer_0/angular_velocity = 0.0
+0:0/1 = 1
+0:0/1/flip_h = true
+0:0/1/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/1/physics_layer_0/angular_velocity = 0.0
+0:0/2 = 2
+0:0/2/flip_v = true
+0:0/2/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/2/physics_layer_0/angular_velocity = 0.0
+0:0/3 = 3
+0:0/3/flip_h = true
+0:0/3/flip_v = true
+0:0/3/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/3/physics_layer_0/angular_velocity = 0.0
+0:0/4 = 4
+0:0/4/transpose = true
+0:0/4/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/4/physics_layer_0/angular_velocity = 0.0
+0:0/5 = 5
+0:0/5/flip_h = true
+0:0/5/transpose = true
+0:0/5/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/5/physics_layer_0/angular_velocity = 0.0
+0:0/6 = 6
+0:0/6/flip_v = true
+0:0/6/transpose = true
+0:0/6/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/6/physics_layer_0/angular_velocity = 0.0
+0:0/7 = 7
+0:0/7/flip_h = true
+0:0/7/flip_v = true
+0:0/7/transpose = true
+0:0/7/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/7/physics_layer_0/angular_velocity = 0.0
+
+[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_suguu"]
+texture = ExtResource("1")
+margins = Vector2i(128, 96)
+texture_region_size = Vector2i(32, 32)
+0:0/next_alternative_id = 8
+0:0/0 = 0
+0:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/0/physics_layer_0/angular_velocity = 0.0
+0:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -10, 16, -10, 16, 16, -16, 16)
+0:0/1 = 1
+0:0/1/flip_h = true
+0:0/1/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/1/physics_layer_0/angular_velocity = 0.0
+0:0/1/physics_layer_0/polygon_0/points = PackedVector2Array(16, -10, -16, -10, -16, 16, 16, 16)
+0:0/2 = 2
+0:0/2/flip_v = true
+0:0/2/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/2/physics_layer_0/angular_velocity = 0.0
+0:0/2/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 10, 16, 10, 16, -16, -16, -16)
+0:0/3 = 3
+0:0/3/flip_h = true
+0:0/3/flip_v = true
+0:0/3/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/3/physics_layer_0/angular_velocity = 0.0
+0:0/3/physics_layer_0/polygon_0/points = PackedVector2Array(16, 10, -16, 10, -16, -16, 16, -16)
+0:0/4 = 4
+0:0/4/transpose = true
+0:0/4/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/4/physics_layer_0/angular_velocity = 0.0
+0:0/4/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -10, 16, -10, 16, 16, -16, 16)
+0:0/5 = 5
+0:0/5/flip_h = true
+0:0/5/transpose = true
+0:0/5/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/5/physics_layer_0/angular_velocity = 0.0
+0:0/5/physics_layer_0/polygon_0/points = PackedVector2Array(16, -10, -16, -10, -16, 16, 16, 16)
+0:0/6 = 6
+0:0/6/flip_v = true
+0:0/6/transpose = true
+0:0/6/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/6/physics_layer_0/angular_velocity = 0.0
+0:0/6/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 10, 16, 10, 16, -16, -16, -16)
+0:0/7 = 7
+0:0/7/flip_h = true
+0:0/7/flip_v = true
+0:0/7/transpose = true
+0:0/7/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/7/physics_layer_0/angular_velocity = 0.0
+0:0/7/physics_layer_0/polygon_0/points = PackedVector2Array(16, 10, -16, 10, -16, -16, 16, -16)
+
+[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_erd6k"]
+texture = ExtResource("1")
+margins = Vector2i(128, 0)
+texture_region_size = Vector2i(32, 32)
+0:0/next_alternative_id = 8
+0:0/0 = 0
+0:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/0/physics_layer_0/angular_velocity = 0.0
+0:0/1 = 1
+0:0/1/flip_h = true
+0:0/1/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/1/physics_layer_0/angular_velocity = 0.0
+0:0/2 = 2
+0:0/2/flip_v = true
+0:0/2/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/2/physics_layer_0/angular_velocity = 0.0
+0:0/3 = 3
+0:0/3/flip_h = true
+0:0/3/flip_v = true
+0:0/3/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/3/physics_layer_0/angular_velocity = 0.0
+0:0/4 = 4
+0:0/4/transpose = true
+0:0/4/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/4/physics_layer_0/angular_velocity = 0.0
+0:0/5 = 5
+0:0/5/flip_h = true
+0:0/5/transpose = true
+0:0/5/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/5/physics_layer_0/angular_velocity = 0.0
+0:0/6 = 6
+0:0/6/flip_v = true
+0:0/6/transpose = true
+0:0/6/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/6/physics_layer_0/angular_velocity = 0.0
+0:0/7 = 7
+0:0/7/flip_h = true
+0:0/7/flip_v = true
+0:0/7/transpose = true
+0:0/7/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/7/physics_layer_0/angular_velocity = 0.0
+
+[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_l8f8l"]
+texture = ExtResource("1")
+margins = Vector2i(64, 32)
+texture_region_size = Vector2i(32, 96)
+0:0/next_alternative_id = 2
+0:0/0 = 0
+0:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/0/physics_layer_0/angular_velocity = 0.0
+0:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -10, 16, 22.5, 16, 48, -16, 48)
+0:0/1 = 1
+0:0/1/flip_h = true
+0:0/1/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/1/physics_layer_0/angular_velocity = 0.0
+0:0/1/physics_layer_0/polygon_0/points = PackedVector2Array(16, -10, -16, 22, -16, 48, 16, 48)
+
+[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_5pwh6"]
+texture = ExtResource("1")
+margins = Vector2i(32, 32)
+texture_region_size = Vector2i(32, 32)
+0:0/next_alternative_id = 8
+0:0/0 = 0
+0:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/0/physics_layer_0/angular_velocity = 0.0
+0:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 12, -16, 12, 16, -16, 16)
+0:0/1 = 1
+0:0/1/flip_h = true
+0:0/1/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/1/physics_layer_0/angular_velocity = 0.0
+0:0/1/physics_layer_0/polygon_0/points = PackedVector2Array(16, -16, -12, -16, -12, 16, 16, 16)
+0:0/2 = 2
+0:0/2/flip_v = true
+0:0/2/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/2/physics_layer_0/angular_velocity = 0.0
+0:0/2/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 16, 12, 16, 12, -16, -16, -16)
+0:0/3 = 3
+0:0/3/flip_h = true
+0:0/3/flip_v = true
+0:0/3/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/3/physics_layer_0/angular_velocity = 0.0
+0:0/3/physics_layer_0/polygon_0/points = PackedVector2Array(16, 16, -12, 16, -12, -16, 16, -16)
+0:0/4 = 4
+0:0/4/transpose = true
+0:0/4/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/4/physics_layer_0/angular_velocity = 0.0
+0:0/4/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 12, -16, 12, 16, -16, 16)
+0:0/5 = 5
+0:0/5/flip_h = true
+0:0/5/transpose = true
+0:0/5/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/5/physics_layer_0/angular_velocity = 0.0
+0:0/5/physics_layer_0/polygon_0/points = PackedVector2Array(16, -16, -12, -16, -12, 16, 16, 16)
+0:0/6 = 6
+0:0/6/flip_v = true
+0:0/6/transpose = true
+0:0/6/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/6/physics_layer_0/angular_velocity = 0.0
+0:0/6/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 16, 12, 16, 12, -16, -16, -16)
+0:0/7 = 7
+0:0/7/flip_h = true
+0:0/7/flip_v = true
+0:0/7/transpose = true
+0:0/7/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/7/physics_layer_0/angular_velocity = 0.0
+0:0/7/physics_layer_0/polygon_0/points = PackedVector2Array(16, 16, -12, 16, -12, -16, 16, -16)
+
+[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_seqgr"]
+texture = ExtResource("1")
+margins = Vector2i(32, 64)
+texture_region_size = Vector2i(32, 32)
+0:0/next_alternative_id = 8
+0:0/0 = 0
+0:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/0/physics_layer_0/angular_velocity = 0.0
+0:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(12, -10, 16, -10, 16, 16, -16, 16, -16, -16, 12, -16)
+0:0/1 = 1
+0:0/1/flip_h = true
+0:0/1/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/1/physics_layer_0/angular_velocity = 0.0
+0:0/1/physics_layer_0/polygon_0/points = PackedVector2Array(-12, -10, -16, -10, -16, 16, 16, 16, 16, -16, -12, -16)
+0:0/2 = 2
+0:0/2/flip_v = true
+0:0/2/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/2/physics_layer_0/angular_velocity = 0.0
+0:0/2/physics_layer_0/polygon_0/points = PackedVector2Array(12, 10, 16, 10, 16, -16, -16, -16, -16, 16, 12, 16)
+0:0/3 = 3
+0:0/3/flip_h = true
+0:0/3/flip_v = true
+0:0/3/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/3/physics_layer_0/angular_velocity = 0.0
+0:0/3/physics_layer_0/polygon_0/points = PackedVector2Array(-12, 10, -16, 10, -16, -16, 16, -16, 16, 16, -12, 16)
+0:0/4 = 4
+0:0/4/transpose = true
+0:0/4/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/4/physics_layer_0/angular_velocity = 0.0
+0:0/4/physics_layer_0/polygon_0/points = PackedVector2Array(12, -10, 16, -10, 16, 16, -16, 16, -16, -16, 12, -16)
+0:0/5 = 5
+0:0/5/flip_h = true
+0:0/5/transpose = true
+0:0/5/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/5/physics_layer_0/angular_velocity = 0.0
+0:0/5/physics_layer_0/polygon_0/points = PackedVector2Array(-12, -10, -16, -10, -16, 16, 16, 16, 16, -16, -12, -16)
+0:0/6 = 6
+0:0/6/flip_v = true
+0:0/6/transpose = true
+0:0/6/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/6/physics_layer_0/angular_velocity = 0.0
+0:0/6/physics_layer_0/polygon_0/points = PackedVector2Array(12, 10, 16, 10, 16, -16, -16, -16, -16, 16, 12, 16)
+0:0/7 = 7
+0:0/7/flip_h = true
+0:0/7/flip_v = true
+0:0/7/transpose = true
+0:0/7/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/7/physics_layer_0/angular_velocity = 0.0
+0:0/7/physics_layer_0/polygon_0/points = PackedVector2Array(-12, 10, -16, 10, -16, -16, 16, -16, 16, 16, -12, 16)
+
+[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_5an2c"]
+texture = ExtResource("1")
+margins = Vector2i(64, 0)
+texture_region_size = Vector2i(32, 32)
+0:0/next_alternative_id = 8
+0:0/0 = 0
+0:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/0/physics_layer_0/angular_velocity = 0.0
+0:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -10, 16, -10, 16, 16, -16, 16)
+0:0/0/physics_layer_0/polygon_0/one_way = true
+0:0/1 = 1
+0:0/1/flip_h = true
+0:0/1/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/1/physics_layer_0/angular_velocity = 0.0
+0:0/1/physics_layer_0/polygon_0/points = PackedVector2Array(16, -10, -16, -10, -16, 16, 16, 16)
+0:0/1/physics_layer_0/polygon_0/one_way = true
+0:0/2 = 2
+0:0/2/flip_v = true
+0:0/2/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/2/physics_layer_0/angular_velocity = 0.0
+0:0/2/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 10, 16, 10, 16, -16, -16, -16)
+0:0/2/physics_layer_0/polygon_0/one_way = true
+0:0/3 = 3
+0:0/3/flip_h = true
+0:0/3/flip_v = true
+0:0/3/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/3/physics_layer_0/angular_velocity = 0.0
+0:0/3/physics_layer_0/polygon_0/points = PackedVector2Array(16, 10, -16, 10, -16, -16, 16, -16)
+0:0/3/physics_layer_0/polygon_0/one_way = true
+0:0/4 = 4
+0:0/4/transpose = true
+0:0/4/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/4/physics_layer_0/angular_velocity = 0.0
+0:0/4/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -10, 16, -10, 16, 16, -16, 16)
+0:0/4/physics_layer_0/polygon_0/one_way = true
+0:0/5 = 5
+0:0/5/flip_h = true
+0:0/5/transpose = true
+0:0/5/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/5/physics_layer_0/angular_velocity = 0.0
+0:0/5/physics_layer_0/polygon_0/points = PackedVector2Array(16, -10, -16, -10, -16, 16, 16, 16)
+0:0/5/physics_layer_0/polygon_0/one_way = true
+0:0/6 = 6
+0:0/6/flip_v = true
+0:0/6/transpose = true
+0:0/6/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/6/physics_layer_0/angular_velocity = 0.0
+0:0/6/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 10, 16, 10, 16, -16, -16, -16)
+0:0/6/physics_layer_0/polygon_0/one_way = true
+0:0/7 = 7
+0:0/7/flip_h = true
+0:0/7/flip_v = true
+0:0/7/transpose = true
+0:0/7/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/7/physics_layer_0/angular_velocity = 0.0
+0:0/7/physics_layer_0/polygon_0/points = PackedVector2Array(16, 10, -16, 10, -16, -16, 16, -16)
+0:0/7/physics_layer_0/polygon_0/one_way = true
+
+[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_diy7l"]
+texture = ExtResource("1")
+margins = Vector2i(96, 0)
+texture_region_size = Vector2i(32, 32)
+0:0/next_alternative_id = 8
+0:0/0 = 0
+0:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/0/physics_layer_0/angular_velocity = 0.0
+0:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -10, 12, -10, 12, 16, -16, 16)
+0:0/0/physics_layer_0/polygon_0/one_way = true
+0:0/1 = 1
+0:0/1/flip_h = true
+0:0/1/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/1/physics_layer_0/angular_velocity = 0.0
+0:0/1/physics_layer_0/polygon_0/points = PackedVector2Array(16, -10, -12, -10, -12, 16, 16, 16)
+0:0/1/physics_layer_0/polygon_0/one_way = true
+0:0/2 = 2
+0:0/2/flip_v = true
+0:0/2/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/2/physics_layer_0/angular_velocity = 0.0
+0:0/2/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 10, 12, 10, 12, -16, -16, -16)
+0:0/2/physics_layer_0/polygon_0/one_way = true
+0:0/3 = 3
+0:0/3/flip_h = true
+0:0/3/flip_v = true
+0:0/3/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/3/physics_layer_0/angular_velocity = 0.0
+0:0/3/physics_layer_0/polygon_0/points = PackedVector2Array(16, 10, -12, 10, -12, -16, 16, -16)
+0:0/3/physics_layer_0/polygon_0/one_way = true
+0:0/4 = 4
+0:0/4/transpose = true
+0:0/4/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/4/physics_layer_0/angular_velocity = 0.0
+0:0/4/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -10, 12, -10, 12, 16, -16, 16)
+0:0/4/physics_layer_0/polygon_0/one_way = true
+0:0/5 = 5
+0:0/5/flip_h = true
+0:0/5/transpose = true
+0:0/5/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/5/physics_layer_0/angular_velocity = 0.0
+0:0/5/physics_layer_0/polygon_0/points = PackedVector2Array(16, -10, -12, -10, -12, 16, 16, 16)
+0:0/5/physics_layer_0/polygon_0/one_way = true
+0:0/6 = 6
+0:0/6/flip_v = true
+0:0/6/transpose = true
+0:0/6/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/6/physics_layer_0/angular_velocity = 0.0
+0:0/6/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 10, 12, 10, 12, -16, -16, -16)
+0:0/6/physics_layer_0/polygon_0/one_way = true
+0:0/7 = 7
+0:0/7/flip_h = true
+0:0/7/flip_v = true
+0:0/7/transpose = true
+0:0/7/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/7/physics_layer_0/angular_velocity = 0.0
+0:0/7/physics_layer_0/polygon_0/points = PackedVector2Array(16, 10, -12, 10, -12, -16, 16, -16)
+0:0/7/physics_layer_0/polygon_0/one_way = true
+
+[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_05unx"]
+texture = ExtResource("1")
+margins = Vector2i(0, 32)
+texture_region_size = Vector2i(32, 32)
+0:0/next_alternative_id = 8
+0:0/0 = 0
+0:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/0/physics_layer_0/angular_velocity = 0.0
+0:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16)
+0:0/1 = 1
+0:0/1/flip_h = true
+0:0/1/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/1/physics_layer_0/angular_velocity = 0.0
+0:0/1/physics_layer_0/polygon_0/points = PackedVector2Array(16, -16, -16, -16, -16, 16, 16, 16)
+0:0/2 = 2
+0:0/2/flip_v = true
+0:0/2/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/2/physics_layer_0/angular_velocity = 0.0
+0:0/2/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 16, 16, 16, 16, -16, -16, -16)
+0:0/3 = 3
+0:0/3/flip_h = true
+0:0/3/flip_v = true
+0:0/3/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/3/physics_layer_0/angular_velocity = 0.0
+0:0/3/physics_layer_0/polygon_0/points = PackedVector2Array(16, 16, -16, 16, -16, -16, 16, -16)
+0:0/4 = 4
+0:0/4/transpose = true
+0:0/4/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/4/physics_layer_0/angular_velocity = 0.0
+0:0/4/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16)
+0:0/5 = 5
+0:0/5/flip_h = true
+0:0/5/transpose = true
+0:0/5/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/5/physics_layer_0/angular_velocity = 0.0
+0:0/5/physics_layer_0/polygon_0/points = PackedVector2Array(16, -16, -16, -16, -16, 16, 16, 16)
+0:0/6 = 6
+0:0/6/flip_v = true
+0:0/6/transpose = true
+0:0/6/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/6/physics_layer_0/angular_velocity = 0.0
+0:0/6/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 16, 16, 16, 16, -16, -16, -16)
+0:0/7 = 7
+0:0/7/flip_h = true
+0:0/7/flip_v = true
+0:0/7/transpose = true
+0:0/7/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/7/physics_layer_0/angular_velocity = 0.0
+0:0/7/physics_layer_0/polygon_0/points = PackedVector2Array(16, 16, -16, 16, -16, -16, 16, -16)
+
+[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_ucjks"]
+texture = ExtResource("1")
+margins = Vector2i(192, 32)
+texture_region_size = Vector2i(32, 32)
+0:0/next_alternative_id = 8
+0:0/0 = 0
+0:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/0/physics_layer_0/angular_velocity = 0.0
+0:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 8, -16, 8)
+0:0/1 = 1
+0:0/1/flip_h = true
+0:0/1/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/1/physics_layer_0/angular_velocity = 0.0
+0:0/1/physics_layer_0/polygon_0/points = PackedVector2Array(16, -16, -16, -16, -16, 8, 16, 8)
+0:0/2 = 2
+0:0/2/flip_v = true
+0:0/2/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/2/physics_layer_0/angular_velocity = 0.0
+0:0/2/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 16, 16, 16, 16, -8, -16, -8)
+0:0/3 = 3
+0:0/3/flip_h = true
+0:0/3/flip_v = true
+0:0/3/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/3/physics_layer_0/angular_velocity = 0.0
+0:0/3/physics_layer_0/polygon_0/points = PackedVector2Array(16, 16, -16, 16, -16, -8, 16, -8)
+0:0/4 = 4
+0:0/4/transpose = true
+0:0/4/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/4/physics_layer_0/angular_velocity = 0.0
+0:0/4/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 8, -16, 8)
+0:0/5 = 5
+0:0/5/flip_h = true
+0:0/5/transpose = true
+0:0/5/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/5/physics_layer_0/angular_velocity = 0.0
+0:0/5/physics_layer_0/polygon_0/points = PackedVector2Array(16, -16, -16, -16, -16, 8, 16, 8)
+0:0/6 = 6
+0:0/6/flip_v = true
+0:0/6/transpose = true
+0:0/6/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/6/physics_layer_0/angular_velocity = 0.0
+0:0/6/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 16, 16, 16, 16, -8, -16, -8)
+0:0/7 = 7
+0:0/7/flip_h = true
+0:0/7/flip_v = true
+0:0/7/transpose = true
+0:0/7/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/7/physics_layer_0/angular_velocity = 0.0
+0:0/7/physics_layer_0/polygon_0/points = PackedVector2Array(16, 16, -16, 16, -16, -8, 16, -8)
+
+[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_dq2ee"]
+texture = ExtResource("1")
+margins = Vector2i(224, 32)
+texture_region_size = Vector2i(32, 32)
+0:0/next_alternative_id = 8
+0:0/0 = 0
+0:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/0/physics_layer_0/angular_velocity = 0.0
+0:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 12, -16, 12, 8, -16, 8)
+0:0/1 = 1
+0:0/1/flip_h = true
+0:0/1/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/1/physics_layer_0/angular_velocity = 0.0
+0:0/1/physics_layer_0/polygon_0/points = PackedVector2Array(16, -16, -12, -16, -12, 8, 16, 8)
+0:0/2 = 2
+0:0/2/flip_v = true
+0:0/2/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/2/physics_layer_0/angular_velocity = 0.0
+0:0/2/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 16, 12, 16, 12, -8, -16, -8)
+0:0/3 = 3
+0:0/3/flip_h = true
+0:0/3/flip_v = true
+0:0/3/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/3/physics_layer_0/angular_velocity = 0.0
+0:0/3/physics_layer_0/polygon_0/points = PackedVector2Array(16, 16, -12, 16, -12, -8, 16, -8)
+0:0/4 = 4
+0:0/4/transpose = true
+0:0/4/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/4/physics_layer_0/angular_velocity = 0.0
+0:0/4/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 12, -16, 12, 8, -16, 8)
+0:0/5 = 5
+0:0/5/flip_h = true
+0:0/5/transpose = true
+0:0/5/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/5/physics_layer_0/angular_velocity = 0.0
+0:0/5/physics_layer_0/polygon_0/points = PackedVector2Array(16, -16, -12, -16, -12, 8, 16, 8)
+0:0/6 = 6
+0:0/6/flip_v = true
+0:0/6/transpose = true
+0:0/6/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/6/physics_layer_0/angular_velocity = 0.0
+0:0/6/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 16, 12, 16, 12, -8, -16, -8)
+0:0/7 = 7
+0:0/7/flip_h = true
+0:0/7/flip_v = true
+0:0/7/transpose = true
+0:0/7/physics_layer_0/linear_velocity = Vector2(0, 0)
+0:0/7/physics_layer_0/angular_velocity = 0.0
+0:0/7/physics_layer_0/polygon_0/points = PackedVector2Array(16, 16, -12, 16, -12, -8, 16, -8)
+
+[resource]
+tile_size = Vector2i(32, 32)
+physics_layer_0/collision_layer = 16
+physics_layer_0/collision_mask = 0
+sources/0 = SubResource("TileSetAtlasSource_24d4o")
+sources/1 = SubResource("TileSetAtlasSource_opo1u")
+sources/2 = SubResource("TileSetAtlasSource_l8f8l")
+sources/3 = SubResource("TileSetAtlasSource_5pwh6")
+sources/4 = SubResource("TileSetAtlasSource_seqgr")
+sources/5 = SubResource("TileSetAtlasSource_5an2c")
+sources/6 = SubResource("TileSetAtlasSource_diy7l")
+sources/7 = SubResource("TileSetAtlasSource_05unx")
+sources/8 = SubResource("TileSetAtlasSource_ucjks")
+sources/9 = SubResource("TileSetAtlasSource_dq2ee")
+sources/10 = SubResource("TileSetAtlasSource_val0e")
+sources/11 = SubResource("TileSetAtlasSource_vw3dp")
+sources/12 = SubResource("TileSetAtlasSource_ofvgn")
+sources/13 = SubResource("TileSetAtlasSource_suguu")
+sources/14 = SubResource("TileSetAtlasSource_erd6k")

+ 0 - 0
2d/platformer/assets/audio/music/music.ogg → 2d/platformer/music.ogg


+ 19 - 0
2d/platformer/music.ogg.import

@@ -0,0 +1,19 @@
+[remap]
+
+importer="oggvorbisstr"
+type="AudioStreamOggVorbis"
+uid="uid://cx6hrmvjvhkt5"
+path="res://.godot/imported/music.ogg-3bd46d3a4b41702b152014078d12a390.oggvorbisstr"
+
+[deps]
+
+source_file="res://music.ogg"
+dest_files=["res://.godot/imported/music.ogg-3bd46d3a4b41702b152014078d12a390.oggvorbisstr"]
+
+[params]
+
+loop=true
+loop_offset=0
+bpm=0
+beat_count=0
+bar_beats=4

+ 8 - 0
2d/platformer/music.tscn

@@ -0,0 +1,8 @@
+[gd_scene load_steps=2 format=3 uid="uid://do7htx4sqmcnh"]
+
+[ext_resource type="AudioStream" uid="uid://cx6hrmvjvhkt5" path="res://music.ogg" id="1_8pjkj"]
+
+[node name="Music" type="AudioStreamPlayer"]
+process_mode = 1
+stream = ExtResource("1_8pjkj")
+autoplay = true

+ 13 - 0
2d/platformer/player/bullet.gd

@@ -0,0 +1,13 @@
+class_name Bullet extends RigidBody2D
+
+
+@onready var animation_player := $AnimationPlayer as AnimationPlayer
+
+
+func destroy() -> void:
+	animation_player.play(&"destroy")
+
+
+func _on_body_entered(body: Node) -> void:
+	if body is Enemy:
+		(body as Enemy).destroy()

+ 32 - 27
2d/platformer/src/Objects/Bullet.tscn → 2d/platformer/player/bullet.tscn

@@ -1,41 +1,41 @@
-[gd_scene load_steps=8 format=2]
+[gd_scene load_steps=9 format=3 uid="uid://bdeyraansvyga"]
 
-[ext_resource path="res://assets/art/player/bullet/bullet.png" type="Texture2D" id=1]
-[ext_resource path="res://src/Objects/Bullet.gd" type="Script" id=2]
+[ext_resource type="Script" path="res://player/bullet.gd" id="1_cokcn"]
+[ext_resource type="Texture2D" uid="uid://c2aisfmq85suf" path="res://player/bullet.webp" id="2_4bup8"]
 
-[sub_resource type="CanvasItemMaterial" id=1]
+[sub_resource type="CanvasItemMaterial" id="1"]
 
-[sub_resource type="CanvasItemMaterial" id=2]
+[sub_resource type="CanvasItemMaterial" id="2"]
 blend_mode = 1
 
-[sub_resource type="CanvasItemMaterial" id=3]
+[sub_resource type="CanvasItemMaterial" id="3"]
 
-[sub_resource type="CircleShape2D" id=4]
+[sub_resource type="CircleShape2D" id="4"]
 radius = 4.5
 
-[sub_resource type="Animation" id=5]
+[sub_resource type="Animation" id="5"]
 resource_name = "destroy"
 length = 0.3
 tracks/0/type = "method"
+tracks/0/imported = false
+tracks/0/enabled = true
 tracks/0/path = NodePath(".")
 tracks/0/interp = 1
 tracks/0/loop_wrap = true
-tracks/0/imported = false
-tracks/0/enabled = true
 tracks/0/keys = {
 "times": PackedFloat32Array(0.3),
 "transitions": PackedFloat32Array(1),
 "values": [{
 "args": [],
-"method": "queue_free"
+"method": &"queue_free"
 }]
 }
 tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
 tracks/1/path = NodePath("Sprite2D:self_modulate")
 tracks/1/interp = 1
 tracks/1/loop_wrap = true
-tracks/1/imported = false
-tracks/1/enabled = true
 tracks/1/keys = {
 "times": PackedFloat32Array(0, 0.3),
 "transitions": PackedFloat32Array(1, 1),
@@ -43,11 +43,11 @@ tracks/1/keys = {
 "values": [Color(1, 1, 1, 1), Color(1, 1, 1, 0)]
 }
 tracks/2/type = "value"
+tracks/2/imported = false
+tracks/2/enabled = true
 tracks/2/path = NodePath("GPUParticles2D:self_modulate")
 tracks/2/interp = 1
 tracks/2/loop_wrap = true
-tracks/2/imported = false
-tracks/2/enabled = true
 tracks/2/keys = {
 "times": PackedFloat32Array(0, 0.3),
 "transitions": PackedFloat32Array(1, 1),
@@ -55,40 +55,45 @@ tracks/2/keys = {
 "values": [Color(1, 1, 1, 1), Color(1, 1, 1, 0)]
 }
 
-[node name="Bullet" type="RigidDynamicBody2D"]
-material = SubResource( 1 )
+[sub_resource type="AnimationLibrary" id="AnimationLibrary_li3y6"]
+_data = {
+"destroy": SubResource("5")
+}
+
+[node name="Bullet" type="RigidBody2D"]
+material = SubResource("1")
 collision_layer = 0
 collision_mask = 26
 continuous_cd = 2
-contacts_reported = 1
+max_contacts_reported = 4
 contact_monitor = true
-script = ExtResource( 2 )
+script = ExtResource("1_cokcn")
 
 [node name="GPUParticles2D" type="CPUParticles2D" parent="."]
-material = SubResource( 2 )
+material = SubResource("2")
 emitting = false
 lifetime = 0.3
 speed_scale = 3.0
-local_coords = false
-texture = ExtResource( 1 )
+texture = ExtResource("2_4bup8")
 spread = 0.0
 gravity = Vector2(0, 0)
-scale_amount = 0.8
 color = Color(1, 1, 1, 0.705882)
 
 [node name="Sprite2D" type="Sprite2D" parent="."]
-material = SubResource( 3 )
-texture = ExtResource( 1 )
+material = SubResource("3")
+texture = ExtResource("2_4bup8")
 
 [node name="CollisionShape2D" type="CollisionShape2D" parent="."]
-shape = SubResource( 4 )
+shape = SubResource("4")
 
 [node name="Timer" type="Timer" parent="."]
 one_shot = true
 autostart = true
 
 [node name="AnimationPlayer" type="AnimationPlayer" parent="."]
-anims/destroy = SubResource( 5 )
+libraries = {
+"": SubResource("AnimationLibrary_li3y6")
+}
 
 [connection signal="body_entered" from="." to="." method="_on_body_entered"]
 [connection signal="timeout" from="Timer" to="." method="destroy"]

BIN
2d/platformer/player/bullet.webp


+ 4 - 4
2d/platformer/assets/art/player/bullet/bullet.png.import → 2d/platformer/player/bullet.webp.import

@@ -3,22 +3,22 @@
 importer="texture"
 type="CompressedTexture2D"
 uid="uid://c2aisfmq85suf"
-path="res://.godot/imported/bullet.png-a148438922f3743d5615622ef8134c9f.ctex"
+path="res://.godot/imported/bullet.webp-afcd8f50a20e81f25285b6f580e633e3.ctex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://assets/art/player/bullet/bullet.png"
-dest_files=["res://.godot/imported/bullet.png-a148438922f3743d5615622ef8134c9f.ctex"]
+source_file="res://player/bullet.webp"
+dest_files=["res://.godot/imported/bullet.webp-afcd8f50a20e81f25285b6f580e633e3.ctex"]
 
 [params]
 
 compress/mode=0
+compress/high_quality=false
 compress/lossy_quality=0.7
 compress/hdr_compression=1
-compress/bptc_ldr=0
 compress/normal_map=0
 compress/channel_pack=0
 mipmaps/generate=false

+ 0 - 0
2d/platformer/assets/audio/sfx/coin_pickup.wav → 2d/platformer/player/coin_pickup.wav


+ 3 - 3
2d/platformer/assets/audio/sfx/coin_pickup.wav.import → 2d/platformer/player/coin_pickup.wav.import

@@ -3,12 +3,12 @@
 importer="wav"
 type="AudioStreamWAV"
 uid="uid://bw67pgdlhpqd0"
-path="res://.godot/imported/coin_pickup.wav-69d455f3063e30fd994846647c281aea.sample"
+path="res://.godot/imported/coin_pickup.wav-cc06e43e2f58c4fe505090708655bec0.sample"
 
 [deps]
 
-source_file="res://assets/audio/sfx/coin_pickup.wav"
-dest_files=["res://.godot/imported/coin_pickup.wav-69d455f3063e30fd994846647c281aea.sample"]
+source_file="res://player/coin_pickup.wav"
+dest_files=["res://.godot/imported/coin_pickup.wav-cc06e43e2f58c4fe505090708655bec0.sample"]
 
 [params]
 

+ 25 - 0
2d/platformer/player/gun.gd

@@ -0,0 +1,25 @@
+class_name Gun extends Marker2D
+## Represents a weapon that spawns and shoots bullets.
+## The Cooldown timer controls the cooldown duration between shots.
+
+
+const BULLET_VELOCITY = 500.0
+const Bullet = preload("res://player/bullet.tscn")
+
+@onready var sound_shoot := $Shoot as AudioStreamPlayer2D
+@onready var timer := $Cooldown as Timer
+
+
+# This method is only called by Player.gd.
+func shoot(direction: float = 1.0) -> bool:
+	if not timer.is_stopped():
+		return false
+	var bullet := Bullet.instantiate() as Bullet
+	bullet.global_position = global_position
+	bullet.linear_velocity = Vector2(direction * BULLET_VELOCITY, 0.0)
+
+	bullet.set_as_top_level(true)
+	add_child(bullet)
+	sound_shoot.play()
+	timer.start()
+	return true

+ 0 - 0
2d/platformer/assets/audio/sfx/jump.wav → 2d/platformer/player/jump.wav


+ 3 - 3
2d/platformer/assets/audio/sfx/jump.wav.import → 2d/platformer/player/jump.wav.import

@@ -3,12 +3,12 @@
 importer="wav"
 type="AudioStreamWAV"
 uid="uid://i2vnokf2khqj"
-path="res://.godot/imported/jump.wav-127418ac4fc0b61a7fed0684053202c7.sample"
+path="res://.godot/imported/jump.wav-d94eb6ad27159bf77e7ba7ab65914fbd.sample"
 
 [deps]
 
-source_file="res://assets/audio/sfx/jump.wav"
-dest_files=["res://.godot/imported/jump.wav-127418ac4fc0b61a7fed0684053202c7.sample"]
+source_file="res://player/jump.wav"
+dest_files=["res://.godot/imported/jump.wav-d94eb6ad27159bf77e7ba7ab65914fbd.sample"]
 
 [params]
 

+ 88 - 0
2d/platformer/player/player.gd

@@ -0,0 +1,88 @@
+class_name Player extends CharacterBody2D
+
+
+signal coin_collected()
+
+const WALK_SPEED = 200.0
+const ACCELERATION_SPEED = WALK_SPEED * 6.0
+const JUMP_VELOCITY = -400.0
+## Maximum speed at which the player can fall.
+const TERMINAL_VELOCITY = 400
+
+## The player listens for input actions appended with this suffix.[br]
+## Used to separate controls for multiple players in splitscreen.
+@export var action_suffix := ""
+
+var gravity: int = ProjectSettings.get("physics/2d/default_gravity")
+@onready var platform_detector := $PlatformDetector as RayCast2D
+@onready var animation_player := $AnimationPlayer as AnimationPlayer
+@onready var shoot_timer := $ShootAnimation as Timer
+@onready var sprite := $Sprite2D as Sprite2D
+@onready var jump_sound := $Jump as AudioStreamPlayer2D
+@onready var gun = sprite.get_node(^"Gun") as Gun
+@onready var camera := $Camera as Camera2D
+var _double_jump_charged := false
+
+
+func _physics_process(delta: float) -> void:
+	if is_on_floor():
+		_double_jump_charged = true
+	if Input.is_action_just_pressed("jump" + action_suffix):
+		try_jump()
+	elif Input.is_action_just_released("jump" + action_suffix) and velocity.y < 0.0:
+		# The player let go of jump early, reduce vertical momentum.
+		velocity.y *= 0.6
+	# Fall.
+	velocity.y = minf(TERMINAL_VELOCITY, velocity.y + gravity * delta)
+
+	var direction := Input.get_axis("move_left" + action_suffix, "move_right" + action_suffix) * WALK_SPEED
+	velocity.x = move_toward(velocity.x, direction, ACCELERATION_SPEED * delta)
+
+	if not is_zero_approx(velocity.x):
+		if velocity.x > 0.0:
+			sprite.scale.x = 1.0
+		else:
+			sprite.scale.x = -1.0
+
+	floor_stop_on_slope = not platform_detector.is_colliding()
+	move_and_slide()
+
+	var is_shooting := false
+	if Input.is_action_just_pressed("shoot" + action_suffix):
+		is_shooting = gun.shoot(sprite.scale.x)
+
+	var animation := get_new_animation(is_shooting)
+	if animation != animation_player.current_animation and shoot_timer.is_stopped():
+		if is_shooting:
+			shoot_timer.start()
+		animation_player.play(animation)
+
+
+func get_new_animation(is_shooting := false) -> String:
+	var animation_new: String
+	if is_on_floor():
+		if absf(velocity.x) > 0.1:
+			animation_new = "run"
+		else:
+			animation_new = "idle"
+	else:
+		if velocity.y > 0.0:
+			animation_new = "falling"
+		else:
+			animation_new = "jumping"
+	if is_shooting:
+		animation_new += "_weapon"
+	return animation_new
+
+
+func try_jump() -> void:
+	if is_on_floor():
+		jump_sound.pitch_scale = 1.0
+	elif _double_jump_charged:
+		_double_jump_charged = false
+		velocity.x *= 2.5
+		jump_sound.pitch_scale = 1.5
+	else:
+		return
+	velocity.y = JUMP_VELOCITY
+	jump_sound.play()

+ 72 - 83
2d/platformer/src/Actors/Player.tscn → 2d/platformer/player/player.tscn

@@ -1,26 +1,21 @@
-[gd_scene load_steps=21 format=2]
+[gd_scene load_steps=18 format=3 uid="uid://d0ni64ucb3ym2"]
 
-[ext_resource path="res://src/Actors/Player.gd" type="Script" id=1]
-[ext_resource path="res://assets/art/player/robot_demo.png" type="Texture2D" id=2]
-[ext_resource path="res://assets/audio/sfx/jump.wav" type="AudioStream" id=3]
-[ext_resource path="res://assets/audio/sfx/shoot.wav" type="AudioStream" id=4]
-[ext_resource path="res://assets/art/ui/touch_button_left.png" type="Texture2D" id=5]
-[ext_resource path="res://assets/art/ui/touch_button_right.png" type="Texture2D" id=6]
-[ext_resource path="res://assets/art/ui/touch_button_jump.png" type="Texture2D" id=7]
-[ext_resource path="res://assets/art/ui/touch_button_fire.png" type="Texture2D" id=8]
-[ext_resource path="res://src/Actors/Gun.gd" type="Script" id=9]
+[ext_resource type="Script" path="res://player/player.gd" id="1"]
+[ext_resource type="Texture2D" uid="uid://go76jbr7e1px" path="res://player/player.webp" id="2"]
+[ext_resource type="AudioStream" uid="uid://i2vnokf2khqj" path="res://player/jump.wav" id="3"]
+[ext_resource type="AudioStream" uid="uid://bpxywy45eqgwy" path="res://player/shoot.wav" id="4"]
+[ext_resource type="Script" path="res://player/gun.gd" id="9"]
 
-[sub_resource type="Animation" id=1]
+[sub_resource type="Animation" id="1"]
 resource_name = "crouch"
 length = 0.01
-loop = true
 step = 0.25
 tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
 tracks/0/path = NodePath("Sprite2D:frame")
 tracks/0/interp = 1
 tracks/0/loop_wrap = true
-tracks/0/imported = false
-tracks/0/enabled = true
 tracks/0/keys = {
 "times": PackedFloat32Array(0),
 "transitions": PackedFloat32Array(1),
@@ -28,17 +23,16 @@ tracks/0/keys = {
 "values": [22]
 }
 
-[sub_resource type="Animation" id=2]
+[sub_resource type="Animation" id="2"]
 resource_name = "falling"
 length = 0.01
-loop = true
 step = 0.25
 tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
 tracks/0/path = NodePath("Sprite2D:frame")
 tracks/0/interp = 1
 tracks/0/loop_wrap = true
-tracks/0/imported = false
-tracks/0/enabled = true
 tracks/0/keys = {
 "times": PackedFloat32Array(0),
 "transitions": PackedFloat32Array(1),
@@ -46,17 +40,16 @@ tracks/0/keys = {
 "values": [21]
 }
 
-[sub_resource type="Animation" id=3]
+[sub_resource type="Animation" id="3"]
 resource_name = "falling_weapon"
 length = 0.5
-loop = true
 step = 0.25
 tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
 tracks/0/path = NodePath("Sprite2D:frame")
 tracks/0/interp = 1
 tracks/0/loop_wrap = true
-tracks/0/imported = false
-tracks/0/enabled = true
 tracks/0/keys = {
 "times": PackedFloat32Array(0),
 "transitions": PackedFloat32Array(1),
@@ -64,16 +57,15 @@ tracks/0/keys = {
 "values": [26]
 }
 
-[sub_resource type="Animation" id=4]
+[sub_resource type="Animation" id="4"]
 length = 7.0
-loop = true
 step = 0.25
 tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
 tracks/0/path = NodePath("Sprite2D:frame")
 tracks/0/interp = 1
 tracks/0/loop_wrap = true
-tracks/0/imported = false
-tracks/0/enabled = true
 tracks/0/keys = {
 "times": PackedFloat32Array(0, 1.25, 1.5, 2, 4.5, 4.75, 5, 5.25),
 "transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1, 1),
@@ -81,16 +73,15 @@ tracks/0/keys = {
 "values": [16, 17, 18, 16, 19, 20, 19, 16]
 }
 
-[sub_resource type="Animation" id=5]
+[sub_resource type="Animation" id="5"]
 length = 0.5
-loop = true
 step = 0.25
 tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
 tracks/0/path = NodePath("Sprite2D:frame")
 tracks/0/interp = 1
 tracks/0/loop_wrap = true
-tracks/0/imported = false
-tracks/0/enabled = true
 tracks/0/keys = {
 "times": PackedFloat32Array(0),
 "transitions": PackedFloat32Array(1),
@@ -98,16 +89,15 @@ tracks/0/keys = {
 "values": [25]
 }
 
-[sub_resource type="Animation" id=6]
+[sub_resource type="Animation" id="6"]
 length = 0.5
-loop = true
 step = 0.25
 tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
 tracks/0/path = NodePath("Sprite2D:frame")
 tracks/0/interp = 1
 tracks/0/loop_wrap = true
-tracks/0/imported = false
-tracks/0/enabled = true
 tracks/0/keys = {
 "times": PackedFloat32Array(0, 0.25, 0.5),
 "transitions": PackedFloat32Array(1, 1, 1),
@@ -115,16 +105,15 @@ tracks/0/keys = {
 "values": [23, 24, 23]
 }
 
-[sub_resource type="Animation" id=7]
+[sub_resource type="Animation" id="7"]
 length = 0.5
-loop = true
 step = 0.25
 tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
 tracks/0/path = NodePath("Sprite2D:frame")
 tracks/0/interp = 1
 tracks/0/loop_wrap = true
-tracks/0/imported = false
-tracks/0/enabled = true
 tracks/0/keys = {
 "times": PackedFloat32Array(0),
 "transitions": PackedFloat32Array(1),
@@ -132,16 +121,15 @@ tracks/0/keys = {
 "values": [26]
 }
 
-[sub_resource type="Animation" id=8]
+[sub_resource type="Animation" id="8"]
 length = 1.25
-loop = true
 step = 0.25
 tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
 tracks/0/path = NodePath("Sprite2D:frame")
 tracks/0/interp = 1
 tracks/0/loop_wrap = true
-tracks/0/imported = false
-tracks/0/enabled = true
 tracks/0/keys = {
 "times": PackedFloat32Array(0, 0.25, 0.5, 0.75, 1, 1.25),
 "transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1),
@@ -149,16 +137,15 @@ tracks/0/keys = {
 "values": [0, 1, 2, 3, 4, 0]
 }
 
-[sub_resource type="Animation" id=9]
+[sub_resource type="Animation" id="9"]
 length = 1.25
-loop = true
 step = 0.25
 tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
 tracks/0/path = NodePath("Sprite2D:frame")
 tracks/0/interp = 1
 tracks/0/loop_wrap = true
-tracks/0/imported = false
-tracks/0/enabled = true
 tracks/0/keys = {
 "times": PackedFloat32Array(0, 0.25, 0.5, 0.75, 1, 1.25),
 "transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1),
@@ -166,16 +153,15 @@ tracks/0/keys = {
 "values": [5, 6, 7, 8, 9, 5]
 }
 
-[sub_resource type="Animation" id=10]
+[sub_resource type="Animation" id="10"]
 length = 1.25
-loop = true
 step = 0.25
 tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
 tracks/0/path = NodePath("Sprite2D:frame")
 tracks/0/interp = 1
 tracks/0/loop_wrap = true
-tracks/0/imported = false
-tracks/0/enabled = true
 tracks/0/keys = {
 "times": PackedFloat32Array(0, 0.25, 0.5, 0.75, 1, 1.25),
 "transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1),
@@ -183,68 +169,75 @@ tracks/0/keys = {
 "values": [10, 11, 12, 13, 14, 5]
 }
 
-[sub_resource type="RectangleShape2D" id=11]
-extents = Vector2(10, 14)
+[sub_resource type="AnimationLibrary" id="AnimationLibrary_r678v"]
+_data = {
+"crouch": SubResource("1"),
+"falling": SubResource("2"),
+"falling_weapon": SubResource("3"),
+"idle": SubResource("4"),
+"idle_weapon": SubResource("5"),
+"jumping": SubResource("6"),
+"jumping_weapon": SubResource("7"),
+"run": SubResource("8"),
+"run_weapon": SubResource("9"),
+"standing_weapon_ready": SubResource("10")
+}
+
+[sub_resource type="RectangleShape2D" id="11"]
+size = Vector2(20, 28)
 
 [node name="Player" type="CharacterBody2D"]
-collision_mask = 30
-script = ExtResource( 1 )
+collision_mask = 28
+floor_max_angle = 0.907571
+floor_snap_length = 20.0
+safe_margin = 0.2
+script = ExtResource("1")
 
 [node name="ShootAnimation" type="Timer" parent="."]
-process_mode = 0
 wait_time = 0.2
 one_shot = true
 
 [node name="PlatformDetector" type="RayCast2D" parent="."]
-enabled = true
-cast_to = Vector2(0, 6)
 collision_mask = 8
 
 [node name="Sprite2D" type="Sprite2D" parent="."]
 position = Vector2(0, -14)
-texture = ExtResource( 2 )
+texture = ExtResource("2")
 hframes = 16
 vframes = 2
 frame = 16
 
-[node name="Gun" type="Position2D" parent="Sprite2D"]
+[node name="Gun" type="Marker2D" parent="Sprite2D"]
 position = Vector2(14, 1)
-script = ExtResource( 9 )
+script = ExtResource("9")
 
 [node name="Shoot" type="AudioStreamPlayer2D" parent="Sprite2D/Gun"]
 position = Vector2(-30.6589, -6.13176)
-stream = ExtResource( 4 )
+stream = ExtResource("4")
 
 [node name="Cooldown" type="Timer" parent="Sprite2D/Gun"]
-process_mode = 0
 wait_time = 0.3
 one_shot = true
 
 [node name="AnimationPlayer" type="AnimationPlayer" parent="."]
-playback_speed = 2.6
-anims/crouch = SubResource( 1 )
-anims/falling = SubResource( 2 )
-anims/falling_weapon = SubResource( 3 )
-anims/idle = SubResource( 4 )
-anims/idle_weapon = SubResource( 5 )
-anims/jumping = SubResource( 6 )
-anims/jumping_weapon = SubResource( 7 )
-anims/run = SubResource( 8 )
-anims/run_weapon = SubResource( 9 )
-anims/standing_weapon_ready = SubResource( 10 )
+libraries = {
+"": SubResource("AnimationLibrary_r678v")
+}
 
-[node name="Camera3D" type="Camera2D" parent="."]
+[node name="Camera" type="Camera2D" parent="."]
 position = Vector2(0, -28)
-current = true
-zoom = Vector2(0.5, 0.5)
-process_mode = 0
+zoom = Vector2(2, 2)
+limit_left = -315
+limit_top = -250
+limit_right = 955
+limit_bottom = 690
 
 [node name="CollisionShape2D" type="CollisionShape2D" parent="."]
 position = Vector2(0, -14)
-shape = SubResource( 11 )
+shape = SubResource("11")
 
 [node name="Jump" type="AudioStreamPlayer2D" parent="."]
-stream = ExtResource( 3 )
+stream = ExtResource("3")
 
 [node name="UI" type="CanvasLayer" parent="."]
 layer = 0
@@ -252,7 +245,6 @@ layer = 0
 [node name="Left" type="TouchScreenButton" parent="UI"]
 position = Vector2(27.7593, 360.87)
 scale = Vector2(1.49157, 1.46265)
-normal = ExtResource( 5 )
 passby_press = true
 action = "move_left"
 visibility_mode = 1
@@ -260,7 +252,6 @@ visibility_mode = 1
 [node name="Right" type="TouchScreenButton" parent="UI"]
 position = Vector2(121.542, 361.415)
 scale = Vector2(1.49157, 1.46265)
-normal = ExtResource( 6 )
 passby_press = true
 action = "move_right"
 visibility_mode = 1
@@ -268,13 +259,11 @@ visibility_mode = 1
 [node name="Jump" type="TouchScreenButton" parent="UI"]
 position = Vector2(666.224, 359.02)
 scale = Vector2(1.49157, 1.46265)
-normal = ExtResource( 7 )
 action = "jump"
 visibility_mode = 1
 
 [node name="Fire" type="TouchScreenButton" parent="UI"]
 position = Vector2(668.073, 262.788)
 scale = Vector2(1.49157, 1.46265)
-normal = ExtResource( 8 )
 action = "shoot"
 visibility_mode = 1

BIN
2d/platformer/player/player.webp


+ 4 - 4
2d/platformer/assets/art/player/robot_demo.png.import → 2d/platformer/player/player.webp.import

@@ -3,22 +3,22 @@
 importer="texture"
 type="CompressedTexture2D"
 uid="uid://go76jbr7e1px"
-path="res://.godot/imported/robot_demo.png-cd7cbcf6d0c47d4a233ea7ce93b142c2.ctex"
+path="res://.godot/imported/player.webp-f8efd9c2246a95708b9c4853ed21513e.ctex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://assets/art/player/robot_demo.png"
-dest_files=["res://.godot/imported/robot_demo.png-cd7cbcf6d0c47d4a233ea7ce93b142c2.ctex"]
+source_file="res://player/player.webp"
+dest_files=["res://.godot/imported/player.webp-f8efd9c2246a95708b9c4853ed21513e.ctex"]
 
 [params]
 
 compress/mode=0
+compress/high_quality=false
 compress/lossy_quality=0.7
 compress/hdr_compression=1
-compress/bptc_ldr=0
 compress/normal_map=0
 compress/channel_pack=0
 mipmaps/generate=false

+ 0 - 0
2d/platformer/assets/audio/sfx/shoot.wav → 2d/platformer/player/shoot.wav


+ 3 - 3
2d/platformer/assets/audio/sfx/shoot.wav.import → 2d/platformer/player/shoot.wav.import

@@ -3,12 +3,12 @@
 importer="wav"
 type="AudioStreamWAV"
 uid="uid://bpxywy45eqgwy"
-path="res://.godot/imported/shoot.wav-f3ce9b4ae60220ecd3cf78df7278a10f.sample"
+path="res://.godot/imported/shoot.wav-c76164c7ce3589c9fdcbf989e9819ed2.sample"
 
 [deps]
 
-source_file="res://assets/audio/sfx/shoot.wav"
-dest_files=["res://.godot/imported/shoot.wav-f3ce9b4ae60220ecd3cf78df7278a10f.sample"]
+source_file="res://player/shoot.wav"
+dest_files=["res://.godot/imported/shoot.wav-c76164c7ce3589c9fdcbf989e9819ed2.sample"]
 
 [params]
 

+ 26 - 79
2d/platformer/project.godot

@@ -8,59 +8,20 @@
 
 config_version=5
 
-_global_script_classes=[{
-"base": "CharacterBody2D",
-"class": &"Actor",
-"language": &"GDScript",
-"path": "res://src/Actors/Actor.gd"
-}, {
-"base": "RigidBody2D",
-"class": &"Bullet",
-"language": &"GDScript",
-"path": "res://src/Objects/Bullet.gd"
-}, {
-"base": "Area2D",
-"class": &"Coin",
-"language": &"GDScript",
-"path": "res://src/Objects/Coin.gd"
-}, {
-"base": "Actor",
-"class": &"Enemy",
-"language": &"GDScript",
-"path": "res://src/Actors/Enemy.gd"
-}, {
-"base": "Marker2D",
-"class": &"Gun",
-"language": &"GDScript",
-"path": "res://src/Actors/Gun.gd"
-}, {
-"base": "Actor",
-"class": &"Player",
-"language": &"GDScript",
-"path": "res://src/Actors/Player.gd"
-}]
-_global_script_class_icons={
-"Actor": "",
-"Bullet": "",
-"Coin": "",
-"Enemy": "",
-"Gun": "",
-"Player": ""
-}
-
 [application]
 
 config/name="Platformer 2D"
-config/description="This demo is a pixel art 2D platformer with graphics and sound.
+config/description="This demo is a pixel art 2D platformer with single-player
+and two player splitscreen multiplayer.
 
-It shows you how to code characters and physics-based objects
+It demonstrates how to code characters and physics-based objects
 in a real game context. This is a relatively complete demo
 where the player can jump, walk on slopes, fire bullets,
-interact with enemies, and more. It contains one closed
-level, and the player is invincible, unlike the enemies."
-run/main_scene="res://src/Main/Game.tscn"
+interact with enemies, and collect items. It contains one
+level. The player is invincible, unlike the enemies."
+run/main_scene="res://game_singleplayer.tscn"
 config/features=PackedStringArray("4.0")
-config/icon="res://icon.png"
+config/icon="res://icon.webp"
 target_fps="60"
 
 [debug]
@@ -69,7 +30,6 @@ gdscript/warnings/unsafe_property_access=true
 gdscript/warnings/unsafe_method_access=true
 gdscript/warnings/unsafe_cast=true
 gdscript/warnings/unsafe_call_argument=true
-gdscript/completion/autocomplete_setters_and_getters=true
 
 [display]
 
@@ -105,108 +65,95 @@ texture={
 
 jump={
 "deadzone": 0.5,
-"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":16777232,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
-, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":0,"pressure":0.0,"pressed":false,"script":null)
-, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":87,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
+"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":0,"pressure":0.0,"pressed":false,"script":null)
+, 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":87,"key_label":0,"unicode":119,"echo":false,"script":null)
 ]
 }
 move_left={
 "deadzone": 0.5,
-"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":16777231,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
-, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":14,"pressure":0.0,"pressed":false,"script":null)
-, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":65,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
+"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":14,"pressure":0.0,"pressed":false,"script":null)
+, 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)
 , Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":-1.0,"script":null)
 ]
 }
 move_right={
 "deadzone": 0.5,
-"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":16777233,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
-, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":15,"pressure":0.0,"pressed":false,"script":null)
-, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":68,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
+"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":15,"pressure":0.0,"pressed":false,"script":null)
+, 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)
 , Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":1.0,"script":null)
 ]
 }
 shoot={
 "deadzone": 0.5,
-"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":32,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
+"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)
 , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":2,"pressure":0.0,"pressed":false,"script":null)
-, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":90,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
+, 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":4194325,"key_label":0,"unicode":0,"echo":false,"script":null)
 , Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":1,"pressed":false,"double_click":false,"script":null)
-, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":16777350,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
-, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":16777238,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
 ]
 }
 toggle_fullscreen={
 "deadzone": 0.5,
-"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":16777254,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
+"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194342,"key_label":0,"unicode":0,"echo":false,"script":null)
 ]
 }
 toggle_pause={
 "deadzone": 0.5,
-"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":16777217,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
-, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":11,"pressure":0.0,"pressed":false,"script":null)
+"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":11,"pressure":0.0,"pressed":false,"script":null)
+, 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":4194305,"key_label":0,"unicode":0,"echo":false,"script":null)
 ]
 }
 jump_p1={
 "deadzone": 0.5,
-"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":87,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
+"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":0,"echo":false,"script":null)
 , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":0,"pressure":0.0,"pressed":false,"script":null)
 ]
 }
 move_left_p1={
 "deadzone": 0.5,
-"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":65,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
+"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"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":0,"echo":false,"script":null)
 , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":14,"pressure":0.0,"pressed":false,"script":null)
 , Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":-1.0,"script":null)
 ]
 }
 move_right_p1={
 "deadzone": 0.5,
-"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":68,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
+"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)
 , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":15,"pressure":0.0,"pressed":false,"script":null)
 , Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":1.0,"script":null)
 ]
 }
 shoot_p1={
 "deadzone": 0.5,
-"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":90,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
-, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":32,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
+"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":4194325,"key_label":0,"unicode":0,"echo":false,"script":null)
 , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":2,"pressure":0.0,"pressed":false,"script":null)
 ]
 }
 jump_p2={
 "deadzone": 0.5,
-"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":16777232,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
+"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":73,"key_label":0,"unicode":105,"echo":false,"script":null)
 , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":1,"button_index":0,"pressure":0.0,"pressed":false,"script":null)
 ]
 }
 move_left_p2={
 "deadzone": 0.5,
-"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":16777231,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
+"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":74,"key_label":0,"unicode":106,"echo":false,"script":null)
 , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":1,"button_index":14,"pressure":0.0,"pressed":false,"script":null)
 , Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":1,"axis":0,"axis_value":-1.0,"script":null)
 ]
 }
 move_right_p2={
 "deadzone": 0.5,
-"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":16777233,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
+"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":76,"key_label":0,"unicode":108,"echo":false,"script":null)
 , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":1,"button_index":15,"pressure":0.0,"pressed":false,"script":null)
 , Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":1,"axis":0,"axis_value":1.0,"script":null)
 ]
 }
 shoot_p2={
 "deadzone": 0.5,
-"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":16777350,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
-, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":16777238,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
+"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":47,"key_label":0,"unicode":47,"echo":false,"script":null)
 , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":1,"button_index":2,"pressure":0.0,"pressed":false,"script":null)
 ]
 }
-splitscreen={
-"deadzone": 0.5,
-"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":10,"pressure":0.0,"pressed":false,"script":null)
-, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":16777218,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
-]
-}
 
 [layer_names]
 

BIN
2d/platformer/screenshots/layout.png


Some files were not shown because too many files changed in this diff