module Game.Entities.Shooter (mkShooter) where import Data.Bits (Bits (..)) import Game.Entities.Common import Game.Entities.Const import Game.Entities.Types import Game.Sprites qualified as S blasterCoolDown :: Int blasterCoolDown = 128 mkShooter :: S.SpriteSheet -> Int -> Int -> Dir -> Collision -> Collision -> IsBlocked -> Collision -> IO Entity mkShooter sprites x y d playerCollision playerInLine isBlocked playerVsBlast = do s <- S.get sprites "shooter" pure Entity { typ = TypeEnemy, x = x, y = y, delay = frameDelay, frame = 0, set = toSpriteSet d, jumping = False, gravity = gravityOff, dir = d, sprite = s, update = updateShooter playerCollision playerInLine isBlocked playerVsBlast, destroy = False, actions = [], dat = ShooterData 0 } updateShooter :: Collision -> Collision -> IsBlocked -> Collision -> Entity -> IO Entity updateShooter touchedPlayer playerInLine isBlocked playerVsBlast e = do touched <- touchedPlayer e line <- playerInLine e pure $ update touched line (updateFrame True (updateCoolDown e)) where update :: Bool -> Bool -> Entity -> Entity update wasTouched wasInLine ent | wasInLine && ent.dat.coolDown == 0 = ent { dat = ShooterData blasterCoolDown, actions = [ActionAddBlast blastX (ent.y + 8) ent.dir playerVsBlast isBlocked], frame = 1, delay = frameDelay * 2 } | wasTouched = ent {actions = [ActionHitPlayer]} | testBit ent.delay 1 = ent | ent.dir == DirLeft && (isBlocked (ent.x - 1) (ent.y + 17) || isBlocked (ent.x - 1) (ent.y + 17) || not (isBlocked (ent.x - 1) (ent.y + 24))) = ent {dir = DirRight, set = toSpriteSet DirRight} | ent.dir == DirLeft = ent {x = ent.x - 1} | ent.dir == DirRight && (isBlocked (ent.x + 16) (ent.y + 17) || isBlocked (ent.x + 16) (ent.y + 17) || not (isBlocked (ent.x + 16) (ent.y + 24))) = ent {dir = DirLeft, set = toSpriteSet DirLeft} | ent.dir == DirRight = ent {x = ent.x + 1} | otherwise = ent updateCoolDown :: Entity -> Entity updateCoolDown ent | ent.dat.coolDown > 0 = ent {dat = ShooterData (ent.dat.coolDown - 1)} | otherwise = ent blastX = case e.dir of DirLeft -> e.x - 16 DirRight -> e.x + 16