Browse Source

Merge pull request #400 from aaronfranke/2d-physics-pl

Update 2D physics platformer
Aaron Franke 5 years ago
parent
commit
704ebeec81

+ 1 - 1
2d/particles/particles.tscn

@@ -190,7 +190,7 @@ scale = 0.5
 scale_random = 1.0
 scale_random = 1.0
 color = Color( 0.214844, 1, 0.392731, 1 )
 color = Color( 0.214844, 1, 0.392731, 1 )
 
 
-[node name="Node" type="Node"]
+[node name="Particles" type="Node"]
 
 
 [node name="Fire" type="Particles2D" parent="."]
 [node name="Fire" type="Particles2D" parent="."]
 material = SubResource( 1 )
 material = SubResource( 1 )

+ 12 - 13
2d/physics_platformer/Stage.tscn

@@ -1,4 +1,4 @@
-[gd_scene load_steps=21 format=2]
+[gd_scene load_steps=22 format=2]
 
 
 [ext_resource path="res://Tileset.tres" type="TileSet" id=1]
 [ext_resource path="res://Tileset.tres" type="TileSet" id=1]
 [ext_resource path="res://coin/Coin.tscn" type="PackedScene" id=2]
 [ext_resource path="res://coin/Coin.tscn" type="PackedScene" id=2]
@@ -8,14 +8,7 @@
 [ext_resource path="res://player/Player.tscn" type="PackedScene" id=6]
 [ext_resource path="res://player/Player.tscn" type="PackedScene" id=6]
 [ext_resource path="res://enemy/Enemy.tscn" type="PackedScene" id=7]
 [ext_resource path="res://enemy/Enemy.tscn" type="PackedScene" id=7]
 [ext_resource path="res://background/ParallaxBg.tscn" type="PackedScene" id=8]
 [ext_resource path="res://background/ParallaxBg.tscn" type="PackedScene" id=8]
-
-
-
-
-
-
-
-
+[ext_resource path="res://audio/music.ogg" type="AudioStream" id=9]
 
 
 [sub_resource type="PhysicsMaterial" id=1]
 [sub_resource type="PhysicsMaterial" id=1]
 friction = 0.0
 friction = 0.0
@@ -53,7 +46,7 @@ friction = 0.0
 [sub_resource type="PhysicsMaterial" id=12]
 [sub_resource type="PhysicsMaterial" id=12]
 friction = 0.0
 friction = 0.0
 
 
-[node name="Stage" type="Node"]
+[node name="Stage" type="Node2D"]
 
 
 [node name="TileMap" type="TileMap" parent="."]
 [node name="TileMap" type="TileMap" parent="."]
 tile_set = ExtResource( 1 )
 tile_set = ExtResource( 1 )
@@ -64,7 +57,8 @@ __meta__ = {
 "_edit_lock_": true
 "_edit_lock_": true
 }
 }
 
 
-[node name="Coins" type="Node" parent="."]
+[node name="Coins" type="Node2D" parent="."]
+editor/display_folded = true
 
 
 [node name="Coin" parent="Coins" instance=ExtResource( 2 )]
 [node name="Coin" parent="Coins" instance=ExtResource( 2 )]
 position = Vector2( 672, 1179 )
 position = Vector2( 672, 1179 )
@@ -192,7 +186,8 @@ position = Vector2( 4236.75, 541.058 )
 [node name="Coin42" parent="Coins" instance=ExtResource( 2 )]
 [node name="Coin42" parent="Coins" instance=ExtResource( 2 )]
 position = Vector2( 4172.75, 541.058 )
 position = Vector2( 4172.75, 541.058 )
 
 
-[node name="Props" type="Node" parent="."]
+[node name="Props" type="Node2D" parent="."]
+editor/display_folded = true
 
 
 [node name="MovingPlatform" parent="Props" instance=ExtResource( 3 )]
 [node name="MovingPlatform" parent="Props" instance=ExtResource( 3 )]
 position = Vector2( 1451.86, 742.969 )
 position = Vector2( 1451.86, 742.969 )
