summaryrefslogtreecommitdiff
path: root/demos/2d/kinematic_char/player.gd
blob: 3549ba3830d88d54e4b9553c7c86827a436d8db1 (plain)
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134

extends KinematicBody2D

#This is a simple collision demo showing how
#the kinematic cotroller works.
#move() will allow to move the node, and will
#always move it to a non-colliding spot, 
#as long as it starts from a non-colliding spot too.


#pixels / second
const GRAVITY = 500.0

#Angle in degrees towards either side that the player can 
#consider "floor".
const FLOOR_ANGLE_TOLERANCE = 40
const WALK_FORCE = 600
const WALK_MIN_SPEED=10
const WALK_MAX_SPEED = 200
const STOP_FORCE = 1300
const JUMP_SPEED = 200
const JUMP_MAX_AIRBORNE_TIME=0.2

const SLIDE_STOP_VELOCITY=1.0 #one pixel per second
const SLIDE_STOP_MIN_TRAVEL=1.0 #one pixel
var velocity = Vector2()
var on_air_time=100
var jumping=false

var prev_jump_pressed=false

func _fixed_process(delta):

	#create forces
	var force = Vector2(0,GRAVITY)

	var stop = velocity.x!=0.0
	
	var walk_left = Input.is_action_pressed("move_left")
	var walk_right = Input.is_action_pressed("move_right")
	var jump = Input.is_action_pressed("jump")

	var stop=true
	
	if (walk_left):
		if (velocity.x<=WALK_MIN_SPEED and velocity.x > -WALK_MAX_SPEED):
			force.x-=WALK_FORCE			
			stop=false
		
	elif (walk_right):
		if (velocity.x>=-WALK_MIN_SPEED and velocity.x < WALK_MAX_SPEED):
			force.x+=WALK_FORCE
			stop=false
	
	if (stop):
		var vsign = sign(velocity.x)
		var vlen = abs(velocity.x)
		
		vlen -= STOP_FORCE * delta
		if (vlen<0):
			vlen=0
			
		velocity.x=vlen*vsign
		

		
	#integrate forces to velocity
	velocity += force * delta
	
	#integrate velocity into motion and move
	var motion = velocity * delta

	#move and consume motion
	motion = move(motion)


	var floor_velocity=Vector2()

	if (is_colliding()):
		# you can check which tile was collision against with this
		# print(get_collider_metadata())

		#ran against something, is it the floor? get normal
		var n = get_collision_normal()

		if ( rad2deg(acos(n.dot( Vector2(0,-1)))) < FLOOR_ANGLE_TOLERANCE ):
			#if angle to the "up" vectors is < angle tolerance
			#char is on floor
			on_air_time=0
			floor_velocity=get_collider_velocity()
			

		if (on_air_time==0 and force.x==0 and get_travel().length() < SLIDE_STOP_MIN_TRAVEL and abs(velocity.x) < SLIDE_STOP_VELOCITY and get_collider_velocity()==Vector2()):
			#Since this formula will always slide the character around, 
			#a special case must be considered to to stop it from moving 
			#if standing on an inclined floor. Conditions are:
			# 1) Standin on floor (on_air_time==0)
			# 2) Did not move more than one pixel (get_travel().length() < SLIDE_STOP_MIN_TRAVEL)
			# 3) Not moving horizontally (abs(velocity.x) < SLIDE_STOP_VELOCITY)
			# 4) Collider is not moving
						
			revert_motion()
			velocity.y=0.0

		else:
			#For every other case of motion,our motion was interrupted.
			#Try to complete the motion by "sliding"
			#by the normal				
			
			motion = n.slide(motion)
			velocity = n.slide(velocity)		
			#then move again
			move(motion)

	if (floor_velocity!=Vector2()):
		#if floor moves, move with floor
		move(floor_velocity*delta)

	if (jumping and velocity.y>0):
		jumping=false
		
	if (on_air_time<JUMP_MAX_AIRBORNE_TIME and jump and not prev_jump_pressed and not jumping):	
		velocity.y=-JUMP_SPEED	
		jumping=true
		
	on_air_time+=delta
	prev_jump_pressed=jump	

func _ready():
	#Initalization here
	set_fixed_process(true)
	pass