-
Notifications
You must be signed in to change notification settings - Fork 122
/
one_way_platforms_player.script
165 lines (146 loc) · 4.95 KB
/
one_way_platforms_player.script
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
-- gravity pulling the player down in pixel units/sˆ2
local gravity = -20
-- take-off speed when jumping in pixel units/s
local jump_takeoff_speed = 900
function init(self)
-- this tells the engine to send input to on_input() in this script
msg.post(".", "acquire_input_focus")
msg.post("camera", "acquire_camera_focus")
msg.post("@render:", "use_camera_projection")
--msg.post("@system:", "toggle_physics_debug")
-- save the starting position
self.position = go.get_position()
-- keep track of movement vector and if there is ground contact
self.velocity = vmath.vector3(0, 0, 0)
self.ground_contact = false
-- also keep track of if there is contact with a platform from below it
self.platform_contact_from_below = false
self.platform_contact_from_below_last_frame = false
end
function final(self)
-- Return input focus when the object is deleted
msg.post(".", "release_input_focus")
msg.post("camera", "release_camera_focus")
end
function update(self, dt)
msg.post("@render:", "clear_color", { color = vmath.vector4(95 /256, 129 / 256, 161 / 256, 1 ) })
local gravity = vmath.vector3(0, gravity, 0)
if self.move_left then
self.velocity.x = -250
sprite.set_hflip("#sprite", true)
elseif self.move_right then
self.velocity.x = 250
sprite.set_hflip("#sprite", false)
else
self.velocity.x = 0
end
if not self.ground_contact then
-- Apply gravity if there's no ground contact
self.velocity = self.velocity + gravity
end
-- apply velocity to the player character
go.set_position(go.get_position() + self.velocity * dt)
-- reset volatile state
self.correction = vmath.vector3()
self.ground_contact = false
self.platform_contact_from_below_last_frame = self.platform_contact_from_below
self.platform_contact_from_below = false
end
local function handle_geometry_contact(self, normal, distance)
-- project the correction vector onto the contact normal
-- (the correction vector is the 0-vector for the first contact point)
local proj = vmath.dot(self.correction, normal)
-- calculate the compensation we need to make for this contact point
local comp = (distance - proj) * normal
-- add it to the correction vector
self.correction = self.correction + comp
-- apply the compensation to the player character
go.set_position(go.get_position() + comp)
-- check if the normal points enough up to consider the player standing on the ground
-- (0.7 is roughly equal to 45 degrees deviation from pure vertical direction)
if normal.y > 0.7 then
self.ground_contact = true
end
-- project the velocity onto the normal
proj = vmath.dot(self.velocity, normal)
-- if the projection is negative, it means that some of the velocity points towards the contact point
if proj < 0 then
-- remove that component in that case
self.velocity = self.velocity - proj * normal
end
end
function on_message(self, message_id, message, sender)
if message_id == hash("contact_point_response") then
-- check if we received a contact point message. One message for each contact point
if message.group == hash("ground") then
handle_geometry_contact(self, message.normal, message.distance)
elseif message.group == hash("platform") then
-- If the message normal is pointing up and we didn't have
-- platform contact from below last frame then we have fallen on top
-- of a platform and need to treat it like geometry contact
-- Any other contact with "platform" is considered as contact where the
-- player is passing through the platform from below
if message.normal.y > 0 then
if not self.platform_contact_from_below_last_frame then
handle_geometry_contact(self, message.normal, message.distance)
self.platform_contact_from_below = false
else
self.platform_contact_from_below = true
end
else
self.platform_contact_from_below = true
end
end
end
end
local function jump(self)
-- only allow jump from ground
if self.ground_contact then
-- set take-off speed
self.velocity.y = jump_takeoff_speed
end
end
local function abort_jump(self)
-- cut the jump short if we are still going up
if self.velocity.y > 0 then
-- scale down the upwards speed
self.velocity.y = self.velocity.y * 0.5
end
end
function on_input(self, action_id, action)
if action_id == hash("trigger") or action_id == hash("touch") then
if action.pressed then
jump(self)
elseif action.released then
abort_jump(self)
end
end
if action_id == hash("left") then
if action.pressed then
self.move_left = true
elseif action.released then
self.move_left = false
end
elseif action_id == hash("right") then
if action.pressed then
self.move_right = true
elseif action.released then
self.move_right = false
end
end
--[[if action_id == hash("up") then
if action.pressed then
self.velocity.y = 250
elseif action.released then
self.velocity.y = 0
end
elseif action_id == hash("down") then
if action.pressed then
self.velocity.y = -250
elseif action.released then
self.velocity.y = 0
end
end--]]
end
function on_reload(self)
end