@@ -219,7 +214,8 @@ position = Vector2( 927.698, 1120.81 )
 position = Vector2( 251.684, 1045.6 )
 position = Vector2( 251.684, 1045.6 )
 physics_material_override = SubResource( 1 )
 physics_material_override = SubResource( 1 )
 
 
-[node name="Enemies" type="Node" parent="."]
+[node name="Enemies" type="Node2D" parent="."]
+editor/display_folded = true
 
 
 [node name="Enemy1" parent="Enemies" instance=ExtResource( 7 )]
 [node name="Enemy1" parent="Enemies" instance=ExtResource( 7 )]
 position = Vector2( 834.664, 1309.6 )
 position = Vector2( 834.664, 1309.6 )
@@ -277,3 +273,6 @@ size_flags_vertical = 0
 text = "This is a simple demo on how to make a platformer game with Godot.\"This version uses physics and the 2D physics engine for motion and collision.\"\"The demo also shows the benefits of using the scene system, where coins,\"enemies and the player are edited separatedly and instanced in the stage.\"\"To edit the base tiles for the  tileset, open the tileset_edit.tscn file and follow \"instructions.\""
 text = "This is a simple demo on how to make a platformer game with Godot.\"This version uses physics and the 2D physics engine for motion and collision.\"\"The demo also shows the benefits of using the scene system, where coins,\"enemies and the player are edited separatedly and instanced in the stage.\"\"To edit the base tiles for the  tileset, open the tileset_edit.tscn file and follow \"instructions.\""
 autowrap = true
 autowrap = true
 
 
+[node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="."]
+stream = ExtResource( 9 )
+autoplay = true

+ 1 - 5
2d/physics_platformer/Stage2.tscn

@@ -4,10 +4,7 @@
 [ext_resource path="res://player/Player.tscn" type="PackedScene" id=2]
 [ext_resource path="res://player/Player.tscn" type="PackedScene" id=2]
 [ext_resource path="res://background/ParallaxBg.tscn" type="PackedScene" id=3]
 [ext_resource path="res://background/ParallaxBg.tscn" type="PackedScene" id=3]
 
 
-
-
-
-[node name="Stage" type="Node"]
+[node name="Stage2" type="Node2D"]
 
 
 [node name="TileMap" type="TileMap" parent="."]
 [node name="TileMap" type="TileMap" parent="."]
 tile_set = ExtResource( 1 )
 tile_set = ExtResource( 1 )
@@ -32,4 +29,3 @@ size_flags_horizontal = 2
 size_flags_vertical = 0
 size_flags_vertical = 0
 text = "This is a simple demo on how to make a platformer game with Godot.\"This version uses physics and the 2D physics engine for motion and collision.\"\"The demo also shows the benefits of using the scene system, where coins,\"enemies and the player are edited separatedly and instanced in the stage.\"\"To edit the base tiles for the  tileset, open the tileset_edit.tscn file and follow \"instructions.\""
 text = "This is a simple demo on how to make a platformer game with Godot.\"This version uses physics and the 2D physics engine for motion and collision.\"\"The demo also shows the benefits of using the scene system, where coins,\"enemies and the player are edited separatedly and instanced in the stage.\"\"To edit the base tiles for the  tileset, open the tileset_edit.tscn file and follow \"instructions.\""
 autowrap = true
 autowrap = true
-

+ 1 - 2
2d/physics_platformer/TilesetEdit.tscn

@@ -2,7 +2,7 @@
 
 
 [ext_resource path="res://tiles_demo.png" type="Texture" id=1]
 [ext_resource path="res://tiles_demo.png" type="Texture" id=1]
 
 
-[node name="Node" type="Node"]
+[node name="TilesetEdit" type="Node2D"]
 
 
 [node name="Floor" type="Sprite" parent="."]
 [node name="Floor" type="Sprite" parent="."]
 texture = ExtResource( 1 )
 texture = ExtResource( 1 )
