packages feed

layers-game-0.3: src/Rendering/Renderer.hs

module Rendering.Renderer where
import Control.Monad (forM_)
import qualified Graphics.Rendering.OpenGL.Raw as GL
import qualified Gamgine.Gfx as G
import Gamgine.Gfx ((<<), (<<<<), (<<<))
import qualified Gamgine.Coroutine as CO
import Gamgine.Math.Vect
import qualified Gamgine.State.RenderState as RS
import qualified GameData.Star as S
import qualified Rendering.Ressources as RR

type Finished = Bool
-- | a render routine which is called/used until it returns Finished=True,
--   used for temporary animations
type Renderer = CO.CoroutineM IO RS.RenderState Finished

runRenderer = CO.runCoroutineM

finishRenderer :: (Bool, Renderer)
finishRenderer = (True, CO.CoroutineM $ f)
   where f state = return (True, CO.CoroutineM $ f)

continueRenderer f = (False, CO.CoroutineM $ f)

mkRenderer rd = CO.CoroutineM rd


fadeOutStar :: Vect -> Double -> RS.RenderState -> IO (Finished, Renderer)
fadeOutStar pos factor rstate = do
   let texId   = RR.textureId RR.Star $ RS.ressources rstate
       (sx,sy) = S.starSize
       f'      = factor + 0.02
   if f' < 1
      then do
         renderStar pos (sx+f',sy+f') (1,1,1,1-f') texId
         return $ continueRenderer $ fadeOutStar pos f'

      else return finishRenderer

   where
      renderStar :: Vect -> (Double,Double) -> G.RGBA -> GL.GLuint -> IO ()
      renderStar (px:.py:._) (sx,sy) color texId = do
         let (minX, minY) = (px, py)
             (maxX, maxY) = (px + sx, py + sy)
         G.withTexture2d texId $
            G.withBlend GL.gl_SRC_ALPHA GL.gl_ONE_MINUS_SRC_ALPHA $
               G.withPrimitive GL.gl_QUADS $ do
                  let coords   = G.quadTexCoords 1 1
                      vertices = G.quad (minX,minY) (maxX,maxY)
                  GL.glColor4f <<<< color
                  forM_ (zip coords vertices) (\(c,v) -> do
                     GL.glTexCoord2f << c
                     GL.glVertex2f << v)


fadeOutEnemy :: Vect -> (Double,Double) -> RS.RenderState -> IO (Finished, Renderer)
fadeOutEnemy pos (sizeX, sizeY) rstate = do
   let texId = RR.textureId RR.Enemy $ RS.ressources rstate
   G.withPushedMatrix $ do
      GL.glTranslatef <<< G.xyz (sizeX * 0.5) (sizeY * 0.5) 0
      GL.glTranslatef <<< pos
      G.withTexture2d texId $
         G.withBlend GL.gl_SRC_ALPHA GL.gl_ONE_MINUS_SRC_ALPHA $
            G.withPrimitive GL.gl_QUADS $ do
               let coords   = G.quadTexCoords 1 1
                   vertices = G.quad (sizeX * (-0.5), sizeY * (-0.5)) (sizeX * 0.5, sizeY * 0.5)
               GL.glColor3f <<< G.rgb 1 1 1
               forM_ (zip coords vertices) (\(c,v) -> do
                  GL.glTexCoord2f << c
                  GL.glVertex2f << v)

   let sizeY' = sizeY - 0.05
   if sizeY' > 0
      then return $ continueRenderer $ fadeOutEnemy pos (sizeX, sizeY')
      else return finishRenderer