-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathslope_player.gd
106 lines (95 loc) · 4.3 KB
/
slope_player.gd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
extends KinematicBody2D
const GRAV_PULL = 1000.0 # Gravity Scale
const SLOPE_MAX = 89.0 # Angle at which slopes can be moved along
const SLOPE_CONVERSION_THRESHOLD = 0.18 # this value is strange.. but necessary for correctly moving down slopes based on speed..
const SLOPE_DOWN_CHECK = SLOPE_CONVERSION_THRESHOLD * SLOPE_MAX
var GRAVITY = GRAV_PULL
const WALK_SPEED = 200 # how far you can move horizontally per second
const JUMP_SPEED = - 400
const OVERLAP_FOR_CRUSH = 3
var MAX_DOWN_MOVE = min( 3, tan( deg2rad(SLOPE_MAX) )) #how far you can move down per second
var velocity = Vector2()
onready var COL_MARGIN = get_collision_margin()
signal crushed
func _ready():
set_fixed_process(true)
func _fixed_process(delta):
# Make sure gravity doesn't effect player when on a block
if test_move(Vector2(0,1)):
GRAVITY = 0
velocity.y = 0
if Input.is_action_pressed("ui_up"):
velocity.y = JUMP_SPEED
else: GRAVITY = GRAV_PULL
velocity.y += delta * GRAVITY
# Handle input for moving and such
if (Input.is_action_pressed("ui_left")): velocity.x = - WALK_SPEED
elif (Input.is_action_pressed("ui_right")): velocity.x = WALK_SPEED
else: velocity.x = 0
# Begin moving
var was_on_floor = test_move( Vector2( 0, 4) ) && velocity.y >= 0
var motion = velocity * delta
var oldPos = get_global_pos()
motion = move(motion)
# Handle the priotized logic (Slopes moving up or down)
if is_colliding() :
# Attempt to correctly move UP slopes, sliding up them - speed non reduced
# Get the collision normal to solve for angle
var n = get_collision_normal()
var angle = rad2deg(acos(n.dot(Vector2(0,-1))))
if angle < SLOPE_MAX: # can move up
motion = Vector2( motion.x, 0)
motion = n.slide(motion).normalized() * abs(motion.x)
elif angle < 90 && angle >= SLOPE_MAX: # Can't move up, stop in tracks
motion = Vector2(0, motion.y)
revert_motion()
else: motion = n.slide(motion) # Naturally slide against all other cases
if !test_move(Vector2()) && !test_move(motion):
move(motion)
elif was_on_floor && get_collision_at_feet( Vector2( 0, abs(velocity.x) * delta * SLOPE_DOWN_CHECK) ) != null:
# We can potentially move down, we will try if there's a collision amongst one of our bottom edges
var col = get_collision_at_feet( Vector2( 0, abs(velocity.x) * delta * SLOPE_DOWN_CHECK) )
if col != null:
var pos = get_global_pos()
var point = get_collision_point_below(col)
# can move down is based on the change in y from our FEET to the desired position
var can_move_down = ( abs((pos.y+8)-point.y) <= (MAX_DOWN_MOVE * delta * abs(velocity.x)) )
if can_move_down:
# forcefully push ourselves to the nearest collided point on an edge (IF Accepted slope)
set_global_pos( point - Vector2(0,8))
if !feet_are_free() : set_global_pos( pos ) #reset position on spiked inclines
# Update the player's position for moving blocks...
was_on_floor = test_move( Vector2( 0, 9) ) && velocity.y >= 0
if was_on_floor :
var saved = get_global_pos()
move( Vector2( 0, 9 ) )
if is_colliding():
set_global_pos(saved)
var vel = get_collider_velocity() * delta
move( vel )
else: set_global_pos(saved)
set_collision_margin( -OVERLAP_FOR_CRUSH )
if test_move(Vector2()):
emit_signal("crushed")
print("crushed!!!")
set_collision_margin( COL_MARGIN )
func vector_angle( a, b ): return rad2deg(acos(b.dot(a)))
func feet_are_free():
var space = get_world_2d().get_direct_space_state()
var left = get_node("bot_l").get_global_pos() + Vector2( 0, - .5)
var right = get_node("bot_r").get_global_pos() + Vector2( 0, - .5 )
var col1 = space.intersect_ray( left, right, [self])
return col1.empty()
func get_collision_at_feet(pushDown = WALK_SPEED * SLOPE_DOWN_CHECK ):
var space = get_world_2d().get_direct_space_state()
var left = get_node("bot_l").get_global_pos()
var right = get_node("bot_r").get_global_pos()
var col1 = space.intersect_ray( right, pushDown + right, [self])
var col2 = space.intersect_ray( left, pushDown + left, [self])
if col1.empty() and col2.empty() : return null
elif col1.empty() : return col2
elif col2.empty() : return col1
elif col1.position.y < col2.position.y: return col1
else: return col2
func get_slope_on( colMap ): return rad2deg(acos(colMap.normal.dot(Vector2(0,-1))))
func get_collision_point_below( colMap ): return Vector2( get_global_pos().x, colMap.position.y )