@@ -156,4 +156,3 @@ text = "This scene serves as a tool for editing the tileset.
 This will save a tileset. Saving over it will merge your changes.
 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."
 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."
-

+ 0 - 1
2d/physics_platformer/background/ParallaxBg.tscn

@@ -71,4 +71,3 @@ position = Vector2( 0, 225 )
 texture = ExtResource( 6 )
 texture = ExtResource( 6 )
 centered = false
 centered = false
 region_rect = Rect2( 0, 0, 800, 256 )
 region_rect = Rect2( 0, 0, 800, 256 )
-

+ 2 - 2
2d/physics_platformer/coin/Coin.tscn

@@ -105,6 +105,7 @@ emission_sphere_radius = 20.0
 flag_disable_z = true
 flag_disable_z = true
 gravity = Vector3( 0, 0, 0 )
 gravity = Vector3( 0, 0, 0 )
 initial_velocity = 1.0
 initial_velocity = 1.0
+angular_velocity = 0.0191222
 orbit_velocity = 0.0
 orbit_velocity = 0.0
 orbit_velocity_random = 0.0
 orbit_velocity_random = 0.0
 scale = 0.3
 scale = 0.3
@@ -117,7 +118,7 @@ script = ExtResource( 1 )
 texture = ExtResource( 2 )
 texture = ExtResource( 2 )
 hframes = 4
 hframes = 4
 
 
