packages feed

IrrHaskell-0.1: sample.hs

module Main where
	
import Irrlicht
import Data.Time
import Data.Time.Clock.POSIX
import Memo1
import Control.Concurrent.Chan

--import SOE hiding (Region, Event)
--import qualified SOE as G (Region, Event)
import Animation (picToGraphic)
import Shape
import Picture

import Draw (xWin,yWin,intToFloat)

infixr 1 =>>, ->>
infixr 1 `untilB`, `switch`, `stepAccum`, `step`
infixr 4 <*, >*
infixl 0 .|.
infixr 3 &&*
infixr 2 ||*

type Caption = String
type Counter = Int

caption1, caption2, caption3, caption4 :: Behavior Caption
caption1    = constB "Initial Caption"
caption2	= constB "Any Key Pressed"
caption3    = constB "a Key Pressed"
caption4    = constB "b Key Pressed"

counter1 :: Behavior Counter
counter1    = constB 999

capt1 :: Behavior Caption
capt1 = caption1 `untilB` key ->> caption2

capt2 :: Behavior Caption
capt2 = caption1 `switch` (key =>> \c ->
           case c of 'a' -> caption3
                     'b' -> caption4
                     _   -> caption1  )


countBeh :: Behavior Counter
countBeh = (0 `stepAccum` key ->> (+1)) `untilB` when (time >* 10) ->> counter1

type Time = POSIXTime

data EventStruct = Key {
               char :: Char
             }
  deriving Show

type UserAction = EventStruct

data GameChan = GameChan {
  eventsChan :: Chan UserAction
}

initGameChan :: IO GameChan
initGameChan = do 
            eventsChan <- newChan
            return GameChan {eventsChan = eventsChan }

newtype Behavior a = Behavior (([Maybe UserAction],[Time]) -> [a])

newtype Event a = Event (([Maybe UserAction],[Time]) -> [Maybe a])

time :: Behavior Time
time = Behavior (\(_,ts) -> ts)

constB :: a -> Behavior a
constB x = Behavior (\_ -> repeat x)

($*) :: Behavior (a->b) -> Behavior a -> Behavior b
Behavior ff $* Behavior fb = Behavior (\uts -> zipWith ($) (ff uts) (fb uts))

lift0 :: a -> Behavior a
lift0 = constB

lift1 :: (a -> b) -> (Behavior a -> Behavior b)
lift1 f b1 = lift0 f $* b1

lift2 :: (a -> b -> c) -> (Behavior a -> Behavior b -> Behavior c)
lift2 f b1 b2 = lift1 f b1 $* b2

lift3 :: (a -> b -> c -> d) -> (Behavior a -> Behavior b -> Behavior c -> Behavior d)
lift3 f b1 b2 b3 = lift2 f b1 b2 $* b3

pairB :: Behavior a -> Behavior b -> Behavior (a,b)
pairB = lift2 (,)

fstB :: Behavior (a,b) -> Behavior a
fstB  = lift1 fst
sndB :: Behavior (a,b) -> Behavior b
sndB  = lift1 snd

shape :: Behavior Shape -> Behavior Region
shape   = lift1 Shape

ell, rec :: Behavior Float -> Behavior Float -> Behavior Region
ell x y = shape (lift2 Ellipse   x y) 
rec x y = shape (lift2 Rectangle x y)

translate :: (Behavior Float, Behavior Float) -> Behavior Region -> Behavior Region
translate (Behavior fx, Behavior fy) (Behavior fp) = Behavior (\uts -> zipWith3 aux (fx uts) (fy uts) (fp uts))
         where aux x y p = Translate (x,y) p

(>*),(<*) :: Ord a => Behavior a -> Behavior a -> Behavior Bool
(>*) = lift2 (>)
(<*) = lift2 (<)

(&&*),(||*) :: Behavior Bool -> Behavior Bool -> Behavior Bool
(&&*) = lift2 (&&)
(||*) = lift2 (||)

over :: Behavior Picture -> Behavior Picture -> Behavior Picture
over = lift2 Over

instance Fractional a => Fractional (Behavior a) where
  (/) = lift2 (/)
  fromRational = lift0 . fromRational

instance Num a => Num (Behavior a) where
  (+) = lift2 (+)
  (*) = lift2 (*)
  negate = lift1 negate
  abs = lift1 abs
  signum = lift1 signum
  fromInteger = lift0 . fromInteger

instance Show (Behavior a)  where
  showsPrec n a s = "<< Behavior >>"

instance Eq (Behavior a) where
  a1 == a2 = error "Can't compare behaviors."

