Browse Source

Merge pull request #405 from NathanLovato/feature/2d-platformer-remake

Remake the 2d platformer demo
Aaron Franke 5 years ago
parent
commit
13ca65800d
91 changed files with 1533 additions and 1313 deletions
  1. 29 0
      2d/platformer/README.md
  2. 0 17
      2d/platformer/Stage.tscn
  3. 0 243
      2d/platformer/TileSet.tres
  4. 0 324
      2d/platformer/TilesetEdit.tscn
  5. 0 0
      2d/platformer/assets/art/background/cloud_1.png
  6. 3 3
      2d/platformer/assets/art/background/cloud_1.png.import
  7. 0 0
      2d/platformer/assets/art/background/cloud_2.png
  8. 3 3
      2d/platformer/assets/art/background/cloud_2.png.import
  9. 0 0
      2d/platformer/assets/art/background/cloud_3.png
  10. 34 0
      2d/platformer/assets/art/background/cloud_3.png.import
  11. BIN
      2d/platformer/assets/art/background/distant_platforms_1.png
  12. 3 3
      2d/platformer/assets/art/background/distant_platforms_1.png.import
  13. BIN
      2d/platformer/assets/art/background/distant_platforms_2.png
  14. 3 3
      2d/platformer/assets/art/background/distant_platforms_2.png.import
  15. 0 0
      2d/platformer/assets/art/background/sky.png
  16. 34 0
      2d/platformer/assets/art/background/sky.png.import
  17. 0 0
      2d/platformer/assets/art/coin/coin.png
  18. 3 3
      2d/platformer/assets/art/coin/coin.png.import
  19. 0 0
      2d/platformer/assets/art/enemy/enemy.png
  20. 3 3
      2d/platformer/assets/art/enemy/enemy.png.import
  21. BIN
      2d/platformer/assets/art/platforms/moving_platform.png
  22. 3 3
      2d/platformer/assets/art/platforms/moving_platform.png.import
  23. 0 0
      2d/platformer/assets/art/platforms/one_way_platform.png
  24. 3 3
      2d/platformer/assets/art/platforms/one_way_platform.png.import
  25. 0 0
      2d/platformer/assets/art/player/bullet/bullet.png
  26. 3 3
      2d/platformer/assets/art/player/bullet/bullet.png.import
  27. 0 0
      2d/platformer/assets/art/player/robot_demo.png
  28. 3 3
      2d/platformer/assets/art/player/robot_demo.png.import
  29. BIN
      2d/platformer/assets/art/tileset/tiles_demo.png
  30. 3 3
      2d/platformer/assets/art/tileset/tiles_demo.png.import
  31. 263 0
      2d/platformer/assets/art/tileset/tileset.tres
  32. 0 0
      2d/platformer/assets/art/ui/touch_button_fire.png
  33. 3 3
      2d/platformer/assets/art/ui/touch_button_fire.png.import
  34. 0 0
      2d/platformer/assets/art/ui/touch_button_jump.png
  35. 3 3
      2d/platformer/assets/art/ui/touch_button_jump.png.import
  36. 0 0
      2d/platformer/assets/art/ui/touch_button_left.png
  37. 3 3
      2d/platformer/assets/art/ui/touch_button_left.png.import
  38. 0 0
      2d/platformer/assets/art/ui/touch_button_right.png
  39. 3 3
      2d/platformer/assets/art/ui/touch_button_right.png.import
  40. 0 0
      2d/platformer/assets/audio/music/music.ogg
  41. 15 0
      2d/platformer/assets/audio/music/music.ogg.import
  42. 0 0
      2d/platformer/assets/audio/sfx/coin_pickup.wav
  43. 21 0
      2d/platformer/assets/audio/sfx/coin_pickup.wav.import
  44. 0 0
      2d/platformer/assets/audio/sfx/explode.wav
  45. 3 3
      2d/platformer/assets/audio/sfx/explode.wav.import
  46. 0 0
      2d/platformer/assets/audio/sfx/hit.wav
  47. 3 3
      2d/platformer/assets/audio/sfx/hit.wav.import
  48. 0 0
      2d/platformer/assets/audio/sfx/jump.wav
  49. 3 3
      2d/platformer/assets/audio/sfx/jump.wav.import
  50. 0 0
      2d/platformer/assets/audio/sfx/shoot.wav
  51. 3 3
      2d/platformer/assets/audio/sfx/shoot.wav.import
  52. BIN
      2d/platformer/assets/theme/fonts/kenney_mini_square.ttf
  53. 82 0
      2d/platformer/assets/theme/user_interface.tres
  54. 0 15
      2d/platformer/audio/music.ogg.import
  55. 0 21
      2d/platformer/audio/sound_explode.wav.import
  56. 0 71
      2d/platformer/background/ParallaxBg.tscn
  57. BIN
      2d/platformer/background/scroll_bg_fg_1.png
  58. BIN
      2d/platformer/background/scroll_bg_fg_2.png
  59. 0 140
      2d/platformer/coin/Coin.tscn
  60. 0 11
      2d/platformer/coin/coin.gd
  61. 0 50
      2d/platformer/enemy/enemy.gd
  62. 0 16
      2d/platformer/platform/MovingPlatform.tscn
  63. 0 17
      2d/platformer/platform/OneWayPlatform.tscn
  64. 0 17
      2d/platformer/platform/moving_platform.gd
  65. BIN
      2d/platformer/platform/moving_platform.png
  66. 0 11
      2d/platformer/player/bullet.gd
  67. 0 34
      2d/platformer/player/osb_left.png.import
  68. 0 34
      2d/platformer/player/osb_right.png.import
  69. 0 97
      2d/platformer/player/player.gd
  70. 41 14
      2d/platformer/project.godot
  71. 0 0
      2d/platformer/screenshots/.gdignore
  72. BIN
      2d/platformer/screenshots/layout.png
  73. BIN
      2d/platformer/screenshots/shoot.png
  74. 18 0
      2d/platformer/src/Actors/Actor.gd
  75. 79 0
      2d/platformer/src/Actors/Enemy.gd
  76. 110 73
      2d/platformer/src/Actors/Enemy.tscn
  77. 24 0
      2d/platformer/src/Actors/Gun.gd
  78. 96 0
      2d/platformer/src/Actors/Player.gd
  79. 48 37
      2d/platformer/src/Actors/Player.tscn
  80. 52 0
      2d/platformer/src/Level/Level.tscn
  81. 174 0
      2d/platformer/src/Level/ParallaxBackground.tscn
  82. 31 0
      2d/platformer/src/Main/Game.gd
  83. 16 0
      2d/platformer/src/Main/Game.tscn
  84. 14 0
      2d/platformer/src/Objects/Bullet.gd
  85. 16 14
      2d/platformer/src/Objects/Bullet.tscn
  86. 15 0
      2d/platformer/src/Objects/Coin.gd
  87. 161 0
      2d/platformer/src/Objects/Coin.tscn
  88. 21 0
      2d/platformer/src/Platforms/Platform.tscn
  89. 26 0
      2d/platformer/src/UserInterface/PauseMenu.gd
  90. 56 0
      2d/platformer/src/UserInterface/PauseMenu.tscn
  91. BIN
      2d/platformer/tiles_demo.png

+ 29 - 0
2d/platformer/README.md

@@ -0,0 +1,29 @@
+# 2D Platformer
+
+This demo is a pixel art 2D platformer with graphics and sound.
+
+It shows you 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.
+
+## Features
+
+- Side-scrolling player controller.
+    - Can walk on and snap to slopes.
+    - Can shoot, including while jumping.
+- 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.
+- Platforms that can move in any direction.
+- Gun that shoots bullets with rigid body (natural) physics.
+- Collectible coins.
+- Pause and pause menu.
+- Pixel art visuals.
+- Sound effects and music.
+
+## Screenshots
+
+![Player shooting in the direction of an enemy](screenshots/shoot.png)
+![The entire level layout viewed in the editor](screenshots/layout.png)

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


+ 0 - 243
2d/platformer/TileSet.tres

@@ -1,243 +0,0 @@
-[gd_resource type="TileSet" load_steps=14 format=2]
-
-[ext_resource path="res://tiles_demo.png" type="Texture" id=1]
-
-[sub_resource type="ConvexPolygonShape2D" id=1]
-
-custom_solver_bias = 0.0
-points = PoolVector2Array( 32, -24, 32, 32, -32, 32, -32, -24 )
-
-[sub_resource type="ConvexPolygonShape2D" id=2]
-
-custom_solver_bias = 0.0
-points = PoolVector2Array( -32, -24, 24, -24, 24, 32, -32, 32 )
-
-[sub_resource type="ConvexPolygonShape2D" id=3]
-
-custom_solver_bias = 0.0
-points = PoolVector2Array( 32, -32, 32, 32, -32, 32, -32, -32 )
-
-[sub_resource type="ConvexPolygonShape2D" id=4]
-
-custom_solver_bias = 0.0
-points = PoolVector2Array( -32, -56, 32, 8, 32, 64, -32, 64 )
-
-[sub_resource type="ConvexPolygonShape2D" id=5]
-
-custom_solver_bias = 0.0
-points = PoolVector2Array( -32, -32, 24, -32, 24, 32, -32, 32 )
-
-[sub_resource type="ConvexPolygonShape2D" id=6]
-
-custom_solver_bias = 0.0
-points = PoolVector2Array( 32, -24, 32, 24, -32, 24, -32, -24 )
-
-[sub_resource type="ConvexPolygonShape2D" id=7]
-
-custom_solver_bias = 0.0
-points = PoolVector2Array( 24, -24, 24, 24, -32, 24, -32, -24 )
-
-[sub_resource type="ConvexPolygonShape2D" id=8]
-
-custom_solver_bias = 0.0
-points = PoolVector2Array( -32, -32, 24, -32, 24, 32, -32, 32 )
-
-[sub_resource type="ConvexPolygonShape2D" id=9]
-
-custom_solver_bias = 0.0
-points = PoolVector2Array( -64, -32, -8, -32, -8, 32, -64, 32 )
-
-[sub_resource type="ConvexPolygonShape2D" id=10]
-
-custom_solver_bias = 0.0
-points = PoolVector2Array( -32, -32, 24, -32, 32, -24, 32, 32, -32, 32 )
-
-[sub_resource type="ConvexPolygonShape2D" id=11]
-
-custom_solver_bias = 0.0
-points = PoolVector2Array( -32, -24, 32, -24, 32, 32, -32, 32 )
-
-[sub_resource type="ConvexPolygonShape2D" id=12]
-
-custom_solver_bias = 0.0
-points = PoolVector2Array( -32, -24, 32, -24, 32, 32, -32, 32 )
-
-[resource]
-
-0/name = "floor"
-0/texture = ExtResource( 1 )
-0/tex_offset = Vector2( 0, 0 )
-0/modulate = Color( 1, 1, 1, 1 )
-0/region = Rect2( 0, 0, 64, 64 )
-0/occluder_offset = Vector2( 32, 32 )
-0/navigation_offset = Vector2( 32, 32 )
-0/shapes = [ {
-"one_way": false,
-"shape": SubResource( 1 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 32, 32 )
-} ]
-1/name = "edge"
-1/texture = ExtResource( 1 )
-1/tex_offset = Vector2( 0, 0 )
-1/modulate = Color( 1, 1, 1, 1 )
-1/region = Rect2( 64, 0, 64, 64 )
-1/occluder_offset = Vector2( 32, 32 )
-1/navigation_offset = Vector2( 32, 32 )
-1/shapes = [ {
-"one_way": false,
-"shape": SubResource( 2 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 32, 32 )
-} ]
-2/name = "wall"
-2/texture = ExtResource( 1 )
-2/tex_offset = Vector2( 0, 0 )
-2/modulate = Color( 1, 1, 1, 1 )
-2/region = Rect2( 64, 64, 64, 64 )
-2/occluder_offset = Vector2( 32, 32 )
-2/navigation_offset = Vector2( 32, 32 )
-2/shapes = [ {
-"one_way": false,
-"shape": SubResource( 8 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 32, 32 )
-} ]
-3/name = "wall_deco"
-3/texture = ExtResource( 1 )
-3/tex_offset = Vector2( 0, 0 )
-3/modulate = Color( 1, 1, 1, 1 )
-3/region = Rect2( 320, 128, 128, 64 )
-3/occluder_offset = Vector2( 64, 32 )
-3/navigation_offset = Vector2( 64, 32 )
-3/shapes = [ {
-"one_way": false,
-"shape": SubResource( 9 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 64, 32 )
-} ]
-4/name = "corner"
-4/texture = ExtResource( 1 )
-4/tex_offset = Vector2( 0, 0 )
-4/modulate = Color( 1, 1, 1, 1 )
-4/region = Rect2( 64, 128, 64, 64 )
-4/occluder_offset = Vector2( 32, 32 )
-4/navigation_offset = Vector2( 32, 32 )
-4/shapes = [ {
-"one_way": false,
-"shape": SubResource( 10 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 32, 32 )
-} ]
-5/name = "flowers"
-5/texture = ExtResource( 1 )
-5/tex_offset = Vector2( 0, 0 )
-5/modulate = Color( 1, 1, 1, 1 )
-5/region = Rect2( 192, 192, 64, 64 )
-5/occluder_offset = Vector2( 32, 32 )
-5/navigation_offset = Vector2( 32, 32 )
-5/shapes = [ {
-"one_way": false,
-"shape": SubResource( 11 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 32, 32 )
-} ]
-6/name = "tree_base"
-6/texture = ExtResource( 1 )
-6/tex_offset = Vector2( 0, 0 )
-6/modulate = Color( 1, 1, 1, 1 )
-6/region = Rect2( 256, 192, 64, 64 )
-6/occluder_offset = Vector2( 32, 32 )
-6/navigation_offset = Vector2( 32, 32 )
-6/shapes = [ {
-"one_way": false,
-"shape": SubResource( 12 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 32, 32 )
-} ]
-7/name = "tree_mid"
-7/texture = ExtResource( 1 )
-7/tex_offset = Vector2( 0, 0 )
-7/modulate = Color( 1, 1, 1, 1 )
-7/region = Rect2( 256, 128, 64, 64 )
-7/occluder_offset = Vector2( 32, 32 )
-7/navigation_offset = Vector2( 32, 32 )
-7/shapes = [  ]
-8/name = "tree_mid 2"
-8/texture = ExtResource( 1 )
-8/tex_offset = Vector2( 0, 0 )
-8/modulate = Color( 1, 1, 1, 1 )
-8/region = Rect2( 256, 64, 64, 64 )
-8/occluder_offset = Vector2( 32, 32 )
-8/navigation_offset = Vector2( 32, 32 )
-8/shapes = [  ]
-9/name = "tree_top"
-9/texture = ExtResource( 1 )
-9/tex_offset = Vector2( 0, 0 )
-9/modulate = Color( 1, 1, 1, 1 )
-9/region = Rect2( 256, 0, 64, 64 )
-9/occluder_offset = Vector2( 32, 32 )
-9/navigation_offset = Vector2( 32, 32 )
-9/shapes = [  ]
-10/name = "solid"
-10/texture = ExtResource( 1 )
-10/tex_offset = Vector2( 0, 0 )
-10/modulate = Color( 1, 1, 1, 1 )
-10/region = Rect2( 0, 64, 64, 64 )
-10/occluder_offset = Vector2( 32, 32 )
-10/navigation_offset = Vector2( 32, 32 )
-10/shapes = [  ]
-11/name = "ceiling"
-11/texture = ExtResource( 1 )
-11/tex_offset = Vector2( 0, 0 )
-11/modulate = Color( 1, 1, 1, 1 )
-11/region = Rect2( 384, 64, 64, 64 )
-11/occluder_offset = Vector2( 32, 32 )
-11/navigation_offset = Vector2( 32, 32 )
-11/shapes = [ {
-"one_way": false,
-"shape": SubResource( 3 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 32, 32 )
-} ]
-12/name = "ramp"
-12/texture = ExtResource( 1 )
-12/tex_offset = Vector2( 0, 0 )
-12/modulate = Color( 1, 1, 1, 1 )
-12/region = Rect2( 128, 128, 64, 128 )
-12/occluder_offset = Vector2( 32, 64 )
-12/navigation_offset = Vector2( 32, 64 )
-12/shapes = [ {
-"one_way": false,
-"shape": SubResource( 4 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 32, 64 )
-} ]
-13/name = "ceiling2wall"
-13/texture = ExtResource( 1 )
-13/tex_offset = Vector2( 0, 0 )
-13/modulate = Color( 1, 1, 1, 1 )
-13/region = Rect2( 448, 64, 64, 64 )
-13/occluder_offset = Vector2( 32, 32 )
-13/navigation_offset = Vector2( 32, 32 )
-13/shapes = [ {
-"one_way": false,
-"shape": SubResource( 5 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 32, 32 )
-} ]
-14/name = "platform_floor"
-14/texture = ExtResource( 1 )
-14/tex_offset = Vector2( 0, 0 )
-14/modulate = Color( 1, 1, 1, 1 )
-14/region = Rect2( 128, 0, 64, 64 )
-14/occluder_offset = Vector2( 32, 32 )
-14/navigation_offset = Vector2( 32, 32 )
-14/shapes = [ {
-"one_way": false,
-"shape": SubResource( 6 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 32, 32 )
-} ]
-15/name = "platform_edge"
-15/texture = ExtResource( 1 )
-15/tex_offset = Vector2( 0, 0 )
-15/modulate = Color( 1, 1, 1, 1 )
-15/region = Rect2( 192, 0, 64, 64 )
-15/occluder_offset = Vector2( 32, 32 )
-15/navigation_offset = Vector2( 32, 32 )
-15/shapes = [ {
-"one_way": false,
-"shape": SubResource( 7 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 32, 32 )
-} ]
-

