packages feed

brillo-examples-2.0.0: picture/Occlusion/Main.hs

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PatternGuards #-}

import Brillo.Data.Extent
import Brillo.Data.QuadTree
import Brillo.Interface.Pure.Game
import Cell
import Data
import Data.Maybe
import State
import System.Environment
import World


main :: IO ()
main =
  do
    args <- getArgs
    case args of
      [fileName] ->
        do
          world <- loadWorld fileName
          mainWithWorld world
      _ -> do
        let world = readWorld worldData
        mainWithWorld world


mainWithWorld :: World -> IO ()
mainWithWorld world =
  play
    ( InWindow
        "Occlusion"
        (windowSizeOfWorld world)
        (10, 10)
    )
    black
    10
    (initState world)
    drawState
    (handleInput world)
    (\_ -> id)


-- | Convert the state to a picture.
drawState :: State -> Picture
drawState state =
  let world = stateWorld state

      -- The ray cast by the user.
      p1 = stateLineStart state
      p2 = stateLineEnd state
      picRay = drawRay world p1 p2

      -- The cell hit by the ray (if any)
      mHitCell = castSegIntoWorld world p1 p2
      hitCells = maybeToList mHitCell
      picCellsHit = Pictures $ map (drawHitCell world) hitCells

      -- All the cells in the world.
      cellsAll = flattenQuadTree (worldExtent world) (worldTree world)
      picCellsAll = Pictures $ map (uncurry (drawCell False world)) cellsAll

      -- The cells visible from the designated point.
      cellsVisible =
        [ (coord, cell)
        | (coord, cell) <- flattenQuadTree (worldExtent world) (worldTree world)
        , cellAtCoordIsVisibleFromPoint world p1 coord
        ]

      picCellsVisible = Pictures $ map (uncurry (drawCell True world)) cellsVisible

      -- How big to draw the cells.
      scaleFactor = fromIntegral $ worldCellSize world

      (windowSizeX, windowSizeY) =
        windowSizeOfWorld $
          stateWorld state

      -- Shift the cells so they are centered in the window.
      offsetX = -(fromIntegral $ windowSizeX `div` 2)
      offsetY = -(fromIntegral $ windowSizeY `div` 2)
  in  Translate offsetX offsetY $
        Scale scaleFactor scaleFactor $
          Pictures [picCellsAll, picCellsVisible, picCellsHit, picRay]


-- | Draw the cell hit by the ray defined by the user.
drawHitCell :: World -> (Point, Extent, Cell) -> Picture
drawHitCell _ (_, extent, _) =
  let (_, s, _, w) = takeExtent extent
      x = w
      y = s

      posX = fromIntegral x
      posY = fromIntegral y
  in  Pictures [Color blue $ cellShape 1 posX posY]


-- | Draw the ray defined by the user.
drawRay :: World -> Point -> Point -> Picture
drawRay _ p1@(x, y) p2 =
  Pictures
    [ Color red $ Line [p1, p2]
    , Color cyan $
        Translate x y $
          Pictures
            [ Line [(-0.3, -0.3), (0.3, 0.3)]
            , Line [(-0.3, 0.3), (0.3, -0.3)]
            ]
    ]


-- | Draw a cell in the world.
drawCell :: Bool -> World -> Coord -> Cell -> Picture
drawCell visible world (x, y) cell =
  let cs = fromIntegral (worldCellSize world)
      -- cp      = fromIntegral (worldCellSpace world)

      posX = fromIntegral x
      posY = fromIntegral y
  in  if visible
        then pictureOfCell (worldCellSize world) posX posY cell
        else Color (greyN 0.4) (cellShape cs posX posY)