packages feed

topkata-0.2.4: Topkata/Topka/Ghost.hs

module Topkata.Topka.Ghost where

--import Graphics.UI.GLFW
import Graphics.Rendering.OpenGL
import Topkata.Topka.Base
import Vector
import Labygen
import Data.Array ( (!) )
import Data.List 
-- import Debug.Trace (trace)

data GhostState = GhostState {
      ghostPosition     :: Vector3 GLdouble,
      ghostOrientation  :: Direction,
      ghostSpeed        :: GLdouble,
      ghostPhase        :: GLuint
}


newGhost x z = GhostState {
  ghostPosition    = Vector3 x 0.5 z,
  ghostOrientation = East,
  ghostSpeed       = 0.01,
  ghostPhase       = 0
  
}

drawGhost et pm phase = do
  texture Texture2D $= Enabled
  textureBinding Texture2D $= et
  --textureFunction $= Decal
  mapM_ (\ a -> drawSegment pm $ segment a (a+epsilon)) [0, epsilon .. pi+epsilon]
  color (Color3 0.0 1.0 (1.0  :: GLfloat))
  mapM_ (\ y -> drawSegment pm $ ringSegment (-y) (-y-epsilon) phase) [0, epsilon .. pi+epsilon]
  texture Texture2D $= Disabled

showGhosts ghosts tops =
    mapM_ (\ g -> showGhost g tops) ghosts

ghostPhi = angleOfDirection . ghostOrientation
    
showGhost ghost tops = 
    preservingMatrix  $ do
      let trans = ghostPosition ghost
          phase = ghostPhase ghost
          phi =  ghostPhi ghost
      translate trans
      scale 0.3 0.3 (0.3 :: GLdouble)
      rotate (180*phi/pi-90) (Vector3 0 1 (0 :: GLfloat))
      blend $= Enabled
      blendFunc $= (SrcAlpha, One)
      depthMask $= Disabled
      callList (DisplayList (tops+phase+52))
      depthMask $= Enabled
      blend $= Disabled



animateGhost rand laby ghost target = 
    let speed                  = ghostSpeed ghost 
        dir                    = ghostOrientation ghost
        angle                  = angleOfDirection dir
        dx                     = speed * sin angle
        dz                     = speed * cos angle
        pos@(Vector3 x y z)    = ghostPosition ghost
        (nx, nz)               = (x+dx, z+dz)
        isMiddle1 c            = c' >= 0.45 && c' <= 0.55  where c'= c - ifloor c 
        isMiddle2              = isMiddle1 nx && isMiddle1 nz
        lpos                   = Pos3 (floor x, 0, floor z)
        flur                   = ways laby lpos
        dij                    = dijkstra laby target
        shorter p1 p2          = compare (dij ! p1) (dij !p2)  
        dbg l                  = l --trace (show (zip l (map (\x -> dij !x) l))) l
        best                   = head $ sortBy shorter flur
        bestDir                = if isMiddle2 
                                   then dirToNeighbor lpos best
                                   else dir
        (wx, wz)               = (nx+0.3*sin angle, nz +0.3 * cos angle)  
        rot                    = if odd rand then rotCW else rotCCW
        rangle                 = angleOfDirection (rot dir)
        randomTurn             = rand `mod` 25 == 0 && 
                                    let (tx, tz) = (x+sin rangle, z + cos rangle)  in
                                       not $ inWall laby (tx+1) (y+1) (tz+1)
        (newOrient, newPos)    = if inWall laby wx y wz  || randomTurn
                                   then (rot dir, pos)
                                   else (bestDir, Vector3 nx y nz)
        newSpeed                = if newOrient == dir  
                                    then min 0.020 (speed + 0.001)
                                    else 0.005
        ghostPhase'             = (ghostPhase ghost + 1) `mod` 51
        ghost'                  = ghost { ghostOrientation = newOrient,
                                          ghostSpeed = newSpeed,
                                          ghostPosition = newPos,
                                          ghostPhase = ghostPhase'}
    in ghost'