Files
loop/src/Dodge/Creature/Impulse/Movement.hs
T

101 lines
2.7 KiB
Haskell

module Dodge.Creature.Impulse.Movement where
import Dodge.Base
import Control.Lens
import Dodge.Creature.Statistics
import Dodge.Data.World
import Geometry
{- | Creature attempts to moves under its own steam.
The idea is that this may or may not work, depending on the status of the creature.
For now, though, this cannot fail.
-}
crMvBy ::
-- | Movement translation vector, will be made relative to creature direction
Point2 ->
Creature ->
Creature
crMvBy p cr = crMvAbsolute (rotateV (_crDir cr) p) cr
crMvAbsolute ::
-- | Movement translation vector
Point2 ->
Creature ->
Creature
crMvAbsolute p' cr =
advanceStepCounter (magV p) cr
& crPos %~ (+.+ p)
& crMvDir .~ argV p
where
p = strengthFactor (getCrStrength cr) *.* p'
strengthFactor :: Int -> Float
strengthFactor i
| i > 50 = 1
| i < 1 = 0
| otherwise = 0.02 * fromIntegral i
crMvForward ::
-- | Speed
Float ->
Creature ->
Creature
crMvForward speed = crMvBy (V2 speed 0)
advanceStepCounter ::
-- | Speed
Float ->
Creature ->
Creature
advanceStepCounter speed = crStance . carriage %~ f
where
f car = case car of
Standing -> f (Walking 0 RightForward)
Walking i ff -> Walking (i + ceiling speed) ff
_ -> car
creatureTurn :: Float -> Creature -> Creature
creatureTurn a = crDir +~ a
creatureTurnTo :: Point2 -> Creature -> Creature
creatureTurnTo p cr
| vToTarg == V2 0 0 = cr -- this should deal with the angleVV error
| otherwise = cr & crDir .~ dirToTarget
where
vToTarg = p -.- _crPos cr
dirToTarget = argV vToTarg
-- the following is perhaps not ideal because it mixes normalizeAngle with
-- angleVV, but it seems to work
creatureTurnTowardDir ::
-- | Angle
Float ->
-- | Turn speed
Float ->
Creature ->
Creature
creatureTurnTowardDir a turnSpeed cr
| abs (normalizeAnglePi (a - cdir)) <= turnSpeed = cr & crDir .~ dirToTarget
| otherwise = cr & crDir %~ addOrSub turnSpeed
where
addOrSub | isLeftOfA dirToTarget cdir = (+)
| otherwise = subtract
cdir = _crDir cr
dirToTarget = argV $ rotateV a (V2 1 0)
creatureTurnToward :: Point2 -> Float -> Creature -> Creature
creatureTurnToward p turnSpeed cr
| vToTarg == V2 0 0 = cr -- this should deal with the angleVV error
| errorAngleVV 3 vToTarg (unitVectorAtAngle (_crDir cr)) <= turnSpeed =
cr & crDir .~ dirToTarget
| isLeftOfA (normalizeAngle dirToTarget) (normalizeAngle $ _crDir cr) = cr & crDir +~ turnSpeed
| otherwise = cr & crDir -~ turnSpeed
where
vToTarg = p -.- _crPos cr
dirToTarget = argV vToTarg
-- | Speed modifier of an item when not aiming.
equipSpeed :: Item -> Float
equipSpeed _ = 1