blob: 91e756f40be81ee959e3730e22d636838dbb827b (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
module Game.Entities.Slime (mkSlime) where
import Data.Bits (Bits (..))
import Data.IORef
import Game.Entities.Common
import Game.Entities.Const
import Game.Entities.Types
import qualified Game.Sprites as S
mkSlime :: S.SpriteSheet -> Int -> Int -> IORef Entity -> IsBlocked -> IO () -> IO Entity
mkSlime sprites x y playerRef isBlocked hitPlayer' = do
s <- S.get sprites "slime"
pure
Entity
{ typ = TypeEnemy,
x = x,
y = y,
delay = frameDelay,
frame = 0,
jumping = False,
gravity = gravityOff,
dir = DirRight,
sprite = s,
update = updateSlime (collision playerRef) isBlocked hitPlayer',
destroy = False,
spawns = []
}
updateSlime :: Collision -> IsBlocked -> IO () -> Entity -> IO Entity
updateSlime touchedPlayer isBlocked hitPlayer' e = do
touched <- touchedPlayer e
let updated = updateSlimeFrame
if touched then fmap (const e) hitPlayer' else pure $ updateMovement updated
where
updateMovement :: Entity -> Entity
updateMovement ent
| testBit ent.delay 1 = ent
| ent.dir == DirLeft
&& (isBlocked (ent.x - 1) (ent.y + 15) || isBlocked (ent.x - 1) (ent.y + 10) || not (isBlocked (ent.x - 1) (ent.y + 16))) =
ent {dir = DirRight}
| ent.dir == DirLeft = ent {x = ent.x - 1}
| ent.dir == DirRight
&& (isBlocked (ent.x + 16) (ent.y + 15) || isBlocked (ent.x + 16) (ent.y + 10) || not (isBlocked (ent.x + 16) (ent.y + 16))) =
ent {dir = DirLeft}
| ent.dir == DirRight = ent {x = ent.x + 1}
| otherwise = ent
updateSlimeFrame :: Entity
updateSlimeFrame
| e.delay > 0 = e {delay = e.delay - 1}
| e.frame + 1 < frameLimit e = e {delay = frameDelay + 2, frame = e.frame + 1}
| otherwise = e {delay = frameDelay + 2, frame = 0}
|