Refactor creature ai

This commit is contained in:
2021-05-20 21:25:42 +02:00
parent 4463dc7716
commit 114335fdbe
32 changed files with 449 additions and 270 deletions
+1 -1
View File
@@ -14,11 +14,11 @@ import Dodge.Data
import Dodge.Base.Zone import Dodge.Base.Zone
import Dodge.Base.Window import Dodge.Base.Window
import Dodge.Base.Collide import Dodge.Base.Collide
--import Dodge.Config.Data
import Geometry import Geometry
import Picture import Picture
import Control.Lens import Control.Lens
--import Control.Monad.State --import Control.Monad.State
import Data.List import Data.List
--import Data.Function --import Data.Function
+1 -1
View File
@@ -1,5 +1,5 @@
{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-} --{-# LANGUAGE OverloadedStrings #-}
module Dodge.Config.KeyConfig module Dodge.Config.KeyConfig
where where
--import Data.Aeson --import Data.Aeson
+4 -13
View File
@@ -7,12 +7,12 @@ module Dodge.Creature
, spreadGunCrit , spreadGunCrit
, autoCrit , autoCrit
, chaseCrit , chaseCrit
, armourChaseCrit
, smallChaseCrit , smallChaseCrit
) )
where where
--import Dodge.Creature.Stance.Data --import Dodge.Creature.Stance.Data
import Dodge.Creature.State.Data import Dodge.Creature.State.Data
import Dodge.Creature.ImpulseRat
--import Dodge.Creature.ReaderUpdate --import Dodge.Creature.ReaderUpdate
--import Dodge.Creature.AlertLevel --import Dodge.Creature.AlertLevel
--import Dodge.Creature.SetTarget --import Dodge.Creature.SetTarget
@@ -25,6 +25,7 @@ import Dodge.Creature.LtAutoCrit
import Dodge.Creature.SpreadGunCrit import Dodge.Creature.SpreadGunCrit
import Dodge.Creature.AutoCrit import Dodge.Creature.AutoCrit
import Dodge.Creature.ChaseCrit import Dodge.Creature.ChaseCrit
import Dodge.Creature.ArmourChase
import Dodge.Data import Dodge.Data
import Dodge.Default import Dodge.Default
import Dodge.Base import Dodge.Base
@@ -37,7 +38,7 @@ import Dodge.Creature.Inanimate
import Dodge.Creature.State import Dodge.Creature.State
import Dodge.Creature.Picture import Dodge.Creature.Picture
import Dodge.Creature.Rationality import Dodge.Creature.Rationality
import Dodge.Creature.ChooseTarget --import Dodge.Creature.ChooseTarget
--import Dodge.Item --import Dodge.Item
import Dodge.Picture.Layer import Dodge.Picture.Layer
import Picture import Picture
@@ -61,16 +62,6 @@ spawnerCrit = defaultCreature
, _crPict = basicCrPict blue , _crPict = basicCrPict blue
, _crInv = IM.empty -- IM.fromList [(0,frontArmour)] , _crInv = IM.empty -- IM.fromList [(0,frontArmour)]
} }
armourChaseCrit :: Creature
armourChaseCrit = defaultCreature
{ _crUpdate = stateUpdate $ meleeCooldown $ impulsiveAI $ chaseTarget targetYouLOS
, _crHP = 300
, _crPict = basicCrPict green
, _crInv = IM.fromList
[(0,frontArmour)
,(1,medkit 200)
]
}
miniGunCrit :: Creature miniGunCrit :: Creature
miniGunCrit = defaultCreature miniGunCrit = defaultCreature
{ _crPict = basicCrPict red { _crPict = basicCrPict red
@@ -174,7 +165,7 @@ startInventory = IM.fromList (zip [0..20]
,lasGun ,lasGun
,autoGun ,autoGun
,flamer ,flamer
--,poisonSprayer ,poisonSprayer
,launcher ,launcher
--,lasGun --,lasGun
--,grenade --,grenade
+35
View File
@@ -0,0 +1,35 @@
module Dodge.Creature.ArmourChase
where
import Dodge.Data
import Dodge.Default
import Dodge.Creature.State
import Dodge.Creature.Rationality
import Dodge.Creature.ReaderUpdate
import Dodge.Creature.AlertLevel
import Dodge.Creature.ChooseTarget
import Dodge.Creature.Picture
import Dodge.Item.Equipment
import Dodge.Item.Consumable
import Picture
import qualified Data.IntMap.Strict as IM
import Control.Lens
import Control.Monad.Reader
armourChaseCrit :: Creature
armourChaseCrit = defaultCreature
{ _crUpdate = stateUpdate $ impulsiveAIR $
doStrategyActionsR >=>
performActionsR >=>
overrideMeleeCloseTargetR >=>
chaseTargetR targetYouLOS >=>
basicPerceptionUpdateR [0] >=>
targetYouWhenCognizantR >=>
return . (crMeleeCooldown . _Just %~ (max 0 . subtract 1))
, _crHP = 300
, _crPict = basicCrPict green
, _crInv = IM.fromList
[(0,frontArmour)
,(1,medkit 200)
]
}
+1 -1
View File
@@ -21,7 +21,7 @@ import qualified Data.IntMap.Strict as IM
autoCrit :: Creature autoCrit :: Creature
autoCrit = defaultCreature autoCrit = defaultCreature
{ _crPict = basicCrPict red { _crPict = basicCrPict red
, _crUpdate = stateUpdate $ impulsiveAIR $ sentinelAI , _crUpdate = stateUpdate $ impulsiveAIR sentinelAI
, _crActionPlan = ActionPlan , _crActionPlan = ActionPlan
{ _crImpulse = [] { _crImpulse = []
, _crAction = [] , _crAction = []
+255
View File
@@ -0,0 +1,255 @@
module Dodge.Creature.Boid
where
import Dodge.Data
import Dodge.Base
import Dodge.Creature.State.Data
import Dodge.Creature.ImpulseRat
import Geometry
import Control.Monad.Reader
import Control.Lens
import qualified Data.IntMap as IM
interpWith :: Float -> Point2 -> Point2 -> Point2
interpWith x a b = x *.* a +.+ (1 - x) *.* b
invertEncircleDistP :: Float -> Creature -> Point2 -> Creature -> Point2
invertEncircleDistP d tcr cenp cr = ypos +.+
d *.* (reflectIn (cenp -.- ypos) $ safeNormalizeV (cpos -.- cenp))
where
cpos = _crPos cr
ypos = _crPos tcr
encircleDistP :: Float -> Creature -> Point2 -> Creature -> Point2
encircleDistP d tcr cenp cr = ypos +.+ d *.* safeNormalizeV (cpos -.- cenp)
where
cpos = _crPos cr
ypos = _crPos tcr
encircleP :: Creature -> Point2 -> Creature -> Point2
encircleP tcr cenp cr = ypos +.+ 50 *.* safeNormalizeV (cpos -.- cenp)
where
cpos = _crPos cr
ypos = _crPos tcr
--f x = 150 * sigmoid (x-10)
encircleCloseP :: Creature -> Point2 -> Creature -> Point2
encircleCloseP tcr cenp cr = ypos +.+ f (max 0 (magV (ypos -.- cenp) - 80) ) *.* safeNormalizeV (cpos -.- cenp)
where
cpos = _crPos cr
ypos = _crPos tcr
f x = 150 * sigmoid (x-10)
forbidFlee
:: (Creature -> Point2 -> Creature -> Point2)
-> Creature
-> Point2
-> Creature
-> Point2
forbidFlee f tcr cenp cr
| ptargTest = tpos
| otherwise = ptarg
where
cpos = _crPos cr
tpos = _crPos tcr
ptarg = f tcr cenp cr
ptargTest = isLHS cpos (cpos +.+ rotateV (negate (pi/2)) (cpos -.- tpos)) ptarg
-- && isRHS cpos (cpos +.+ rotateV (pi/3) (cpos -.- tpos)) ptarg
--targBehindCrit = isLHS cpos (vNormal $ cpos +.+ unitVectorAtAngle (_crDir cr)) ptarg
pincerP :: Creature -> Point2 -> Creature -> Point2
pincerP tcr cenp cr = tpos +.+ splitp -- +.+ 25 *.* (normalizeV $ tpos -.- cenp)
where
cpos = _crPos cr
tpos = _crPos tcr
splitp
| isLHS cenp cpos tpos
= 150 *.* orthCenpTpos
| otherwise
= negate 150 *.* orthCenpTpos
--d = min 150 (dist cpos tpos)
--orthCenpTpos = safeNormalizeV (vNormal $ tpos -.- cpos)
orthCenpTpos = safeNormalizeV (vNormal $ tpos -.- cenp)
pincerP''' :: Creature -> Point2 -> Creature -> Point2
pincerP''' tcr cenp cr = interpWith (sigmoid $ 0.05 * dtcen) cenawayp cenclosep
where
cpos = _crPos cr
tpos = _crPos tcr
dtcen = dist tpos cenp
f x = 150 * sigmoid (x-10)
cenawayp
| dist cenp tpos < dist cpos tpos = tpos +.+ splitp
| otherwise = cenp +.+ splitp
splitp
| isLHS cenp cpos tpos
= f (max 0 (magV (tpos -.- cenp) - 80) ) *.* orthCenpTpos
| otherwise
= negate ( f $ max 0 $ magV (tpos -.- cenp) - 80) *.* orthCenpTpos
orthCenpTpos = safeNormalizeV (vNormal $ tpos -.- cenp)
cenclosep
= tpos +.+ f (max 0 (magV (tpos -.- cenp) - 80) ) *.* safeNormalizeV (cpos -.- cenp)
pincerP' :: Creature -> Point2 -> Creature -> Point2
pincerP' tcr cenp cr
| dist cenp tpos > dist cpos tpos
= cenp +.+ f (max 0 (magV (tpos -.- cenp) - 80) ) *.* safeNormalizeV (cpos -.- cenp)
| otherwise = tpos +.+ f (max 0 (magV (tpos -.- cenp) - 80) ) *.* safeNormalizeV (cpos -.- cenp)
where
cpos = _crPos cr
tpos = _crPos tcr
f x = 150 * sigmoid (x-10)
pincerP'' :: Creature -> Point2 -> Creature -> Point2
pincerP'' tcr cenp cr
| dist cenp tpos > dist cpos tpos && isLHS cenp cpos tpos
= cenp +.+ f (max 0 (magV (tpos -.- cenp) - 80) ) *.* safeNormalizeV (vNormal $ tpos -.- cenp)
| dist cenp tpos > dist cpos tpos
= cenp +.+ f (max 0 (magV (tpos -.- cenp) - 80) ) *.* safeNormalizeV (vNormal $ cenp -.- tpos)
| otherwise = tpos +.+ f (max 0 (magV (tpos -.- cenp) - 80) ) *.* safeNormalizeV (cpos -.- cenp)
where
cpos = _crPos cr
tpos = _crPos tcr
f x = 150 * sigmoid (x-10)
encircle :: Creature -> IM.IntMap Creature -> Creature -> Point2
encircle tcr crs cr
| length crs <= 1 = ypos
| otherwise = ypos +.+ f (max 0 (magV (ypos -.- cenp) - 80) ) *.* safeNormalizeV (cpos -.- cenp)
where
cpos = _crPos cr
ypos = _crPos tcr
f x = 150 * sigmoid (x-10)
cenp = centroid (map _crPos $ IM.elems crs)
lineOrth :: Creature -> IM.IntMap Creature -> Creature -> Point2
lineOrth tcr crs cr = p
where
ypos = _crPos tcr
cpos = _crPos cr
ps = map _crPos $ IM.elems crs
cen = (1 / fromIntegral (length ps)) *.* foldr1 (+.+) ps
p | dist cen ypos < 20 = ypos
| otherwise = errorClosestPointOnLine 500 ypos (ypos +.+ vNormal (cen -.- ypos)) cpos
holdForm :: Creature -> IM.IntMap Creature -> Creature -> Point2
holdForm ycr crs cr = p
where
ypos = _crPos ycr
cpos = _crPos cr
ps = map _crPos $ IM.elems crs
cen = (1 / fromIntegral (length ps)) *.* foldr1 (+.+) ps
p | dist cen ypos < 20 = ypos
| otherwise = ypos +.+ cpos -.- cen
lineUp :: Creature -> IM.IntMap Creature -> Creature -> Point2
lineUp ycr crs cr = p
where
ypos = _crPos ycr
cpos = _crPos cr
ps = map _crPos $ IM.elems crs
cen = (1 / fromIntegral (length ps)) *.* foldr1 (+.+) ps
p = (0.05 *.* ypos) +.+ (0.95 *.* errorClosestPointOnLine 500 cen ypos cpos)
-- not nice, a kind of encircle
spreadOut :: Creature -> IM.IntMap Creature -> Creature -> Point2
spreadOut ycr crs cr = p
where
ypos = _crPos ycr
cpos = _crPos cr
ps = map _crPos $ IM.elems crs
cen = (1 / fromIntegral (length ps)) *.* foldr1 (+.+) ps
p | dist cen ypos < 30 = ypos
| otherwise = ypos +.+ (spreadFactor *.* cpos -.- cen)
spreadFactor
| dist ypos cpos > 90 = 1
| otherwise = 1.5
swarmUsingCenter
:: (Creature -> Point2 -> Creature -> Creature)
-> (Point2 -> Creature -> Creature)
-> World
-> Creature
-> Creature
swarmUsingCenter updT upd w cr = case _crTarget cr of
Nothing -> upd cenp cr
Just tcr -> updT tcr cenp cr
where
cid = _crID cr
cenp = _crGroupCenter $ _creatureGroups w IM.! _crGroupID (_crGroup $ _creatures w IM.! cid)
flockChaseTarget
:: (Creature -> IM.IntMap Creature -> Creature -> Creature) -- ^ Update with target
-> (IM.IntMap Creature -> Creature -> Creature) -- ^ Update without target
-> World
-> Creature
-> Creature
flockChaseTarget updT upd w cr = case _crTarget cr of
Nothing -> upd crs cr
Just tcr -> updT tcr crs cr
where
is = _swarm $ _crGroup cr
crs = IM.restrictKeys (_creatures w) is
flockPointTarget
:: (Creature -> IM.IntMap Creature -> Creature -> Point2)
-> (Creature -> World -> Maybe Creature) -- ^ Function for determining target
-> World
-> Creature
-> Creature
flockPointTarget f targFunc w cr = case targFunc cr w of
Nothing -> cr
Just crTarg -> cr & crActionPlan . crImpulse .~ mvPointMeleeTarg p cr crTarg
where
is = _swarm $ _crGroup cr
crs = IM.restrictKeys (_creatures w) is
p = f crTarg crs cr
flockToPointUsing
:: (Creature -> Point2 -> Creature -> Point2)
-> (Point2 -> Creature -> Creature -> [Impulse])
-> Creature
-> Reader World Creature
flockToPointUsing pf mvf cr = reader $ \w -> case _crTarget cr of
Nothing -> cr
Just tcr -> cr & crActionPlan . crImpulse .~ mvf ptarg cr tcr
where
cenp = _crGroupCenter $ _creatureGroups w IM.! _crGroupID (_crGroup cr)
ptarg = pf tcr cenp cr
flockFunc
:: (Creature -> Point2 -> Creature -> Point2)
-> (Creature -> World -> Maybe Creature) -- ^ Function for determining target
-> Creature
-> Reader World Creature
flockFunc f targFunc cr = reader $ \w -> case targFunc cr w of
Nothing -> cr
Just crTarg -> cr & crActionPlan . crImpulse .~ mvPointMeleeTarg p cr crTarg
where
cenp = _crGroupCenter $ _creatureGroups w IM.! (_crGroupID (_crGroup cr))
p = f crTarg cenp cr
flockCenterFunc
:: (Creature -> Point2 -> Creature -> Point2)
-> (Creature -> World -> Maybe Creature) -- ^ Function for determining target
-> Creature
-> Reader World Creature
flockCenterFunc f targFunc cr = reader $ \w -> case targFunc cr w of
Nothing -> cr
Just crTarg -> cr & crActionPlan . crImpulse .~ mvPointMeleeTarg p cr crTarg
where
cenp = _crGroupCenter $ _creatureGroups w IM.! (_crGroupID (_crGroup cr))
p = f crTarg cenp cr
flockPointTargetR
:: (Creature -> IM.IntMap Creature -> Creature -> Point2)
-> (Creature -> World -> Maybe Creature) -- ^ Function for determining target
-> Creature
-> Reader World Creature
flockPointTargetR f targFunc cr = reader $ \w -> case targFunc cr w of
Nothing -> cr
Just crTarg -> cr & crActionPlan . crImpulse .~ mvPointMeleeTarg p cr crTarg
where
is = _swarm $ _crGroup cr
crs = IM.restrictKeys (_creatures w) is
p = f crTarg crs cr
+33 -124
View File
@@ -1,130 +1,14 @@
module Dodge.Creature.ImpulseRat module Dodge.Creature.ImpulseRat
where where
import Dodge.Data import Dodge.Data
import Dodge.Base --import Dodge.Base
--import Dodge.Creature.ChooseTarget --import Dodge.Creature.ChooseTarget
import Dodge.Creature.State.Data --import Dodge.Creature.State.Data
import Geometry import Geometry
import qualified Data.IntMap as IM --import qualified Data.IntMap as IM
import Control.Lens import Control.Lens
import Control.Monad.Reader --import Control.Monad.Reader
encircle :: Creature -> IM.IntMap Creature -> Creature -> Point2
encircle tcr crs cr
| length crs <= 1 = ypos
| otherwise = ypos +.+ f (max 0 (magV (ypos -.- cenp) - 80) ) *.* safeNormalizeV (cpos -.- cenp)
where
cpos = _crPos cr
ypos = _crPos tcr
f x = 150 * sigmoid (x-10)
cenp = (1 / fromIntegral (length crs)) *.* foldr1 (+.+) (map _crPos $ IM.elems crs)
lineOrth :: Creature -> IM.IntMap Creature -> Creature -> Point2
lineOrth tcr crs cr = p
where
ypos = _crPos tcr
cpos = _crPos cr
ps = map _crPos $ IM.elems crs
cen = (1 / fromIntegral (length ps)) *.* foldr1 (+.+) ps
p | dist cen ypos < 20 = ypos
| otherwise = errorClosestPointOnLine 500 ypos (ypos +.+ vNormal (cen -.- ypos)) cpos
holdForm :: Creature -> IM.IntMap Creature -> Creature -> Point2
holdForm ycr crs cr = p
where
ypos = _crPos ycr
cpos = _crPos cr
ps = map _crPos $ IM.elems crs
cen = (1 / fromIntegral (length ps)) *.* foldr1 (+.+) ps
p | dist cen ypos < 20 = ypos
| otherwise = ypos +.+ cpos -.- cen
lineUp :: Creature -> IM.IntMap Creature -> Creature -> Point2
lineUp ycr crs cr = p
where
ypos = _crPos ycr
cpos = _crPos cr
ps = map _crPos $ IM.elems crs
cen = (1 / fromIntegral (length ps)) *.* foldr1 (+.+) ps
p = (0.05 *.* ypos) +.+ (0.95 *.* errorClosestPointOnLine 500 cen ypos cpos)
-- not nice, a kind of encircle
spreadOut :: Creature -> IM.IntMap Creature -> Creature -> Point2
spreadOut ycr crs cr = p
where
ypos = _crPos ycr
cpos = _crPos cr
ps = map _crPos $ IM.elems crs
cen = (1 / fromIntegral (length ps)) *.* foldr1 (+.+) ps
p | dist cen ypos < 30 = ypos
| otherwise = ypos +.+ (spreadFactor *.* cpos -.- cen)
spreadFactor
| dist ypos cpos > 90 = 1
| otherwise = 1.5
swarmUsingCenter
:: (Creature -> Point2 -> Creature -> Creature)
-> (Point2 -> Creature -> Creature)
-> World
-> Creature
-> Creature
swarmUsingCenter updT upd w cr = case _crTarget cr of
Nothing -> upd cenp cr
Just tcr -> updT tcr cenp cr
where
cid = _crID cr
cenp = _crGroupCenter $ _creatureGroups w IM.! (_crGroupID $ _crGroup $ _creatures w IM.! cid)
flockChaseTarget
:: (Creature -> IM.IntMap Creature -> Creature -> Creature) -- ^ Update with target
-> (IM.IntMap Creature -> Creature -> Creature) -- ^ Update without target
-> World
-> Creature
-> Creature
flockChaseTarget updT upd w cr = case _crTarget cr of
Nothing -> upd crs cr
Just tcr -> updT tcr crs cr
where
is = _swarm $ _crGroup cr
crs = IM.restrictKeys (_creatures w) is
flockPointTarget
:: (Creature -> IM.IntMap Creature -> Creature -> Point2)
-> (Creature -> World -> Maybe Creature) -- ^ Function for determining target
-> World
-> Creature
-> Creature
flockPointTarget f targFunc w cr = case targFunc cr w of
Nothing -> cr
Just crTarg -> cr & crActionPlan . crImpulse .~ chaseTarg' p cr crTarg
where
is = _swarm $ _crGroup cr
crs = IM.restrictKeys (_creatures w) is
p = f crTarg crs cr
flockPointTargetR
:: (Creature -> IM.IntMap Creature -> Creature -> Point2)
-> (Creature -> World -> Maybe Creature) -- ^ Function for determining target
-> Creature
-> Reader World Creature
flockPointTargetR f targFunc cr = reader $ \w -> case targFunc cr w of
Nothing -> cr
Just crTarg -> cr & crActionPlan . crImpulse .~ chaseTarg' p cr crTarg
where
is = _swarm $ _crGroup cr
crs = IM.restrictKeys (_creatures w) is
p = f crTarg crs cr
--swarmUseCenter
-- :: (Creature -> Point2 -> Creature -> Point2)
-- :: (Creature -> IM.IntMap Creature -> Creature -> Point2)
-- -> (Creature -> World -> Maybe Creature) -- ^ Function for determining target
-- -> World
-- -> Creature
-- -> Creature
--swarmUseCenter
chaseTarget chaseTarget
@@ -149,9 +33,34 @@ overrideMeleeCloseTarget _ cr = case _crTarget cr of
where where
cpos = _crPos cr cpos = _crPos cr
meleeHeadingMove
:: Float -- ^ max turn speed
-> Float -- ^ min turn speed
-> Float -- ^ turn speed cutoff angle
-> Float -- ^ move speed
-> Point2 -- ^ target point
-> Creature -- ^ start creature
-> Creature -- ^ target creature
-> [Impulse]
meleeHeadingMove maxta minta tacutoff speed tp cr tcr
| dist tpos cpos < combinedRad + 5
&& abs (_crDir cr - argV (tpos -.- cpos)) < tacutoff
&& _crMeleeCooldown cr == Just 0
= [Melee (_crID tcr), Turn pi]
| dist tpos cpos < combinedRad + 5
&& abs (_crDir cr - argV (tpos -.- cpos)) < tacutoff
= [ TurnToward tpos minta ]
| abs (_crDir cr - argV (tp -.- cpos)) < tacutoff
= [MoveForward speed , TurnToward tp maxta , RandomTurn maxta ]
| otherwise = [MoveForward speed , TurnToward tp minta, RandomTurn maxta ]
where
cpos = _crPos cr
tpos = _crPos tcr
combinedRad = _crRad cr + _crRad tcr
chaseTarg' :: Point2 -> Creature -> Creature -> [Impulse]
chaseTarg' p cr crT mvPointMeleeTarg :: Point2 -> Creature -> Creature -> [Impulse]
mvPointMeleeTarg p cr crT
| dist tpos cpos < combinedRad + 5 | dist tpos cpos < combinedRad + 5
&& abs (_crDir cr - argV (tpos -.- cpos)) < pi/4 && abs (_crDir cr - argV (tpos -.- cpos)) < pi/4
&& _crMeleeCooldown cr == Just 0 && _crMeleeCooldown cr == Just 0
@@ -160,8 +69,8 @@ chaseTarg' p cr crT
&& abs (_crDir cr - argV (tpos -.- cpos)) < pi/4 && abs (_crDir cr - argV (tpos -.- cpos)) < pi/4
= [ TurnToward tpos 0.05 ] = [ TurnToward tpos 0.05 ]
| abs (_crDir cr - argV (p -.- cpos)) < pi/4 | abs (_crDir cr - argV (p -.- cpos)) < pi/4
= [MoveForward 2.5 , TurnToward p 0.2 , RandomTurn 0.2 ] = [MoveForward 3 , TurnToward p 0.2 , RandomTurn 0.2 ]
| otherwise = [MoveForward 2.5 , TurnToward p 0.05, RandomTurn 0.2 ] | otherwise = [MoveForward 3 , TurnToward p 0.05, RandomTurn 0.2 ]
where where
cpos = _crPos cr cpos = _crPos cr
tpos = _crPos crT tpos = _crPos crT
+3 -2
View File
@@ -36,8 +36,9 @@ launcherCrit = defaultCreature
>=> doStrategyActionsR >=> doStrategyActionsR
>=> reloadOverrideR >=> reloadOverrideR
>=> targetYouWhenCognizantR >=> targetYouWhenCognizantR
>=> (overrideInternalR (onBoth (&&) crHasTarget (crStratConMatches (GetTo (0,0)))) >=> overrideInternalR
$ \ _ -> crActionPlan . crStrategy .~ WatchAndWait) (onBoth (&&) crHasTarget (crStratConMatches (GetTo (0,0))))
(\ _ -> crActionPlan . crStrategy .~ WatchAndWait)
, _crActionPlan = ActionPlan , _crActionPlan = ActionPlan
{ _crImpulse = [] { _crImpulse = []
, _crAction = [] , _crAction = []
+3 -2
View File
@@ -44,8 +44,9 @@ ltAutoCrit = defaultCreature
>=> doStrategyActionsR >=> doStrategyActionsR
>=> reloadOverrideR >=> reloadOverrideR
>=> targetYouWhenCognizantR >=> targetYouWhenCognizantR
>=> (overrideInternalR (onBoth (&&) crHasTarget (crStratConMatches (GetTo (0,0)))) >=> overrideInternalR
$ \ _ -> crActionPlan . crStrategy .~ WatchAndWait) (onBoth (&&) crHasTarget (crStratConMatches (GetTo (0,0))))
(\ _ -> crActionPlan . crStrategy .~ WatchAndWait)
, _crActionPlan = ActionPlan , _crActionPlan = ActionPlan
{ _crImpulse = [] { _crImpulse = []
, _crAction = [] , _crAction = []
+2 -2
View File
@@ -6,7 +6,7 @@ module Dodge.Creature.Picture
, circLine , circLine
) where ) where
import Dodge.Data import Dodge.Data
import Dodge.Creature.Stance.Data --import Dodge.Creature.Stance.Data
import Dodge.Creature.State.Data import Dodge.Creature.State.Data
--import Dodge.Creature.AlertLevel.Data --import Dodge.Creature.AlertLevel.Data
import Dodge.Picture.Layer import Dodge.Picture.Layer
@@ -67,7 +67,7 @@ drawEquipment
drawEquipment cr = pictures $ map f $ IM.toList (_crInv cr) drawEquipment cr = pictures $ map f $ IM.toList (_crInv cr)
where where
f (i,it) = case it ^? itEquipPict of f (i,it) = case it ^? itEquipPict of
Just g | (cr ^? crStance . posture) == Just Aiming -> g cr i Just g -> g cr i
_ -> blank _ -> blank
circLine :: Float -> Picture circLine :: Float -> Picture
+3 -1
View File
@@ -28,7 +28,9 @@ impulsiveAIR
-> (World -> World, StdGen) -> (World -> World, StdGen)
-> Creature -> Creature
-> ((World -> World, StdGen) , Maybe Creature) -> ((World -> World, StdGen) , Maybe Creature)
impulsiveAIR impf w (f,g) cr = followImpulses w (f,g) . ($ w) . runReader . impf $ cr impulsiveAIR impf w (f,g) = followImpulses w (f,g') . ($ w) . runReader . impf
where
(g',_) = split g
impulsiveAI impulsiveAI
:: (World -> Creature -> Creature) -- ^ Internal AI update, should determine impulses :: (World -> Creature -> Creature) -- ^ Internal AI update, should determine impulses
+1 -1
View File
@@ -67,7 +67,7 @@ reloadOverrideR cr
| cr ^? crInv . ix (_crInvSel cr) . wpLoadedAmmo == Just 0 | cr ^? crInv . ix (_crInvSel cr) . wpLoadedAmmo == Just 0
&& cr ^. crStance . posture == Aiming && cr ^. crStance . posture == Aiming
= return $ cr & crActionPlan . crStrategy .~ StrategyActions Reload reloadActions = return $ cr & crActionPlan . crStrategy .~ StrategyActions Reload reloadActions
| otherwise = return $ cr | otherwise = return cr
where where
reloadActions = reloadActions =
[ holsterWeapon [ holsterWeapon
+5 -5
View File
@@ -48,7 +48,6 @@ sentinelAI = sentinelExtraWatchUpdate
) )
] ]
>=> reloadOverrideR >=> reloadOverrideR
where
sentinelFireType sentinelFireType
:: (Int -> Action) :: (Int -> Action)
@@ -66,8 +65,9 @@ sentinelFireType f = performActionsR
>=> doStrategyActionsR >=> doStrategyActionsR
>=> reloadOverrideR >=> reloadOverrideR
>=> targetYouWhenCognizantR >=> targetYouWhenCognizantR
>=> (overrideInternalR (onBoth (&&) crHasTarget (crStratConMatches (GetTo (0,0)))) >=> overrideInternalR
$ \ _ -> crActionPlan . crStrategy .~ WatchAndWait) (onBoth (&&) crHasTarget (crStratConMatches (GetTo (0,0))))
(\ _ -> crActionPlan . crStrategy .~ WatchAndWait)
where where
drawwp = DoActionIfElse NoAction crIsAiming (DoActionThen drawWeapon (WaitThen 50 NoAction)) drawwp = DoActionIfElse NoAction crIsAiming (DoActionThen drawWeapon (WaitThen 50 NoAction))
aiming = AimAtCloseSlow aiming = AimAtCloseSlow
@@ -89,8 +89,8 @@ sentinelExtraWatchUpdate xs = performActionsR
>=> doStrategyActionsR >=> doStrategyActionsR
-- >=> reloadOverrideR -- >=> reloadOverrideR
>=> targetYouWhenCognizantR >=> targetYouWhenCognizantR
>=> (overrideInternalR (onBoth (&&) crHasTarget (crStratConMatches (GetTo (0,0)))) >=> overrideInternalR (onBoth (&&) crHasTarget (crStratConMatches (GetTo (0,0))))
$ \ _ -> crActionPlan . crStrategy .~ WatchAndWait) (\ _ -> crActionPlan . crStrategy .~ WatchAndWait)
shootAtAdvance :: Int -> [Action] shootAtAdvance :: Int -> [Action]
+2 -2
View File
@@ -44,8 +44,8 @@ spreadGunCrit = defaultCreature
>=> doStrategyActionsR >=> doStrategyActionsR
>=> reloadOverrideR >=> reloadOverrideR
>=> targetYouWhenCognizantR >=> targetYouWhenCognizantR
>=> (overrideInternalR (onBoth (&&) crHasTarget (crStratConMatches (GetTo (0,0)))) >=> overrideInternalR (onBoth (&&) crHasTarget (crStratConMatches (GetTo (0,0))))
$ \ _ -> crActionPlan . crStrategy .~ WatchAndWait) (\ _ -> crActionPlan . crStrategy .~ WatchAndWait)
, _crActionPlan = ActionPlan , _crActionPlan = ActionPlan
{ _crImpulse = [] { _crImpulse = []
, _crAction = [] , _crAction = []
+12 -2
View File
@@ -5,10 +5,11 @@ module Dodge.Creature.SwarmCrit
import Dodge.Data import Dodge.Data
import Dodge.Default import Dodge.Default
import Dodge.Creature.Picture import Dodge.Creature.Picture
import Dodge.Creature.Boid
--import Dodge.Creature.Test --import Dodge.Creature.Test
--import Dodge.Creature.ActionRat --import Dodge.Creature.ActionRat
import Dodge.Creature.ImpulseRat import Dodge.Creature.ImpulseRat
import Dodge.Creature.ChooseTarget --import Dodge.Creature.ChooseTarget
--import Dodge.Creature.SetTarget --import Dodge.Creature.SetTarget
import Dodge.Creature.Rationality import Dodge.Creature.Rationality
import Dodge.Creature.ReaderUpdate import Dodge.Creature.ReaderUpdate
@@ -30,7 +31,7 @@ import Control.Monad.Reader
swarmCrit :: Creature swarmCrit :: Creature
swarmCrit = defaultCreature swarmCrit = defaultCreature
{ _crUpdate = stateUpdate $ impulsiveAIR $ { _crUpdate = stateUpdate $ impulsiveAIR $
flockPointTargetR encircle targetYouLOS flockToPointUsing (encircleDistP (100)) (meleeHeadingMove 0.1 0.1 (pi/4) 3.9)
>=> return . (crMeleeCooldown . _Just %~ (max 0 . subtract 1)) >=> return . (crMeleeCooldown . _Just %~ (max 0 . subtract 1))
>=> basicPerceptionUpdateR [0] >=> basicPerceptionUpdateR [0]
>=> doStrategyActionsR >=> doStrategyActionsR
@@ -46,3 +47,12 @@ swarmCrit = defaultCreature
, _crFaction = ColorFaction yellow , _crFaction = ColorFaction yellow
, _crMeleeCooldown = Just 0 , _crMeleeCooldown = Just 0
} }
--swarmCritMoveFunc :: Creature -> Point2 -> Creature -> Point2
--swarmCritMoveFunc tcr cenp cr
-- | targBehindCrit
-- where
-- cpos = _crPos cr
-- ypos = _crPos tcr
+1 -2
View File
@@ -24,7 +24,7 @@ yourControl w (f,g) cr =
, Just . mouseActionsCr (_mouseButtons w) $ wasdWithAiming w speed 0 cr , Just . mouseActionsCr (_mouseButtons w) $ wasdWithAiming w speed 0 cr
) )
where where
speed = _varMovementSpeedModifier w * equipFactor speed = 3 * equipFactor
equipFactor = product $ map equipSpeed $ IM.elems $ _crInv $ _creatures w IM.! 0 equipFactor = product $ map equipSpeed $ IM.elems $ _crInv $ _creatures w IM.! 0
{- | Turn key presses into creature movement. -} {- | Turn key presses into creature movement. -}
wasdWithAiming wasdWithAiming
@@ -50,7 +50,6 @@ wasdWithAiming w speed i cr
*.* rotateV (_cameraRot w) (_mousePos w) *.* rotateV (_cameraRot w) (_mousePos w)
_ -> normalizeAngle $ argV (_mousePos w) + _cameraRot w _ -> normalizeAngle $ argV (_mousePos w) + _cameraRot w
wasdM :: World -> SDL.Scancode -> Point2 wasdM :: World -> SDL.Scancode -> Point2
wasdM w scancode wasdM w scancode
| scancode == moveUpKey (_keyConfig w) = ( 0, 1) | scancode == moveUpKey (_keyConfig w) = ( 0, 1)
-2
View File
@@ -91,8 +91,6 @@ data World = World
, _seenLocations :: IM.IntMap (World -> Point2,String) , _seenLocations :: IM.IntMap (World -> Point2,String)
, _selLocation :: Int , _selLocation :: Int
, _keyConfig :: KeyConfigSDL , _keyConfig :: KeyConfigSDL
, _varMovementSpeedModifier :: Float
, _varMovementStrafeSpeedModifier :: Float
, _debugMode :: Bool , _debugMode :: Bool
, _config :: Configuration , _config :: Configuration
, _sideEffects :: [PreloadData SoundOrigin -> IO (PreloadData SoundOrigin)] , _sideEffects :: [PreloadData SoundOrigin -> IO (PreloadData SoundOrigin)]
-2
View File
@@ -272,8 +272,6 @@ defaultWorld = World
] ]
, _selLocation = 0 , _selLocation = 0
, _keyConfig = defaultKeyConfigSDL , _keyConfig = defaultKeyConfigSDL
, _varMovementSpeedModifier = 3
, _varMovementStrafeSpeedModifier = 3
, _debugMode = True , _debugMode = True
, _config = defaultConfig , _config = defaultConfig
, _sideEffects = [] , _sideEffects = []
+1 -1
View File
@@ -125,7 +125,7 @@ wheelDownEvent w = case _carteDisplay w of
upInvPos :: World -> World upInvPos :: World -> World
upInvPos w = stopSoundFrom (CrReloadSound 0) $ w upInvPos w = stopSoundFrom (CrReloadSound 0) $ w
& creatures . ix (_yourID w) . crInvSel %~ (`mod` n) . (subtract 1) & creatures . ix (_yourID w) . crInvSel %~ (`mod` n) . subtract 1
where where
n = length $ IM.keys $ _crInv $ _creatures w IM.! _yourID w n = length $ IM.keys $ _crInv $ _creatures w IM.! _yourID w
downInvPos :: World -> World downInvPos :: World -> World
-2
View File
@@ -60,8 +60,6 @@ handlePressedKey _ scode w
debugKey :: Scancode -> World -> Maybe World debugKey :: Scancode -> World -> Maybe World
debugKey scancode w debugKey scancode w
| scancode == ScancodeF7 = Just $ w & varMovementSpeedModifier -~ 1
| scancode == ScancodeF8 = Just $ w & varMovementSpeedModifier +~ 1
| scancode == ScancodeF5 = Just $ dropLight w | scancode == ScancodeF5 = Just $ dropLight w
| scancode == ScancodeF6 = Just $ dropLight' w | scancode == ScancodeF6 = Just $ dropLight' w
debugKey _ w = Just w debugKey _ w = Just w
+3 -3
View File
@@ -50,14 +50,14 @@ roomTreex = do
t = treeFromTrunk t = treeFromTrunk
[[StartRoom] [[StartRoom]
,[Corridor] ,[Corridor]
,[Corridor]
,[SpecificRoom . pure . pure . Right $ roomGlassOctogon 400 ,[SpecificRoom . pure . pure . Right $ roomGlassOctogon 400
& rmPS %~ ([swarmPS 0 (x,y) 0 swarmCrit | x <- [-20,-19.5.. 20] , y <- [200] ]++) & rmPS %~ ([sPS (0,50) 0 $ PutCrit armourChaseCrit ]++)
] ]
,[Corridor] ,[Corridor]
,[SpecificRoom . pure . pure . Right $ roomGlassOctogon 400 ,[SpecificRoom . pure . pure . Right $ roomGlassOctogon 400
& rmPS %~ ([sPS (0,50) 0 $ PutCrit autoCrit ]++) & rmPS %~ ([swarmPS 0 (x,y) 0 swarmCrit | x <- [-20,-19.5.. 20] , y <- [200,202] ]++)
] ]
,[Corridor]
,[SpecificRoom . pure . pure . Right $ roomGlassOctogon 400 ,[SpecificRoom . pure . pure . Right $ roomGlassOctogon 400
& rmPS %~ ([sPS (0,50) 0 $ PutCrit pistolCrit ]++) & rmPS %~ ([sPS (0,50) 0 $ PutCrit pistolCrit ]++)
] ]
+1 -1
View File
@@ -21,7 +21,7 @@ medkit i = defaultConsumable
, _itAmount = 1 , _itAmount = 1
, _cnEffect = heal i , _cnEffect = heal i
, _itFloorPict = onLayer FlItLayer $ color blue $ circleSolid 3 , _itFloorPict = onLayer FlItLayer $ color blue $ circleSolid 3
, _itEquipPict = drawWeapon $ color blue $ circleSolid 3 , _itEquipPict = pictureItem $ color blue $ circleSolid 3
, _itID = Nothing , _itID = Nothing
} }
+18 -3
View File
@@ -2,17 +2,32 @@ module Dodge.Item.Draw
where where
import Dodge.Data import Dodge.Data
import Dodge.Picture.Layer import Dodge.Picture.Layer
import Dodge.Creature.Stance.Data
import Picture import Picture
{- | {- |
Places an item picture onto a creature when the item is selected. -} Places an item picture onto a creature when the item is selected. -}
drawWeapon pictureWeaponOnAim
:: Picture :: Picture
-> Creature -> Creature
-> Int -- ^ Position of item in inventory -> Int -- ^ Position of item in inventory
-> Picture -> Picture
drawWeapon p cr posInInv pictureWeaponOnAim p cr posInInv
| _crInvSel cr == posInInv && _posture (_crStance cr) == Aiming
= onLayer PtLayer drawnWep
| _crInvSel cr == posInInv
= onLayer PtLayer holsteredWep
| otherwise = blank
where
drawnWep = uncurry translate (_crRad cr,0) p
holsteredWep = uncurry translate (_crRad cr,0) (scale 0.1 1 p)
pictureItem
:: Picture
-> Creature
-> Int -- ^ Position of item in inventory
-> Picture
pictureItem p cr posInInv
| _crInvSel cr == posInInv = onLayer PtLayer drawnWep | _crInvSel cr == posInInv = onLayer PtLayer drawnWep
| otherwise = blank | otherwise = blank
where where
drawnWep = uncurry translate (_crRad cr,0) p drawnWep = uncurry translate (_crRad cr,0) p
+23 -22
View File
@@ -59,7 +59,6 @@ pistol
,teslaLauncher ,teslaLauncher
,remoteLauncher ,remoteLauncher
,bezierGun ,bezierGun
,poisonSprayer
,defaultThrowable ,defaultThrowable
-- ,shatterGun -- ,shatterGun
,longGun,flamer,blinkGun,forceFieldGun :: Item ,longGun,flamer,blinkGun,forceFieldGun :: Item
@@ -88,7 +87,7 @@ pistol = Weapon
, _itAimingSpeed = 1 , _itAimingSpeed = 1
, _itAimingRange = 0 , _itAimingRange = 0
, _itZoom = defaultItZoom , _itZoom = defaultItZoom
, _itEquipPict = drawWeapon $ color green $ polygon $ rectNESW 3 3 (-3) (-3) , _itEquipPict = pictureWeaponOnAim $ color green $ polygon $ rectNESW 3 3 (-3) (-3)
, _itScrollUp = const id , _itScrollUp = const id
, _itScrollDown = const id , _itScrollDown = const id
, _itAttachment = Nothing , _itAttachment = Nothing
@@ -137,7 +136,7 @@ autoGun = defaultGun
, _itAimingSpeed = 0.4 , _itAimingSpeed = 0.4
, _itAimingRange = 1 , _itAimingRange = 1
, _itZoom = defaultItZoom {_itAimZoomFac = 1.5} , _itZoom = defaultItZoom {_itAimZoomFac = 1.5}
, _itEquipPict = drawWeapon $ color red $ polygon $ rectNESW 4 4 (-4) (-4) , _itEquipPict = pictureWeaponOnAim $ color red $ polygon $ rectNESW 4 4 (-4) (-4)
, _itEffect = wpRecock , _itEffect = wpRecock
, _itAttachment = Just $ ItCharMode $ Seq.fromList "MS" , _itAttachment = Just $ ItCharMode $ Seq.fromList "MS"
, _itScrollUp = incCharMode , _itScrollUp = incCharMode
@@ -174,7 +173,7 @@ rezGun = defaultGun
, _itMaxStack = 1 , _itMaxStack = 1
, _itAimingSpeed = 0.4 , _itAimingSpeed = 0.4
, _itAimingRange = 0 , _itAimingRange = 0
, _itEquipPict = drawWeapon $ color chartreuse $ pictures , _itEquipPict = pictureWeaponOnAim $ color chartreuse $ pictures
[polygon $ rectNESW 7 3 1 (-3) [polygon $ rectNESW 7 3 1 (-3)
,polygon $ rectNESW (-1) 3 (-7) (-3) ,polygon $ rectNESW (-1) 3 (-7) (-3)
] ]
@@ -200,7 +199,7 @@ teslaGun = defaultAutoGun
, _itAimingSpeed = 0.4 , _itAimingSpeed = 0.4
, _itZoom = defaultItZoom , _itZoom = defaultItZoom
, _itAimingRange = 0 , _itAimingRange = 0
, _itEquipPict = drawWeapon $ color blue $ pictures , _itEquipPict = pictureWeaponOnAim $ color blue $ pictures
[polygon $ rectNESW 7 3 1 (-3) [polygon $ rectNESW 7 3 1 (-3)
,polygon $ rectNESW (-1) 3 (-7) (-3) ,polygon $ rectNESW (-1) 3 (-7) (-3)
] ]
@@ -222,7 +221,7 @@ lasGun = defaultAutoGun
, _itMaxStack = 1 , _itMaxStack = 1
, _itAimingSpeed = 0.4 , _itAimingSpeed = 0.4
, _itAimingRange = 1 , _itAimingRange = 1
, _itEquipPict = drawWeapon $ color blue $ polygon $ rectNESW 3 3 (-3) (-3) , _itEquipPict = pictureWeaponOnAim $ color blue $ polygon $ rectNESW 3 3 (-3) (-3)
, _itAttachment = Just $ ItCharMode $ Seq.fromList "/VZ" , _itAttachment = Just $ ItCharMode $ Seq.fromList "/VZ"
, _itScrollUp = incCharMode , _itScrollUp = incCharMode
, _itScrollDown = decCharMode , _itScrollDown = decCharMode
@@ -282,7 +281,7 @@ tractorGun = defaultAutoGun
, _itMaxStack = 1 , _itMaxStack = 1
, _itAimingSpeed = 0.4 , _itAimingSpeed = 0.4
, _itAimingRange = 0.5 , _itAimingRange = 0.5
, _itEquipPict = drawWeapon $ color blue $ pictures [polygon $ rectNESW 1.5 6 (-1.5) 0 ] , _itEquipPict = pictureWeaponOnAim $ color blue $ pictures [polygon $ rectNESW 1.5 6 (-1.5) 0 ]
} }
launcher = defaultGun launcher = defaultGun
{ _itName = "ROCKO" { _itName = "ROCKO"
@@ -301,7 +300,7 @@ launcher = defaultGun
, _itMaxStack = 1 , _itMaxStack = 1
, _itAimingSpeed = 0.2 , _itAimingSpeed = 0.2
, _itAimingRange = 0.5 , _itAimingRange = 0.5
, _itEquipPict = drawWeapon $ color cyan $ polygon $ rectNESW 5 5 (-5) (-5) , _itEquipPict = pictureWeaponOnAim $ color cyan $ polygon $ rectNESW 5 5 (-5) (-5)
, _itHammer = NoHammer , _itHammer = NoHammer
, _itEffect = NoItEffect , _itEffect = NoItEffect
} }
@@ -390,7 +389,7 @@ remoteLauncher = defaultGun
, _itMaxStack = 1 , _itMaxStack = 1
, _itAimingSpeed = 0.2 , _itAimingSpeed = 0.2
, _itAimingRange = 0.5 , _itAimingRange = 0.5
, _itEquipPict = drawWeapon $ color cyan $ polygon $ rectNESW 5 5 (-5) (-5) , _itEquipPict = pictureWeaponOnAim $ color cyan $ polygon $ rectNESW 5 5 (-5) (-5)
, _itAttachment = Just $ ItScope (0,0) 0 1 True , _itAttachment = Just $ ItScope (0,0) 0 1 True
} }
hvAutoGun = defaultAutoGun hvAutoGun = defaultAutoGun
@@ -409,7 +408,7 @@ hvAutoGun = defaultAutoGun
, _itMaxStack = 1 , _itMaxStack = 1
, _itAimingSpeed = 0.2 , _itAimingSpeed = 0.2
, _itAimingRange = 1 , _itAimingRange = 1
, _itEquipPict = drawWeapon $ color orange $ polygon $ rectNESW 5 5 (-5) (-5) , _itEquipPict = pictureWeaponOnAim $ color orange $ polygon $ rectNESW 5 5 (-5) (-5)
} }
where where
mkHvBul = withSound (fromIntegral longGunSound) mkHvBul = withSound (fromIntegral longGunSound)
@@ -439,7 +438,7 @@ ltAutoGun = defaultAutoGun
, _itAimingSpeed = 1 , _itAimingSpeed = 1
, _itAimingRange = 0 , _itAimingRange = 0
, _itZoom = defaultItZoom , _itZoom = defaultItZoom
, _itEquipPict = drawWeapon $ color green $ pictures [polygon $ rectNSWE 4 (-4) (-4) 0 , _itEquipPict = pictureWeaponOnAim $ color green $ pictures [polygon $ rectNSWE 4 (-4) (-4) 0
,circleSolid 4 ,circleSolid 4
] ]
} }
@@ -464,7 +463,7 @@ miniGun = defaultAutoGun
, _itMaxStack = 1 , _itMaxStack = 1
, _itAimingSpeed = 0.4 , _itAimingSpeed = 0.4
, _itAimingRange = 1 , _itAimingRange = 1
, _itEquipPict = drawWeapon $ color red $ polygon $ rectNESW 9 5 (-9) (-5) , _itEquipPict = pictureWeaponOnAim $ color red $ polygon $ rectNESW 9 5 (-9) (-5)
} }
spreadGun = defaultGun spreadGun = defaultGun
{ _itName = "SPREAD" { _itName = "SPREAD"
@@ -486,7 +485,7 @@ spreadGun = defaultGun
, _itMaxStack = 1 , _itMaxStack = 1
, _itAimingSpeed = 1 , _itAimingSpeed = 1
, _itAimingRange = 0 , _itAimingRange = 0
, _itEquipPict = drawWeapon $ color green $ pictures [ polygon [(-3,0),(3,6),(3,-6)] ] , _itEquipPict = pictureWeaponOnAim $ color green $ pictures [ polygon [(-3,0),(3,6),(3,-6)] ]
} }
multGun = defaultGun multGun = defaultGun
{ _itName = "MULTGUN" { _itName = "MULTGUN"
@@ -509,7 +508,7 @@ multGun = defaultGun
, _itAimingSpeed = 0.4 , _itAimingSpeed = 0.4
, _itAimingRange = 1 , _itAimingRange = 1
, _itZoom = defaultItZoom {_itAimZoomFac = 1.5} , _itZoom = defaultItZoom {_itAimZoomFac = 1.5}
, _itEquipPict = drawWeapon multGunPic , _itEquipPict = pictureWeaponOnAim multGunPic
} }
where where
multGunPic = color red $ pictures multGunPic = color red $ pictures
@@ -542,7 +541,7 @@ longGun = defaultGun
, _itAimingSpeed = 0.2 , _itAimingSpeed = 0.2
, _itAimingRange = 1 , _itAimingRange = 1
, _itZoom = defaultItZoom {_itAimZoomMax = 0.5, _itAimZoomMin = 0.5} , _itZoom = defaultItZoom {_itAimZoomMax = 0.5, _itAimZoomMin = 0.5}
, _itEquipPict = drawWeapon $ pictures [color orange $ polygon $ rectNESW 3 6 (-3) (-6) ] , _itEquipPict = pictureWeaponOnAim $ pictures [color orange $ polygon $ rectNESW 3 6 (-3) (-6) ]
, _itScrollUp = startZoomInLongGun , _itScrollUp = startZoomInLongGun
, _itScrollDown = startZoomOutLongGun , _itScrollDown = startZoomOutLongGun
, _itAttachment = Just $ ItScope (0,0) 0 1 False , _itAttachment = Just $ ItScope (0,0) 0 1 False
@@ -556,6 +555,7 @@ startZoomOutLongGun :: Int -> World -> World
startZoomOutLongGun _ w = w & creatures . ix 0 . crInv . ix (_crInvSel (_creatures w IM.! 0)) startZoomOutLongGun _ w = w & creatures . ix 0 . crInv . ix (_crInvSel (_creatures w IM.! 0))
. itAttachment . _Just . scopeZoomChange %~ \x -> min (-5) (x-5) . itAttachment . _Just . scopeZoomChange %~ \x -> min (-5) (x-5)
poisonSprayer :: Item
poisonSprayer = defaultAutoGun poisonSprayer = defaultAutoGun
{ _itName = "POISON" { _itName = "POISON"
, _itIdentity = PoisonSprayer , _itIdentity = PoisonSprayer
@@ -574,7 +574,7 @@ poisonSprayer = defaultAutoGun
, _itAimingSpeed = 0.2 , _itAimingSpeed = 0.2
, _itAimingRange = 0 , _itAimingRange = 0
, _itZoom = defaultItZoom , _itZoom = defaultItZoom
, _itEquipPict = drawWeapon $ color yellow $ polygon $ rectNESW 4 4 (-4) (-4) , _itEquipPict = pictureWeaponOnAim $ color yellow $ polygon $ rectNESW 4 4 (-4) (-4)
} }
flamer = defaultAutoGun flamer = defaultAutoGun
@@ -595,7 +595,7 @@ flamer = defaultAutoGun
, _itAimingSpeed = 0.5 , _itAimingSpeed = 0.5
, _itAimingRange = 0 , _itAimingRange = 0
, _itZoom = defaultItZoom {_itAimZoomMax = 5, _itAimZoomMin = 1.5} , _itZoom = defaultItZoom {_itAimZoomMax = 5, _itAimZoomMin = 1.5}
, _itEquipPict = drawWeapon $ color yellow $ polygon $ rectNESW 4 4 (-4) (-4) , _itEquipPict = pictureWeaponOnAim $ color yellow $ polygon $ rectNESW 4 4 (-4) (-4)
, _itAttachment = Nothing , _itAttachment = Nothing
} }
blinkGun = defaultGun blinkGun = defaultGun
@@ -873,7 +873,7 @@ grenade = Throwable
, _itAimingSpeed = 1 , _itAimingSpeed = 1
, _itAimingRange = 0 , _itAimingRange = 0
, _itZoom = defaultItZoom {_itAimZoomMax = f fuseTime, _itAimZoomMin = f fuseTime} , _itZoom = defaultItZoom {_itAimZoomMax = f fuseTime, _itAimZoomMin = f fuseTime}
, _itEquipPict = drawWeapon $ grenadePic fuseTime , _itEquipPict = pictureWeaponOnAim $ grenadePic fuseTime
, _itID = Nothing , _itID = Nothing
, _itUseRate = 50 , _itUseRate = 50
, _itUseTime = 0 , _itUseTime = 0
@@ -918,7 +918,7 @@ remoteBomb = defaultThrowable
, _twAccuracy = 30 , _twAccuracy = 30
, _twFire = hammerCheck throwRemoteBomb , _twFire = hammerCheck throwRemoteBomb
, _itAttachment = Just $ ItScope (0,0) 0 1 True , _itAttachment = Just $ ItScope (0,0) 0 1 True
, _itEquipPict = drawWeapon remoteBombUnarmedPic , _itEquipPict = pictureWeaponOnAim remoteBombUnarmedPic
} }
@@ -1099,7 +1099,7 @@ explodeRemoteBomb itid pjid n w
where where
resetName = set (creatures . ix n . crInv . ix j . itName) "REMOTEBOMB" resetName = set (creatures . ix n . crInv . ix j . itName) "REMOTEBOMB"
resetPict = set (creatures . ix n . crInv . ix j . itEquipPict ) resetPict = set (creatures . ix n . crInv . ix j . itEquipPict )
(drawWeapon remoteBombUnarmedPic) (pictureWeaponOnAim remoteBombUnarmedPic)
-- resetScope = creatures . ix n . crInv . ix j . itScope . _Just . scopePos .~ (0,0) -- resetScope = creatures . ix n . crInv . ix j . itScope . _Just . scopePos .~ (0,0)
j = _crInvSel $ _creatures w IM.! n j = _crInvSel $ _creatures w IM.! n
remoteBombPic remoteBombPic
@@ -1148,7 +1148,7 @@ radar = defaultGun
, _itMaxStack = 1 , _itMaxStack = 1
, _itAimingRange = 1 , _itAimingRange = 1
, _itZoom = defaultItZoom {_itAimZoomMax = 1, _itZoomMax = 1} , _itZoom = defaultItZoom {_itAimZoomMax = 1, _itZoomMax = 1}
, _itEquipPict = drawWeapon $ color blue $ polygon $ rectNESW 5 5 (-5) (-5) , _itEquipPict = pictureWeaponOnAim $ color blue $ polygon $ rectNESW 5 5 (-5) (-5)
} }
{- | {- |
Sends out pulses that display creatures. -} Sends out pulses that display creatures. -}
@@ -1170,7 +1170,7 @@ sonar = defaultGun
, _itMaxStack = 1 , _itMaxStack = 1
, _itAimingRange = 1 , _itAimingRange = 1
, _itZoom = defaultItZoom {_itAimZoomMax = 1, _itZoomMax = 1} , _itZoom = defaultItZoom {_itAimZoomMax = 1, _itZoomMax = 1}
, _itEquipPict = drawWeapon $ color blue $ polygon $ rectNESW 5 5 (-5) (-5) , _itEquipPict = pictureWeaponOnAim $ color blue $ polygon $ rectNESW 5 5 (-5) (-5)
} }
{- | {- |
Automatically sends out pulses that display creatures. -} Automatically sends out pulses that display creatures. -}
@@ -1229,3 +1229,4 @@ spawnCrNextTo cr i w = w & creatures %~ IM.insert k newCr
& crID .~ k & crID .~ k
& crPos .~ _crPos sCr +.+ unitVectorAtAngle (_crDir sCr) & crPos .~ _crPos sCr +.+ unitVectorAtAngle (_crDir sCr)
& crOldPos .~ _crPos sCr +.+ unitVectorAtAngle (_crDir sCr) & crOldPos .~ _crPos sCr +.+ unitVectorAtAngle (_crDir sCr)
+2 -2
View File
@@ -60,7 +60,7 @@ throwGrenade
-> Int -- ^ Creature id -> Int -- ^ Creature id
-> World -> World
-> World -> World
throwGrenade explosion n w = setWp $ removePict $ over projectiles addG $ w throwGrenade explosion n w = setWp $ removePict $ over projectiles addG w
where where
addG = IM.insert i $ Shell addG = IM.insert i $ Shell
{ _pjPos = p { _pjPos = p
@@ -95,7 +95,7 @@ throwArmReset x = ItInvEffect {_itInvEffect = f ,_itEffectCounter = x }
counterDown it counterDown it
| _itEffectCounter (_itEffect it) == 0 = it | _itEffectCounter (_itEffect it) == 0 = it
& itHammer .~ HammerUp & itHammer .~ HammerUp
& itEquipPict .~ drawWeapon (grenadePic 50) & itEquipPict .~ pictureWeaponOnAim (grenadePic 50)
| otherwise = it & itEffect . itEffectCounter -~ 1 | otherwise = it & itEffect . itEffectCounter -~ 1
--(grenadeAccL, grenadeAccA) = (0.1, 0.1) --(grenadeAccL, grenadeAccA) = (0.1, 0.1)
+1 -1
View File
@@ -21,6 +21,7 @@ import Control.Lens
import Control.Monad.State import Control.Monad.State
--import Data.Maybe --import Data.Maybe
--import qualified Data.IntMap.Strict as IM --import qualified Data.IntMap.Strict as IM
--
-- | Basic bullet hit creature effect. -- | Basic bullet hit creature effect.
bulHitCr :: Particle -> Point2 -> Creature -> World -> World bulHitCr :: Particle -> Point2 -> Creature -> World -> World
bulHitCr bt p cr w bulHitCr bt p cr w
@@ -39,7 +40,6 @@ bulHitCr bt p cr w
cid = _crID cr cid = _crID cr
(d1,_) = randomR (-0.7,0.7) $ _randGen w (d1,_) = randomR (-0.7,0.7) $ _randGen w
colID = _btColor' bt colID = _btColor' bt
--(colID,_) = randomR (0,11) $ _randGen w
p1 = p +.+ 2 *.* safeNormalizeV (p -.- _crPos cr) p1 = p +.+ 2 *.* safeNormalizeV (p -.- _crPos cr)
{- | Bounce off armoured creatures, otherwise do damage. -} {- | Bounce off armoured creatures, otherwise do damage. -}
bulBounceArmCr' :: Particle -> Point2 -> Creature -> World -> World bulBounceArmCr' :: Particle -> Point2 -> Creature -> World -> World
+1 -1
View File
@@ -87,7 +87,7 @@ f = incidenceToFunction $ pairsToIncidence
-- ] -- ]
pathBetween :: Point2 -> Point2 -> World -> Maybe [Point2] pathBetween :: Point2 -> Point2 -> World -> Maybe [Point2]
pathBetween a b w = (makePath' $ \p -> _pathInc w M.! p) <$> a' <*> b' pathBetween a b w = makePath' (\p -> _pathInc w M.! p) <$> a' <*> b'
where where
nsa :: [Point2] nsa :: [Point2]
nsa = map snd $ concat $ lookLookups (zoneAroundPoint a) (_pathPoints w) nsa = map snd $ concat $ lookLookups (zoneAroundPoint a) (_pathPoints w)
+1 -1
View File
@@ -56,7 +56,7 @@ menuScreen cfig hw hh mLays = case mLays of
mavol = f $ _volume_master cfig mavol = f $ _volume_master cfig
snvol = f $ _volume_sound cfig snvol = f $ _volume_sound cfig
muvol = f $ _volume_music cfig muvol = f $ _volume_music cfig
f x = show $ (round $ 10 * x :: Int) f x = show (round $ 10 * x :: Int)
showShadRes i = "1/"++ show i showShadRes i = "1/"++ show i
optionsList optionsList
+3 -3
View File
@@ -218,7 +218,7 @@ moveFlamelet w pt
damifclose cr damifclose cr
| isClose cr = cr & crState . crDamage %~ ( Flaming 3 sp ep ep : ) | isClose cr = cr & crState . crDamage %~ ( Flaming 3 sp ep ep : )
| otherwise = cr | otherwise = cr
-- | At writing the radius is half the size of the effect area
makeGasCloud makeGasCloud
:: Point2 -- ^ Position :: Point2 -- ^ Position
-> Point2 -- ^ Velocity -> Point2 -- ^ Velocity
@@ -234,7 +234,7 @@ makeGasCloud pos vel w = w
, _clVel = vel , _clVel = vel
, _clPict = \_ -> onLayer CrLayer $ color (withAlpha 0.1 col) , _clPict = \_ -> onLayer CrLayer $ color (withAlpha 0.1 col)
$ circleSolid 20 $ circleSolid 20
, _clRad = 20 , _clRad = 10
, _clTimer = 400 , _clTimer = 400
, _clEffect = cloudPoisonDamage , _clEffect = cloudPoisonDamage
} }
@@ -247,7 +247,7 @@ cloudPoisonDamage :: Cloud -> World -> World
cloudPoisonDamage c w = w & creatures %~ flip (foldr (IM.adjust doDam)) damagedCrs cloudPoisonDamage c w = w & creatures %~ flip (foldr (IM.adjust doDam)) damagedCrs
where where
damagedCrs = IM.keys $ IM.filter f $ creaturesNearPoint (_clPos c) w damagedCrs = IM.keys $ IM.filter f $ creaturesNearPoint (_clPos c) w
f cr = dist (_crPos cr) (_clPos c) < _crRad cr + _clRad c f cr = dist (_crPos cr) (_clPos c) < _crRad cr + _clRad c + 10
doDam cr = cr & crState . crDamage %~ (:) (PoisonDam 1) doDam cr = cr & crState . crDamage %~ (:) (PoisonDam 1)
{- {-
+1 -1
View File
@@ -194,7 +194,7 @@ difference x y
| x > y = x - y | x > y = x - y
| otherwise = y - x | otherwise = y - x
-- | Given vector line direction and a vector movement, -- | Given vector line direction and a vector movement,
-- reflects the movement accoring to the line. -- reflects the movement according to the line.
reflectIn :: Point2 -> Point2 -> Point2 reflectIn :: Point2 -> Point2 -> Point2
reflectIn line vec = rotateV angle vec reflectIn line vec = rotateV angle vec
where where
+1 -1
View File
@@ -134,7 +134,7 @@ but is symmetric around 0:
-} -}
roundPoint2 :: Point2 -> Point2 roundPoint2 :: Point2 -> Point2
roundPoint2 (x,y) = (fromIntegral $ (round x :: Int),fromIntegral $ (round y :: Int)) roundPoint2 (x,y) = (fromIntegral (round x :: Int),fromIntegral (round y :: Int))
-- | Given two points, finds the linear gradient if it is non-infinite. -- | Given two points, finds the linear gradient if it is non-infinite.
linGrad :: (Eq a,Fractional a) => (a,a) -> (a,a) -> Maybe a linGrad :: (Eq a,Fractional a) => (a,a) -> (a,a) -> Maybe a
linGrad (x,y) (a,b) linGrad (x,y) (a,b)
+31 -65
View File
@@ -2,8 +2,7 @@
module Geometry.Vector module Geometry.Vector
where where
import Geometry.Data import Geometry.Data
{- | Moves from to three dimensions, adding zero in z direction. {- | Moves from to three dimensions, adding zero in z direction. -}
-}
zeroZ :: Point2 -> Point3 zeroZ :: Point2 -> Point3
{-# INLINE zeroZ #-} {-# INLINE zeroZ #-}
zeroZ (x,y) = (x,y,0) zeroZ (x,y) = (x,y,0)
@@ -11,8 +10,7 @@ zeroZ (x,y) = (x,y,0)
infixl 6 +.+, -.- infixl 6 +.+, -.-
infixl 7 *.* infixl 7 *.*
{- | 2D coordinate-wise addition. {- | 2D coordinate-wise addition. -}
-}
(+.+) :: Point2 -> Point2 -> Point2 (+.+) :: Point2 -> Point2 -> Point2
{-# INLINE (+.+) #-} {-# INLINE (+.+) #-}
(x1, y1) +.+ (x2, y2) = (x1, y1) +.+ (x2, y2) =
@@ -20,8 +18,7 @@ infixl 7 *.*
!x = x1 + x2 !x = x1 + x2
!y = y1 + y2 !y = y1 + y2
in (x, y) in (x, y)
{- | 2D coordinate-wise subtraction. {- | 2D coordinate-wise subtraction. -}
-}
(-.-) :: Point2 -> Point2 -> Point2 (-.-) :: Point2 -> Point2 -> Point2
{-# INLINE (-.-) #-} {-# INLINE (-.-) #-}
(x1, y1) -.- (x2, y2) = (x1, y1) -.- (x2, y2) =
@@ -29,8 +26,7 @@ infixl 7 *.*
!x = x1 - x2 !x = x1 - x2
!y = y1 - y2 !y = y1 - y2
in (x, y) in (x, y)
{- | 2D scalar multiplication. {- | 2D scalar multiplication. -}
-}
(*.*) :: Float -> Point2 -> Point2 (*.*) :: Float -> Point2 -> Point2
{-# INLINE (*.*) #-} {-# INLINE (*.*) #-}
a *.* (x2, y2) = a *.* (x2, y2) =
@@ -42,9 +38,7 @@ a *.* (x2, y2) =
infixl 6 +.+.+, -.-.- infixl 6 +.+.+, -.-.-
infixl 7 *.*.* infixl 7 *.*.*
{- | 3D coordinate-wise addition. -}
{- | 3D coordinate-wise addition.
-}
(+.+.+) :: Point3 -> Point3 -> Point3 (+.+.+) :: Point3 -> Point3 -> Point3
{-# INLINE (+.+.+) #-} {-# INLINE (+.+.+) #-}
(x1, y1, z1) +.+.+ (x2, y2, z2) = (x1, y1, z1) +.+.+ (x2, y2, z2) =
@@ -53,9 +47,7 @@ infixl 7 *.*.*
!y = y1 + y2 !y = y1 + y2
!z = z1 + z2 !z = z1 + z2
in (x, y, z) in (x, y, z)
{- | 3D coordinate-wise subtraction. -}
{- | 3D coordinate-wise subtraction.
-}
(-.-.-) :: Point3 -> Point3 -> Point3 (-.-.-) :: Point3 -> Point3 -> Point3
{-# INLINE (-.-.-) #-} {-# INLINE (-.-.-) #-}
(x1, y1, z1) -.-.- (x2, y2, z2) = (x1, y1, z1) -.-.- (x2, y2, z2) =
@@ -64,9 +56,7 @@ infixl 7 *.*.*
!y = y1 - y2 !y = y1 - y2
!z = z1 - z2 !z = z1 - z2
in (x, y, z) in (x, y, z)
{- | 3D scalar multiplication. -}
{- | 3D scalar multiplication.
-}
(*.*.*) :: Point3 -> Point3 -> Point3 (*.*.*) :: Point3 -> Point3 -> Point3
{-# INLINE (*.*.*) #-} {-# INLINE (*.*.*) #-}
(x1, y1, z1) *.*.* (x2, y2, z2) = (x1, y1, z1) *.*.* (x2, y2, z2) =
@@ -75,16 +65,11 @@ infixl 7 *.*.*
!y = y1 * y2 !y = y1 * y2
!z = z1 * z2 !z = z1 * z2
in (x, y, z) in (x, y, z)
{- | Normalize a vector to length 1. -}
{- | Normalize a vector to length 1.
-}
normalizeV :: Point2 -> Point2 normalizeV :: Point2 -> Point2
{-# INLINE normalizeV #-} {-# INLINE normalizeV #-}
normalizeV p = (1 / magV p) *.* p normalizeV p = (1 / magV p) *.* p
{- | Angle between two vectors. Always positive. -}
{- | Angle between two vectors.
Always positive.
-}
angleVV :: Point2 -> Point2 -> Float angleVV :: Point2 -> Point2 -> Float
{-# INLINE angleVV #-} {-# INLINE angleVV #-}
angleVV a b = angleVV a b =
@@ -92,58 +77,44 @@ angleVV a b =
mb = magV b mb = magV b
d = a `dotV` b d = a `dotV` b
in acos $ d / (ma * mb) in acos $ d / (ma * mb)
{- | Safe version of 'angleVV' that returns 0 if either vector is null. -} {- | Safe version of 'angleVV' that returns 0 if either vector is null. -}
safeAngleVV :: Point2 -> Point2 -> Float safeAngleVV :: Point2 -> Point2 -> Float
{-# INLINE safeAngleVV #-} {-# INLINE safeAngleVV #-}
safeAngleVV a b safeAngleVV a b
| a == (0,0) || b == (0,0) = 0 | a == (0,0) || b == (0,0) = 0
| otherwise = angleVV a b | otherwise = angleVV a b
{- | Dot product. -}
{- | Dot product.
-}
dotV :: Point2 -> Point2 -> Float dotV :: Point2 -> Point2 -> Float
{-# INLINE dotV #-} {-# INLINE dotV #-}
dotV (x,y) (z,w) = x*z + y*w dotV (x,y) (z,w) = x*z + y*w
{- | Given vector, returns the angle, anticlockwise from +ve x-axis, in radians. -}
{- | Given vector, returns the angle, anticlockwise from +ve x-axis, in radians.
-}
argV :: Point2 -> Float argV :: Point2 -> Float
{-# INLINE argV #-} {-# INLINE argV #-}
argV (x,y) = normalizeAngle $ atan2 y x argV (x,y) = normalizeAngle $ atan2 y x
{- | Determinant of the matrix formed by two vectors. -}
{- | Determinant of the matrix formed by two vectors.
-}
detV :: Point2 -> Point2 -> Float detV :: Point2 -> Point2 -> Float
{-# INLINE detV #-} {-# INLINE detV #-}
detV (x1, y1) (x2, y2) detV (x1, y1) (x2, y2) = x1 * y2 - y1 * x2
= x1 * y2 - y1 * x2 {- | Given an angle in radians, anticlockwise from +ve x-axis,
- returns the corresponding unit vector. -}
{- | Given an angle in radians, anticlockwise from +ve x-axis, returns the
corresponding unit vector.
-}
unitVectorAtAngle :: Float -> Point2 unitVectorAtAngle :: Float -> Point2
{-# INLINE unitVectorAtAngle #-} {-# INLINE unitVectorAtAngle #-}
unitVectorAtAngle r unitVectorAtAngle r = (cos r, sin r)
= (cos r, sin r)
-- | Rotate a vector by an angle (in radians). +ve angle is counter-clockwise. -- | Rotate a vector by an angle (in radians). +ve angle is counter-clockwise.
rotateV :: Float -> Point2 -> Point2 rotateV :: Float -> Point2 -> Point2
rotateV r (x, y) rotateV r (x, y) =
= ( x * cos r - y * sin r ( x * cos r - y * sin r
, x * sin r + y * cos r) , x * sin r + y * cos r
)
{-# INLINE rotateV #-} {-# INLINE rotateV #-}
-- | Convert degrees to radians -- | Convert degrees to radians
degToRad :: Float -> Float degToRad :: Float -> Float
degToRad d = d * pi / 180 degToRad d = d * pi / 180
{-# INLINE degToRad #-} {-# INLINE degToRad #-}
-- | Convert radians to degrees -- | Convert radians to degrees
radToDeg :: Float -> Float radToDeg :: Float -> Float
radToDeg r = r * 180 / pi radToDeg r = r * 180 / pi
{-# INLINE radToDeg #-} {-# INLINE radToDeg #-}
-- | Normalize an angle to be between 0 and 2*pi radians -- | Normalize an angle to be between 0 and 2*pi radians
normalizeAngle :: Float -> Float normalizeAngle :: Float -> Float
{-# INLINE normalizeAngle #-} {-# INLINE normalizeAngle #-}
@@ -151,34 +122,29 @@ normalizeAngle f = f - 2 * pi * floor' (f / (2 * pi))
where where
floor' :: Float -> Float floor' :: Float -> Float
floor' x = fromIntegral (floor x :: Int) floor' x = fromIntegral (floor x :: Int)
{- | Rotate vector by pi/2 clockwise. -}
{- | Rotate vector by pi/2 clockwise.
-}
vNormal :: Point2 -> Point2 vNormal :: Point2 -> Point2
{-# INLINE vNormal #-} {-# INLINE vNormal #-}
vNormal (x,y) = (y,-x) vNormal (x,y) = (y,-x)
{- | Negate a vector. -}
{- | Negate a vector.
-}
vInverse :: Point2 -> Point2 vInverse :: Point2 -> Point2
vInverse (x,y) = (-x,-y) vInverse (x,y) = (-x,-y)
{- | Normalize a vector safely: on (0,0) return (0,0). -}
{- | Normalize a vector safely: on (0,0) return (0,0).
-}
safeNormalizeV :: Point2 -> Point2 safeNormalizeV :: Point2 -> Point2
{-# INLINE safeNormalizeV #-} {-# INLINE safeNormalizeV #-}
safeNormalizeV (0,0) = (0,0) safeNormalizeV (0,0) = (0,0)
safeNormalizeV p = (1/magV p ) *.* p safeNormalizeV p = (1/magV p ) *.* p
{- | Magnitude of a vector. -}
{- | Magnitude of a vector.
-}
magV :: Point2 -> Float magV :: Point2 -> Float
{-# INLINE magV #-} {-# INLINE magV #-}
magV (x,y) = sqrt $ x^(2::Int) + y^(2::Int) magV (x,y) = sqrt $ x^(2::Int) + y^(2::Int)
{- | Magnitude of the cross product of two vectors. {- | Magnitude of the cross product of two vectors.
Identical to detV. Identical to detV. -}
-}
crossV :: Point2 -> Point2 -> Float crossV :: Point2 -> Point2 -> Float
crossV (ax,ay) (bx,by) = ax*by - ay*bx crossV (ax,ay) (bx,by) = ax*by - ay*bx
{- | TO CHECK Orthographic projection of one vector onto another. -}
projV
:: Point2
-> Point2
-> Point2
projV fromv onv = (fromv `dotV` onv) / (onv `dotV` onv) *.* onv