Skip to content

Commit

Permalink
Refactor the Player and gun to fit our code guidelines
Browse files Browse the repository at this point in the history
  • Loading branch information
NathanLovato committed Nov 12, 2019
1 parent 55d8e1d commit c7de3b4
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 56 deletions.
6 changes: 6 additions & 0 deletions platformer-2d-rework/project.godot
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ _global_script_classes=[ {
"language": "GDScript",
"path": "res://src/Actors/Enemy.gd"
}, {
"base": "Position2D",
"class": "Gun",
"language": "GDScript",
"path": "res://src/Actors/Gun.gd"
}, {
"base": "Node2D",
"class": "MovingPlatform",
"language": "GDScript",
Expand All @@ -44,6 +49,7 @@ _global_script_class_icons={
"Bullet": "",
"Coin": "",
"Enemy": "",
"Gun": "",
"MovingPlatform": "",
"Player": ""
}
Expand Down
22 changes: 22 additions & 0 deletions platformer-2d-rework/src/Actors/Gun.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
extends Position2D
class_name Gun


onready var sound_shoot: AudioStreamPlayer2D = $Shoot
onready var timer: Timer = $Cooldown

const Bullet = preload("res://src/Objects/Bullet.tscn")
const BULLET_VELOCITY := 1000.0


func shoot(direction: int = 1) -> bool:
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
106 changes: 56 additions & 50 deletions platformer-2d-rework/src/Actors/Player.gd
Original file line number Diff line number Diff line change
@@ -1,67 +1,59 @@
extends Actor

class_name Player

onready var ray: RayCast2D = $PlatformDetector

onready var platform_detector: RayCast2D = $PlatformDetector
onready var sprite: Sprite = $Sprite
onready var sound_shoot: AudioStreamPlayer2D = $SoundShoot
onready var animation_player: AnimationPlayer = $AnimationPlayer
onready var gun_position: Position2D = $Sprite/GunPosition

const BULLET_VELOCITY := 1000.0
const SHOOT_TIME_SHOW_WEAPON := 0.2

var _current_animation := ""
var _shoot_time := 99.0 # time since last shot

var Bullet = preload("res://src/Objects/Bullet.tscn")


func _physics_process(delta):
_shoot_time += delta
onready var shoot_timer: = $ShootAnimation
onready var gun: 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: float) -> void:
var direction: = get_direction()

var is_jump_interrupted: = Input.is_action_just_released("jump") and _velocity.y < 0.0

var direction: = get_direction()
_velocity = calculate_move_velocity(_velocity, direction, speed, is_jump_interrupted)
var is_snapping: Vector2 = Vector2.DOWN * 60.0 if direction.y == 0.0 else Vector2.ZERO
var is_on_platform: = ray.is_colliding()

var is_snapping: = Vector2.DOWN * 60.0 if direction.y == 0.0 else Vector2.ZERO
var is_on_platform: = platform_detector.is_colliding()
_velocity = move_and_slide_with_snap(
_velocity, is_snapping, FLOOR_NORMAL, not is_on_platform, 4, 0.9, false
)

### Shooting
if Input.is_action_just_pressed("shoot"):
var bullet = Bullet.instance()
bullet.position = gun_position.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
sound_shoot.play()
_shoot_time = 0

### Animation
var new_animation = "idle"

if abs(direction.x) > 0:
# 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

if is_on_floor():
if abs(_velocity.x) > 0:
new_animation = "run"
else:

if _velocity.y > 0:
new_animation = "falling"
else:
new_animation = "jumping"

if _shoot_time < SHOOT_TIME_SHOW_WEAPON:
new_animation += "_weapon"
# We use the sprite's scale to store Robi’s look direction which allows us in turn 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)

if new_animation != _current_animation:
_current_animation = new_animation
animation_player.play(new_animation)

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() -> Vector2:
Expand All @@ -71,6 +63,10 @@ func get_direction() -> Vector2:
)


"""
This function calculates a new velocity whenever you need it.
It allows you to interrupt jumps.
"""
func calculate_move_velocity(
linear_velocity: Vector2,
direction: Vector2,
Expand All @@ -83,5 +79,15 @@ func calculate_move_velocity(
velocity.y = speed.y * direction.y
if is_jump_interrupted:
velocity.y = 0.0

return velocity


func get_new_animation(is_shooting: bool = false) -> String:
var animation_new: = ""
if is_on_floor():
animation_new = "run" if abs(_velocity.x) > 0 else "idle"
else:
animation_new = "falling" if _velocity.y > 0 else "jumping"
if is_shooting:
animation_new += "_weapon"
return animation_new
26 changes: 20 additions & 6 deletions platformer-2d-rework/src/Actors/Player.tscn
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[gd_scene load_steps=20 format=2]
[gd_scene load_steps=21 format=2]

[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]
Expand All @@ -8,6 +8,7 @@
[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"
Expand Down Expand Up @@ -191,6 +192,11 @@ script = ExtResource( 1 )
speed = Vector2( 400, 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="."]
position = Vector2( 0, 29.9245 )
enabled = true
Expand All @@ -201,9 +207,20 @@ collision_mask = 8
texture = ExtResource( 2 )
vframes = 2
hframes = 16
frame = 26

[node name="GunPosition" 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="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
Expand All @@ -225,12 +242,9 @@ current = true
position = Vector2( 0.291992, -0.835023 )
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

Expand Down

0 comments on commit c7de3b4

Please sign in to comment.