| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
- local puju = {}
- function puju:idle()
- self.target = self:closest('minion', 'shruju')
- if self.target then
- self.state = 'move'
- end
- end
- function puju:move()
- if self.target and self.target.isMinion and self.target.dead then
- self.state = 'idle'
- self.target = nil
- return
- end
- self.target = self:closest('minion', 'shruju')
- if self.target then
- sign = self:signTo(self.target)
- else
- sign = util.sign(self.destination.x - self.position.x)
- end
- if sign ~= 0 then
- self.animation.flipped = sign > 0
- end
- local distance = self:distanceTo(self.target)
- local angle = self:directionTo(self.target)
- local targetVelocityX = math.cos(angle) * self.config.speed * lib.tick.rate
- local targetVelocityY = math.sin(angle) * self.config.speed * lib.tick.rate
- if self.target.isShruju then
- self.velocity.x = util.lerp(self.velocity.x, targetVelocityX, lib.tick.getLerpFactor(self.config.acceleration))
- self.velocity.y = util.lerp(self.velocity.y, targetVelocityY, lib.tick.getLerpFactor(self.config.acceleration))
- if self:isCarryingShruju(self.target) then
- self.state = 'run'
- end
- if self:distanceTo(self.target) <= self.config.radius + self.target.config.radius then
- if self:pickupShruju(self.target) then
- self.state = 'run'
- end
- end
- return
- end
- local distanceFactor = util.clamp((distance - self.config.range) / (self.config.range / 4), 0, 1)
- self.velocity.x = util.lerp(self.velocity.x, targetVelocityX, lib.tick.getLerpFactor(self.config.acceleration))
- self.velocity.y = util.lerp(self.velocity.y, targetVelocityY, lib.tick.getLerpFactor(self.config.acceleration))
- if self:isInRangeOf(self.target) and love.math.random() < lib.tick.rate * 2 and not self.target.isShruju then
- self.state = 'attack'
- end
- end
- function puju:attack()
- self.attackThread = self.attackThread or lib.quilt.add(function()
- self.attackDirection = self:directionTo(self.target)
- self.chargeStart = lib.tick.index
- self.animation:set('mouthsuck')
- coroutine.yield(self.config.chargeTime)
- self.animation:set('mouthblow')
- self.chargeStart = nil
- app.context:addObject(app.spells.seed, {
- position = util.copy(self.position),
- direction = self.attackDirection,
- owner = self
- })
- self.velocity.x = util.dx(self.config.recoil, self.attackDirection + math.pi)
- self.velocity.y = util.dy(self.config.recoil, self.attackDirection + math.pi)
- self.yank = -self.velocity.x / 2
- coroutine.yield(self.config.attackCooldown)
- self.state = 'idle'
- self.attackDirection = nil
- self.attackThread = nil
- end)
- self.velocity.x = util.lerp(self.velocity.x, 0, lib.tick.getLerpFactor(self.config.acceleration))
- self.velocity.y = util.lerp(self.velocity.y, 0, lib.tick.getLerpFactor(self.config.acceleration))
- end
- function puju:run()
- local targetX, targetY
- if self.position.x < app.context.scene.width / 2 then
- targetX = 0
- targetY = app.context.scene.height / 2
- else
- targetX = app.context.scene.width
- targetY = app.context.scene.height / 2
- end
- local distance = self:distanceToPoint(targetX, targetY)
- local angle = self:directionToPoint(targetX, targetY)
- local velocityX = math.cos(angle) * self.config.speed / 3 * lib.tick.rate
- local velocityY = math.sin(angle) * self.config.speed / 3 * lib.tick.rate
- self.velocity.x = util.lerp(self.velocity.x, velocityX, lib.tick.getLerpFactor(self.config.acceleration))
- self.velocity.y = util.lerp(self.velocity.y, velocityY, lib.tick.getLerpFactor(self.config.acceleration))
- if distance < 50 then
- self.target:die()
- self.state = 'idle'
- end
- end
- function puju:isHovered(x, y)
- local hoverAllowanceFactor = 1.5
- local dis = util.distance(self.position.x, self.position.y, x, y)
- local dir = util.angle(self.position.x, self.position.y, x, y)
- local ellipseHover = dis < self.config.radius * hoverAllowanceFactor / (2 - math.abs(math.cos(dir)))
- local image = app.art.puju
- local baseScale = self:getBaseScale()
- local scale = g.imageScale(image, 35 * baseScale)
- local width, height = self.config.radius * 2, image:getHeight() * scale
- local offset = math.sin(lib.tick.index * lib.tick.rate * 3) * 4
- local x1 = self.position.x - width / 2
- local y1 = self.position.y - 20 + offset - height
- local mouseHover = util.inside(x, y, x1, y1, width, height)
- return self:isTargetable() and (mouseHover or ellipseHover)
- end
- function puju:drift()
- self.velocity.x = self.velocity.x + math.sin((self.floatOffset + lib.tick.index) * lib.tick.rate * 2) * lib.tick.rate
- self.velocity.y = self.velocity.y + math.cos((self.floatOffset + lib.tick.index) * lib.tick.rate * 2) * lib.tick.rate
- self.position.x = self.position.x + self.velocity.x
- self.position.y = self.position.y + self.velocity.y
- local yank = util.clamp(self.velocity.x / (self.config.speed * lib.tick.rate), -1, 1)
- self.yank = util.lerp(self.yank, yank, lib.tick.getLerpFactor(.02))
- end
- function puju:getBaseScale()
- return self.chargeStart and 1 + ((lib.tick.index - self.chargeStart) * lib.tick.rate / self.config.chargeTime) * .5 or 1
- end
- function puju:draw()
- local baseScale = self:getBaseScale()
- local image = app.art.shadow
- local offset = math.sin(lib.tick.index * lib.tick.rate * 3) * 4
- local scale = g.imageScale(image, (70 + offset) * baseScale)
- g.white(70 * self.alpha)
- g.draw(image, self.position.x, self.position.y, 0, scale, scale / 1.5, image:getWidth() / 2, image:getHeight() / 2)
- self:drawRing(255, 40, 40)
- g.white()
- self.animation:tick(lib.tick.delta)
- self.animation.skeleton:findBone('body').rotation = 270 + self.yank * 20 * (self.animation.flipped and 1 or -1)
- if util.timeSince(self.lastHurt) < self.config.damageFlashDuration then
- self.animation:draw(self.position.x, self.position.y)
- app.shaders.colorize:send('color', { 1, 1, 1, 1 - util.timeSince(self.lastHurt) / self.config.damageFlashDuration })
- g.setShader(app.shaders.colorize)
- self.animation:draw(self.position.x, self.position.y)
- g.setShader()
- else
- self.animation:draw(self.position.x, self.position.y)
- end
- local image = app.art.puju
- local scale = g.imageScale(image, 35 * baseScale)
- g.white(self.alpha * 255)
- --g.draw(image, self.position.x, self.position.y - 20 + offset - image:getHeight() * scale, self.yank * .4, scale * self.direction, scale, image:getWidth() / 2, 0)
- return -self.position.y
- end
- function puju:die()
- if self.attackThread then
- lib.quilt.remove(self.attackThread)
- end
- if self.dead then return end
- self.dead = true
- self:dropShruju()
- lib.flux.to(self, .4, { alpha = 0 }):ease('cubicout'):oncomplete(function()
- self:remove()
- end)
- end
- return puju
|