-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplayer.lua
297 lines (227 loc) · 14.2 KB
/
player.lua
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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
--[[ BEGINNING OF COMMENT
This script will have the code for the main character. It starts with an uppercase letter since it’s a class, and classes are
written beginning with capital letters.
I will use class.lua to make a class in Lua, and I will create the playable character’s properties by creating a class. To do this,
I will use a good portion of the code shown from Colton’s 2018 Game Dev class which can be found here:
https://www.youtube.com/watch?v=3IdOCxHGMIo&t=2006s .
END OF COMMENT --]]
-- This creates the class that will create the main character
Player = Class{}
--[[ I will create a global variable that will check if the player is changing rooms, whic will allow me
to reset the player's position to the far left side of the room if they enter into any treasure room. The variable by
default will be false. If the player enters any treasure room, the variable will temporarily change to "true"
to have their position reset to the far left side of the room.
Then, the variable will change back to false to allow the player to move, that is, so that they aren't stuck in
the far left side of the room when trying to move. ]]
resetPlayerPositionToEntranceOfRoom = false
--[[ This adds the value for gravity. It seems that, by increasing gravity and self.dy, I can make the character
fall faster and jump higher by using "self.dy = Number * dt" (that is, by using dt, so that the game runs
the same on fast and slow computers, with vsync actvated or not.)
The original value for gravity was "19", and the original value for self.dy (without dt) was of "-6". ]]
local GRAVITY = 3300
-- Initializing function, which will contain many of the properties of the main character’s class.
function Player:init()
self.image = love.graphics.newImage('graphics/player.png')
-- This automatically obtains the width of the player’s sprite
self.width = self.image:getWidth()
self.height = self.image:getHeight()
--[[ X and y coordinates of the player. Initially, I will put him on the (100, 100) coordinates.
I edited the y coordinate so it initially starts at 445 px, which is the height at which the player walks
on the floor with the lowest height. --]]
self.x = 30
self.y = 445
--[[ This is the player's initical vertical speed. If I don't initialize it here, I will get an error
once I try to apply gravity to the player. --]]
self.dy = 0
--[[ This will store the current position of the player into a table, and set
it as their last position. I will use this to reset the player’s position once they collide with the floor so that
they don’t clip through the floor (source: https://sheepolution.com/learn/book/23 ). ]]
self.last = {}
self.last.x = self.x
self.last.y = self.y
--[[ Initially, the player won’t be able to jump (source: https://sheepolution.com/learn/book/24 ). ]]
self.canJump = false
end
--[[ This will check collision between 2 bodies (source: https://youtu.be/3IdOCxHGMIo?t=5867 ). More specifically,
it will check collision between the player and the floor.
I’m not using a constant to get the width and the height of the floor (unlike Colton), so I will get the width and the height by
using getWidth() and getHeight() from Floor.lua.
I don't need (for the time being) to check if I'm touching on the x axis the floor.
I NEED TO MODIFY THIS TO COMPARE THE CENTER OF THE FLOOR SPRITE AND OF THE PLAYER’S SPRITE TO USE RESOLVECOLLISION().
I will use a simplified code that will check if the player and the floor are touching each other. I technically don’t
need to check if they’re horizontally aligned, so I will only check if they touch each other on the y coordinates
(source: https://sheepolution.com/learn/book/23 )
I changed the player's y position to "last.y" to get the previous y position from the last{} table.
Since I want to have the same collision detection on the platforms as in the floor, I will change “floor” by a
generic variable.
I think I need to check for collision detection on the x axis as well so that the game checks that I’m both vertically
and horizontally aligned to the floor or the platform before pushing me back upwards so that I don’t fall through
the floor/platform, but I don’t float in the air either. Without checking collision on the x axis, the character will
float if it’s at the same height as any of the platforms.--]]
function Player:collides(e)
return self.last.y + self.height > e.y
and self.last.y < e.y + e.height
and self.last.x + self.width > e.x
and self.last.x < e.x + e.width
end
--[[ This will make the player do any actions (run, throw blocks, fall due to gravity, etc) --]]
function Player:update(dt)
--[[ This is the speed that the player will gain due to gravity when falling
It seems that the solution was using "dt / 2" (source: http://openarena.ws/board/index.php?topic=5100.0)
IT DIDN'T WORK. FIX THIS BUG before continuing.
BUG: My character is falling too slow after jumping, and jumps lower and slower in powerful desktop computers,
instead of jumping and falling as they should like it does on my laptop. FIX THIS BUG.
--]]
self.dy = self.dy + GRAVITY * dt / 2
--[[ Thsi will make the player rewspan if the fall into a bottomless pit. I would need to first check if the
player’s position is higher than the viewport’s height (that is, if the player has fallen below the bottom of
the screen). If it does, I would have to change the player’s position so that it reappears on the left side of
the screen (really close to the room’s door).
I could put an “if” statement on either main.lua or Player.lua to check for the player’s position to check if they
are below the bottom of the screen.
I may use the Player.lua script since it already has a table that stores each position of the player when the
player moves (each x and y coordinate). So, I could use that table to check if the last y position of the player
was way below the bottom of the screen (something like “VIRTUAL_WIDTH + 1000”). If it is, I would reset the player’s
position to the left side of the room (something like “VIRTUAL_WIDTH - (141 * 3) - 150, -80 + VIRTUAL_HEIGHT - 62”,
which is where one of the treasure chests is located.)
I would use something like the code that I’m using for collision detection on Player.lua, but, instead of preventing
the player from falling through the floor, it would make the player respawn at the beginning of the room.
]]
if self.y > VIRTUAL_HEIGHT + 1500 then
self.y = 300
self.x = 100
end
--[[ This will make the player to be on the far left side of the room each time that they enter into a
treasure room. That is, the player will always start at the beginning of the treasure room, regardless
of the position that the door had back in the main hub. ]]
if currentRoom ~= 0 and resetPlayerPositionToEntranceOfRoom == true then
self.x = 100
self.y = 445
resetPlayerPositionToEntranceOfRoom = false
end
--[[ This makes the player jump. This is where the keysPressed table from main.lua is being used.
I will also prevent the player from jumping again mid-jump (source: https://sheepolution.com/learn/book/24 ).
I need to specify that, besides pressing the spacebar, you also need the canJump variable to be “true” to be able to jump.
I added "+ dt" so the character jumps at the same height in every computer, be it a powerful one, a weak one,
or regardless of whether or not vsync is on (source: https://love2d.org/forums/viewtopic.php?t=76758 )
I had to increase the values for the self.dy and the gravity so that I could use "dt" in the vertical speed calculation
and I could still fall fast and jump high.
--]]
if love.keyboard.wasPressed('space') and self.canJump then
self.dy = -1300
self.canJump = false
end
--[[ DEBUGGING CODE. This will make the player move downwards if the user presses the down arrow key
(source: https://sheepolution.com/learn/book/23 )]]
-- if love.keyboard.isDown("down") then
-- self.y = self.y + 200 * dt
-- end
--[[ This will make the player move left or right by pressing the arrow keys. ]]
if love.keyboard.isDown("left") then
self.x = self.x - 260 * dt
elseif love.keyboard.isDown("right") then
self.x = self.x + 260 * dt
end
--[[ DEBUGGING CODE. DELETE LATER. This will change the room number if I press any of the number keys (between 0
and 5,) and tell me the current x and y coordinates of the player. ]]
if love.keyboard.wasPressed('1') then
currentRoom = 1
print("Room 1.")
elseif love.keyboard.wasPressed('2') then
currentRoom = 2
print("Room 2.")
elseif love.keyboard.wasPressed('3') then
currentRoom = 3
print("Room 3.")
elseif love.keyboard.wasPressed('4') then
currentRoom = 4
print("Room 4.")
elseif love.keyboard.wasPressed('5') then
currentRoom = 5
print("Room 5.")
elseif love.keyboard.wasPressed('0') then
currentRoom = 0
print("Main Hub.")
elseif love.keyboard.wasPressed('p') then
print(self.x, self.y)
end
--[[ This will make the player fall due to gravity (by updating his y coordinate).
I added an "if" statement that will check whether the player is in the air (be it from
jumping or by falling.) If the player is in the air, I will apply gravity to them.
It works, but the player will sometimes get their feet deeper into the floor when junping too high.
They can still jump, but it's still a bug. However, I would need a better collision detector
to fix that, so I may leave that as is.
Now, I need to find a way to jump only once. Right now, I can jump infinitely.
It seems that the solution was using "dt / 2" so that the character jumps at the same height
in any computer, no matter how powerful lthe computer is or if vsync is on or off. (source: http://openarena.ws/board/index.php?topic=5100.0)
I used "(self.dy * dt)" so that the vertical speed is calculated with "dt", and so that the character could
fall fast and jump high on powerful computers, as well as in my laptop. SEE IF IT WORKS.
--]]
if playerCollision == false or love.keyboard.wasPressed('space') then
self.y = self.y + (self.dy * dt)
self.dy = self.dy + GRAVITY * dt / 2
end
--[[ This will store the previous position of the player into the last{} table (source:
-- https://sheepolution.com/learn/book/23 ) ]]
self.last.x = self.x
self.last.y = self.y
end
--[[ Besides the standard collision detection, I will also detect if the player and the object are one on top of the
other, or in other words, if they have the same x coordinate (source: https://sheepolution.com/learn/book/23 ).
This could also be called that they are horizontally aligned.
This will prevent the player from appearing on top of a platform if they walk below a platform. ]]
function Player:sameHorizontalPosition(e)
return self.last.x < e.x + e.width and self.last.x + self.width > e.x
end
--[[ For the time being, I WON'T check for horizontal collision detection, because, otherwise, my character will clip
through the floor.
I would have to create a different collision detection that is entirely separate for the floor. However, I don't need
that urgently for the time being.]]
-- function Player:sameVerticalPosition(e)
-- return self.last.y < e.y + e.height and self.last.y + self.height > e.y
-- end
--[[ This function will make it so that, if the player touches the floor (or a wall,) that they won’t clip
through the floor, since they will go back to their previous position (source: https://sheepolution.com/learn/book/23 .)
After further reading, it turns out that I shouldn’t return the player to their previous position (by using last{}).
Instead, I should create a variable which will subtract the distance in which the player falls through the floor.
This way, the player will only touch the floor, NOT fall through it (source: https://sheepolution.com/learn/book/23 .)
I will now check if the center of the player's sprite is higher than the center of the floor's sprite. If so, I will
push the player upwards, so that they don't fall through the floor. After that, I subtract the player's height to the floor's
y coordinate, and push them upwards at exactly that distance so that the player's feet never fall through the floor.
IT WORKS, but the player will fall through the floor once their weight due to gravity becomes large enough.
I added some code to reset the gravity back to 0 for the player if they touch the floor (source:
https://sheepolution.com/learn/book/24 ). In my case, “self.dy” stores the player’s weight due to gravity.
I will change “floor” by a generic variable to let the player land on both the floor and the platforms.
I will add an extra condition to resolveCollision(): to check if the player and the object are in the same horizontal
position (source: https://sheepolution.com/learn/book/23 ). This way, the player won’t spawn on top of a platform if
they walk below the platforms.
I was able to more or less fix the bug where the player was spawning on top of the platforms if they walked below them
by changing "e.height/2" by "e.height/10" (or a smaller number). This is because the platform sprite is very tall, so
the player was never walking below the vertical center of the platforms' sprites.
In the end, I had to cut the platform sprite into 2 parts: the top part (the red rectangle), and the bottom blue base.
The top part will have collision detection.
I will make my character to be pushed downwards if they jump below the platform. This will prevent the player
from going to the top of platforms 1 and 2 if I jump high enough from below, and will prevnt the player from
getting stuck below platform 3 if they jump below it (source: https://sheepolution.com/learn/book/23).]]
function Player:resolveCollision(e)
if self:collides(e) then
if self:sameHorizontalPosition(e) then
if self.y + self.height/2 < e.y + e.height/2 then
local pushback = self.y + self.height - e.y
self.y = self.y - pushback
self.dy = 0
else
local pushback = e.y + e.height - self.y
self.y = self.y + pushback
end
-- local pushback = self.y + self.height - floor.y
-- self.y = self.y + pushback
-- self.x = self.last.x
-- self.y = self.last.y
end
end
end
-- This will render the player’s sprite onscreen
function Player:render()
love.graphics.draw(self.image, self.x, self.y)
end