Behavior fb `untilB` Event fe =
  memoB $ Behavior (\uts@(us,ts) -> loop us ts (fe uts) (fb uts))
    where loop (_:us) (_:ts) ~(e:es) (b:bs) =
            b : case e of 
                  Nothing             -> loop us ts es bs
                  Just (Behavior fb') -> fb' (us,ts)

memoB :: Behavior a -> Behavior a

memoB (Behavior fb) = Behavior (memo1 fb)

Behavior fb `switch` Event fe =
  memoB $ Behavior (\uts@(us,ts) -> loop us ts (fe uts) (fb uts))
    where loop (_:us) (_:ts) ~(e:es) ~(b:bs) = 
            b : case e of 
                  Nothing             -> loop us ts es bs
                  Just (Behavior fb') -> loop us ts es (fb' (us,ts))

(=>>) :: Event a -> (a->b) -> Event b

Event fe =>> f = Event (map (fmap f) . fe)

e ->> v = e =>> \_ -> v

unique :: (Show a, Eq a) => Event a -> Event a
unique (Event fe) =
      Event (\uts -> aux (fe uts))
      where aux xs = zipWith remdup (Nothing:xs) xs
            remdup x y | x==y      = Nothing
                       | otherwise = y

when :: Behavior Bool -> Event ()
when = unique . while

while :: Behavior Bool -> Event ()

while (Behavior fb) 
  = Event (\uts -> map aux (fb uts))
    where aux True  = Just ()
          aux False = Nothing

withElem  :: Event a -> [b] -> Event (a,b)
withElem (Event fe) bs = Event (\uts -> loop (fe uts) bs)
  where loop (Just a  : evs) (b:bs) = Just (a,b) : loop evs bs
        loop (Nothing : evs)    bs  = Nothing    : loop evs bs

withElem_ :: Event a -> [b] -> Event b
withElem_ e bs = e `withElem` bs =>> snd

(.|.) :: Event a -> Event a -> Event a
Event fe1 .|. Event fe2 
  = Event (\uts -> zipWith aux (fe1 uts) (fe2 uts))
      where aux           Nothing  Nothing  = Nothing
            aux (Just x) _        = Just x
            aux _        (Just y) = Just y

key :: Event Char
key = Event (\(uas,_) -> map getkey uas)
      where getkey (Just (Key ch)) = Just ch
            getkey _               = Nothing

snapshot :: Event a -> Behavior b -> Event (a,b)
Event fe `snapshot` Behavior fb
  = Event (\uts -> zipWith' aux (fe uts) (fb uts))
      where aux (Just x) y = Just (x, y)
            aux Nothing  _ = Nothing

zipWith' f ~(x:xs) ~(y:ys) = f x y : zipWith' f xs ys

snapshot_ :: Event a -> Behavior b -> Event b
snapshot_ e b = e `snapshot` b =>> snd

step :: a -> Event a -> Behavior a

a `step` e = constB a `switch` e =>> constB

stepAccum :: a -> Event (a->a) -> Behavior a

a `stepAccum` e = b 
   where b = a `step` (e `snapshot` b =>> uncurry ($))

reactimate :: GameChan -> Behavior Caption -> IO ()
reactimate gameCh franProg = do 
        (user,addEvents) <- windowUser gameCh
        addEvents
        let drawPic (Just p) = do
                running <- deviceRun
                videoBeginScene True True 255 200 200 200
                sceneDrawAll
                guiDrawAll
                deviceSetWindowCaption (show p)
                ch <- getCharEvent
                writeChan (eventsChan gameCh) (Key { char = ch })
                videoEndScene
                addEvents
            drawPic Nothing  = return ()
        mapM_ drawPic (runEvent (sample `snapshot_` franProg) user)
           
runEvent (Event fe) u = fe u           

sample :: Event ()
sample = Event (\(us,_) -> map aux us)
  where aux Nothing  = Just ()
        aux (Just _) = Nothing

    
-- have to create an instance of channel, globally accessible or something like that, replace Window type
maybeGetWindowEvent :: GameChan -> IO (Maybe UserAction)
maybeGetWindowEvent gameCh = do
    --print "maybeGetWindowEvent"
    noEvents <- isEmptyChan (eventsChan gameCh)
    if noEvents       
        then return Nothing
        else do
            event <- readChan (eventsChan gameCh)
            if ((char event) == ' ')
                then return Nothing
                else return (Just event)

-- adapt windowUser
windowUser :: GameChan -> IO (([Maybe UserAction], [POSIXTime]), IO ())
windowUser gameCh = do 
    (evs, addEv) <- makeStream
    t0 <- getPOSIXTime    
    let loop rt = do
        mev <- maybeGetWindowEvent gameCh
        --print mev
        case mev of
            Nothing -> return ()
            Just e  -> do addEv (Just e, rt)
                          loop rt                                
    let addEvents = do
        t <- getPOSIXTime
        let rt = t - t0
        loop rt
        addEv (Nothing, rt)
    return ((map fst evs, map snd evs), addEvents)

makeStream :: IO ([a], a -> IO ())
makeStream = do
    ch <- newChan
    contents <- getChanContents ch
    return (contents, writeChan ch)	                

gameLoop t0 gameCh= 
	do
		running <- deviceRun
		videoBeginScene True True 255 200 200 200
		sceneDrawAll
		guiDrawAll

		ch <- getCharEvent
		
		writeChan (eventsChan gameCh) (Key { char = ch })		
		
		videoEndScene
		if (running > 0)
			then gameLoop t0 gameCh
			else return ()

main = do
	irrCreateDevice EDT_OPENGL 640 480 False False False
	fileSystemAddZipFileArchive "/home/maciek/media/map-20kdm2.pk3"
	mesh <- sceneGetMesh "20kdm2.bsp"
	node <- sceneAddOctTreeSceneNode(mesh)
	sceneNodeSetPosition ((-1300), (-144), (-1249)) node
	sceneAddCameraSceneNodeFPS
	deviceSetEventReceiver 1
	
	gameCh <- initGameChan
	
	t0 <- getPOSIXTime
	--gameLoop t0 gameCh
	reactimate gameCh capt2
	deviceDrop