-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplayer.lua
222 lines (184 loc) · 6.43 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
love.filesystem.load("input.lua")()
player = {}
local playerStart = { x = 2500, y = 1400 }
local radius = 20
local mass = 25
local imgPath = "gfx/characters/player.png"
local yOfDeath = 5000
local minJump = 1
local jumpExp = 6
local jumpForce = 75000
local jumpMemory = 0.15
local jumpPoolMax = 1
local jumpTime = 0.5
player.label = "player"
player.acceleration = { air = 15000, ground = 20000 }
player.maxSpeed = 200
player.friction = { air = 0.1, ground = 500 }
player.floorSpeed = 0.005
player.start = { x = playerStart.x, y = playerStart.y }
player.state = "ground"
player.onGround = false
player.moveVector = { x = 0, y = 0 }
player.jumpPool = 0
player.lastJump = -math.huge
player.blocked = { left = false, right = false }
player.circle = nil
player.world = nil
player.checkpoint = nil
player.groundCallback = nil
player.leftRightCallback = nil
player.topCallback = nil
-- Callbacks below are used for raycasting and should (I think, bad docs)
-- be able to be considered as part of the update loop
function player:getGroundCallback()
local self = self
local function groundHitCallback(fixture, x, y, xn, yn, fraction)
other = fixture:getUserData()
if other == self or other.label == "checkpoint" then
return -1
end
self.onGround = true
-- Call "you were stomped" callback
if other and other.playerStompCallback then
other.playerStompCallback(other, self)
end
return 0
end
return groundHitCallback
end
function player:getLeftRightCallback()
local self = self
local function callback(fixture, x, y, xn, yn, fraction)
other = fixture:getUserData()
if other == self then
return -1
end
local oldX, oldY = self.circle.body:getPosition()
if x < oldX then
self.blocked.left = true
else
self.blocked.right = true
end
return 0
end
return callback
end
function player:getTopCallback()
local self = self
local function callback(fixture, x, y, xn, yn, fraction)
other = fixture:getUserData()
if other.label == "evilbox" then
print("DEATHSTOMP")
self:dead()
return 0
else
return -1
end
end
return callback
end
function player:print()
print("--- Player info: ---")
print("state:\t", self.state)
print("position: ", self.circle:getX(), self.circle:getY())
print("moveVector: ", self.moveVector.x, self.moveVector.y)
print()
end
function player:dead()
love.event.push("reload")
end
function player:load(world)
self.world = world
self.circle = love.filesystem.load("circle.lua")()
self.circle:load(world, playerStart.x, playerStart.y, radius, imgPath)
self.circle.fixture:setRestitution(0) -- bounce
self.circle.body:setSleepingAllowed(false)
self.circle.body:setMass(mass)
self.circle.fixture:setUserData(self)
self.circle.fixture:setCategory(playerCollisionMask)
self.groundCallback = self:getGroundCallback()
self.leftRightCallback = self:getLeftRightCallback()
self.topCallback = self:getTopCallback()
end
function player:reload()
self.moveVector = { x = 0, y = 0}
if self.checkpoint ~= nil then
self.circle.body:setPosition(self.checkpoint.x, self.checkpoint.y)
else
self.circle.body:setPosition(self.start.x, self.start.y)
end
self.circle.body:setLinearVelocity(0,0)
self.circle.body:setAngle(0)
self.circle.body:setAngularVelocity(0)
end
function player:update(dt)
if self.circle:getY() > yOfDeath then
print("FLY YOU FOOLS")
self:dead()
end
self.moveVector.x = input.getXAxis()
self.moveVector.y = input.getYAxis()
self.onGround = false
self.blocked = { left = false, right = false }
self.world:rayCast(self.circle:getX(), self.circle:getY(),
self.circle:getX(), self.circle:getY() + self.circle:getRadius() + 3,
self.groundCallback)
self.world:rayCast(self.circle:getX(), self.circle:getY(),
self.circle:getX() + self.circle:getRadius(), self.circle:getY(),
self.leftRightCallback)
self.world:rayCast(self.circle:getX(), self.circle:getY(),
self.circle:getX() - self.circle:getRadius(), self.circle:getY(),
self.leftRightCallback)
self.world:rayCast(self.circle:getX(), self.circle:getY(),
self.circle:getX(), self.circle:getY() - (self.circle:getRadius() + 3),
self.topCallback)
if self.blocked.right and self.blocked.left then
print("SQUASHED")
self:dead()
return
end
self.state = self.onGround and "ground" or "air"
local jump = input.getJump()
if not self.jump and jump then
self.lastJump = love.timer.getTime()
elseif love.timer.getTime() - self.lastJump < jumpMemory then
jump = true
end
self.jump = jump
if self.jump and self.jumpPool <= jumpPoolMax - jumpTime and self.onGround then
self.jumpPool = jumpPoolMax
-- Stop so we don't get irregular jump heights
self.circle.body:setLinearVelocity(self.circle.body:getLinearVelocity(),0)
end
local velX, velY = self.circle.body:getLinearVelocity()
local moveDir = self.moveVector.x < 0 and -1 or self.moveVector.x > 0 and 1 or 0
local maxSpeed = self.maxSpeed * math.abs(self.moveVector.x)^2
maxSpeed = math.max(0, 2*(maxSpeed-0.5))
-- Apply force if below maxSpeed (or trying to stop)
if self.onGround and velX * moveDir < maxSpeed then
self.circle.body:applyForce(self.acceleration[self.state] * self.moveVector.x, 0)
elseif not self.onGround and velX * moveDir < maxSpeed/2 then
self.circle.body:applyForce(self.acceleration[self.state] * self.moveVector.x, 0)
end
if math.abs(velX) < self.floorSpeed then
velX = 0
self.circle.body:setLinearVelocity(velX, velY)
elseif velX * self.moveVector.x <= 0 then -- Not moving or trying to stop
self.circle.body:applyForce(-velX*self.friction[self.state], 0)
end
if self.jumpPool > jumpPoolMax - jumpTime then
self.circle.body:applyForce(0, -1 * jumpForce * self.jumpPool^jumpExp)
self.jumpPool = self.jumpPool - dt
end
end
function player:draw()
self.circle:draw()
end
function player:getX()
return self.circle:getX()
end
function player:getY()
return self.circle:getY()
end
return player