| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- GhostPlayer = class()
- GhostPlayer.radius = 48
- GhostPlayer.first = true
- function GhostPlayer:init(owner)
- self.owner = owner
- self.x = owner.x
- self.y = owner.y + owner.height
- self.alpha = 0
- self.vx = 0
- self.vy = -600
- self.prevx = self.x
- self.prevy = self.y
- self.prevalpha = self.alpha
- self.image = data.media.graphics.spiritMuju
- self.angle = -math.pi / 2
- self.maxRange = ctx.map.height - ctx.map.groundHeight
- self.maxDis = lume.lerp(self.maxRange, 0, (1 - (self.owner.deathTimer / self.owner.deathDuration)) ^ 5)
- local sound = ctx.sound:play('spirit')
- if sound then sound:setVolume(.12) end
- if not ctx.effects.active then ctx.view:register(self) end
- end
- function GhostPlayer:update()
- self.prevx = self.x
- self.prevy = self.y
- self.prevalpha = self.alpha
- local px, py = self.owner.x, self.owner.y + self.owner.height
- if lume.distance(self.x, self.y, px, py) < self.radius + 16 and self.owner:hasShruju('diffuse') and self.owner.deathDuration - self.owner.deathTimer > 1 then
- self.owner:spawn()
- return
- end
- local speed = 140 * self.owner.ghostSpeedMultiplier
- local gx, gy = 0, 0
- if self.owner.joystick then
- gx, gy = self.owner.joystick:getGamepadAxis('leftx'), self.owner.joystick:getGamepadAxis('lefty')
- if math.abs(gx) < .1 then gx = 0 end
- if math.abs(gy) < .1 then gy = 0 end
- end
- if gx ~= 0 or gy ~= 0 then
- self.vx = lume.lerp(self.vx, speed * gx, 8 * ls.tickrate)
- self.vy = lume.lerp(self.vy, speed * gy, 8 * ls.tickrate)
- if gx < 0 then
- self.angle = math.anglerp(self.angle, -math.pi / 2 - (math.pi / 7 * (self.vx / -speed)), 12 * ls.tickrate)
- elseif gx > 0 then
- self.angle = math.anglerp(self.angle, -math.pi / 2 + (math.pi / 7 * (self.vx / speed)), 12 * ls.tickrate)
- end
- else
- if love.keyboard.isDown('left', 'a') then
- self.vx = lume.lerp(self.vx, -speed, 8 * ls.tickrate)
- self.angle = math.anglerp(self.angle, -math.pi / 2 - (math.pi / 7 * (self.vx / -speed)), 12 * ls.tickrate)
- elseif love.keyboard.isDown('right', 'd') then
- self.vx = lume.lerp(self.vx, speed, 8 * ls.tickrate)
- self.angle = math.anglerp(self.angle, -math.pi / 2 + (math.pi / 7 * (self.vx / speed)), 12 * ls.tickrate)
- else
- self.vx = lume.lerp(self.vx, 0, 2 * ls.tickrate)
- end
- if love.keyboard.isDown('up', 'w') then
- self.vy = lume.lerp(self.vy, -speed, 8 * ls.tickrate)
- elseif love.keyboard.isDown('down', 's') then
- self.vy = lume.lerp(self.vy, speed, 8 * ls.tickrate)
- else
- self.vy = lume.lerp(self.vy, 0, 2 * ls.tickrate)
- end
- end
- local len = (self.vx ^ 2 + self.vy ^ 2) ^ .5
- if len > 0 and self.owner.deathTimer < self.owner.deathDuration - 1 then
- self.vx = (self.vx / len) * math.min(len, speed)
- self.vy = (self.vy / len) * math.min(len, speed)
- end
- self.x = self.x + self.vx * ls.tickrate
- self.y = self.y + self.vy * ls.tickrate
- local contained = false
- self.maxDis = lume.lerp(self.maxRange, 0, (1 - (self.owner.deathTimer / self.owner.deathDuration)) ^ 5)
- if lume.distance(self.x, self.y, px, py) + self.radius > self.maxDis then
- local angle = lume.angle(px, py, self.x, self.y)
- self.x = lume.lerp(self.x, px + math.dx(self.maxDis - self.radius, angle), 1)
- self.y = lume.lerp(self.y, py + math.dy(self.maxDis - self.radius, angle), 1)
- contained = true
- end
- self.x = math.clamp(self.x, self.radius, ctx.map.width - self.radius)
- self.y = math.clamp(self.y, self.radius, ctx.map.height - self.radius - ctx.map.groundHeight)
- local scale = math.min(self.owner.deathTimer, 2) / 2
- if self.owner.deathDuration - self.owner.deathTimer < 1 then
- scale = self.owner.deathDuration - self.owner.deathTimer
- end
- if ctx.tutorial.active then scale = 1 end
- scale = .4 + scale * .4
- self.radius = 40 * scale
- self.alpha = math.min(self.alpha + ls.tickrate, 1)
- ctx.particles:emit('ghosttrail', self.x, self.y, math.min(lume.round(len / speed, 1) + (contained and 1 or 0)), {
- linearAcceleration = {-self.vx * 1, -self.vy * 1, -self.vx * 1.5, -self.vy * 1.5}
- })
- end
- function GhostPlayer:despawn()
- GhostPlayer.first = false
- if not ctx.effects.active then ctx.view:unregister(self) end
- end
- function GhostPlayer:draw()
- local g = love.graphics
- local x, y = lume.lerp(self.prevx, self.x, ls.accum / ls.tickrate), lume.lerp(self.prevy, self.y, ls.accum / ls.tickrate)
- local alpha = lume.lerp(self.prevalpha, self.alpha, ls.accum / ls.tickrate)
- local scale = math.min(self.owner.deathTimer, 2) / 2
- if self.owner.deathDuration - self.owner.deathTimer < 1 then
- scale = self.owner.deathDuration - self.owner.deathTimer
- end
- if ctx.tutorial.active then scale = 1 end
- scale = .4 + scale * .4
- local alphaScale = math.min(self.owner.deathTimer * 6 / self.owner.deathDuration, 1)
- local color = {128, 0, 255}
- color = table.interpolate(color, {255, 255, 255}, .8)
- color[4] = 200 * alpha * alphaScale
- g.setColor(color)
- g.draw(self.image, x, y, self.angle, .6 * scale, .6 * scale, self.image:getWidth() / 2, self.image:getHeight() / 2)
- g.setBlendMode('additive')
- color[4] = 75 * alpha * alphaScale
- g.setColor(color)
- g.draw(self.image, x, y, self.angle, .75 * scale, .75 * scale, self.image:getWidth() / 2, self.image:getHeight() / 2)
- color[4] = 30 * alpha * alphaScale
- g.setColor(color)
- g.draw(self.image, x, y, self.angle, 1 * scale, 1 * scale, self.image:getWidth() / 2, self.image:getHeight() / 2)
- g.setBlendMode('alpha')
- g.setColor(255, 255, 255, 15)
- g.arc('fill', self.owner.x, self.owner.y + self.owner.height, self.maxDis, 0, -math.pi, self.maxDis / 2)
- end
|