Enemy = {} class('Enemy').extends(NobleSprite) function Enemy:init(x, y, isScout) Enemy.super.init(self) self:moveTo(x, y) self:setZIndex(4) self:add(x,y) self.markImage = Graphics.image.new("assets/sprites/bomber/enemy_alive_"..math.random(1,2)) self.deadImage = Graphics.image.new("assets/sprites/bomber/enemy_dead") self.hitSound = playdate.sound.fileplayer.new("assets/audio/hit1") self:setImage(self.markImage) self.removed = false self:setGroups(CollideGroups.enemy) self:setCollidesWithGroups({ CollideGroups.granade, CollideGroups.enemy }) self:setCollideRect(-6, -6, 46, 46) self:setSize(32, 32) self.vx = 0 self.vy = 0 self.isDying = false self.friction = 0.95 self.isScout = isScout or false if self.isScout then self.baseSpeed = math.random(8, 14) / 10 self.zigzagTime = math.random() * 100 self.zigzagAmplitude = math.random(8, 15) / 10 self.zigzagFrequency = math.random(4, 8) / 100 else self.baseSpeed = math.random(2, 8) / 10 end end function Enemy:update() if not BomberScene.instance then return end local speed = 0 if self.isDying then self.vx = self.vx * self.friction self.vy = self.vy * self.friction self:moveBy(self.vx, self.vy + BomberScene.instance.scrollSpeed) if math.abs(self.vx) < 0.1 and math.abs(self.vy) < 0.1 then self.isDying = false self.removed = true end elseif not self.removed then speed = self.baseSpeed + (BomberScene.enemySpeedBonus or 0) local dx = 0 if self.isScout then self.zigzagTime = self.zigzagTime + self.zigzagFrequency dx = math.sin(self.zigzagTime) * self.zigzagAmplitude end self:moveBy(dx, BomberScene.instance.scrollSpeed + speed) else self:moveBy(0, BomberScene.instance.scrollSpeed) end local actualX, actualY, collisions, numberOfCollisions = self:checkCollisions(self.x, self.y) if numberOfCollisions > 0 then for i, collision in ipairs(collisions) do if collision.other:getTag() == Tags.granade and collision.other.currentRadius <= 0.05 and not self.isDying then self:setImage(self.deadImage) self.hitSound:play() self:applyExplosionForce(collision.other.x, collision.other.y) end end end if self.y > SCREEN_H + 10 then if not self.removed then self:remove() self:superRemove() self.removed = true end end end function Enemy:applyExplosionForce(explosionX, explosionY) local dx = self.x - explosionX local dy = self.y - explosionY local dist = math.sqrt(dx*dx + dy*dy) if dist == 0 then dist = 0.001 end dx = dx / dist dy = dy / dist local maxForce = 5 local maxRadius = 100 local force = maxForce * (1 - math.min(dist, maxRadius) / maxRadius) force = math.max(force, 1) self.vx = dx * force self.vy = dy * force * 0.5 self.isDying = true BomberScene.killCount = BomberScene.killCount + 1 FloatingText(self.x, self.y) self:setRotation(math.random() * 360) end