+ 0 - 324
2d/platformer/TilesetEdit.tscn

@@ -1,324 +0,0 @@
-[gd_scene load_steps=2 format=2]
-
-[ext_resource path="res://tiles_demo.png" type="Texture" id=1]
-
-[node name="Node" type="Node"]
-
-[node name="floor" type="Sprite" parent="."]
-
-texture = ExtResource( 1 )
-region_enabled = true
-region_rect = Rect2( 0, 0, 64, 64 )
-
-[node name="collision" type="StaticBody2D" parent="floor"]
-
-input_pickable = false
-collision_layer = 1
-collision_mask = 1
-constant_linear_velocity = Vector2( 0, 0 )
-constant_angular_velocity = 0.0
-friction = 1.0
-bounce = 0.0
-
-[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="floor/collision"]
-
-build_mode = 0
-polygon = PoolVector2Array( 32, -24, 32, 32, -32, 32, -32, -24 )
-
-[node name="edge" type="Sprite" parent="."]
-
-position = Vector2( 64, 0 )
-texture = ExtResource( 1 )
-region_enabled = true
-region_rect = Rect2( 64, 0, 64, 64 )
-
-[node name="collision" type="StaticBody2D" parent="edge"]
-
-input_pickable = false
-collision_layer = 1
-collision_mask = 1
-constant_linear_velocity = Vector2( 0, 0 )
-constant_angular_velocity = 0.0
-friction = 1.0
-bounce = 0.0
-
-[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="edge/collision"]
-
-build_mode = 0
-polygon = PoolVector2Array( -32, -24, 24, -24, 24, 32, -32, 32 )
-
-[node name="wall" type="Sprite" parent="."]
-
-position = Vector2( 64, 64 )
-texture = ExtResource( 1 )
-region_enabled = true
-region_rect = Rect2( 64, 64, 64, 64 )
-
-[node name="collision" type="StaticBody2D" parent="wall"]
-
-input_pickable = false
-collision_layer = 1
-collision_mask = 1
-constant_linear_velocity = Vector2( 0, 0 )
-constant_angular_velocity = 0.0
-friction = 1.0
-bounce = 0.0
-
-[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="wall/collision"]
-
-build_mode = 0
-polygon = PoolVector2Array( -32, -32, 24, -32, 24, 32, -32, 32 )
-
-[node name="wall_deco" type="Sprite" parent="."]
-
-position = Vector2( 96, 128 )
-texture = ExtResource( 1 )
-region_enabled = true
-region_rect = Rect2( 320, 128, 128, 64 )
-
-[node name="collision" type="StaticBody2D" parent="wall_deco"]
-
-input_pickable = false
-collision_layer = 1
-collision_mask = 1
-constant_linear_velocity = Vector2( 0, 0 )
-constant_angular_velocity = 0.0
-friction = 1.0
-bounce = 0.0
-
-[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="wall_deco/collision"]
-
-build_mode = 0
-polygon = PoolVector2Array( -64, -32, -8, -32, -8, 32, -64, 32 )
-
-[node name="corner" type="Sprite" parent="."]
-
-position = Vector2( 64, 192 )
-texture = ExtResource( 1 )
-region_enabled = true
-region_rect = Rect2( 64, 128, 64, 64 )
-
-[node name="collision" type="StaticBody2D" parent="corner"]
-
-input_pickable = false
-collision_layer = 1
-collision_mask = 1
-constant_linear_velocity = Vector2( 0, 0 )
-constant_angular_velocity = 0.0
-friction = 1.0
-bounce = 0.0
-
-[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="corner/collision"]
-
-build_mode = 0
-polygon = PoolVector2Array( -32, -32, 24, -32, 32, -24, 32, 32, -32, 32 )
-
-[node name="flowers" type="Sprite" parent="."]
-
-position = Vector2( 128, 192 )
-texture = ExtResource( 1 )
-region_enabled = true
-region_rect = Rect2( 192, 192, 64, 64 )
-
-[node name="collision" type="StaticBody2D" parent="flowers"]
-
-input_pickable = false
-collision_layer = 1
-collision_mask = 1
-constant_linear_velocity = Vector2( 0, 0 )
-constant_angular_velocity = 0.0
-friction = 1.0
-bounce = 0.0
-
-[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="flowers/collision"]
-
-build_mode = 0
-polygon = PoolVector2Array( -32, 32, 32, 32, 32, -24, -32, -24 )
-
-[node name="tree_base" type="Sprite" parent="."]
-
-position = Vector2( 192, 192 )
-texture = ExtResource( 1 )
-region_enabled = true
-region_rect = Rect2( 256, 192, 64, 64 )
-
-[node name="collision" type="StaticBody2D" parent="tree_base"]
-
-input_pickable = false
-collision_layer = 1
-collision_mask = 1
-constant_linear_velocity = Vector2( 0, 0 )
-constant_angular_velocity = 0.0
-friction = 1.0
-bounce = 0.0
-
-[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="tree_base/collision"]
-
-build_mode = 0
-polygon = PoolVector2Array( -32, 32, 32, 32, 32, -24, -32, -24 )
-
-[node name="tree_mid" type="Sprite" parent="."]
-
-position = Vector2( 192, 128 )
-texture = ExtResource( 1 )
-region_enabled = true
-region_rect = Rect2( 256, 128, 64, 64 )
-
-[node name="tree_mid 2" type="Sprite" parent="."]
-
-position = Vector2( 192, 64 )
-texture = ExtResource( 1 )
-region_enabled = true
-region_rect = Rect2( 256, 64, 64, 64 )
-
-[node name="tree_top" type="Sprite" parent="."]
-
-position = Vector2( 192, 0 )
-texture = ExtResource( 1 )
-region_enabled = true
-region_rect = Rect2( 256, 0, 64, 64 )
-
-[node name="solid" type="Sprite" parent="."]
-
-position = Vector2( 0, 64 )
-texture = ExtResource( 1 )
-region_enabled = true
-region_rect = Rect2( 0, 64, 64, 64 )
-
-[node name="ceiling" type="Sprite" parent="."]
-
-position = Vector2( 0, 128 )
-texture = ExtResource( 1 )
-region_enabled = true
-region_rect = Rect2( 384, 64, 64, 64 )
-
-[node name="collision" type="StaticBody2D" parent="ceiling"]
-
-input_pickable = false
-collision_layer = 1
-collision_mask = 1
-constant_linear_velocity = Vector2( 0, 0 )
-constant_angular_velocity = 0.0
-friction = 1.0
-bounce = 0.0
-
-[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="ceiling/collision"]
-
-build_mode = 0
-polygon = PoolVector2Array( 32, -32, 32, 32, -32, 32, -32, -32 )
-
-[node name="ramp" type="Sprite" parent="."]
-
-position = Vector2( 256, 224 )
-texture = ExtResource( 1 )
-region_enabled = true
-region_rect = Rect2( 128, 128, 64, 128 )
-
-[node name="collision" type="StaticBody2D" parent="ramp"]
-
-input_pickable = false
-collision_layer = 1
-collision_mask = 1
-constant_linear_velocity = Vector2( 0, 0 )
-constant_angular_velocity = 0.0
-friction = 1.0
-bounce = 0.0
-
-[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="ramp/collision"]
-
-build_mode = 0
-polygon = PoolVector2Array( -32, -56, 32, 8, 32, 64, -32, 64 )
-
-[node name="ceiling2wall" type="Sprite" parent="."]
-
-position = Vector2( 0, 192 )
-texture = ExtResource( 1 )
-region_enabled = true
-region_rect = Rect2( 448, 64, 64, 64 )
-
-[node name="collision" type="StaticBody2D" parent="ceiling2wall"]
-
-input_pickable = false
-collision_layer = 1
-collision_mask = 1
-constant_linear_velocity = Vector2( 0, 0 )
-constant_angular_velocity = 0.0
-friction = 1.0
-bounce = 0.0
-
-[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="ceiling2wall/collision"]
-
-build_mode = 0
-polygon = PoolVector2Array( -32, -32, 24, -32, 24, 32, -32, 32 )
-
-[node name="platform_floor" type="Sprite" parent="."]
-
-position = Vector2( 0, 256 )
-texture = ExtResource( 1 )
-region_enabled = true
-region_rect = Rect2( 128, 0, 64, 64 )
-
-[node name="collision" type="StaticBody2D" parent="platform_floor"]
-
-input_pickable = false
-collision_layer = 1
-collision_mask = 1
-constant_linear_velocity = Vector2( 0, 0 )
-constant_angular_velocity = 0.0
-friction = 1.0
-bounce = 0.0
-
-[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="platform_floor/collision"]
-
-build_mode = 0
-polygon = PoolVector2Array( 32, -24, 32, 24, -32, 24, -32, -24 )
-
-[node name="platform_edge" type="Sprite" parent="."]
-
-position = Vector2( 64, 256 )
-texture = ExtResource( 1 )
-region_enabled = true
-region_rect = Rect2( 192, 0, 64, 64 )
-
-[node name="collision" type="StaticBody2D" parent="platform_edge"]
-
-input_pickable = false
-collision_layer = 1
-collision_mask = 1
-constant_linear_velocity = Vector2( 0, 0 )
-constant_angular_velocity = 0.0
-friction = 1.0
-bounce = 0.0
-
-[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="platform_edge/collision"]
-
-build_mode = 0
-polygon = PoolVector2Array( 24, -24, 24, 24, -32, 24, -32, -24 )
-
-[node name="help" type="Label" parent="."]
-
-anchor_left = 0.0
-anchor_top = 0.0
-anchor_right = 0.0
-anchor_bottom = 0.0
-margin_left = 1.0
-margin_top = 331.0
-margin_right = 727.0
-margin_bottom = 422.0
-rect_pivot_offset = Vector2( 0, 0 )
-rect_clip_content = false
-mouse_filter = 2
-size_flags_horizontal = 2
-size_flags_vertical = 0
-text = "This scene serves as a tool for editing the tileset.
-Nodes (sprites) and their respective collisionsare edited here.
-
-To create a tileset from this, a \"TileSet\" resoucre must be created. Use the helper in: Scene -> Convert To -> TileSet.
-This will save a tileset. Saving over it will merge your changes.
-
-Finally, the saved tileset resource (tileset.tres in this case), can be opened to be used into a TileMap node for editing a tile map."
-percent_visible = 1.0
-lines_skipped = 0
-max_lines_visible = -1
-
-

+ 0 - 0
2d/platformer/background/scroll_bg_cloud_1.png → 2d/platformer/assets/art/background/cloud_1.png


+ 3 - 3
2d/platformer/player/osb_fire.png.import → 2d/platformer/assets/art/background/cloud_1.png.import

@@ -2,15 +2,15 @@
 
 importer="texture"
 type="StreamTexture"
-path="res://.import/osb_fire.png-67a49910acd764fd7c67429af0ad5cb8.stex"
+path="res://.import/cloud_1.png-03c0ad8be397b731df0dd38fa3c87727.stex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://player/osb_fire.png"
-dest_files=[ "res://.import/osb_fire.png-67a49910acd764fd7c67429af0ad5cb8.stex" ]
+source_file="res://assets/art/background/cloud_1.png"
+dest_files=[ "res://.import/cloud_1.png-03c0ad8be397b731df0dd38fa3c87727.stex" ]
 
 [params]
 

+ 0 - 0
2d/platformer/background/scroll_bg_cloud_2.png → 2d/platformer/assets/art/background/cloud_2.png


+ 3 - 3
2d/platformer/player/osb_jump.png.import → 2d/platformer/assets/art/background/cloud_2.png.import

@@ -2,15 +2,15 @@
 
 importer="texture"
 type="StreamTexture"
-path="res://.import/osb_jump.png-0d4d2b2d1a7d2c11e3e4fd800b8589ed.stex"
+path="res://.import/cloud_2.png-4ddf8c5bceca4aa07a8bc86d7d788e02.stex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://player/osb_jump.png"
-dest_files=[ "res://.import/osb_jump.png-0d4d2b2d1a7d2c11e3e4fd800b8589ed.stex" ]
+source_file="res://assets/art/background/cloud_2.png"
+dest_files=[ "res://.import/cloud_2.png-4ddf8c5bceca4aa07a8bc86d7d788e02.stex" ]
 
 [params]
 

+ 0 - 0
2d/platformer/background/scroll_bg_cloud_3.png → 2d/platformer/assets/art/background/cloud_3.png


+ 34 - 0
2d/platformer/assets/art/background/cloud_3.png.import

@@ -0,0 +1,34 @@
+[remap]
+
+importer="texture"
+type="StreamTexture"
+path="res://.import/cloud_3.png-a1b7dc71aa84bea9cb4f78f585dcc65d.stex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://assets/art/background/cloud_3.png"
+dest_files=[ "res://.import/cloud_3.png-a1b7dc71aa84bea9cb4f78f585dcc65d.stex" ]
+
+[params]
+
+compress/mode=0
+compress/lossy_quality=0.7
+compress/hdr_mode=0
+compress/bptc_ldr=0
+compress/normal_map=0
+flags/repeat=0
+flags/filter=false
+flags/mipmaps=false
+flags/anisotropic=false
+flags/srgb=2
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/HDR_as_SRGB=false
+process/invert_color=false
+stream=false
+size_limit=0
+detect_3d=false
+svg/scale=1.0

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