-[node name="Anim" type="AnimationPlayer" parent="."]
+[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
 autoplay = "spin"
 autoplay = "spin"
 anims/spin = SubResource( 1 )
 anims/spin = SubResource( 1 )
 anims/taken = SubResource( 2 )
 anims/taken = SubResource( 2 )
@@ -139,5 +140,4 @@ texture = ExtResource( 4 )
 
 
 [node name="Enabler" type="VisibilityEnabler2D" parent="."]
 [node name="Enabler" type="VisibilityEnabler2D" parent="."]
 pause_particles = false
 pause_particles = false
-
 [connection signal="body_entered" from="." to="." method="_on_body_enter"]
 [connection signal="body_entered" from="." to="." method="_on_body_enter"]

+ 3 - 6
2d/physics_platformer/coin/coin.gd

@@ -1,11 +1,8 @@
-extends Area2D
-
 class_name Coin
 class_name Coin
+extends Area2D
 
 
-# Member variables
 var taken = false
 var taken = false
 
 
-
-func _on_body_enter( body ):
+func _on_body_enter(body):
 	if not taken and body is Player:
 	if not taken and body is Player:
-		($Anim as AnimationPlayer).play("taken")
+		($AnimationPlayer as AnimationPlayer).play("taken")

+ 2 - 2
2d/physics_platformer/enemy/Enemy.tscn

@@ -117,6 +117,7 @@ flag_disable_z = true
 spread = 180.0
 spread = 180.0
 gravity = Vector3( 0, 98, 0 )
 gravity = Vector3( 0, 98, 0 )
 initial_velocity = 322.73
 initial_velocity = 322.73
+angular_velocity = 1.5
 orbit_velocity = 0.0
 orbit_velocity = 0.0
 orbit_velocity_random = 0.0
 orbit_velocity_random = 0.0
 scale = 2.4
 scale = 2.4
@@ -133,7 +134,7 @@ position = Vector2( 16.2569, 11.0034 )
 scale = Vector2( 23.5056, 10.8629 )
 scale = Vector2( 23.5056, 10.8629 )
 pause_particles = false
 pause_particles = false
 
 
-[node name="Anim" type="AnimationPlayer" parent="."]
+[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
 anims/explode = SubResource( 2 )
 anims/explode = SubResource( 2 )
 anims/idle = SubResource( 3 )
 anims/idle = SubResource( 3 )
 anims/walk = SubResource( 4 )
 anims/walk = SubResource( 4 )
@@ -179,4 +180,3 @@ stream = ExtResource( 4 )
 
 
 [node name="SoundExplode" type="AudioStreamPlayer2D" parent="."]
 [node name="SoundExplode" type="AudioStreamPlayer2D" parent="."]
 stream = ExtResource( 5 )
 stream = ExtResource( 5 )
-

+ 37 - 35
2d/physics_platformer/enemy/enemy.gd

@@ -1,53 +1,30 @@
-extends RigidBody2D
-
 class_name Enemy
 class_name Enemy
+extends RigidBody2D
 
 
-# Member variables
 const WALK_SPEED = 50
 const WALK_SPEED = 50
-const STATE_WALKING = 0
-const STATE_DYING = 1
 
 
-# state machine
-var state = STATE_WALKING
+enum State {
+	WALKING,
+	DYING
+}
+
+var state = State.WALKING
 
 
 var direction = -1
 var direction = -1
 var anim = ""
 var anim = ""
 
 
-onready var rc_left = $RaycastLeft
-onready var rc_right = $RaycastRight
-
 var Bullet = preload("res://player/bullet.gd")
 var Bullet = preload("res://player/bullet.gd")
 
 
-
-func _die():
-	queue_free()
-
-func _pre_explode():
-	#make sure nothing collides against this
-	$Shape1.queue_free()
-	$Shape2.queue_free()
-	$Shape3.queue_free()
-	
-	# Stay there
-	mode = MODE_STATIC
-	($SoundExplode as AudioStreamPlayer2D).play()
-	
-func _bullet_collider(cc, s, dp):
-	mode = MODE_RIGID
-	state = STATE_DYING
-	
-	s.set_angular_velocity(sign(dp.x) * 33.0)
-	set_friction(1)
-	cc.disable()
-	($SoundHit as AudioStreamPlayer2D).play()
+onready var rc_left = $RaycastLeft
+onready var rc_right = $RaycastRight
 
 
 func _integrate_forces(s):
 func _integrate_forces(s):
 	var lv = s.get_linear_velocity()
 	var lv = s.get_linear_velocity()
 	var new_anim = anim
 	var new_anim = anim
 
 
-	if state == STATE_DYING:
+	if state == State.DYING:
 		new_anim = "explode"
 		new_anim = "explode"
-	elif state == STATE_WALKING:
+	elif state == State.WALKING:
 		new_anim = "walk"
 		new_anim = "walk"
 		
 		
 		var wall_side = 0.0
 		var wall_side = 0.0
@@ -81,6 +58,31 @@ func _integrate_forces(s):
 	
 	
 	if anim != new_anim:
 	if anim != new_anim:
 		anim = new_anim
 		anim = new_anim
-		($Anim as AnimationPlayer).play(anim)
+		($AnimationPlayer as AnimationPlayer).play(anim)
 	
 	
 	s.set_linear_velocity(lv)
 	s.set_linear_velocity(lv)
+
+
+func _die():
+	queue_free()
+
+
+func _pre_explode():
+	#make sure nothing collides against this
+	$Shape1.queue_free()
+	$Shape2.queue_free()
+	$Shape3.queue_free()
+	
+	# Stay there
+	mode = MODE_STATIC
+	($SoundExplode as AudioStreamPlayer2D).play()
+
+
+func _bullet_collider(cc, s, dp):
+	mode = MODE_RIGID
+	state = State.DYING
+	
+	s.set_angular_velocity(sign(dp.x) * 33.0)
+	set_friction(1)
+	cc.disable()
+	($SoundHit as AudioStreamPlayer2D).play()

+ 1 - 2
2d/physics_platformer/platform/MovingPlatform.tscn

@@ -3,7 +3,7 @@
 [ext_resource path="res://platform/moving_platform.gd" type="Script" id=1]
 [ext_resource path="res://platform/moving_platform.gd" type="Script" id=1]
 [ext_resource path="res://platform/moving_platform.png" type="Texture" id=2]
 [ext_resource path="res://platform/moving_platform.png" type="Texture" id=2]
 
 
-[node name="Moving_platform" type="Node2D"]
+[node name="MovingPlatform" type="Node2D"]
 script = ExtResource( 1 )
 script = ExtResource( 1 )
 
 
 [node name="Platform" type="RigidBody2D" parent="."]
 [node name="Platform" type="RigidBody2D" parent="."]
@@ -14,4 +14,3 @@ texture = ExtResource( 2 )
 
 
 [node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="Platform"]
 [node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="Platform"]
 polygon = PoolVector2Array( -88, -24, 88, -24, 88, 24, -88, 24 )
 polygon = PoolVector2Array( -88, -24, 88, -24, 88, 24, -88, 24 )
-

+ 1 - 2
2d/physics_platformer/platform/OneWayPlatform.tscn

@@ -5,7 +5,7 @@
 [sub_resource type="RectangleShape2D" id=1]
 [sub_resource type="RectangleShape2D" id=1]
 extents = Vector2( 100, 10 )
 extents = Vector2( 100, 10 )
 
 
-[node name="One_way_platform" type="StaticBody2D"]
+[node name="OneWayPlatform" type="StaticBody2D"]
 
 
 [node name="Sprite" type="Sprite" parent="."]
 [node name="Sprite" type="Sprite" parent="."]
 texture = ExtResource( 1 )
 texture = ExtResource( 1 )
@@ -14,4 +14,3 @@ texture = ExtResource( 1 )
 position = Vector2( 1.46304, -13.1672 )
 position = Vector2( 1.46304, -13.1672 )
 shape = SubResource( 1 )
 shape = SubResource( 1 )
 one_way_collision = true
 one_way_collision = true
-

+ 3 - 6
2d/physics_platformer/platform/moving_platform.gd

@@ -1,17 +1,14 @@
-extends Node2D
-
 class_name MovingPlatform
 class_name MovingPlatform
+extends Node2D
 
 
-# Member variables
 export var motion = Vector2()
 export var motion = Vector2()
 export var cycle = 1.0
 export var cycle = 1.0
 
 
 var accum = 0.0
 var accum = 0.0
 
 
-
 func _physics_process(delta):
 func _physics_process(delta):
-	accum += delta * (1.0 / cycle) * PI * 2.0
-	accum = fmod(accum, PI * 2.0)
+	accum += delta * (1.0 / cycle) * TAU
+	accum = fmod(accum, TAU)
 	
 	
 	var d = sin(accum)
 	var d = sin(accum)
 	var xf = Transform2D()
 	var xf = Transform2D()

+ 1 - 2
2d/physics_platformer/player/Bullet.tscn

@@ -80,7 +80,6 @@ shape = SubResource( 3 )
 [node name="Timer" type="Timer" parent="."]
 [node name="Timer" type="Timer" parent="."]
 one_shot = true
 one_shot = true
 
 
-[node name="Anim" type="AnimationPlayer" parent="."]
+[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
 anims/shutdown = SubResource( 4 )
 anims/shutdown = SubResource( 4 )
-
 [connection signal="timeout" from="Timer" to="." method="disable"]
 [connection signal="timeout" from="Timer" to="." method="disable"]

+ 1 - 2
2d/physics_platformer/player/Player.tscn

@@ -229,7 +229,7 @@ local_coords = false
 process_material = SubResource( 4 )
 process_material = SubResource( 4 )
 texture = ExtResource( 3 )
 texture = ExtResource( 3 )
 
 
-[node name="Anim" type="AnimationPlayer" parent="."]
+[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
 anims/crouch = SubResource( 5 )
 anims/crouch = SubResource( 5 )
 anims/falling = SubResource( 6 )
 anims/falling = SubResource( 6 )
 anims/falling_weapon = SubResource( 7 )
 anims/falling_weapon = SubResource( 7 )
@@ -295,4 +295,3 @@ stream = ExtResource( 8 )
 
 
 [node name="SoundJump" type="AudioStreamPlayer2D" parent="."]
 [node name="SoundJump" type="AudioStreamPlayer2D" parent="."]
 stream = ExtResource( 9 )
 stream = ExtResource( 9 )
-

+ 5 - 7
2d/physics_platformer/player/bullet.gd

@@ -1,17 +1,15 @@
-extends RigidBody2D
-
 class_name Bullet
 class_name Bullet
+extends RigidBody2D
 
 
-# Member variables
 var disabled = false
 var disabled = false
 
 
-
 func _ready():
 func _ready():
 	($Timer as Timer).start()
 	($Timer as Timer).start()
 
 
+
 func disable():
 func disable():
 	if disabled:
 	if disabled:
 		return
 		return
-		
-	($Anim as AnimationPlayer).play("shutdown")
-	disabled = true
+	
+	($AnimationPlayer as AnimationPlayer).play("shutdown")
+	disabled = true

+ 66 - 68
2d/physics_platformer/player/player.gd

@@ -1,30 +1,28 @@
-extends RigidBody2D
-
 class_name Player
 class_name Player
+extends RigidBody2D
 
 
-""" Character Demo, written by Juan Linietsky.
-
-  Implementation of a 2D Character controller.
-  This implementation uses the physics engine for
-  controlling a character, in a very similar way
-  than a 3D character controller would be implemented.
-
-  Using the physics engine for this has the main advantages:
-    - Easy to write.
-    - Interaction with other physics-based objects is free
-    - Only have to deal with the object linear velocity, not position
-    - All collision/area framework available
-
-  But also has the following disadvantages:
-    - Objects may bounce a little bit sometimes
-    - Going up ramps sends the chracter flying up, small hack is needed.
-    - A ray collider is needed to avoid sliding down on ramps and  
-      undesiderd bumps, small steps and rare numerical precision errors.
-      (another alternative may be to turn on friction when the character is not moving).
-    - Friction cant be used, so floor velocity must be considered
-      for moving platforms. """
+# Character Demo, written by Juan Linietsky.
+#
+#  Implementation of a 2D Character controller.
+#  This implementation uses the physics engine for
+#  controlling a character, in a very similar way
+#  than a 3D character controller would be implemented.
+#
+#  Using the physics engine for this has the main advantages:
+#    - Easy to write.
+#    - Interaction with other physics-based objects is free
+#    - Only have to deal with the object linear velocity, not position
+#    - All collision/area framework available
+#
+#  But also has the following disadvantages:
+#    - Objects may bounce a little bit sometimes
+#    - Going up ramps sends the chracter flying up, small hack is needed.
+#    - A ray collider is needed to avoid sliding down on ramps and
+#      undesiderd bumps, small steps and rare numerical precision errors.
+#      (another alternative may be to turn on friction when the character is not moving).
+#    - Friction cant be used, so floor velocity must be considered
+#      for moving platforms.
 
 
-# Member variables
 const WALK_ACCEL = 800.0
 const WALK_ACCEL = 800.0
 const WALK_DEACCEL = 800.0
 const WALK_DEACCEL = 800.0
 const WALK_MAX_VELOCITY = 200.0
 const WALK_MAX_VELOCITY = 200.0
@@ -49,27 +47,6 @@ var shoot_time = 1e20
 var Bullet = preload("res://player/Bullet.tscn")
 var Bullet = preload("res://player/Bullet.tscn")
 var Enemy = preload("res://enemy/Enemy.tscn")
 var Enemy = preload("res://enemy/Enemy.tscn")
 
 
-
-func _shot_bullet():
-	shoot_time = 0
-	var bi = Bullet.instance()
-	var ss
-	if siding_left:
-		ss = -1.0
-	else:
-		ss = 1.0
-	var pos = position + ($BulletShoot as Position2D).position * Vector2(ss, 1.0)
-		
-	bi.position = pos
-	get_parent().add_child(bi)
-	
-	bi.linear_velocity = Vector2(800.0 * ss, -80)
-	
-	($Sprite/Smoke as Particles2D).restart()
-	($SoundShoot as AudioStreamPlayer2D).play()
-	
-	add_collision_exception_with(bi) # Make bullet and this not collide
-
 func _integrate_forces(s):
 func _integrate_forces(s):
 	var lv = s.get_linear_velocity()
 	var lv = s.get_linear_velocity()
 	var step = s.get_step()
 	var step = s.get_step()
@@ -77,7 +54,7 @@ func _integrate_forces(s):
 	var new_anim = anim
 	var new_anim = anim
 	var new_siding_left = siding_left
 	var new_siding_left = siding_left
 	
 	
-	# Get the controls
+	# Get the controls.
 	var move_left = Input.is_action_pressed("move_left")
 	var move_left = Input.is_action_pressed("move_left")
 	var move_right = Input.is_action_pressed("move_right")
 	var move_right = Input.is_action_pressed("move_right")
 	var jump = Input.is_action_pressed("jump")
 	var jump = Input.is_action_pressed("jump")
@@ -85,19 +62,13 @@ func _integrate_forces(s):
 	var spawn = Input.is_action_pressed("spawn")
 	var spawn = Input.is_action_pressed("spawn")
 	
 	
 	if spawn:
 	if spawn:
-		var e = Enemy.instance()
-		var p = position
-		
-		p.y = p.y - 100
-		e.position = p
-		
-		get_parent().add_child(e)
+		call_deferred("_spawn_enemy_above")
 	
 	
-	# Deapply prev floor velocity
+	# Deapply prev floor velocity.
 	lv.x -= floor_h_velocity
 	lv.x -= floor_h_velocity
 	floor_h_velocity = 0.0
 	floor_h_velocity = 0.0
 	
 	
-	# Find the floor (a contact with upwards facing collision normal)
+	# Find the floor (a contact with upwards facing collision normal).
 	var found_floor = false
 	var found_floor = false
 	var floor_index = -1
 	var floor_index = -1
 	
 	
@@ -118,14 +89,14 @@ func _integrate_forces(s):
 	if found_floor:
 	if found_floor:
 		airborne_time = 0.0
 		airborne_time = 0.0
 	else:
 	else:
-		airborne_time += step # Time it spent in the air
+		airborne_time += step # Time it spent in the air.
 	
 	
 	var on_floor = airborne_time < MAX_FLOOR_AIRBORNE_TIME
 	var on_floor = airborne_time < MAX_FLOOR_AIRBORNE_TIME
 
 
-	# Process jump
+	# Process jump.
 	if jumping:
 	if jumping:
 		if lv.y > 0:
 		if lv.y > 0:
-			# Set off the jumping flag if going down
+			# Set off the jumping flag if going down.
 			jumping = false
 			jumping = false
 		elif not jump:
 		elif not jump:
 			stopping_jump = true
 			stopping_jump = true
@@ -134,7 +105,7 @@ func _integrate_forces(s):
 			lv.y += STOP_JUMP_FORCE * step
 			lv.y += STOP_JUMP_FORCE * step
 	
 	
 	if on_floor:
 	if on_floor:
-		# Process logic when character is on floor
+		# Process logic when character is on floor.
 		if move_left and not move_right:
 		if move_left and not move_right:
 			if lv.x > -WALK_MAX_VELOCITY:
 			if lv.x > -WALK_MAX_VELOCITY:
 				lv.x -= WALK_ACCEL * step
 				lv.x -= WALK_ACCEL * step
@@ -148,14 +119,14 @@ func _integrate_forces(s):
 				xv = 0
 				xv = 0
 			lv.x = sign(lv.x) * xv
 			lv.x = sign(lv.x) * xv
 		
 		
-		# Check jump
+		# Check jump.
 		if not jumping and jump:
 		if not jumping and jump:
 			lv.y = -JUMP_VELOCITY
 			lv.y = -JUMP_VELOCITY
 			jumping = true
 			jumping = true
 			stopping_jump = false
 			stopping_jump = false
 			($SoundJump as AudioStreamPlayer2D).play()
 			($SoundJump as AudioStreamPlayer2D).play()
 		
 		
-		# Check siding
+		# Check siding.
 		if lv.x < 0 and move_left:
 		if lv.x < 0 and move_left:
 			new_siding_left = true
 			new_siding_left = true
 		elif lv.x > 0 and move_right:
 		elif lv.x > 0 and move_right:
@@ -173,7 +144,7 @@ func _integrate_forces(s):
 			else:
 			else:
 				new_anim = "run"
 				new_anim = "run"
 	else:
 	else:
-		# Process logic when the character is in the air
+		# Process logic when the character is in the air.
 		if move_left and not move_right:
 		if move_left and not move_right:
 			if lv.x > -WALK_MAX_VELOCITY:
 			if lv.x > -WALK_MAX_VELOCITY:
 				lv.x -= AIR_ACCEL * step
 				lv.x -= AIR_ACCEL * step
@@ -199,7 +170,7 @@ func _integrate_forces(s):
 			else:
 			else:
 				new_anim = "falling"
 				new_anim = "falling"
 	
 	
-	# Update siding
+	# Update siding.
 	if new_siding_left != siding_left:
 	if new_siding_left != siding_left:
 		if new_siding_left:
 		if new_siding_left:
 			($Sprite as Sprite).scale.x = -1
 			($Sprite as Sprite).scale.x = -1
@@ -208,18 +179,45 @@ func _integrate_forces(s):
 		
 		
 		siding_left = new_siding_left
 		siding_left = new_siding_left
 	
 	
-	# Change animation
+	# Change animation.
 	if new_anim != anim:
 	if new_anim != anim:
 		anim = new_anim
 		anim = new_anim
-		($Anim as AnimationPlayer).play(anim)
+		($AnimationPlayer as AnimationPlayer).play(anim)
 	
 	
 	shooting = shoot
 	shooting = shoot
 	
 	
-	# Apply floor velocity
+	# Apply floor velocity.
 	if found_floor:
 	if found_floor:
 		floor_h_velocity = s.get_contact_collider_velocity_at_position(floor_index).x
 		floor_h_velocity = s.get_contact_collider_velocity_at_position(floor_index).x
 		lv.x += floor_h_velocity
 		lv.x += floor_h_velocity
 	
 	
-	# Finally, apply gravity and set back the linear velocity
+	# Finally, apply gravity and set back the linear velocity.
 	lv += s.get_total_gravity() * step
 	lv += s.get_total_gravity() * step
-	s.set_linear_velocity(lv)
+	s.set_linear_velocity(lv)
+
+
+func _shot_bullet():
+	shoot_time = 0
+	var bi = Bullet.instance()
+	var ss
+	if siding_left:
+		ss = -1.0
+	else:
+		ss = 1.0
+	var pos = position + ($BulletShoot as Position2D).position * Vector2(ss, 1.0)
+		
+	bi.position = pos
+	get_parent().add_child(bi)
+	
+	bi.linear_velocity = Vector2(800.0 * ss, -80)
+	
+	($Sprite/Smoke as Particles2D).restart()
+	($SoundShoot as AudioStreamPlayer2D).play()
+	
+	add_collision_exception_with(bi) # Make bullet and this not collide.
+
+
+func _spawn_enemy_above():
+	var e = Enemy.instance()
+	e.position = position + 100 * Vector2.UP
+	get_parent().add_child(e)

+ 6 - 0
2d/physics_platformer/project.godot

@@ -79,18 +79,23 @@ jump={
 "deadzone": 0.5,
 "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)
 "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(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={
 move_left={
 "deadzone": 0.5,
 "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)
 "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(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={
 move_right={
 "deadzone": 0.5,
 "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)
 "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(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={
 shoot={
@@ -98,6 +103,7 @@ 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)
 "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(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(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(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":7,"pressure":0.0,"pressed":false,"script":null)
  ]
  ]
 }
 }
 spawn={
 spawn={