packages feed

nyx-game-0.1.0.0: app/Enemy/SideToSideSpiral.hs

{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses  #-}
{-# LANGUAGE DuplicateRecordFields  #-}
{-# LANGUAGE FlexibleInstances  #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE OverloadedStrings  #-}

module Enemy.SideToSideSpiral where

import qualified SDL
import qualified Play.Engine.MySDL.MySDL as MySDL
import qualified Data.Map as M
import Control.Monad.Except
import Control.Lens

import Play.Engine

import Bullet
import Enemy
import qualified Attack as A
import qualified Attack.SpiralAttack as SA
import qualified Play.Engine.Movement as MV
import qualified Play.Engine.Sprite as Spr
import Data.Maybe (fromJust)


wantedAssets :: [(String, MySDL.ResourceType FilePath)]
wantedAssets =
  [ ("static", MySDL.Texture "static.png")
  , ("crossdown", MySDL.Texture "crossdown.png")
  ]

make :: IPoint -> M.Map String SDL.Texture -> Result Enemy
make posi ts = do
  case (,) <$> M.lookup "static" ts <*> M.lookup "crossdown" ts of
    Nothing ->
      throwError ["Texture not found: static or crossdown" ]
    Just (et, bt) -> do
      let
        sz = Point 48 48
      pure . mkEnemy $
        MakeEnemy
          { mkePos = posi
          , mkeSize = sz
          , mkeMov = leftRightMovement
          , mkeHealth = 100
          , mkeDirChanger = changeDirection
          , mkeAtk = singleSpiralAttack bt
          , mkeAtkChanger = \_ _ -> Nothing
          , mkeDeathTime = 0
          , mkeDeathParts = Point 3 3
          , mkeDeathTexture = et
          , mkeSprite =
            fromJust
              $ Spr.make
              $ Spr.MakeArgs
              { mkActionmap = ["normal"]
              , mkAction = "normal"
              , mkTexture = et
              , mkSize = sz
              , mkMaxPos = 1
              , mkSpeed = 1
              }
          , mkeHitbox = Hitbox
            { _alignment = Point 4 4
            , _size = sz
              & over x (\n -> n - 8)
              & over y (\n -> n - 8)
            }
          }

leftRightMovement :: MV.Movement
leftRightMovement = MV.make $ MV.MakeArgs
  { MV.startspeed = Point 0 0
  , MV.minspeed = Point 0 0
  , MV.maxspeed = Point 1.5 1.5
  , MV.accel = Point 0.1 0.1
  }

singleSpiralAttack :: SDL.Texture -> A.Attack
singleSpiralAttack = SA.make 6 0 (2, 1.2) $ MV.gradualSlowdown (Point 8 8)

changeDirection :: Size -> Enemy -> FPoint
changeDirection wsize enemy
  | enemy ^. direction . x == 0
  , enemy ^. direction . y == 0
  = Point 0 1

  | enemy ^. pos . y >= 100
  , enemy ^. direction . y == 1
  = Point 1 0

  | enemy ^. pos . x > 2 * (wsize ^. x `div` 3) - enemy ^. sprite . size . x
  , enemy ^. direction . y == 0
  = Point (-1) 0

  | enemy ^. pos . x <= (wsize ^. x `div` 3)
  , enemy ^. direction . y == 0
  = Point 1 0

  | enemy ^. health <= 0
  = Point 0 0

  | otherwise
  = enemy ^. direction