+ 3 - 3
2d/platformer/background/scroll_bg_fg_2.png.import → 2d/platformer/assets/art/background/distant_platforms_1.png.import

@@ -2,15 +2,15 @@
 
 importer="texture"
 type="StreamTexture"
-path="res://.import/scroll_bg_fg_2.png-2b54decd69e8aff2caa33640a336d1e9.stex"
+path="res://.import/distant_platforms_1.png-7286fe6c8587b96abbbe0bc4a8cbc510.stex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://background/scroll_bg_fg_2.png"
-dest_files=[ "res://.import/scroll_bg_fg_2.png-2b54decd69e8aff2caa33640a336d1e9.stex" ]
+source_file="res://assets/art/background/distant_platforms_1.png"
+dest_files=[ "res://.import/distant_platforms_1.png-7286fe6c8587b96abbbe0bc4a8cbc510.stex" ]
 
 [params]
 

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


+ 3 - 3
2d/platformer/background/scroll_bg_fg_1.png.import → 2d/platformer/assets/art/background/distant_platforms_2.png.import

@@ -2,15 +2,15 @@
 
 importer="texture"
 type="StreamTexture"
-path="res://.import/scroll_bg_fg_1.png-20c90ebded5095c6863cdf6b1b82882d.stex"
+path="res://.import/distant_platforms_2.png-ba010b30987da6d74062ce964ab450ef.stex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://background/scroll_bg_fg_1.png"
-dest_files=[ "res://.import/scroll_bg_fg_1.png-20c90ebded5095c6863cdf6b1b82882d.stex" ]
+source_file="res://assets/art/background/distant_platforms_2.png"
+dest_files=[ "res://.import/distant_platforms_2.png-ba010b30987da6d74062ce964ab450ef.stex" ]
 
 [params]
 

+ 0 - 0
2d/platformer/background/scroll_bg_sky.png → 2d/platformer/assets/art/background/sky.png


+ 34 - 0
2d/platformer/assets/art/background/sky.png.import

@@ -0,0 +1,34 @@
+[remap]
+
+importer="texture"
+type="StreamTexture"
+path="res://.import/sky.png-c175b712c46edc17f2b5fc55b9de3c49.stex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://assets/art/background/sky.png"
+dest_files=[ "res://.import/sky.png-c175b712c46edc17f2b5fc55b9de3c49.stex" ]
+
+[params]
+
+compress/mode=0
+compress/lossy_quality=0.7
+compress/hdr_mode=0
+compress/bptc_ldr=0
+compress/normal_map=0
+flags/repeat=1
+flags/filter=false
+flags/mipmaps=false
+flags/anisotropic=false
+flags/srgb=2
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/HDR_as_SRGB=false
+process/invert_color=false
+stream=false
+size_limit=0
+detect_3d=false
+svg/scale=1.0

+ 0 - 0
2d/platformer/coin/coin.png → 2d/platformer/assets/art/coin/coin.png


+ 3 - 3
2d/platformer/coin/coin.png.import → 2d/platformer/assets/art/coin/coin.png.import

@@ -2,15 +2,15 @@
 
 importer="texture"
 type="StreamTexture"
-path="res://.import/coin.png-c9e5c2f51b2a10beb2d794afbbee004f.stex"
+path="res://.import/coin.png-87689993f83db6056500d4fa153313d8.stex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://coin/coin.png"
-dest_files=[ "res://.import/coin.png-c9e5c2f51b2a10beb2d794afbbee004f.stex" ]
+source_file="res://assets/art/coin/coin.png"
+dest_files=[ "res://.import/coin.png-87689993f83db6056500d4fa153313d8.stex" ]
 
 [params]
 

+ 0 - 0
2d/platformer/enemy/enemy.png → 2d/platformer/assets/art/enemy/enemy.png


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

@@ -2,15 +2,15 @@
 
 importer="texture"
 type="StreamTexture"
-path="res://.import/enemy.png-1891d9038eeed672a2459bc4e7db5910.stex"
+path="res://.import/enemy.png-c2f48b2558d3b68a547452306041a310.stex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://enemy/enemy.png"
-dest_files=[ "res://.import/enemy.png-1891d9038eeed672a2459bc4e7db5910.stex" ]
+source_file="res://assets/art/enemy/enemy.png"
+dest_files=[ "res://.import/enemy.png-c2f48b2558d3b68a547452306041a310.stex" ]
 
 [params]
 

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


+ 3 - 3
2d/platformer/platform/moving_platform.png.import → 2d/platformer/assets/art/platforms/moving_platform.png.import

@@ -2,15 +2,15 @@
 
 importer="texture"
 type="StreamTexture"
-path="res://.import/moving_platform.png-7e92061cd93e8b0235df711d3782cd8c.stex"
+path="res://.import/moving_platform.png-479aa8f802d1a4964b138893ada8d372.stex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://platform/moving_platform.png"
-dest_files=[ "res://.import/moving_platform.png-7e92061cd93e8b0235df711d3782cd8c.stex" ]
+source_file="res://assets/art/platforms/moving_platform.png"
+dest_files=[ "res://.import/moving_platform.png-479aa8f802d1a4964b138893ada8d372.stex" ]
 
 [params]
 

+ 0 - 0
2d/platformer/platform/one_way_platform.png → 2d/platformer/assets/art/platforms/one_way_platform.png


+ 3 - 3
2d/platformer/platform/one_way_platform.png.import → 2d/platformer/assets/art/platforms/one_way_platform.png.import

@@ -2,15 +2,15 @@
 
 importer="texture"
 type="StreamTexture"
-path="res://.import/one_way_platform.png-2865772e209813c1636a14aee8d019a3.stex"
+path="res://.import/one_way_platform.png-aaf0179c7171228f27cb489e99e339bd.stex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://platform/one_way_platform.png"
-dest_files=[ "res://.import/one_way_platform.png-2865772e209813c1636a14aee8d019a3.stex" ]
+source_file="res://assets/art/platforms/one_way_platform.png"
+dest_files=[ "res://.import/one_way_platform.png-aaf0179c7171228f27cb489e99e339bd.stex" ]
 
 [params]
 

+ 0 - 0
2d/platformer/player/bullet.png → 2d/platformer/assets/art/player/bullet/bullet.png


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

@@ -2,15 +2,15 @@
 
 importer="texture"
 type="StreamTexture"
-path="res://.import/bullet.png-5615cb9904aab8db60fe6f48e996475f.stex"
+path="res://.import/bullet.png-a148438922f3743d5615622ef8134c9f.stex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://player/bullet.png"
-dest_files=[ "res://.import/bullet.png-5615cb9904aab8db60fe6f48e996475f.stex" ]
+source_file="res://assets/art/player/bullet/bullet.png"
+dest_files=[ "res://.import/bullet.png-a148438922f3743d5615622ef8134c9f.stex" ]
 
 [params]
 

+ 0 - 0
2d/platformer/player/robot_demo.png → 2d/platformer/assets/art/player/robot_demo.png


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

@@ -2,15 +2,15 @@
 
 importer="texture"
 type="StreamTexture"
-path="res://.import/robot_demo.png-7165a8ae8f36b01883df6b585a93f592.stex"
+path="res://.import/robot_demo.png-cd7cbcf6d0c47d4a233ea7ce93b142c2.stex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://player/robot_demo.png"
-dest_files=[ "res://.import/robot_demo.png-7165a8ae8f36b01883df6b585a93f592.stex" ]
+source_file="res://assets/art/player/robot_demo.png"
+dest_files=[ "res://.import/robot_demo.png-cd7cbcf6d0c47d4a233ea7ce93b142c2.stex" ]
 
 [params]
 

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


+ 3 - 3
2d/platformer/tiles_demo.png.import → 2d/platformer/assets/art/tileset/tiles_demo.png.import

@@ -2,15 +2,15 @@
 
 importer="texture"
 type="StreamTexture"
-path="res://.import/tiles_demo.png-7ca5c7c5c02ab8abe0d585a6a8f086bd.stex"
+path="res://.import/tiles_demo.png-f720a7de2b60b01f690cfa3cb881996b.stex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://tiles_demo.png"
-dest_files=[ "res://.import/tiles_demo.png-7ca5c7c5c02ab8abe0d585a6a8f086bd.stex" ]
+source_file="res://assets/art/tileset/tiles_demo.png"
+dest_files=[ "res://.import/tiles_demo.png-f720a7de2b60b01f690cfa3cb881996b.stex" ]
 
 [params]
 

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

