layers-game-0.3: src/Entity/Render.hs
module Entity.Render where
import Control.Monad (when, forM_)
import qualified Graphics.Rendering.OpenGL.Raw as GL
import Gamgine.Control ((?))
import qualified Gamgine.Gfx as G
import qualified Gamgine.Math.Box as B
import Gamgine.Math.Vect as V
import Gamgine.Gfx ((<<), (<<<), (<<<<))
import qualified Gamgine.State.RenderState as RS
import qualified GameData.Entity as E
import qualified GameData.Player as P
import qualified GameData.Enemy as EN
import qualified GameData.Star as S
import qualified GameData.Animation as A
import qualified Entity.Position as EP
import qualified Entity.Velocity as EV
import qualified Rendering.Ressources as RR
interpolateFrame :: Double -> V.Vect -> V.Vect -> V.Vect
interpolateFrame nextFrameFraction position velocity =
position + (velocity * (V.v3 nextFrameFraction nextFrameFraction nextFrameFraction))
interpolateAnimationPos :: Double -> E.PositionOrAnimation -> V.Vect
interpolateAnimationPos _ (Left pos) = pos
interpolateAnimationPos nextFrameFraction (Right ani) =
interpolateFrame nextFrameFraction (A.currentPosition ani) (A.currentVelocity ani)
render :: E.Scope ->
RS.RenderState ->
E.Entity ->
IO ()
render _
RS.RenderState {RS.nextFrameFraction = frac, RS.ressources = res}
E.Player {E.playerPosition = pos, E.playerVelocity = velo@(vx:._),
E.playerOnBottom = onBot, E.playerWalkCycle = (_, angle)} =
renderWalk P.playerSize pos (onBot && vx /= 0 ? angle $ 0) (RR.textureId RR.Player res)
render _
RS.RenderState {RS.nextFrameFraction = frac, RS.ressources = res}
e@E.Enemy {E.enemyPosition = pos, E.enemyLiving = True, E.enemyWalkCycle = (_, angle)} = do
let (vx:._) = EV.velocity e
renderWalk EN.enemySize (interpolateAnimationPos frac pos) (vx /= 0 ? angle $ 0) (RR.textureId RR.Enemy res)
render _
RS.RenderState {RS.ressources = res}
E.Star {E.starPosition = pos, E.starCollected = False} =
G.withPushedMatrix $ do
GL.glTranslatef <<< pos
G.renderTexturedQuad S.starSize $ RR.textureId RR.Star res
render E.ActiveLayerScope
RS.RenderState {RS.nextFrameFraction = frac}
E.Platform {E.platformPosition = posOrAnim, E.platformBound = bound} = do
G.withPushedMatrix $ do
GL.glTranslatef <<< interpolateAnimationPos frac posOrAnim
GL.glColor3f <<< G.rgb 0.7 0.7 0.7 >> G.drawBox bound
GL.glLineWidth 4
G.withPolyMode GL.gl_LINE $ GL.glColor3f <<< G.rgb 0.4 0.4 0.4 >> G.drawBox bound
render E.InactiveLayerScope
RS.RenderState {RS.nextFrameFraction = frac}
E.Platform {E.platformPosition = posOrAnim, E.platformBound = bound} = do
G.withPushedMatrix $ do
GL.glTranslatef <<< interpolateAnimationPos frac posOrAnim
G.withBlend GL.gl_SRC_ALPHA GL.gl_ONE_MINUS_SRC_ALPHA $ do
GL.glColor4f <<<< G.rgba 0.0 0.0 0.1 0.2 >> G.drawBox bound
G.withPolyMode GL.gl_LINE $ GL.glColor4f <<<< G.rgba 0.0 0.0 0.3 0.2 >> G.drawBox bound
render _ _ _ = return ()
renderBound :: E.Bound -> IO ()
renderBound bound = do
GL.glColor3f <<< G.rgb 0 0 0
GL.glLineWidth 1
G.withPolyMode GL.gl_LINE $ G.drawBoxTree bound
renderWalk :: (Double,Double) -> Vect -> Double -> GL.GLuint -> IO ()
renderWalk (sizeX, sizeY) translation angle texture =
G.withPushedMatrix $ do
GL.glTranslatef <<< G.xyz (sizeX * 0.5) (sizeY * 0.5) 0
GL.glTranslatef <<< translation
GL.glRotatef <<<< G.xyzw angle 0 0 (-1)
G.withTexture2d texture $
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)