topkata-0.2: Topkata/Topka/Ghost.hs
module Topkata.Topka.Ghost where
import Graphics.UI.GLUT
import Topkata.Topka.Base
import Vector
import Labygen
-- 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)
callList (DisplayList (tops+phase+52))
blend $= Disabled
animateGhost rand laby ghost =
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)
(wx, wz) = (nx+0.3*sin angle, nz +0.3 * cos angle)
rot = if odd rand then rotCW else rotCCW
(newOrient, newPos) = if inWall laby (wx+1) (y+1) (wz+1)
then (rot dir, pos)
else (dir, Vector3 nx y nz)
newSpeed = if newOrient == dir
then min 0.039 (speed + 0.001)
else 0.005
ghost' = ghost { ghostOrientation = newOrient,
ghostSpeed = newSpeed,
ghostPosition = newPos }
in ghost'