@@ -0,0 +1,263 @@
+[gd_resource type="TileSet" load_steps=14 format=2]
+
+[ext_resource path="res://assets/art/tileset/tiles_demo.png" type="Texture" id=1]
+
+[sub_resource type="ConvexPolygonShape2D" id=1]
+points = PoolVector2Array( 0, 12, 64, 12, 64, 64, 0, 64 )
+
+[sub_resource type="ConvexPolygonShape2D" id=2]
+points = PoolVector2Array( 0, 12, 56, 12, 56, 64, 0, 64 )
+
+[sub_resource type="ConvexPolygonShape2D" id=3]
+points = PoolVector2Array( 0, 0, 64, 0, 64, 64, 0, 64 )
+
+[sub_resource type="ConvexPolygonShape2D" id=4]
+points = PoolVector2Array( 0, 12, 64, 12, 64, 64, 0, 64 )
+
+[sub_resource type="ConvexPolygonShape2D" id=5]
+points = PoolVector2Array( 64, 76, 64, 128, 0, 128, 0, 12 )
+
+[sub_resource type="ConvexPolygonShape2D" id=6]
+points = PoolVector2Array( 0, 0, 56, 0, 56, 64, 0, 64 )
+
+[sub_resource type="ConvexPolygonShape2D" id=7]
+points = PoolVector2Array( 56, 12, 64, 12, 64, 64, 0, 64, 0, 0, 56, 0 )
+
+[sub_resource type="ConvexPolygonShape2D" id=8]
+points = PoolVector2Array( 0, 12, 64, 12, 64, 64, 0, 64 )
+
+[sub_resource type="ConvexPolygonShape2D" id=9]
+points = PoolVector2Array( 0, 12, 56, 12, 56, 64, 0, 64 )
+
+[sub_resource type="ConvexPolygonShape2D" id=10]
+points = PoolVector2Array( 0, 0, 64, 0, 64, 64, 0, 64 )
+
+[sub_resource type="ConvexPolygonShape2D" id=11]
+points = PoolVector2Array( 0, 0, 64, 0, 64, 48, 0, 48 )
+
+[sub_resource type="ConvexPolygonShape2D" id=12]
+points = PoolVector2Array( 0, 0, 56, 0, 56, 48, 0, 48 )
+
+[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, 64, 64 )
+0/tile_mode = 0
+0/occluder_offset = Vector2( 0, 0 )
+0/navigation_offset = Vector2( 0, 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( 64, 0, 64, 64 )
+1/tile_mode = 0
+1/occluder_offset = Vector2( 0, 0 )
+1/navigation_offset = Vector2( 0, 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( 128, 128, 64, 128 )
+2/tile_mode = 0
+2/occluder_offset = Vector2( 0, 0 )
+2/navigation_offset = Vector2( 0, 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( 64, 64, 64, 64 )
+3/tile_mode = 0
+3/occluder_offset = Vector2( 0, 0 )
+3/navigation_offset = Vector2( 0, 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( 64, 128, 64, 64 )
+4/tile_mode = 0
+4/occluder_offset = Vector2( 0, 0 )
+4/navigation_offset = Vector2( 0, 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( 128, 0, 64, 64 )
+5/tile_mode = 0
+5/occluder_offset = Vector2( 0, 0 )
+5/navigation_offset = Vector2( 0, 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( 192, 0, 64, 64 )
+6/tile_mode = 0
+6/occluder_offset = Vector2( 0, 0 )
+6/navigation_offset = Vector2( 0, 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, 64, 64, 64 )
+7/tile_mode = 0
+7/occluder_offset = Vector2( 0, 0 )
+7/navigation_offset = Vector2( 0, 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( 384, 64, 64, 64 )
+8/tile_mode = 0
+8/occluder_offset = Vector2( 0, 0 )
+8/navigation_offset = Vector2( 0, 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( 448, 64, 64, 64 )
+9/tile_mode = 0
+9/occluder_offset = Vector2( 0, 0 )
+9/navigation_offset = Vector2( 0, 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( 320, 64, 64, 64 )
+10/tile_mode = 0
+10/occluder_offset = Vector2( 0, 0 )
+10/navigation_offset = Vector2( 0, 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( 256, 128, 64, 64 )
+11/tile_mode = 0
+11/occluder_offset = Vector2( 0, 0 )
+11/navigation_offset = Vector2( 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( 256, 64, 64, 64 )
+12/tile_mode = 0
+12/occluder_offset = Vector2( 0, 0 )
+12/navigation_offset = Vector2( 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( 256, 192, 64, 64 )
+13/tile_mode = 0
+13/occluder_offset = Vector2( 0, 0 )
+13/navigation_offset = Vector2( 0, 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( 256, 0, 64, 64 )
+14/tile_mode = 0
+14/occluder_offset = Vector2( 0, 0 )
+14/navigation_offset = Vector2( 0, 0 )
+14/shapes = [  ]
+14/z_index = 0

+ 0 - 0
2d/platformer/player/osb_fire.png → 2d/platformer/assets/art/ui/touch_button_fire.png


+ 3 - 3
2d/platformer/background/scroll_bg_cloud_1.png.import → 2d/platformer/assets/art/ui/touch_button_fire.png.import

@@ -2,15 +2,15 @@
 
 importer="texture"
 type="StreamTexture"
-path="res://.import/scroll_bg_cloud_1.png-19f55c25a7e1985c92542faa0106888e.stex"
+path="res://.import/touch_button_fire.png-8b72c42a8cb252207ce8948d4b623690.stex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://background/scroll_bg_cloud_1.png"
-dest_files=[ "res://.import/scroll_bg_cloud_1.png-19f55c25a7e1985c92542faa0106888e.stex" ]
+source_file="res://assets/art/ui/touch_button_fire.png"
+dest_files=[ "res://.import/touch_button_fire.png-8b72c42a8cb252207ce8948d4b623690.stex" ]
 
 [params]
 

+ 0 - 0
2d/platformer/player/osb_jump.png → 2d/platformer/assets/art/ui/touch_button_jump.png


+ 3 - 3
2d/platformer/background/scroll_bg_cloud_2.png.import → 2d/platformer/assets/art/ui/touch_button_jump.png.import

@@ -2,15 +2,15 @@
 
 importer="texture"
 type="StreamTexture"
-path="res://.import/scroll_bg_cloud_2.png-869806dcc546591f3d754e3b845c61c9.stex"
+path="res://.import/touch_button_jump.png-f72afeb370538aa951853dbc52052250.stex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://background/scroll_bg_cloud_2.png"
-dest_files=[ "res://.import/scroll_bg_cloud_2.png-869806dcc546591f3d754e3b845c61c9.stex" ]
+source_file="res://assets/art/ui/touch_button_jump.png"
+dest_files=[ "res://.import/touch_button_jump.png-f72afeb370538aa951853dbc52052250.stex" ]
 
 [params]
 

+ 0 - 0
2d/platformer/player/osb_left.png → 2d/platformer/assets/art/ui/touch_button_left.png


+ 3 - 3
2d/platformer/background/scroll_bg_cloud_3.png.import → 2d/platformer/assets/art/ui/touch_button_left.png.import

@@ -2,15 +2,15 @@
 
 importer="texture"
 type="StreamTexture"
-path="res://.import/scroll_bg_cloud_3.png-831c6ed9fa8b4070081428a936bcc2f7.stex"
+path="res://.import/touch_button_left.png-e48f16cfdaae98fdc92a21f20c157c53.stex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://background/scroll_bg_cloud_3.png"
-dest_files=[ "res://.import/scroll_bg_cloud_3.png-831c6ed9fa8b4070081428a936bcc2f7.stex" ]
+source_file="res://assets/art/ui/touch_button_left.png"
+dest_files=[ "res://.import/touch_button_left.png-e48f16cfdaae98fdc92a21f20c157c53.stex" ]
 
 [params]
 

+ 0 - 0
2d/platformer/player/osb_right.png → 2d/platformer/assets/art/ui/touch_button_right.png


+ 3 - 3
2d/platformer/background/scroll_bg_sky.png.import → 2d/platformer/assets/art/ui/touch_button_right.png.import

@@ -2,15 +2,15 @@
 
 importer="texture"
 type="StreamTexture"
-path="res://.import/scroll_bg_sky.png-377ea542199b2e23d7a822ed940ea99e.stex"
+path="res://.import/touch_button_right.png-74bf87a3a0fa663fbb3574844de31372.stex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://background/scroll_bg_sky.png"
-dest_files=[ "res://.import/scroll_bg_sky.png-377ea542199b2e23d7a822ed940ea99e.stex" ]
+source_file="res://assets/art/ui/touch_button_right.png"
+dest_files=[ "res://.import/touch_button_right.png-74bf87a3a0fa663fbb3574844de31372.stex" ]
 
 [params]
 

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


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

@@ -0,0 +1,15 @@
+[remap]
+
+importer="ogg_vorbis"
+type="AudioStreamOGGVorbis"
+path="res://.import/music.ogg-e27216112531ea490cdad574860a53a5.oggstr"
+
+[deps]
+
+source_file="res://assets/audio/music/music.ogg"
+dest_files=[ "res://.import/music.ogg-e27216112531ea490cdad574860a53a5.oggstr" ]
+
+[params]
+
+loop=true
+loop_offset=0

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


+ 21 - 0
2d/platformer/assets/audio/sfx/coin_pickup.wav.import

@@ -0,0 +1,21 @@
+[remap]
+
+importer="wav"
+type="AudioStreamSample"
+path="res://.import/coin_pickup.wav-69d455f3063e30fd994846647c281aea.sample"
+
+[deps]
+
+source_file="res://assets/audio/sfx/coin_pickup.wav"
+dest_files=[ "res://.import/coin_pickup.wav-69d455f3063e30fd994846647c281aea.sample" ]
+
+[params]
+
+force/8_bit=false
+force/mono=false
+force/max_rate=false
+force/max_rate_hz=44100
+edit/trim=true
+edit/normalize=true
+edit/loop=false
+compress/mode=0

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


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

@@ -2,12 +2,12 @@
 
 importer="wav"
 type="AudioStreamSample"
-path="res://.import/sound_shoot.wav-a37772efd1dbcd76c4fe35742f502bb7.sample"
+path="res://.import/explode.wav-302a3de6d016432bf47477d337a4d553.sample"
 
 [deps]
 
-source_file="res://audio/sound_shoot.wav"
-dest_files=[ "res://.import/sound_shoot.wav-a37772efd1dbcd76c4fe35742f502bb7.sample" ]
+source_file="res://assets/audio/sfx/explode.wav"
+dest_files=[ "res://.import/explode.wav-302a3de6d016432bf47477d337a4d553.sample" ]
 
 [params]
 

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


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

@@ -2,12 +2,12 @@
 
 importer="wav"
 type="AudioStreamSample"
-path="res://.import/sound_hit.wav-6c98c4eeb2c6ac3fc45dc4a7ebd8602f.sample"
+path="res://.import/hit.wav-27e178036f6cee6545e9f025a3865a36.sample"
 
 [deps]
 
-source_file="res://audio/sound_hit.wav"
-dest_files=[ "res://.import/sound_hit.wav-6c98c4eeb2c6ac3fc45dc4a7ebd8602f.sample" ]
+source_file="res://assets/audio/sfx/hit.wav"
+dest_files=[ "res://.import/hit.wav-27e178036f6cee6545e9f025a3865a36.sample" ]
 
 [params]
 

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


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

@@ -2,12 +2,12 @@
 
 importer="wav"
 type="AudioStreamSample"
-path="res://.import/sound_coin.wav-e18cceeba8b7dc02bbb940b85bcad99a.sample"
+path="res://.import/jump.wav-127418ac4fc0b61a7fed0684053202c7.sample"
 
 [deps]
 
-source_file="res://audio/sound_coin.wav"
-dest_files=[ "res://.import/sound_coin.wav-e18cceeba8b7dc02bbb940b85bcad99a.sample" ]
+source_file="res://assets/audio/sfx/jump.wav"
+dest_files=[ "res://.import/jump.wav-127418ac4fc0b61a7fed0684053202c7.sample" ]
 
 [params]
 

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


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

@@ -2,12 +2,12 @@
 
 importer="wav"
 type="AudioStreamSample"
-path="res://.import/sound_jump.wav-7e05b84e4426c7461dd15838765e210b.sample"
+path="res://.import/shoot.wav-f3ce9b4ae60220ecd3cf78df7278a10f.sample"
 
 [deps]
 
-source_file="res://audio/sound_jump.wav"
-dest_files=[ "res://.import/sound_jump.wav-7e05b84e4426c7461dd15838765e210b.sample" ]
+source_file="res://assets/audio/sfx/shoot.wav"
+dest_files=[ "res://.import/shoot.wav-f3ce9b4ae60220ecd3cf78df7278a10f.sample" ]
 
 [params]
 

BIN
2d/platformer/assets/theme/fonts/kenney_mini_square.ttf


+ 82 - 0
2d/platformer/assets/theme/user_interface.tres

@@ -0,0 +1,82 @@
+[gd_resource type="Theme" load_steps=8 format=2]
+
+[ext_resource path="res://assets/theme/fonts/kenney_mini_square.ttf" type="DynamicFontData" id=1]
+
+[sub_resource type="StyleBoxFlat" id=1]
+content_margin_left = 6.0
+content_margin_right = 6.0
+content_margin_top = 4.0
+content_margin_bottom = 4.0
+bg_color = Color( 0.18, 0.207, 0.279, 1 )
+border_width_left = 1
+border_width_top = 1
+border_width_right = 1
+border_width_bottom = 1
+border_color = Color( 0.14, 0.161, 0.217, 1 )
+
+[sub_resource type="StyleBoxFlat" id=2]
+content_margin_left = 6.0
+content_margin_right = 6.0
+content_margin_top = 4.0
+content_margin_bottom = 4.0
+bg_color = Color( 0.15, 0.1725, 0.2325, 1 )
+border_width_left = 1
+border_width_top = 1
+border_width_right = 1
+border_width_bottom = 1
+border_color = Color( 0.41, 0.61, 0.91, 1 )
+
+[sub_resource type="StyleBoxFlat" id=3]
+content_margin_left = 6.0
+content_margin_right = 6.0
+content_margin_top = 4.0
+content_margin_bottom = 4.0
+bg_color = Color( 0.15, 0.1725, 0.2325, 1 )
+border_width_left = 1
+border_width_top = 1
+border_width_right = 1
+border_width_bottom = 1
+border_color = Color( 0.4, 0.4225, 0.4825, 1 )
+
+[sub_resource type="StyleBoxFlat" id=4]
+content_margin_left = 6.0
+content_margin_right = 6.0
+content_margin_top = 4.0
+content_margin_bottom = 4.0
+bg_color = Color( 0.15, 0.1725, 0.2325, 1 )
+border_width_left = 1
+border_width_top = 1
+border_width_right = 1
+border_width_bottom = 1
+border_color = Color( 0.125, 0.14375, 0.19375, 1 )
+
+[sub_resource type="StyleBoxFlat" id=5]
+content_margin_left = 6.0
+content_margin_right = 6.0
+content_margin_top = 4.0
+content_margin_bottom = 4.0
+bg_color = Color( 0.15, 0.1725, 0.2325, 1 )
+border_width_left = 1
+border_width_top = 1
+border_width_right = 1
+border_width_bottom = 1
+border_color = Color( 0.41, 0.61, 0.91, 1 )
+
+[sub_resource type="DynamicFont" id=6]
+font_data = ExtResource( 1 )
+
+[resource]
+default_font = SubResource( 6 )
+Button/colors/font_color = Color( 0.8, 0.8075, 0.8275, 1 )
+Button/colors/font_color_disabled = Color( 1, 1, 1, 0.3 )
+Button/colors/font_color_hover = Color( 0.88, 0.8845, 0.8965, 1 )
+Button/colors/font_color_pressed = Color( 0.41, 0.61, 0.91, 1 )
+Button/colors/icon_color_hover = Color( 1.15, 1.15, 1.15, 1 )
+Button/colors/icon_color_pressed = Color( 0.4715, 0.7015, 1.0465, 1 )
+Button/constants/hseparation = 2
+Button/fonts/font = null
+Button/styles/disabled = SubResource( 1 )
+Button/styles/focus = SubResource( 2 )
+Button/styles/hover = SubResource( 3 )
+Button/styles/normal = SubResource( 4 )
+Button/styles/pressed = SubResource( 5 )

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

@@ -1,15 +0,0 @@
-[remap]
-
-importer="ogg_vorbis"
-type="AudioStreamOGGVorbis"
-path="res://.import/music.ogg-552a37c4bfe46d894cb8004cf1c345ad.oggstr"
-
-[deps]
-
-source_file="res://audio/music.ogg"
-dest_files=[ "res://.import/music.ogg-552a37c4bfe46d894cb8004cf1c345ad.oggstr" ]
-
-[params]
-
-loop=true
-loop_offset=0

+ 0 - 21
2d/platformer/audio/sound_explode.wav.import

@@ -1,21 +0,0 @@
-[remap]
-
-importer="wav"
-type="AudioStreamSample"
-path="res://.import/sound_explode.wav-536668d880bfb277b9e5253774598e9e.sample"
-
-[deps]
-
-source_file="res://audio/sound_explode.wav"
-dest_files=[ "res://.import/sound_explode.wav-536668d880bfb277b9e5253774598e9e.sample" ]
-
-[params]
-
-force/8_bit=false
-force/mono=false
-force/max_rate=false
-force/max_rate_hz=44100
-edit/trim=true
-edit/normalize=true
-edit/loop=false
-compress/mode=0

+ 0 - 71
2d/platformer/background/ParallaxBg.tscn

@@ -1,71 +0,0 @@
-[gd_scene load_steps=7 format=2]
-
-[ext_resource path="res://background/scroll_bg_sky.png" type="Texture" id=1]
-[ext_resource path="res://background/scroll_bg_cloud_1.png" type="Texture" id=2]
-[ext_resource path="res://background/scroll_bg_cloud_2.png" type="Texture" id=3]
-[ext_resource path="res://background/scroll_bg_cloud_3.png" type="Texture" id=4]
-[ext_resource path="res://background/scroll_bg_fg_2.png" type="Texture" id=5]
-[ext_resource path="res://background/scroll_bg_fg_1.png" type="Texture" id=6]
-
-[node name="ParallaxBg" type="ParallaxBackground"]
-scroll_base_scale = Vector2( 0.7, 0 )
-
-[node name="Sky" type="ParallaxLayer" parent="."]
-motion_mirroring = Vector2( 800, 0 )
-
-[node name="Sprite" type="Sprite" parent="Sky"]
-scale = Vector2( 128, 0.94 )
-texture = ExtResource( 1 )
-centered = false
-
-[node name="Clouds" type="ParallaxLayer" parent="."]
-motion_scale = Vector2( 0.1, 1 )
-motion_mirroring = Vector2( 800, 0 )
-
-[node name="Sprite1" type="Sprite" parent="Clouds"]
-position = Vector2( 28, 127 )
-texture = ExtResource( 2 )
-centered = false
-
-[node name="Sprite2" type="Sprite" parent="Clouds"]
-position = Vector2( 404, 24 )
-texture = ExtResource( 2 )
-centered = false
-
-[node name="Sprite3" type="Sprite" parent="Clouds"]
-position = Vector2( 154, 46 )
-texture = ExtResource( 3 )
-centered = false
-
-[node name="Sprite4" type="Sprite" parent="Clouds"]
-position = Vector2( 525, 130 )
-texture = ExtResource( 3 )
-centered = false
-
-[node name="Sprite5" type="Sprite" parent="Clouds"]
-position = Vector2( 255, 158 )
-texture = ExtResource( 4 )
-centered = false
-
-[node name="Sprite6" type="Sprite" parent="Clouds"]
-position = Vector2( 674, 70 )
-texture = ExtResource( 4 )
-centered = false
-
-[node name="Mount2" type="ParallaxLayer" parent="."]
-motion_scale = Vector2( 0.2, 1 )
-
-[node name="Sprite" type="Sprite" parent="Mount2"]
-position = Vector2( 0, 353 )
-texture = ExtResource( 5 )
-region_enabled = true
-region_rect = Rect2( 0, 0, 4096, 256 )
-
-[node name="Mount1" type="ParallaxLayer" parent="."]
-motion_scale = Vector2( 0.4, 1 )
-
-[node name="Sprite" type="Sprite" parent="Mount1"]
-position = Vector2( 0, 353 )
-texture = ExtResource( 6 )
-region_enabled = true
-region_rect = Rect2( 0, 0, 4096, 256 )

BIN
2d/platformer/background/scroll_bg_fg_1.png


BIN
2d/platformer/background/scroll_bg_fg_2.png


+ 0 - 140
2d/platformer/coin/Coin.tscn

@@ -1,140 +0,0 @@
-[gd_scene load_steps=11 format=2]
-
-[ext_resource path="res://coin/coin.gd" type="Script" id=1]
-[ext_resource path="res://coin/coin.png" type="Texture" id=2]
-[ext_resource path="res://audio/sound_coin.wav" type="AudioStream" id=3]
-[ext_resource path="res://player/bullet.png" type="Texture" id=4]
-
-[sub_resource type="Animation" id=1]
-resource_name = "spin"
-length = 1.5
-loop = true
-step = 0.25
-tracks/0/type = "value"
-tracks/0/path = NodePath("Sprite:frame")
-tracks/0/interp = 1
-tracks/0/loop_wrap = true
-tracks/0/imported = false
-tracks/0/enabled = true
-tracks/0/keys = {
-"times": PoolRealArray( 0, 0.25, 0.5, 0.75, 1, 1.25, 1.5 ),
-"transitions": PoolRealArray( 1, 1, 1, 1, 1, 1, 1 ),
-"update": 1,
-"values": [ 0, 1, 2, 3, 2, 1, 0 ]
-}
-
-[sub_resource type="Animation" id=2]
-length = 8.0
-step = 0.0
-tracks/0/type = "value"
-tracks/0/path = NodePath("Sprite:frame")
-tracks/0/interp = 1
-tracks/0/loop_wrap = true
-tracks/0/imported = false
-tracks/0/enabled = true
-tracks/0/keys = {
-"times": PoolRealArray( 0 ),
-"transitions": PoolRealArray( 1 ),
-"update": 0,
-"values": [ 0 ]
-}
-tracks/1/type = "method"
-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": PoolRealArray( 2.7 ),
-"transitions": PoolRealArray( 1 ),
-"values": [ {
-"args": [  ],
-"method": "queue_free"
-} ]
-}
-tracks/2/type = "value"
-tracks/2/path = NodePath("Particles:emitting")
-tracks/2/interp = 1
-tracks/2/loop_wrap = true
-tracks/2/imported = false
-tracks/2/enabled = true
-tracks/2/keys = {
-"times": PoolRealArray( 0, 0.98 ),
-"transitions": PoolRealArray( 1, 1 ),
-"update": 1,
-"values": [ true, false ]
-}
-tracks/3/type = "value"
-tracks/3/path = NodePath("Sprite:self_modulate")
-tracks/3/interp = 1
-tracks/3/loop_wrap = true
-tracks/3/imported = false
-tracks/3/enabled = true
-tracks/3/keys = {
-"times": PoolRealArray( 0, 0.33 ),
-"transitions": PoolRealArray( 1, 1 ),
-"update": 0,
-"values": [ Color( 1, 1, 1, 1 ), Color( 1, 1, 1, 0 ) ]
-}
-tracks/4/type = "value"
-tracks/4/path = NodePath("Sound:playing")
-tracks/4/interp = 1
-tracks/4/loop_wrap = true
-tracks/4/imported = false
-tracks/4/enabled = true
-tracks/4/keys = {
-"times": PoolRealArray( 0.01 ),
-"transitions": PoolRealArray( 1 ),
-"update": 1,
-"values": [ true ]
-}
-
-[sub_resource type="CircleShape2D" id=3]
-
-[sub_resource type="CanvasItemMaterial" id=4]
-blend_mode = 1
-
-[sub_resource type="GradientTexture" id=5]
-
-[sub_resource type="ParticlesMaterial" id=6]
-emission_shape = 1
-emission_sphere_radius = 10.0
-flag_disable_z = true
-gravity = Vector3( 0, 90, 0 )
-initial_velocity = 121.98
-angular_velocity = -2.49891e+38
-orbit_velocity = 0.0
-orbit_velocity_random = 0.0
-scale = 0.2
-color_ramp = SubResource( 5 )
-
-[node name="Coin" type="Area2D"]
-script = ExtResource( 1 )
-
-[node name="Sprite" type="Sprite" parent="."]
-texture = ExtResource( 2 )
-hframes = 4
-
-[node name="Anim" type="AnimationPlayer" parent="."]
-autoplay = "spin"
-anims/spin = SubResource( 1 )
-anims/taken = SubResource( 2 )
-
-[node name="Collision" type="CollisionShape2D" parent="."]
-shape = SubResource( 3 )
-
-[node name="Sound" type="AudioStreamPlayer2D" parent="."]
-stream = ExtResource( 3 )
-
-[node name="Particles" type="Particles2D" parent="."]
-material = SubResource( 4 )
-emitting = false
-lifetime = 2.0
-explosiveness = 1.0
-process_material = SubResource( 6 )
-texture = ExtResource( 4 )
-
-[node name="Enabler" type="VisibilityEnabler2D" parent="."]
-pause_particles = false
-
-[connection signal="body_entered" from="." to="." method="_on_coin_body_enter"]

+ 0 - 11
2d/platformer/coin/coin.gd

@@ -1,11 +0,0 @@
-extends Area2D
-
-class_name Coin
-
-
-var taken = false
-
-func _on_coin_body_enter(body):
-	if not taken and body is Player:
-		($Anim as AnimationPlayer).play("taken")
-		taken = true

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

@@ -1,50 +0,0 @@
-extends KinematicBody2D
-
-class_name Enemy
-
-
-const GRAVITY_VEC = Vector2(0, 900)
-const FLOOR_NORMAL = Vector2(0, -1)
-
-const STATE_WALKING = 0
-const STATE_KILLED = 1
-const WALK_SPEED = 70 
-
-var linear_velocity = Vector2()
-var direction = -1
-var anim = ""
-
-# state machine
-var state = STATE_WALKING
-
-onready var DetectFloorLeft = $DetectFloorLeft
-onready var DetectWallLeft = $DetectWallLeft
-onready var DetectFloorRight = $DetectFloorRight
-onready var DetectWallRight = $DetectWallRight
-onready var sprite = $Sprite
-
-func _physics_process(delta):
-	var new_anim = "idle"
-
-	if state == STATE_WALKING:
-		linear_velocity += GRAVITY_VEC * delta
-		linear_velocity.x = direction * WALK_SPEED
-		linear_velocity = move_and_slide(linear_velocity, FLOOR_NORMAL)
-
-		if not DetectFloorLeft.is_colliding() or DetectWallLeft.is_colliding():
-			direction = 1.0
-
-		if not DetectFloorRight.is_colliding() or DetectWallRight.is_colliding():
-			direction = -1.0
-
-		sprite.scale = Vector2(direction, 1.0)
-		new_anim = "walk"
-	else:
-		new_anim = "explode"
-
-	if anim != new_anim:
-		anim = new_anim
-		($Anim as AnimationPlayer).play(anim)
-
-func hit_by_bullet():
-	state = STATE_KILLED

+ 0 - 16
2d/platformer/platform/MovingPlatform.tscn

@@ -1,16 +0,0 @@
-[gd_scene load_steps=3 format=2]
-
-[ext_resource path="res://platform/moving_platform.gd" type="Script" id=1]
-[ext_resource path="res://platform/moving_platform.png" type="Texture" id=2]
-
-[node name="MovingPlatform" type="Node2D"]
-script = ExtResource( 1 )
-
-[node name="Platform" type="KinematicBody2D" parent="."]
-
-[node name="Sprite" type="Sprite" parent="Platform"]
-texture = ExtResource( 2 )
-
-[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="Platform"]
-polygon = PoolVector2Array( -88, -24, 88, -24, 88, 24, -88, 24 )
-

+ 0 - 17
2d/platformer/platform/OneWayPlatform.tscn

@@ -1,17 +0,0 @@
-[gd_scene load_steps=3 format=2]
-
-[ext_resource path="res://platform/one_way_platform.png" type="Texture" id=1]
-
-[sub_resource type="RectangleShape2D" id=1]
-extents = Vector2( 100, 10 )
-
-[node name="OneWayPlatform" type="StaticBody2D"]
-
-[node name="Sprite" type="Sprite" parent="."]
-texture = ExtResource( 1 )
-
-[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
-position = Vector2( 1.46304, -13.1672 )
-shape = SubResource( 1 )
-one_way_collision = true
-

+ 0 - 17
2d/platformer/platform/moving_platform.gd

@@ -1,17 +0,0 @@
-extends Node2D
-
-class_name MovingPlatform
-
-
-# Member variables
-export var motion = Vector2()
-export var cycle = 1.0
-var accum = 0.0
-
-func _physics_process(delta):
-	accum += delta * (1.0 / cycle) * PI * 2.0
-	accum = fmod(accum, PI * 2.0)
-	var d = sin(accum)
-	var xf = Transform2D()
-	xf[2] = motion * d
-	($Platform as KinematicBody2D).transform = xf

BIN
2d/platformer/platform/moving_platform.png


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

@@ -1,11 +0,0 @@
-extends RigidBody2D
-
-class_name Bullet
-
-
-func _on_bullet_body_enter(body):
-	if body.has_method("hit_by_bullet"):
-		body.call("hit_by_bullet")
-
-func _on_Timer_timeout():
-	($Anim as AnimationPlayer).play("shutdown")

+ 0 - 34
2d/platformer/player/osb_left.png.import

@@ -1,34 +0,0 @@
-[remap]
-
-importer="texture"
-type="StreamTexture"
-path="res://.import/osb_left.png-95ec3a371455889d592aa8cae0a755bc.stex"
-metadata={
-"vram_texture": false
-}
-
-[deps]
-
-source_file="res://player/osb_left.png"
-dest_files=[ "res://.import/osb_left.png-95ec3a371455889d592aa8cae0a755bc.stex" ]
-
-[params]
-
-compress/mode=0
-compress/lossy_quality=0.7
-compress/hdr_mode=0
-compress/bptc_ldr=0
-compress/normal_map=0
-flags/repeat=0
-flags/filter=false
-flags/mipmaps=false
-flags/anisotropic=false
-flags/srgb=2
-process/fix_alpha_border=true
-process/premult_alpha=false
-process/HDR_as_SRGB=false
-process/invert_color=false
-stream=false
-size_limit=0
-detect_3d=false
-svg/scale=1.0

+ 0 - 34
2d/platformer/player/osb_right.png.import

@@ -1,34 +0,0 @@
-[remap]
-
-importer="texture"
-type="StreamTexture"
-path="res://.import/osb_right.png-db9bb4651315f3d42b87bd17a86cce76.stex"
-metadata={
-"vram_texture": false
-}
-
-[deps]
-
-source_file="res://player/osb_right.png"
-dest_files=[ "res://.import/osb_right.png-db9bb4651315f3d42b87bd17a86cce76.stex" ]
-
-[params]
-
-compress/mode=0
-compress/lossy_quality=0.7
-compress/hdr_mode=0
-compress/bptc_ldr=0
-compress/normal_map=0
-flags/repeat=0
-flags/filter=false
-flags/mipmaps=false
-flags/anisotropic=false
-flags/srgb=2
-process/fix_alpha_border=true
-process/premult_alpha=false
-process/HDR_as_SRGB=false
-process/invert_color=false
-stream=false
-size_limit=0
-detect_3d=false
-svg/scale=1.0

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

@@ -1,97 +0,0 @@
-extends KinematicBody2D
-
-class_name Player
-
-
-const GRAVITY_VEC = Vector2(0, 900)
-const FLOOR_NORMAL = Vector2(0, -1)
-const SLOPE_SLIDE_STOP = 25.0
-const WALK_SPEED = 250 # pixels/sec
-const JUMP_SPEED = 480
-const SIDING_CHANGE_SPEED = 10
-const BULLET_VELOCITY = 1000
-const SHOOT_TIME_SHOW_WEAPON = 0.2
-
-var linear_vel = Vector2()
-var shoot_time = 99999 # time since last shot
-
-var anim = ""
-
-# cache the sprite here for fast access (we will set scale to flip it often)
-onready var sprite = $Sprite
-# cache bullet for fast access
-var Bullet = preload("res://player/Bullet.tscn")
-
-
-func _physics_process(delta):
-	# Increment counters
-	shoot_time += delta
-
-	### MOVEMENT ###
-
-	# Apply gravity
-	linear_vel += delta * GRAVITY_VEC
-	# Move and slide
-	linear_vel = move_and_slide(linear_vel, FLOOR_NORMAL, SLOPE_SLIDE_STOP)
-	# Detect if we are on floor - only works if called *after* move_and_slide
-	var on_floor = is_on_floor()
-
-	### CONTROL ###
-
-	# Horizontal movement
-	var target_speed = 0
-	if Input.is_action_pressed("move_left"):
-		target_speed -= 1
-	if Input.is_action_pressed("move_right"):
-		target_speed += 1
-
-	target_speed *= WALK_SPEED
-	linear_vel.x = lerp(linear_vel.x, target_speed, 0.1)
-
-	# Jumping
-	if on_floor and Input.is_action_just_pressed("jump"):
-		linear_vel.y = -JUMP_SPEED
-		($SoundJump as AudioStreamPlayer2D).play()
-
-	# Shooting
-	if Input.is_action_just_pressed("shoot"):
-		var bullet = Bullet.instance()
-		bullet.position = ($Sprite/BulletShoot as Position2D).global_position # use node for shoot position
-		bullet.linear_velocity = Vector2(sprite.scale.x * BULLET_VELOCITY, 0)
-		bullet.add_collision_exception_with(self) # don't want player to collide with bullet
-		get_parent().add_child(bullet) # don't want bullet to move with me, so add it as child of parent
-		($SoundShoot as AudioStreamPlayer2D).play()
-		shoot_time = 0
-
-	### ANIMATION ###
-
-	var new_anim = "idle"
-
-	if on_floor:
-		if linear_vel.x < -SIDING_CHANGE_SPEED:
-			sprite.scale.x = -1
-			new_anim = "run"
-
-		if linear_vel.x > SIDING_CHANGE_SPEED:
-			sprite.scale.x = 1
-			new_anim = "run"
-	else:
-		# We want the character to immediately change facing side when the player
-		# tries to change direction, during air control.
-		# This allows for example the player to shoot quickly left then right.
-		if Input.is_action_pressed("move_left") and not Input.is_action_pressed("move_right"):
-			sprite.scale.x = -1
-		if Input.is_action_pressed("move_right") and not Input.is_action_pressed("move_left"):
-			sprite.scale.x = 1
-
-		if linear_vel.y < 0:
-			new_anim = "jumping"
-		else:
-			new_anim = "falling"
-
-	if shoot_time < SHOOT_TIME_SHOW_WEAPON:
-		new_anim += "_weapon"
-
-	if new_anim != anim:
-		anim = new_anim
-		($Anim as AnimationPlayer).play(anim)

+ 41 - 14
2d/platformer/project.godot

@@ -9,43 +9,49 @@
 config_version=4
 
 _global_script_classes=[ {
+"base": "KinematicBody2D",
+"class": "Actor",
+"language": "GDScript",
+"path": "res://src/Actors/Actor.gd"
+}, {
 "base": "RigidBody2D",
 "class": "Bullet",
 "language": "GDScript",
-"path": "res://player/bullet.gd"
+"path": "res://src/Objects/Bullet.gd"
 }, {
 "base": "Area2D",
 "class": "Coin",
 "language": "GDScript",
-"path": "res://coin/coin.gd"
+"path": "res://src/Objects/Coin.gd"
 }, {
-"base": "KinematicBody2D",
+"base": "Actor",
 "class": "Enemy",
 "language": "GDScript",
-"path": "res://enemy/enemy.gd"
+"path": "res://src/Actors/Enemy.gd"
 }, {
-"base": "Node2D",
-"class": "MovingPlatform",
+"base": "Position2D",
+"class": "Gun",
 "language": "GDScript",
-"path": "res://platform/moving_platform.gd"
+"path": "res://src/Actors/Gun.gd"
 }, {
-"base": "KinematicBody2D",
+"base": "Actor",
 "class": "Player",
 "language": "GDScript",
-"path": "res://player/player.gd"
+"path": "res://src/Actors/Player.gd"
 } ]
 _global_script_class_icons={
+"Actor": "",
 "Bullet": "",
 "Coin": "",
 "Enemy": "",
-"MovingPlatform": "",
+"Gun": "",
 "Player": ""
 }
 
 [application]
 
 config/name="Platformer 2D"
-run/main_scene="res://Stage.tscn"
+run/main_scene="res://src/Main/Game.tscn"
 config/icon="res://icon.png"
 target_fps="60"
 
@@ -61,6 +67,7 @@ gdscript/warnings/unsafe_call_argument=true
 
 window/size/width=800
 window/size/height=480
+window/dpi/allow_hidpi=true
 window/stretch/mode="2d"
 window/stretch/aspect="keep_height"
 stretch/aspect="keep_height"
@@ -80,18 +87,23 @@ jump={
 "deadzone": 0.5,
 "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777232,"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,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":87,"unicode":0,"echo":false,"script":null)
  ]
 }
 move_left={
 "deadzone": 0.5,
 "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777231,"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,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":65,"unicode":0,"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,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777233,"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,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":68,"unicode":0,"echo":false,"script":null)
+, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":1.0,"script":null)
  ]
 }
 shoot={
@@ -99,18 +111,33 @@ shoot={
 "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":32,"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)
 , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":90,"unicode":0,"echo":false,"script":null)
+, Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"button_mask":0,"position":Vector2( 0, 0 ),"global_position":Vector2( 0, 0 ),"factor":1.0,"button_index":1,"pressed":false,"doubleclick":false,"script":null)
  ]
 }
-spawn={
+toggle_fullscreen={
 "deadzone": 0.5,
-"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777244,"unicode":0,"echo":false,"script":null)
+"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777254,"unicode":0,"echo":false,"script":null)
+ ]
+}
+toggle_pause={
+"deadzone": 0.5,
+"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777217,"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)
  ]
 }
 
+[layer_names]
+
+2d_physics/layer_1="player"
+2d_physics/layer_2="enemies"
+2d_physics/layer_3="coins"
+2d_physics/layer_4="platforms"
+2d_physics/layer_5="ground"
+
 [physics]
 
 2d/default_gravity=700
+2d/gravity_default=1800.0
 
 [rasterizer]
 
@@ -124,9 +151,9 @@ mipmap_policy=1
 
 quality/intended_usage/framebuffer_allocation=0
 quality/intended_usage/framebuffer_allocation.mobile=1
+quality/2d/use_pixel_snap=true
 quality/filters/anisotropic_filter_level=2
 quality/filters/use_nearest_mipmap_filter=true
-quality/voxel_cone_tracing/high_quality=false
 quality/depth/hdr=false
 
 [texture_import]

+ 0 - 0
2d/platformer/screenshots/.gdignore


BIN
2d/platformer/screenshots/layout.png


BIN
2d/platformer/screenshots/shoot.png


+ 18 - 0
2d/platformer/src/Actors/Actor.gd

@@ -0,0 +1,18 @@
+class_name Actor
+extends KinematicBody2D
+
+# Both the Player and Enemy inherit this scene as they have shared behaviours
+# such as speed and are affected by gravity.
+
+
+export var speed = Vector2(400.0, 500.0)
+export(float) var gravity = ProjectSettings.get("physics/2d/gravity_default")
+
+const FLOOR_NORMAL = Vector2.UP
+
+var _velocity = Vector2.ZERO
+
+# _physics_process is called after the inherited _physics_process function.
+# This allows the Player and Enemy scenes to be affected by gravity.
+func _physics_process(delta):
+	_velocity.y += gravity * delta

+ 79 - 0
2d/platformer/src/Actors/Enemy.gd

@@ -0,0 +1,79 @@
+class_name Enemy
+extends Actor
+
+
+enum State {
+	WALKING,
+	DEAD
+}
+
+var _state = State.WALKING
+
+onready var platform_detector = $PlatformDetector
+onready var floor_detector_left = $FloorDetectorLeft
+onready var floor_detector_right = $FloorDetectorRight
+onready var sprite = $Sprite
+onready var animation_player = $AnimationPlayer
+
+# This function is called when the scene enters the scene tree.
+# We can initialize variables here.
+func _ready():
+	_velocity.x = speed.x
+
+# Physics process is a built-in loop in Godot.
+# If you define _physics_process on a node, Godot will call it every frame.
+
+# At a glance, you can see that the physics process loop:
+# 1. Calculates the move velocity.
+# 2. Moves the character.
+# 3. Updates the sprite direction.
+# 4. Updates the animation.
+
+# Splitting the physics process logic into functions not only makes it
+# easier to read, it help to change or improve the code later on:
+# - If you need to change a calculation, you can use Go To -> Function
+#   (Ctrl Alt F) to quickly jump to the corresponding function.
+# - If you split the character into a state machine or more advanced pattern,
+#   you can easily move individual functions.
+func _physics_process(_delta):
+	_velocity = calculate_move_velocity(_velocity)
+
+	# We only update the y value of _velocity as we want to handle the horizontal movement ourselves.
+	_velocity.y = move_and_slide(_velocity, FLOOR_NORMAL).y
+
+	# We flip the Sprite depending on which way the enemy is moving.
+	sprite.scale.x = 1 if _velocity.x > 0 else -1
+
+	var animation = get_new_animation()
+	if animation != animation_player.current_animation:
+		animation_player.play(animation)
+
+
+# This function calculates a new velocity whenever you need it.
+# If the enemy encounters a wall or an edge, the horizontal velocity is flipped.
+func calculate_move_velocity(linear_velocity):
+	var velocity = linear_velocity
+
+	if not floor_detector_left.is_colliding():
+		velocity.x = speed.x
+	elif not floor_detector_right.is_colliding():
+		velocity.x = -speed.x
+
+	if is_on_wall():
+		velocity.x *= -1
+
+	return velocity
+
+
+func destroy():
+	_state = State.DEAD
+	_velocity = Vector2.ZERO
+
+
+func get_new_animation():
+	var animation_new = ""
+	if _state == State.WALKING:
+		animation_new = "walk" if abs(_velocity.x) > 0 else "idle"
+	else:
+		animation_new = "destroy"
+	return animation_new

+ 110 - 73
2d/platformer/enemy/Enemy.tscn → 2d/platformer/src/Actors/Enemy.tscn

@@ -1,15 +1,16 @@
-[gd_scene load_steps=13 format=2]
-
-[ext_resource path="res://enemy/enemy.gd" type="Script" id=1]
-[ext_resource path="res://enemy/enemy.png" type="Texture" id=2]
-[ext_resource path="res://player/bullet.png" type="Texture" id=3]
-[ext_resource path="res://audio/sound_hit.wav" type="AudioStream" id=4]
-[ext_resource path="res://audio/sound_explode.wav" type="AudioStream" id=5]
-
-[sub_resource type="Animation" id=1]
-resource_name = "explode"
-length = 5.0
-step = 0.0
+[gd_scene load_steps=15 format=2]
+
+[ext_resource path="res://assets/art/player/bullet/bullet.png" type="Texture" 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="Texture" id=4]
+[ext_resource path="res://src/Actors/Enemy.gd" type="Script" id=5]
+
+[sub_resource type="CanvasItemMaterial" id=1]
+
+[sub_resource type="Animation" id=2]
+resource_name = "destroy"
+length = 1.5
 tracks/0/type = "value"
 tracks/0/path = NodePath("Sprite:frame")
 tracks/0/interp = 1
@@ -20,7 +21,7 @@ tracks/0/keys = {
 "times": PoolRealArray( 0 ),
 "transitions": PoolRealArray( 1 ),
 "update": 0,
-"values": [ 0 ]
+"values": [ 7 ]
 }
 tracks/1/type = "value"
 tracks/1/path = NodePath("Sprite:rotation_degrees")
@@ -29,8 +30,8 @@ tracks/1/loop_wrap = true
 tracks/1/imported = false
 tracks/1/enabled = true
 tracks/1/keys = {
-"times": PoolRealArray( 0, 3.2 ),
-"transitions": PoolRealArray( 0.5, 1 ),
+"times": PoolRealArray( 0, 0.8 ),
+"transitions": PoolRealArray( 0.0796601, 1 ),
 "update": 0,
 "values": [ 0.0, 180.0 ]
 }
@@ -41,10 +42,10 @@ tracks/2/loop_wrap = true
 tracks/2/imported = false
 tracks/2/enabled = true
 tracks/2/keys = {
-"times": PoolRealArray( 2.6, 3.4 ),
-"transitions": PoolRealArray( 1, 1 ),
+"times": PoolRealArray( 0, 0.3, 0.9 ),
+"transitions": PoolRealArray( 1, 1, 1 ),
 "update": 0,
-"values": [ Color( 1, 1, 1, 1 ), Color( 1, 1, 1, 0 ) ]
+"values": [ Color( 1, 1, 1, 1 ), Color( 1, 1, 1, 1 ), Color( 1, 1, 1, 0 ) ]
 }
 tracks/3/type = "value"
 tracks/3/path = NodePath("Explosion:emitting")
@@ -53,7 +54,7 @@ tracks/3/loop_wrap = true
 tracks/3/imported = false
 tracks/3/enabled = true
 tracks/3/keys = {
-"times": PoolRealArray( 0, 2.8 ),
+"times": PoolRealArray( 0, 0.8 ),
 "transitions": PoolRealArray( 1, 1 ),
 "update": 1,
 "values": [ false, true ]
@@ -65,13 +66,13 @@ tracks/4/loop_wrap = true
 tracks/4/imported = false
 tracks/4/enabled = true
 tracks/4/keys = {
-"times": PoolRealArray( 2.8, 3.4 ),
+"times": PoolRealArray( 0.4, 0.8 ),
 "transitions": PoolRealArray( 1, 1 ),
 "update": 0,
 "values": [ 1.0, 4.0 ]
 }
 tracks/5/type = "value"
-tracks/5/path = NodePath("SoundHit:playing")
+tracks/5/path = NodePath("Hit:playing")
 tracks/5/interp = 1
 tracks/5/loop_wrap = true
 tracks/5/imported = false
@@ -83,13 +84,13 @@ tracks/5/keys = {
 "values": [ true ]
 }
 tracks/6/type = "value"
-tracks/6/path = NodePath("SoundExplode:playing")
+tracks/6/path = NodePath("Explode:playing")
 tracks/6/interp = 1
 tracks/6/loop_wrap = true
 tracks/6/imported = false
 tracks/6/enabled = true
 tracks/6/keys = {
-"times": PoolRealArray( 2.9 ),
+"times": PoolRealArray( 0.6 ),
 "transitions": PoolRealArray( 1 ),
 "update": 1,
 "values": [ true ]
@@ -101,15 +102,39 @@ tracks/7/loop_wrap = true
 tracks/7/imported = false
 tracks/7/enabled = true
 tracks/7/keys = {
-"times": PoolRealArray( 4.2 ),
+"times": PoolRealArray( 1.5 ),
 "transitions": PoolRealArray( 1 ),
 "values": [ {
 "args": [  ],
 "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 = {
+"times": PoolRealArray( 0 ),
+"transitions": PoolRealArray( 1 ),
+"update": 1,
+"values": [ 0 ]
+}
+tracks/9/type = "value"
+tracks/9/path = NodePath("Sprite:position")
+tracks/9/interp = 1
+tracks/9/loop_wrap = true
+tracks/9/imported = false
+tracks/9/enabled = true
+tracks/9/keys = {
+"times": PoolRealArray( 0, 0.2, 0.4 ),
+"transitions": PoolRealArray( 2.2974, 0.183011, 1 ),
+"update": 0,
+"values": [ Vector2( 0, 0 ), Vector2( 0, -32 ), Vector2( 0, 0 ) ]
+}
 
-[sub_resource type="Animation" id=2]
+[sub_resource type="Animation" id=3]
 length = 6.75
 loop = true
 step = 0.25
@@ -126,8 +151,7 @@ tracks/0/keys = {
 "values": [ 5, 6, 5, 6, 5, 6, 7, 6, 7, 5 ]
 }
 
-[sub_resource type="Animation" id=3]
-resource_name = "walk"
+[sub_resource type="Animation" id=4]
 length = 1.25
 loop = true
 step = 0.25
@@ -144,8 +168,6 @@ tracks/0/keys = {
 "values": [ 0, 1, 2, 3, 4, 0 ]
 }
 
-[sub_resource type="CanvasItemMaterial" id=4]
-
 [sub_resource type="CapsuleShape2D" id=5]
 radius = 13.4556
 height = 14.2002
@@ -153,58 +175,73 @@ height = 14.2002
 [sub_resource type="CanvasItemMaterial" id=6]
 blend_mode = 1
 
-[sub_resource type="ParticlesMaterial" id=7]
+[sub_resource type="Gradient" id=7]
+offsets = PoolRealArray( 0.562963, 1 )
+colors = PoolColorArray( 1, 1, 1, 1, 0, 0, 0, 1 )
+
+[sub_resource type="GradientTexture" id=8]
+gradient = SubResource( 7 )
+width = 256
+
+[sub_resource type="ParticlesMaterial" id=9]
+emission_shape = 1
+emission_sphere_radius = 8.0
 flag_disable_z = true
-gravity = Vector3( 0, 98, 0 )
+spread = 180.0
+gravity = Vector3( 0, 250, 0 )
+initial_velocity = 120.0
+initial_velocity_random = 0.5
 orbit_velocity = 0.0
 orbit_velocity_random = 0.0
+angle = 720.0
+angle_random = 1.0
+scale = 0.4
+scale_random = 1.0
+color_ramp = SubResource( 8 )
+hue_variation = 0.05
+hue_variation_random = 0.46
 
 [node name="Enemy" type="KinematicBody2D"]
-script = ExtResource( 1 )
+collision_layer = 2
+collision_mask = 24
+script = ExtResource( 5 )
+speed = Vector2( 150, 500 )
+gravity = 1800.0
 
-[node name="Enabler" type="VisibilityEnabler2D" parent="."]
-position = Vector2( 16.2569, 11.0034 )
-scale = Vector2( 23.5056, 10.8629 )
-pause_particles = false
+[node name="PlatformDetector" type="RayCast2D" parent="."]
+position = Vector2( 0, 12 )
+enabled = true
+cast_to = Vector2( 0, 8 )
+collision_mask = 8
 
-[node name="Anim" type="AnimationPlayer" parent="."]
-anims/explode = SubResource( 1 )
-anims/idle = SubResource( 2 )
-anims/walk = SubResource( 3 )
+[node name="FloorDetectorLeft" type="RayCast2D" parent="."]
+position = Vector2( -30, -8 )
+enabled = true
+cast_to = Vector2( 0, 70 )
+collision_mask = 24
+
+[node name="FloorDetectorRight" type="RayCast2D" parent="."]
+position = Vector2( 31.16, -8 )
+enabled = true
+cast_to = Vector2( 0, 70 )
+collision_mask = 24
 
 [node name="Sprite" type="Sprite" parent="."]
-material = SubResource( 4 )
-texture = ExtResource( 2 )
+material = SubResource( 1 )
+texture = ExtResource( 4 )
 flip_h = true
 hframes = 8
+frame = 5
+
+[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
+anims/destroy = SubResource( 2 )
+anims/idle = SubResource( 3 )
+anims/walk = SubResource( 4 )
 
 [node name="CollisionShape2D" type="CollisionShape2D" parent="."]
-position = Vector2( -0.00525069, -0.727495 )
 rotation = -1.5708
 shape = SubResource( 5 )
 
-[node name="DetectFloorLeft" type="RayCast2D" parent="."]
-position = Vector2( -33.2868, -9.34363 )
-enabled = true
-cast_to = Vector2( 0, 45 )
-
-[node name="DetectWallLeft" type="RayCast2D" parent="."]
-position = Vector2( -12.1361, -0.739977 )
-rotation = 1.5708
-enabled = true
-cast_to = Vector2( 0, 20 )
-
-[node name="DetectWallRight" type="RayCast2D" parent="."]
-position = Vector2( 3.2788, -0.381488 )
-rotation = -1.5708
-enabled = true
-cast_to = Vector2( 0, 20 )
-
-[node name="DetectFloorRight" type="RayCast2D" parent="."]
-position = Vector2( 29.1987, -9.34363 )
-enabled = true
-cast_to = Vector2( 0, 45 )
-
 [node name="Explosion" type="Particles2D" parent="."]
 self_modulate = Color( 1, 1, 1, 0.12 )
 material = SubResource( 6 )
@@ -213,13 +250,13 @@ amount = 32
 lifetime = 0.5
 one_shot = true
 speed_scale = 1.2
-explosiveness = 0.1
-process_material = SubResource( 7 )
-texture = ExtResource( 3 )
-
-[node name="SoundHit" type="AudioStreamPlayer2D" parent="."]
-stream = ExtResource( 4 )
+explosiveness = 0.76
+draw_order = 215832976
+process_material = SubResource( 9 )
+texture = ExtResource( 1 )
 
-[node name="SoundExplode" type="AudioStreamPlayer2D" parent="."]
-stream = ExtResource( 5 )
+[node name="Hit" type="AudioStreamPlayer2D" parent="."]
+stream = ExtResource( 3 )
 
+[node name="Explode" type="AudioStreamPlayer2D" parent="."]
+stream = ExtResource( 2 )

+ 24 - 0
2d/platformer/src/Actors/Gun.gd

@@ -0,0 +1,24 @@
+class_name Gun
+extends Position2D
+# Represents a weapon that spawns and shoots bullets.
+# The Cooldown timer controls the cooldown duration between shots.
+
+
+const BULLET_VELOCITY = 1000.0
+const Bullet = preload("res://src/Objects/Bullet.tscn")
+
+onready var sound_shoot = $Shoot
+onready var timer = $Cooldown
+
+
+func shoot(direction = 1):
+	if not timer.is_stopped():
+		return false
+	var bullet = Bullet.instance()
+	bullet.global_position = global_position
+	bullet.linear_velocity = Vector2(direction * BULLET_VELOCITY, 0)
+
+	bullet.set_as_toplevel(true)
+	add_child(bullet)
+	sound_shoot.play()
+	return true

+ 96 - 0
2d/platformer/src/Actors/Player.gd

@@ -0,0 +1,96 @@
+class_name Player
+extends Actor
+
+
+const FLOOR_DETECT_DISTANCE = 40.0
+
+onready var platform_detector = $PlatformDetector
+onready var sprite = $Sprite
+onready var animation_player = $AnimationPlayer
+onready var shoot_timer = $ShootAnimation
+onready var gun = $Sprite/Gun
+
+
+# Physics process is a built-in loop in Godot.
+# If you define _physics_process on a node, Godot will call it every frame.
+
+# We use separate functions to calculate the direction and velocity to make this one easier to read.
+# At a glance, you can see that the physics process loop:
+# 1. Calculates the move direction.
+# 2. Calculates the move velocity.
+# 3. Moves the character.
+# 4. Updates the sprite direction.
+# 5. Shoots bullets.
+# 6. Updates the animation.
+
+# Splitting the physics process logic into functions not only makes it
+# easier to read, it help to change or improve the code later on:
+# - If you need to change a calculation, you can use Go To -> Function
+#   (Ctrl Alt F) to quickly jump to the corresponding function.
+# - If you split the character into a state machine or more advanced pattern,
+#   you can easily move individual functions.
+func _physics_process(_delta):
+	var direction = get_direction()
+
+	var is_jump_interrupted = Input.is_action_just_released("jump") and _velocity.y < 0.0
+	_velocity = calculate_move_velocity(_velocity, direction, speed, is_jump_interrupted)
+
+	var snap_vector = Vector2.DOWN * FLOOR_DETECT_DISTANCE if direction.y == 0.0 else Vector2.ZERO
+	var is_on_platform = platform_detector.is_colliding()
+	_velocity = move_and_slide_with_snap(
+		_velocity, snap_vector, FLOOR_NORMAL, not is_on_platform, 4, 0.9, false
+	)
+
+	# When the character’s direction changes, we want to to scale the Sprite accordingly to flip it.
+	# This will make Robi face left or right depending on the direction you move.
+	if direction.x != 0:
+		sprite.scale.x = direction.x
+
+	# We use the sprite's scale to store Robi’s look direction which allows us to shoot
+	# bullets forward.
+	# There are many situations like these where you can reuse existing properties instead of
+	# creating new variables.
+	var is_shooting = false
+	if Input.is_action_just_pressed("shoot"):
+		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_direction():
+	return Vector2(
+		Input.get_action_strength("move_right") - Input.get_action_strength("move_left"),
+		-Input.get_action_strength("jump") if is_on_floor() and Input.is_action_just_pressed("jump") else 0.0
+	)
+
+
+# This function calculates a new velocity whenever you need it.
+# It allows you to interrupt jumps.
+func calculate_move_velocity(
+		linear_velocity,
+		direction,
+		speed,
+		is_jump_interrupted
+	):
+	var velocity = linear_velocity
+	velocity.x = speed.x * direction.x
+	if direction.y != 0.0:
+		velocity.y = speed.y * direction.y
+	if is_jump_interrupted:
+		velocity.y = 0.0
+	return velocity
+
+
+func get_new_animation(is_shooting = false):
+	var animation_new = ""
+	if is_on_floor():
+		animation_new = "run" if abs(_velocity.x) > 0.1 else "idle"
+	else:
+		animation_new = "falling" if _velocity.y > 0 else "jumping"
+	if is_shooting:
+		animation_new += "_weapon"
+	return animation_new

+ 48 - 37
2d/platformer/player/Player.tscn → 2d/platformer/src/Actors/Player.tscn

@@ -1,13 +1,14 @@
-[gd_scene load_steps=20 format=2]
+[gd_scene load_steps=21 format=2]
 
-[ext_resource path="res://player/player.gd" type="Script" id=1]
-[ext_resource path="res://player/robot_demo.png" type="Texture" id=2]
-[ext_resource path="res://audio/sound_jump.wav" type="AudioStream" id=3]
-[ext_resource path="res://audio/sound_shoot.wav" type="AudioStream" id=4]
-[ext_resource path="res://player/osb_left.png" type="Texture" id=5]
-[ext_resource path="res://player/osb_right.png" type="Texture" id=6]
-[ext_resource path="res://player/osb_jump.png" type="Texture" id=7]
-[ext_resource path="res://player/osb_fire.png" type="Texture" id=8]
+[ext_resource path="res://src/Actors/Player.gd" type="Script" id=1]
+[ext_resource path="res://assets/art/player/robot_demo.png" type="Texture" 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="Texture" id=5]
+[ext_resource path="res://assets/art/ui/touch_button_right.png" type="Texture" id=6]
+[ext_resource path="res://assets/art/ui/touch_button_jump.png" type="Texture" id=7]
+[ext_resource path="res://assets/art/ui/touch_button_fire.png" type="Texture" id=8]
+[ext_resource path="res://src/Actors/Gun.gd" type="Script" id=9]
 
 [sub_resource type="Animation" id=1]
 resource_name = "crouch"
@@ -182,26 +183,47 @@ tracks/0/keys = {
 "values": [ 10, 11, 12, 13, 14, 5 ]
 }
 
-[sub_resource type="CapsuleShape2D" id=11]
-height = 44.4787
+[sub_resource type="RectangleShape2D" id=11]
+extents = Vector2( 10, 27 )
 
 [node name="Player" type="KinematicBody2D"]
+collision_mask = 30
 script = ExtResource( 1 )
+speed = Vector2( 300, 700 )
+gravity = 1800.0
+
+[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="Sprite" type="Sprite" parent="."]
+position = Vector2( 0, -28 )
 texture = ExtResource( 2 )
 vframes = 2
 hframes = 16
-frame = 22
-
-[node name="Smoke" type="Node2D" parent="Sprite"]
-position = Vector2( 20.7312, 3.21187 )
-rotation = -1.45648
+frame = 16
 
-[node name="BulletShoot" type="Position2D" parent="Sprite"]
+[node name="Gun" type="Position2D" parent="Sprite"]
 position = Vector2( 30.6589, 6.13176 )
+script = ExtResource( 9 )
+
+[node name="Shoot" type="AudioStreamPlayer2D" parent="Sprite/Gun"]
+position = Vector2( -30.6589, -6.13176 )
+stream = ExtResource( 4 )
 
-[node name="Anim" type="AnimationPlayer" parent="."]
+[node name="Cooldown" type="Timer" parent="Sprite/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 )
@@ -214,20 +236,17 @@ anims/run_weapon = SubResource( 9 )
 anims/standing_weapon_ready = SubResource( 10 )
 
 [node name="Camera" type="Camera2D" parent="."]
+position = Vector2( 0, -28 )
 current = true
-limit_left = 0
-limit_top = 0
+process_mode = 0
 
 [node name="CollisionShape2D" type="CollisionShape2D" parent="."]
-position = Vector2( 0.291992, -0.835023 )
+position = Vector2( 0, -27 )
 shape = SubResource( 11 )
 
-[node name="SoundJump" type="AudioStreamPlayer2D" parent="."]
+[node name="Jump" type="AudioStreamPlayer2D" parent="."]
 stream = ExtResource( 3 )
 
-[node name="SoundShoot" type="AudioStreamPlayer2D" parent="."]
-stream = ExtResource( 4 )
-
 [node name="UI" type="CanvasLayer" parent="."]
 layer = 0
 
@@ -247,23 +266,15 @@ passby_press = true
 action = "move_right"
 visibility_mode = 1
 
-[node name="BottomRightAnchor" type="Control" parent="UI"]
-anchor_left = 1.0
-anchor_top = 1.0
-anchor_right = 1.0
-anchor_bottom = 1.0
-margin_left = -40.0
-margin_top = -40.0
-
-[node name="Jump" type="TouchScreenButton" parent="UI/BottomRightAnchor"]
-position = Vector2( -98.151, -83.768 )
+[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/BottomRightAnchor"]
-position = Vector2( -96.302, -180 )
+[node name="Fire" type="TouchScreenButton" parent="UI"]
+position = Vector2( 668.073, 262.788 )
 scale = Vector2( 1.49157, 1.46265 )
 normal = ExtResource( 8 )
 action = "shoot"

File diff suppressed because it is too large
+ 52 - 0
2d/platformer/src/Level/Level.tscn


+ 174 - 0
2d/platformer/src/Level/ParallaxBackground.tscn

@@ -0,0 +1,174 @@
+[gd_scene load_steps=7 format=2]
+
+[ext_resource path="res://assets/art/background/distant_platforms_2.png" type="Texture" id=1]
+[ext_resource path="res://assets/art/background/sky.png" type="Texture" id=2]
+[ext_resource path="res://assets/art/background/cloud_1.png" type="Texture" id=3]
+[ext_resource path="res://assets/art/background/cloud_2.png" type="Texture" id=4]
+[ext_resource path="res://assets/art/background/cloud_3.png" type="Texture" id=5]
+[ext_resource path="res://assets/art/background/distant_platforms_1.png" type="Texture" id=6]
+
+[node name="ParallaxBackground" type="ParallaxBackground"]
+scroll_base_scale = Vector2( 0.4, 0 )
+
+[node name="Sky" type="ParallaxLayer" parent="."]
+motion_mirroring = Vector2( 800, 0 )
+
+[node name="Sprite" type="Sprite" parent="Sky"]
+scale = Vector2( 128, 0.94 )
+texture = ExtResource( 2 )
+centered = false
+
+[node name="Clouds" type="ParallaxLayer" parent="."]
+motion_scale = Vector2( 0.1, 1 )
+motion_offset = Vector2( -550, 0 )
+
+[node name="CloudGroup1" type="Node2D" parent="Clouds"]
+position = Vector2( -780, 0 )
+
+[node name="Sprite1" type="Sprite" parent="Clouds/CloudGroup1"]
+position = Vector2( -200, 120 )
+texture = ExtResource( 3 )
+centered = false
+
+[node name="Sprite2" type="Sprite" parent="Clouds/CloudGroup1"]
+position = Vector2( 200, 20 )
+texture = ExtResource( 3 )
+centered = false
+
+[node name="Sprite3" type="Sprite" parent="Clouds/CloudGroup1"]
+position = Vector2( -60, 40 )
+texture = ExtResource( 4 )
+centered = false
+
+[node name="Sprite4" type="Sprite" parent="Clouds/CloudGroup1"]
+position = Vector2( 300, 130 )
+texture = ExtResource( 4 )
+centered = false
+
+[node name="Sprite5" type="Sprite" parent="Clouds/CloudGroup1"]
+position = Vector2( 30, 150 )
+texture = ExtResource( 5 )
+centered = false
+
+[node name="Sprite6" type="Sprite" parent="Clouds/CloudGroup1"]
+position = Vector2( 450, 70 )
+texture = ExtResource( 5 )
+centered = false
+
+[node name="CloudGroup2" type="Node2D" parent="Clouds"]
+
+[node name="Sprite1" type="Sprite" parent="Clouds/CloudGroup2"]
+position = Vector2( -200, 120 )
+texture = ExtResource( 3 )
+centered = false
+
+[node name="Sprite2" type="Sprite" parent="Clouds/CloudGroup2"]
+position = Vector2( 200, 20 )
+texture = ExtResource( 3 )
+centered = false
+
+[node name="Sprite3" type="Sprite" parent="Clouds/CloudGroup2"]
+position = Vector2( -60, 40 )
+texture = ExtResource( 4 )
+centered = false
+
+[node name="Sprite4" type="Sprite" parent="Clouds/CloudGroup2"]
+position = Vector2( 300, 130 )
+texture = ExtResource( 4 )
+centered = false
+
+[node name="Sprite5" type="Sprite" parent="Clouds/CloudGroup2"]
+position = Vector2( 30, 150 )
+texture = ExtResource( 5 )
+centered = false
+
+[node name="Sprite6" type="Sprite" parent="Clouds/CloudGroup2"]
+position = Vector2( 450, 70 )
+texture = ExtResource( 5 )
+centered = false
+
+[node name="CloudGroup3" type="Node2D" parent="Clouds"]
+position = Vector2( 780, 0 )
+
+[node name="Sprite1" type="Sprite" parent="Clouds/CloudGroup3"]
+position = Vector2( -200, 120 )
+texture = ExtResource( 3 )
+centered = false
+
+[node name="Sprite2" type="Sprite" parent="Clouds/CloudGroup3"]
+position = Vector2( 200, 20 )
+texture = ExtResource( 3 )
+centered = false
+
+[node name="Sprite3" type="Sprite" parent="Clouds/CloudGroup3"]
+position = Vector2( -60, 40 )
+texture = ExtResource( 4 )
+centered = false
+
+[node name="Sprite4" type="Sprite" parent="Clouds/CloudGroup3"]
+position = Vector2( 300, 130 )
+texture = ExtResource( 4 )
+centered = false
+
+[node name="Sprite5" type="Sprite" parent="Clouds/CloudGroup3"]
+position = Vector2( 30, 150 )
+texture = ExtResource( 5 )
+centered = false
+
+[node name="Sprite6" type="Sprite" parent="Clouds/CloudGroup3"]
+position = Vector2( 450, 70 )
+texture = ExtResource( 5 )
+centered = false
+
+[node name="CloudGroup4" type="Node2D" parent="Clouds"]
+position = Vector2( 1560, 0 )
+
+[node name="Sprite1" type="Sprite" parent="Clouds/CloudGroup4"]
+position = Vector2( -200, 120 )
+texture = ExtResource( 3 )
+centered = false
+
+[node name="Sprite2" type="Sprite" parent="Clouds/CloudGroup4"]
+position = Vector2( 200, 20 )
+texture = ExtResource( 3 )
+centered = false
+
+[node name="Sprite3" type="Sprite" parent="Clouds/CloudGroup4"]
+position = Vector2( -60, 40 )
+texture = ExtResource( 4 )
+centered = false
+
+[node name="Sprite4" type="Sprite" parent="Clouds/CloudGroup4"]
+position = Vector2( 300, 130 )
+texture = ExtResource( 4 )
+centered = false
+
+[node name="Sprite5" type="Sprite" parent="Clouds/CloudGroup4"]
+position = Vector2( 30, 150 )
+texture = ExtResource( 5 )
+centered = false
+
+[node name="Sprite6" type="Sprite" parent="Clouds/CloudGroup4"]
+position = Vector2( 450, 70 )
+texture = ExtResource( 5 )
+centered = false
+
+[node name="Mountains2" type="ParallaxLayer" parent="."]
+position = Vector2( 0, 481 )
+motion_scale = Vector2( 0.2, 1 )
+
+[node name="Sprite" type="Sprite" parent="Mountains2"]
+position = Vector2( 0, -120 )
+texture = ExtResource( 1 )
+region_enabled = true
+region_rect = Rect2( 0, 0, 4096, 256 )
+
+[node name="Mountains1" type="ParallaxLayer" parent="."]
+position = Vector2( 0, 481 )
+motion_scale = Vector2( 0.4, 1 )
+
+[node name="Sprite" type="Sprite" parent="Mountains1"]
+position = Vector2( 0, -100 )
+texture = ExtResource( 6 )
+region_enabled = true
+region_rect = Rect2( 0, 0, 4096, 256 )

+ 31 - 0
2d/platformer/src/Main/Game.gd

@@ -0,0 +1,31 @@
+extends Node
+# This class contains controls that should always be accessible, like pausing
+# the game or toggling the window full-screen.
+
+
+# The "_" prefix is a convention to indicate that variables are private,
+# that is to say, another node or script should not access them.
+onready var _pause_menu = $InterfaceLayer/PauseMenu
+
+
+func _init():
+	OS.min_window_size = OS.window_size
+	OS.max_window_size = OS.get_screen_size()
+
+
+func _input(event):
+	if event.is_action_pressed("toggle_fullscreen"):
+		OS.window_fullscreen = not OS.window_fullscreen
+		get_tree().set_input_as_handled()
+	# The GlobalControls node, in the Stage scene, is set to process even
+	# when the game is paused, so this code keeps running.
+	# To see that, select GlobalControls, and scroll down to the Pause category
+	# in the inspector.
+	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().set_input_as_handled()

+ 16 - 0
2d/platformer/src/Main/Game.tscn

@@ -0,0 +1,16 @@
+[gd_scene load_steps=4 format=2]
+
+[ext_resource path="res://src/UserInterface/PauseMenu.tscn" type="PackedScene" id=1]
+[ext_resource path="res://src/Main/Game.gd" type="Script" id=2]
+[ext_resource path="res://src/Level/Level.tscn" type="PackedScene" id=3]
+
+[node name="Game" type="Node"]
+pause_mode = 2
+script = ExtResource( 2 )
+
+[node name="Level" parent="." instance=ExtResource( 3 )]
+
+[node name="InterfaceLayer" type="CanvasLayer" parent="."]
+layer = 100
+
+[node name="PauseMenu" parent="InterfaceLayer" instance=ExtResource( 1 )]

+ 14 - 0
2d/platformer/src/Objects/Bullet.gd

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

+ 16 - 14
2d/platformer/player/Bullet.tscn → 2d/platformer/src/Objects/Bullet.tscn

@@ -1,7 +1,7 @@
 [gd_scene load_steps=9 format=2]
 
-[ext_resource path="res://player/bullet.gd" type="Script" id=1]
-[ext_resource path="res://player/bullet.png" type="Texture" id=2]
+[ext_resource path="res://assets/art/player/bullet/bullet.png" type="Texture" id=1]
+[ext_resource path="res://src/Objects/Bullet.gd" type="Script" id=2]
 
 [sub_resource type="CanvasItemMaterial" id=1]
 
@@ -22,7 +22,8 @@ color = Color( 1, 1, 1, 0.705882 )
 [sub_resource type="CircleShape2D" id=5]
 
 [sub_resource type="Animation" id=6]
-length = 1.5
+resource_name = "destroy"
+length = 0.3
 tracks/0/type = "method"
 tracks/0/path = NodePath(".")
 tracks/0/interp = 1
@@ -30,7 +31,7 @@ tracks/0/loop_wrap = true
 tracks/0/imported = false
 tracks/0/enabled = true
 tracks/0/keys = {
-"times": PoolRealArray( 1.31 ),
+"times": PoolRealArray( 0.3 ),
 "transitions": PoolRealArray( 1 ),
 "values": [ {
 "args": [  ],
@@ -44,7 +45,7 @@ tracks/1/loop_wrap = true
 tracks/1/imported = false
 tracks/1/enabled = true
 tracks/1/keys = {
-"times": PoolRealArray( 0, 1 ),
+"times": PoolRealArray( 0, 0.3 ),
 "transitions": PoolRealArray( 1, 1 ),
 "update": 0,
 "values": [ Color( 1, 1, 1, 1 ), Color( 1, 1, 1, 0 ) ]
@@ -56,7 +57,7 @@ tracks/2/loop_wrap = true
 tracks/2/imported = false
 tracks/2/enabled = true
 tracks/2/keys = {
-"times": PoolRealArray( 0, 0.5 ),
+"times": PoolRealArray( 0, 0.3 ),
 "transitions": PoolRealArray( 1, 1 ),
 "update": 0,
 "values": [ Color( 1, 1, 1, 1 ), Color( 1, 1, 1, 0 ) ]
@@ -64,10 +65,12 @@ tracks/2/keys = {
 
 [node name="Bullet" type="RigidBody2D"]
 material = SubResource( 1 )
+collision_layer = 0
+collision_mask = 26
 continuous_cd = 2
 contacts_reported = 1
 contact_monitor = true
-script = ExtResource( 1 )
+script = ExtResource( 2 )
 
 [node name="Particles2D" type="Particles2D" parent="."]
 material = SubResource( 2 )
@@ -75,11 +78,11 @@ lifetime = 0.3
 speed_scale = 3.0
 local_coords = false
 process_material = SubResource( 3 )
-texture = ExtResource( 2 )
+texture = ExtResource( 1 )
 
 [node name="Sprite" type="Sprite" parent="."]
 material = SubResource( 4 )
-texture = ExtResource( 2 )
+texture = ExtResource( 1 )
 
 [node name="CollisionShape2D" type="CollisionShape2D" parent="."]
 shape = SubResource( 5 )
@@ -88,8 +91,7 @@ shape = SubResource( 5 )
 one_shot = true
 autostart = true
 
-[node name="Anim" type="AnimationPlayer" parent="."]
-anims/shutdown = SubResource( 6 )
-
-[connection signal="body_entered" from="." to="." method="_on_bullet_body_enter"]
-[connection signal="timeout" from="Timer" to="." method="_on_Timer_timeout"]
+[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
+anims/destroy = SubResource( 6 )
+[connection signal="body_entered" from="." to="." method="_on_body_entered"]
+[connection signal="timeout" from="Timer" to="." method="destroy"]

+ 15 - 0
2d/platformer/src/Objects/Coin.gd

@@ -0,0 +1,15 @@
+class_name Coin
+extends Area2D
+# Collectible that disappears when the player touches it.
+
+onready var animation_player = $AnimationPlayer
+
+# The Coins only detects collisions with the Player thanks to its collision mask.
+# This prevents other characters such as enemies from picking up coins.
+
+# When the player collides with a coin, the coin plays its 'picked' animation.
+# The animation takes cares of making the coin disappear, but also deactivates its
+# collisions and frees it from memory, saving us from writing more complex code.
+# Click the AnimationPlayer node to see the animation timeline.
+func _on_body_entered(_body):
+	animation_player.play("picked")

+ 161 - 0
2d/platformer/src/Objects/Coin.tscn

@@ -0,0 +1,161 @@
+[gd_scene load_steps=7 format=2]
+
+[ext_resource path="res://assets/art/coin/coin.png" type="Texture" 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]
+
+[sub_resource type="Animation" id=1]
+resource_name = "picked"
+length = 1.5
+step = 0.25
+tracks/0/type = "value"
+tracks/0/path = NodePath("Sprite:frame")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/keys = {
+"times": PoolRealArray( 0 ),
+"transitions": PoolRealArray( 1 ),
+"update": 0,
+"values": [ 0 ]
+}
+tracks/1/type = "method"
+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": PoolRealArray( 1 ),
+"transitions": PoolRealArray( 1 ),
+"values": [ {
+"args": [  ],
+"method": "queue_free"
+} ]
+}
+tracks/2/type = "value"
+tracks/2/path = NodePath("Sprite:self_modulate")
+tracks/2/interp = 1
+tracks/2/loop_wrap = true
+tracks/2/imported = false
+tracks/2/enabled = true
+tracks/2/keys = {
+"times": PoolRealArray( 0.25, 1.25 ),
+"transitions": PoolRealArray( 1, 1 ),
+"update": 0,
+"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/keys = {
+"times": PoolRealArray( 0 ),
+"transitions": PoolRealArray( 1 ),
+"update": 2,
+"values": [ true ]
+}
+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/keys = {
+"times": PoolRealArray( 0 ),
+"transitions": PoolRealArray( 1 ),
+"update": 1,
+"values": [ false ]
+}
+tracks/5/type = "value"
+tracks/5/path = NodePath("Sprite:position")
+tracks/5/interp = 1
+tracks/5/loop_wrap = true
+tracks/5/imported = false
+tracks/5/enabled = true
+tracks/5/keys = {
+"times": PoolRealArray( 0, 1.5 ),
+"transitions": PoolRealArray( 1, 1 ),
+"update": 0,
+"values": [ Vector2( 0, 0 ), Vector2( 0, -42 ) ]
+}
+
+[sub_resource type="Animation" id=2]
+length = 1.5
+loop = true
+step = 0.25
+tracks/0/type = "value"
+tracks/0/path = NodePath("Sprite:frame")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/keys = {
+"times": PoolRealArray( 0, 0.25, 0.5, 0.75, 1, 1.25, 1.5 ),
+"transitions": PoolRealArray( 1, 1, 1, 1, 1, 1, 1 ),
+"update": 1,
+"values": [ 0, 1, 2, 3, 2, 1, 0 ]
+}
+tracks/1/type = "value"
+tracks/1/path = NodePath("Sprite:position")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/keys = {
+"times": PoolRealArray( 0 ),
+"transitions": PoolRealArray( 1 ),
+"update": 2,
+"values": [ Vector2( 0, 0 ) ]
+}
+tracks/2/type = "value"
+tracks/2/path = NodePath("Sprite:self_modulate")
+tracks/2/interp = 1
+tracks/2/loop_wrap = true
+tracks/2/imported = false
+tracks/2/enabled = true
+tracks/2/keys = {
+"times": PoolRealArray( 0 ),
+"transitions": PoolRealArray( 1 ),
+"update": 2,
+"values": [ Color( 1, 1, 1, 1 ) ]
+}
+tracks/3/type = "value"
+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": PoolRealArray( 0 ),
+"transitions": PoolRealArray( 1 ),
+"update": 2,
+"values": [ true ]
+}
+
+[sub_resource type="CircleShape2D" id=3]
+
+[node name="Coin" type="Area2D"]
+monitorable = false
+collision_layer = 0
+script = ExtResource( 4 )
+
+[node name="Sprite" type="Sprite" parent="."]
+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 )
+
+[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
+shape = SubResource( 3 )
+
+[node name="Pickup" type="AudioStreamPlayer2D" parent="."]
+stream = ExtResource( 3 )
+[connection signal="body_entered" from="." to="." method="_on_body_entered"]

+ 21 - 0
2d/platformer/src/Platforms/Platform.tscn

@@ -0,0 +1,21 @@
+[gd_scene load_steps=3 format=2]
+
+[ext_resource path="res://assets/art/platforms/moving_platform.png" type="Texture" id=2]
+
+[sub_resource type="RectangleShape2D" id=1]
+extents = Vector2( 94, 12 )
+
+[node name="Platform" type="KinematicBody2D"]
+z_index = -1
+collision_layer = 8
+collision_mask = 0
+collision/safe_margin = 0.12
+motion/sync_to_physics = true
+
+[node name="Sprite" type="Sprite" parent="."]
+texture = ExtResource( 2 )
+
+[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
+position = Vector2( 0, -8 )
+shape = SubResource( 1 )
+one_way_collision = true

+ 26 - 0
2d/platformer/src/UserInterface/PauseMenu.gd

@@ -0,0 +1,26 @@
+extends Control
+
+
+onready var resume_button = $VBoxContainer/ResumeButton
+
+
+func _ready():
+	visible = false
+
+
+func close():
+	visible = false
+
+
+func open():
+	visible = true
+	resume_button.grab_focus()
+
+
+func _on_ResumeButton_pressed():
+	get_tree().paused = false
+	visible = false
+
+
+func _on_QuitButton_pressed():
+	get_tree().quit()

+ 56 - 0
2d/platformer/src/UserInterface/PauseMenu.tscn

@@ -0,0 +1,56 @@
+[gd_scene load_steps=3 format=2]
+
+[ext_resource path="res://assets/theme/user_interface.tres" type="Theme" id=1]
+[ext_resource path="res://src/UserInterface/PauseMenu.gd" type="Script" id=2]
+
+[node name="PauseMenu" type="Control"]
+pause_mode = 2
+anchor_right = 1.0
+anchor_bottom = 1.0
+theme = ExtResource( 1 )
+script = ExtResource( 2 )
+__meta__ = {
+"_edit_use_anchors_": false
+}
+
+[node name="ColorRect" type="ColorRect" parent="."]
+anchor_right = 1.0
+anchor_bottom = 1.0
+color = Color( 0, 0, 0, 0.211765 )
+
+[node name="VBoxContainer" type="VBoxContainer" parent="."]
+anchor_left = 0.5
+anchor_top = 0.5
+anchor_right = 0.5
+anchor_bottom = 0.5
+margin_left = -87.0
+margin_top = -125.0
+margin_right = 87.0
+margin_bottom = 126.0
+alignment = 1
+__meta__ = {
+"_edit_use_anchors_": false
+}
+
+[node name="Label" type="Label" parent="VBoxContainer"]
+margin_top = 71.0
+margin_right = 174.0
+margin_bottom = 91.0
+text = "Game Paused"
+align = 1
+
+[node name="ResumeButton" type="Button" parent="VBoxContainer"]
+margin_top = 95.0
+margin_right = 174.0
+margin_bottom = 135.0
+rect_min_size = Vector2( 0, 40 )
+text = "Resume"
+
+[node name="QuitButton" type="Button" parent="VBoxContainer"]
+margin_top = 139.0
+margin_right = 174.0
+margin_bottom = 179.0
+rect_min_size = Vector2( 0, 40 )
+text = "Quit"
+[connection signal="pressed" from="VBoxContainer/ResumeButton" to="." method="_on_ResumeButton_pressed"]
+[connection signal="pressed" from="VBoxContainer/QuitButton" to="." method="_on_QuitButton_pressed"]

BIN
2d/platformer/tiles_demo.png


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