Files
Princesse-Lactose-Godot/princesse.gd
Thomas Lavocat 8948aa1586 physique: appliquer la graivté en pente descendante
Dans la version précédente, lorsque la princesse déscendait
un pente, il se trouvait que la graivté ne la faisait pas coller
au sol correctement.
Pour corriger le soucis, il faut appliquer la gravité en fonction
de ce que décide le joueur car on a besoin de désactiver la gravité
pour permettre au joueur de remonter la pente, mais l'activer à fond
and il descend la pente pour lui permettre de garde les pieds au sol.
2023-04-29 14:12:31 +02:00

241 lines
7.7 KiB
GDScript

extends CharacterBody2D
## The player listens for input actions appended with this suffix.[br]
## Used to separate controls for multiple players in splitscreen.
@export var action_suffix := ""
var gravity: int = ProjectSettings.get("physics/2d/default_gravity")
@onready var platform_detector := $PlatformDetector as RayCast2D
@onready var animation := $AnimatedSprite2D as AnimatedSprite2D
@onready var animation_player := $AnimationPlayer as AnimationPlayer
@onready var camera := $Camera2D as Camera2D
var _double_jump_charged := false
@export var WALKING_SPEED = 400
@export var FALLING_SPEED = 400
@export var JUMPING_SPEED = 400
@export var X_SPEED_TABLE = [0, 0.1, 0.15, 0.2, 0.3, 0.6, 0.9, 1]
@export var X_SPEED_DECEL = [0, 0.1, 0.6, 1]
@export var X_SPEED_AIR_DECEL =[0, 0.1, 0.6, 1]
@export var FALL_SPEED_TABLE = [0, 0.1, 0.15, 0.2, 0.3, 0.6, 0.9, 1]
@export var JUMP_SPEED_TABLE = [0, 0.1, 0.2, 0.5,
0.6, 0.7, 0.8, 0.9, 1]
@export var KICK_SPEED_TABLE = [0, 0.2, 0.4, 0.6, 1, 1.6, 2.4, 3]
# Nombre d'incrément à rajouter lorsque la touche de saut est maintenue
@export var JUMPING_COUNTER_REFILL = 2
# Tous les combien d'incréments rajouter un refill sur le compteur
@export var JUMPING_KEY_COUNTER_THRESHOLD = 3
# Nombre de frames coyote durant lesquelle le joueur peut encore sauter
# sans encore être au sol
@export var COYOTE_LENGTH := 20
# Direction dans laquelle est positioné le personnage.
var direction : int = 1
# Variables détats relatives à la marche.
var walking : bool = false
var walking_step: int = -1
@export var WALK_INCR_GROUND : int = 1
@export var WALK_INCR_AIR : int = 3
var walk_incr_reserve : int = 0
var init_decel: bool = false
# variables d'état relatives au saut
var jumping : bool = false
var jumping_step : int = -1
var jump_key_counter : int = 0
var falling_step : int = -1
var pressing_wall = false
var grab_wall = false
const PLATFORM_LAYER = 1 << (5 - 1) # collision layer 5
const PICS_BLOCK_LAYER = 1 << (6 - 1) # collision layer 6
var layer_of_collision = null
func walk(direction:int) -> int:
# Fait marcher le personnage.
# Si le personnage est dans l'air, il aura une friction plus faible lors de
# la décélération.
var threshold = WALK_INCR_AIR
if is_on_floor():
threshold = WALK_INCR_GROUND
if is_on_wall():
walking_step = min(walking_step, 1)
# Si le joueur décide de marcher alors, le compteur de pas doit s'incrémenter
# Si le joueur ne veut plus marcher, alors, le compteur de pas décrémente
# La vitese choisie est le numéro d'étape dans le tableau correspondant
# X_SPEED_TABLE pour l'accélération
# X_SPEED_DECEL pour la décélération
var table = X_SPEED_TABLE
if walking:
walking_step = min(walking_step+1, X_SPEED_TABLE.size() -1)
init_decel = true
else:
# Lors de la première frame de la décélération, initialiser la valeur
# du compteur d'incrément en haut du tableau de décélération
table = X_SPEED_DECEL
if init_decel:
walking_step = min(walking_step, X_SPEED_DECEL.size() - 1)
init_decel = false
# Si le compteur d'incrément est supérieur ou égal à zéro, c'est qu'il
# faut bouger, donc il est nécéssaire en premier temps de récupérer la vitesse
# à l'indice courant. Puis si le joueur ne veut plus accélérer, alors, appliquer
# la décélération
if walking_step >= 0:
var speed = table[walking_step] * WALKING_SPEED
if not walking:
walk_incr_reserve += 1
# appliquer le nombre de frames nécéssaire pour décrémenter, dépend
# de où est le personnage (air vs sol)
if walk_incr_reserve >= threshold:
walk_incr_reserve = 0
walking_step-=1
return speed * direction
return velocity.x
func fall() -> int:
if jumping:
falling_step = -1
return velocity.y
if is_on_floor():
if get_floor_normal()[0] < 0: # pente à gauche
if direction >= 0:# on va à droite, désactive la gravité
falling_step = -1
return velocity.y
else: # on va à gauche, gravité à fond
falling_step = FALL_SPEED_TABLE.size()-1
else: # pente à droite
if direction > 0:# on va à droite, active la gravité à fond
falling_step = FALL_SPEED_TABLE.size()-1
else: # on va à gauche, désactive la gravité
falling_step = -1
return velocity.y
else:
if grab_wall:
falling_step = max(falling_step-1, 1)
else:
falling_step = min(falling_step+1, FALL_SPEED_TABLE.size()-1)
return FALL_SPEED_TABLE[falling_step] * FALLING_SPEED
func jump() -> int:
if not jumping:
return velocity.y
if not is_on_ceiling() and jump_key_counter > 0 and jump_key_counter % JUMPING_KEY_COUNTER_THRESHOLD == 0:
jumping_step = min(
jumping_step + JUMPING_COUNTER_REFILL,
JUMP_SPEED_TABLE.size() -1
)
if jumping_step > 0:
jumping_step -= 1
return JUMP_SPEED_TABLE[jumping_step] * JUMPING_SPEED * -1
else:
end_jump()
return velocity.y
func end_jump():
jumping = false
jumping_step = -1
jump_key_counter = 0
func _physics_process(delta: float) -> void:
pressing_wall = is_on_wall_only()
grab_wall = pressing_wall and Input.is_action_pressed("grab" + action_suffix)
if Input.is_action_just_pressed("jump" + action_suffix):
if is_on_floor():
if not jumping:
jumping = true
jumping_step = JUMP_SPEED_TABLE.size()-1
jump_key_counter = 0
if Input.is_action_pressed("jump" + action_suffix):
if jumping:
jump_key_counter += 1
else:
jump_key_counter = 0
velocity.y = jump()
velocity.y = fall()
walking = (
Input.is_action_pressed("move_left" + action_suffix) or
Input.is_action_pressed("move_right" + action_suffix)
)
var axis = Input.get_axis(
"move_left" + action_suffix,
"move_right" + action_suffix
)
if not is_zero_approx(axis):
if axis < 0:
direction = -1
else:
direction = 1
velocity.x = walk(direction)
if not is_zero_approx(velocity.x):
if velocity.x > 0.0:
animation.scale.x = 1.0
else:
animation.scale.x = -1.0
if grab_wall and not jumping:
animation.scale.x *= -1
#floor_stop_on_slope = not platform_detector.is_colliding()
var collision = move_and_slide()
if collision:
var collider = get_last_slide_collision().get_collider()
if collider is TileMap:
var tile_rid = get_last_slide_collision().get_collider_rid()
layer_of_collision = PhysicsServer2D.body_get_collision_layer(tile_rid)
if layer_of_collision == PICS_BLOCK_LAYER:
get_tree(). reload_current_scene()
var anim := get_new_animation(false)
if anim != animation.animation:
animation.animation = anim
animation.play()
func get_new_animation(is_shooting := false) -> String:
var animation_new: String
if is_on_floor():
if walking_step > 0:
animation_new = "walk"
else:
animation_new = "idle"
else:
if velocity.y > 0.0:
if grab_wall:
animation_new = "wall_stick"
else:
if walking_step > 0:
animation_new = "falling_diagonals"
else:
animation_new = "falling_straight"
else:
animation_new = "jumping"
return animation_new