183 lines
4.9 KiB
Haskell
183 lines
4.9 KiB
Haskell
-- | Module defining helper placements for rooms.
|
|
module Dodge.Room.Placement
|
|
where
|
|
import Dodge.Data
|
|
import Dodge.Default.Wall
|
|
import Dodge.LevelGen.Data
|
|
import Dodge.LevelGen.Switch
|
|
import Dodge.Room.Data
|
|
import Dodge.Creature.Inanimate
|
|
import Picture
|
|
import Geometry
|
|
|
|
import Data.List
|
|
import Control.Lens
|
|
import qualified Data.IntMap.Strict as IM
|
|
|
|
putColorLamp :: Point3 -> PSType
|
|
putColorLamp col = PutCrit (colorLamp col 90)
|
|
|
|
putLamp :: PSType
|
|
putLamp = PutCrit (lamp 90)
|
|
|
|
singleBlock :: Point2 -> [Placement]
|
|
singleBlock a =
|
|
[sPS a 0
|
|
$ PutBlock [5,20,20] (greyN 0.5)
|
|
$ reverse
|
|
$ rectNSWE 10 (-10) (-10) 10
|
|
]
|
|
{-
|
|
Places a line of blocks between two points.
|
|
Width 9, also extends out from each point by 9.
|
|
-}
|
|
blockLine :: Point2 -> Point2 -> Placement
|
|
blockLine a b = Placement PS
|
|
{ _psPos = V2 0 0
|
|
, _psRot = 0
|
|
, _psType = PutLineBlock baseBlockPane 9 9 a b
|
|
} (const Nothing)
|
|
|
|
{-
|
|
Places an breakable window between two points.
|
|
Width 8, also extends out from each point by 8.
|
|
-}
|
|
windowLine :: Point2 -> Point2 -> Placement
|
|
windowLine a b = Placement PS
|
|
{ _psPos = V2 0 0
|
|
, _psRot = 0
|
|
, _psType = PutLineBlock baseWindowPane 8 8 a b
|
|
} (const Nothing)
|
|
|
|
{-
|
|
Places an unbreakable window between two points.
|
|
Width 7, also extends out from each point by 7.
|
|
-}
|
|
crystalLine :: Point2 -> Point2 -> Placement
|
|
crystalLine a b = Placement PS
|
|
{ _psPos = V2 0 0
|
|
, _psRot = 0
|
|
, _psType = PutWall ps defaultCrystalWall
|
|
} (const Nothing)
|
|
where
|
|
ps =
|
|
[ a +.+ left +.+ up
|
|
, (a +.+ left) -.- up
|
|
, (b -.- left) -.- up
|
|
, (b -.- left) +.+ up
|
|
]
|
|
left = 7 *.* normalizeV (a-.-b)
|
|
up = vNormal left
|
|
{- Places an unbreakable wall between two points.
|
|
Depth 15, does not extend wider than points.
|
|
-}
|
|
wallLine :: Point2 -> Point2 -> Placement
|
|
wallLine a b = Placement PS
|
|
{ _psPos = V2 0 0
|
|
, _psRot = 0
|
|
, _psType = PutWall ps defaultWall
|
|
} (const Nothing)
|
|
where
|
|
ps =
|
|
[ a +.+ up
|
|
, a -.- up
|
|
, b -.- up
|
|
, b +.+ up
|
|
]
|
|
left = 15 *.* normalizeV (a-.-b)
|
|
up = vNormal left
|
|
|
|
windowLineType :: Point2 -> Point2 -> PSType
|
|
windowLineType = PutLineBlock baseWindowPane 8 8
|
|
|
|
baseBlockPane :: Wall
|
|
baseBlockPane = defaultWall
|
|
{ _wlLine = (V2 0 0,V2 50 0)
|
|
, _wlID = 0
|
|
, _wlColor = greyN 0.5
|
|
, _wlSeen = False
|
|
, _wlIsSeeThrough = False
|
|
, _wlDraw = True
|
|
}
|
|
baseWindowPane :: Wall
|
|
baseWindowPane = defaultWall
|
|
{ _wlLine = (V2 0 0,V2 50 0)
|
|
, _wlID = 0
|
|
, _wlColor = withAlpha 0.2 cyan
|
|
, _wlSeen = False
|
|
, _wlIsSeeThrough = True
|
|
, _wlDraw = True
|
|
}
|
|
{- Replaces instances of a given 'PutID' with 'PSType's drawn from a list. -}
|
|
replacePutID
|
|
:: Int -- ^ The id of 'PutID' to be replaced
|
|
-> [PSType] -- ^ List of replacements
|
|
-> Room
|
|
-> Room
|
|
replacePutID i psts r =
|
|
r & rmPS %~ flip (subZipWith (isPutID i) (\ps pt -> ps & placementSpot . psType .~ pt)) psts
|
|
{- Partition a list by a predicate, apply a zip to those elements
|
|
that satisfy the predicate, concatenate
|
|
the new zipped list and the other (unchanged) half. -}
|
|
subZipWith
|
|
:: (a -> Bool) -- ^ Filter: elements to apply zip to
|
|
-> (a -> b -> a) -- ^ Combining function
|
|
-> [a] -- ^ List to be partition
|
|
-> [b] -- ^ Modifying list
|
|
-> [a]
|
|
subZipWith f g xs ys =
|
|
let (zs,ws) = partition f xs
|
|
in zipWith g zs ys ++ ws
|
|
|
|
isPutID :: Int -> Placement -> Bool
|
|
isPutID i ps = Just i == ps ^? placementSpot . psType . putID
|
|
|
|
putBlockRect
|
|
:: Float
|
|
-> Float
|
|
-> Float
|
|
-> Float
|
|
-> [Placement]
|
|
putBlockRect a x b y = [ blockLine (V2 a b) (V2 a y)
|
|
, blockLine (V2 a y) (V2 x y)
|
|
, blockLine (V2 x y) (V2 x b)
|
|
, blockLine (V2 x b) (V2 a b)
|
|
]
|
|
putBlockV
|
|
:: Float
|
|
-> Float
|
|
-> Float
|
|
-> Float
|
|
-> [Placement]
|
|
putBlockV a x b y = [ blockLine (V2 a b) (V2 a y)
|
|
, blockLine (V2 x b) (V2 a b)
|
|
]
|
|
putBlockC
|
|
:: Float
|
|
-> Float
|
|
-> Float
|
|
-> Float
|
|
-> [Placement]
|
|
putBlockC a x b y = [ blockLine (V2 a b) (V2 a y)
|
|
, blockLine (V2 x b) (V2 a b)
|
|
, blockLine (V2 a y) (V2 x y)
|
|
]
|
|
putBlockN
|
|
:: Float
|
|
-> Float
|
|
-> Float
|
|
-> Float
|
|
-> [Placement]
|
|
putBlockN a x b y = [ blockLine (V2 a b) (V2 a y)
|
|
, blockLine (V2 x b) (V2 a b)
|
|
, blockLine (V2 x y) (V2 x b)
|
|
]
|
|
|
|
switchDoor :: Point2 -> Float -> Point2 -> Point2 -> Color -> Placement
|
|
switchDoor btpos btrot dra drb col = Placement (PS btpos btrot $ PutButton $ makeSwitch col red id id)
|
|
$ \btid -> jsps0J (PutSingleDoor col (cond btid) dra drc 2)
|
|
$ sps0 (PutSingleDoor col (cond btid) drb drc 2)
|
|
where
|
|
drc = 0.5 *.* (dra +.+ drb)
|
|
cond btid w' = _btState (_buttons w' IM.! btid) == BtOn
|