summaryrefslogtreecommitdiff
path: root/src/Game/Main.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Game/Main.hs')
-rw-r--r--src/Game/Main.hs253
1 files changed, 29 insertions, 224 deletions
diff --git a/src/Game/Main.hs b/src/Game/Main.hs
index 5ba5bd7..7aeb2a5 100644
--- a/src/Game/Main.hs
+++ b/src/Game/Main.hs
@@ -9,8 +9,9 @@
-}
module Game (main) where
-import Game.LoadShaders
-import Game.Types
+import Game.Internal.LoadShaders
+import Game.Internal.Types
+import Game.Internal
import Control.Concurrent (threadDelay)
import Control.Lens ((^.), (+~), (&), (%~))
@@ -21,7 +22,7 @@ import Data.List (delete)
import Foreign.Marshal.Array (withArray)
import Foreign.Ptr (nullPtr, plusPtr)
import Foreign.Storable (sizeOf, Storable)
-import GHC.Float (double2Float)
+import GHC.Float (double2Float, int2Double)
import qualified Graphics.UI.GLFW as GLFW
import qualified Graphics.Rendering.OpenGL as GL
@@ -45,8 +46,8 @@ main = do
GLFW.windowHint $ GLFW.WindowHint'ContextVersionMinor 3
GLFW.windowHint $ GLFW.WindowHint'OpenGLProfile GLFW.OpenGLProfile'Core
- -- 4x MSAA
- GLFW.windowHint $ GLFW.WindowHint'Samples $ Just 4
+ -- MSAA
+ GLFW.windowHint $ GLFW.WindowHint'Samples $ Just 8
-- create window
monitor <- GLFW.getPrimaryMonitor
@@ -57,9 +58,10 @@ main = do
GLFW.setWindowCloseCallback window $ Just shutdownWindow
GLFW.setWindowSizeCallback window $ Just resizeWindow
GLFW.setKeyCallback window $ Just (keyPressed Nothing)
+ GLFW.setCursorInputMode window GLFW.CursorInputMode'Hidden
GLFW.setCursorPosCallback window $ Just (cursorPosHandler Nothing)
- (objects, program) <- initResources window
+ (objects, program) <- initResources window testVertices
-- init model
let
@@ -71,7 +73,7 @@ main = do
0 -- yaw
(V3 0 0 (-1)) -- reference vector
(V3 0 0 0) -- velocity
- 0.08 -- mouse sensitivity
+ 2 -- mouse sensitivity
16 -- strafe strength
12 -- jump strength
)
@@ -88,7 +90,7 @@ main = do
GLFW.setKeyCallback window $ Just $ keyPressed $ Just modelRef
GLFW.setCursorPosCallback window $ Just $ cursorPosHandler $ Just modelRef
- loop window (update 0) view modelRef
+ loop window 0 update view modelRef
--------------------------------------------------------------------------------
-- Arrays
@@ -104,157 +106,9 @@ testVertices =
]
--------------------------------------------------------------------------------
--- Shader creation and object initialisation
---------------------------------------------------------------------------------
-
--- | loads models, shaders
-initResources :: GLFW.Window -> IO ([Object], GL.Program)
-initResources window = do
- -- create objects
- testObject0 <- createObject (map (+(V3 (-1) (-1) (-1))) testVertices) 3 GL.TriangleStrip
- testObject1 <- createObject (map (+(V3 (1) (1) (1))) testVertices) 3 GL.TriangleStrip
- testObject2 <- createObject testVertices 3 GL.TriangleStrip
- let objects = [testObject0, testObject1, testObject2]
-
- -- load shaders
- program <- loadShaders
- [ ShaderInfo GL.VertexShader (StringSource vertShader)
- , ShaderInfo GL.FragmentShader (StringSource fragShader)
- ]
- GL.currentProgram $= Just program
-
- return (objects, program)
-
--- a_ vertex shader input
--- v_ varying
--- u_ uniform
--- o_ fragment shader output
-
--- | vertex shader
-vertShader :: String
-vertShader =
- "#version 330 core\n" ++
- "layout (location = 0) in vec3 a_vPos;\n" ++
- "uniform mat4 u_view;\n" ++
- "uniform mat4 u_projection;\n" ++
- "out vec3 v_pos;\n" ++
- "void main()\n" ++
- "{\n" ++
- " gl_Position = u_projection * u_view * vec4(a_vPos.xyz, 1.0);\n" ++
- " v_pos = a_vPos;\n" ++
- "}"
-
--- | fragment shader
-fragShader :: String
-fragShader =
- "#version 330 core\n" ++
- "out vec4 o_vColor;\n" ++
- "in vec3 v_pos;\n" ++
- "void main()\n" ++
- "{\n" ++
- " o_vColor = vec4(0.5 + 0.5 * v_pos, 1);\n" ++
- "}"
-
---------------------------------------------------------------------------------
--- Objects
---------------------------------------------------------------------------------
-
--- | calculates the size in memory of an array
-sizeOfArray :: (Storable a, Num b) => [a] -> b
-sizeOfArray [] = 0
-sizeOfArray (x:xs) = fromIntegral $ (*) (1 + length xs) $ sizeOf x
-
--- | loads a given array into a given attribute index
-createVBO
- :: Storable (a GL.GLfloat)
- => [a GL.GLfloat]
- -> GL.NumComponents
- -> GL.AttribLocation
- -> IO GL.BufferObject
-createVBO array numComponents attribLocation = do
- -- vbo for buffer
- buffer <- GL.genObjectName
- GL.bindBuffer GL.ArrayBuffer $= Just buffer
-
- -- populate buffer
- withArray
- array
- $ \ptr ->
- GL.bufferData GL.ArrayBuffer $= (sizeOfArray array, ptr, GL.StaticDraw)
-
- -- create attribute pointer to buffer
- GL.vertexAttribPointer attribLocation $=
- ( GL.ToFloat
- , GL.VertexArrayDescriptor
- numComponents
- GL.Float
- 0
- (plusPtr nullPtr 0)
- )
- GL.vertexAttribArray attribLocation $= GL.Enabled
-
- return buffer
-
--- | creates an object from a given array; deals with vbos and everything
-createObject
- :: Storable (a GL.GLfloat)
- => [a GL.GLfloat]
- -> GL.NumComponents
- -> GL.PrimitiveMode
- -> IO Object
-createObject array numComponents primitiveMode = do
- -- vao for object
- vao <- GL.genObjectName
- GL.bindVertexArrayObject $= Just vao
-
- -- vbo for vertices
- createVBO array numComponents $ GL.AttribLocation 0
-
- return
- (Object
- vao
- (fromIntegral $ length array)
- numComponents
- primitiveMode
- )
-
---------------------------------------------------------------------------------
-- Elm-like data structures
--------------------------------------------------------------------------------
--- | gameloop
-loop
- :: GLFW.Window -- ^ window to display on
- -> (Model -> Model) -- ^ update function
- -> (GLFW.Window -> Model -> IO ()) -- ^ view function
- -> IORef Model -- ^ model
- -> IO ()
-loop window update view modelRef = do
- -- start frame timer
- Just frameStart <- GLFW.getTime
-
- -- tick model
- modifyIORef' modelRef $ update
- model' <- readIORef modelRef
-
- -- view new model
- view window model'
-
- putStrLn $ (++) "pitch" $ show model'.camera.camPitch
- putStrLn $ (++) "yaw" $ show model'.camera.camYaw
-
- -- end frame timer, wait the difference between expected and actual
- Just frameEnd <- GLFW.getTime
- let
- dt = double2Float $ frameEnd - frameStart
- target = 1 / 60 :: Float
- when (dt < target) $ threadDelay $ floor $ (target - dt) * 1000000
- Just frameEnd' <- GLFW.getTime
- let
- dt' = double2Float $ frameEnd' - frameStart
-
- loop window (Game.update dt') view modelRef
-
-- | update function
update :: Float -> Model -> Model
update dt model =
@@ -275,8 +129,8 @@ updateAcceleration dt model =
zn = if elem GLFW.Key'W model.keys then 1 else 0
xp = if elem GLFW.Key'D model.keys then 1 else 0
xn = if elem GLFW.Key'A model.keys then 1 else 0
- x = xn - xp
- z = zn - zp
+ x = xp - xn
+ z = zp - zn
friction = V3 (1 - model.wprop.friction) 1 (1 - model.wprop.friction)
movement = L.normalize (V3 x 0 z) L.^* (dt * model.camera.strafeStrength)
movement' = L.rotate (L.axisAngle model.wprop.up model.camera.camYaw) movement
@@ -323,17 +177,19 @@ updateVelocity dt model =
updateCameraAngle :: Float -> Model -> Model
updateCameraAngle dt model =
let
- newPitch = model.camera.camPitch - model.camera.mouseSensitivity * dt * (double2Float $ snd model.cursorDeltaPos)
- newPitch' = if newPitch >= (pi / 2) then (0.9999 * pi / 2) else newPitch
- newPitch'' = if newPitch <= ((-1) * pi / 2) then ((-0.9999) * pi / 2) else newPitch
- newYaw = model.camera.camYaw + model.camera.mouseSensitivity * dt * (double2Float $ fst model.cursorDeltaPos)
- newYaw' = newYaw - (mod' newYaw pi)
+ scaleFactor = model.camera.mouseSensitivity * dt
+ newPitch = model.camera.camPitch -
+ scaleFactor * (double2Float $ snd model.cursorDeltaPos) -- mouse sensitivity, update pitch
+ newPitch' = if newPitch > 1.56 then 1.56 else newPitch
+ newPitch'' = if newPitch' < (-1.56) then (-1.56) else newPitch'
+ newYaw = model.camera.camYaw +
+ scaleFactor * (double2Float $ fst model.cursorDeltaPos)
in
model
{ cursorDeltaPos = (0, 0)
, camera = model.camera
- { camPitch = model.camera.camPitch + dt * (double2Float $ snd model.cursorDeltaPos)
- , camYaw = model.camera.camYaw + dt * (double2Float $ fst model.cursorDeltaPos)
+ { camPitch = newPitch''
+ , camYaw = newYaw
}
}
@@ -343,23 +199,6 @@ updateKeyPressed :: GLFW.Key -> Model -> Model
updateKeyPressed key model =
model { keys = key:model.keys }
--- | updates given a keyrelease. escape case is probably caught by GLFW in the
--- handler function itself
-updateKeyReleased :: GLFW.Key -> Model -> Model
-updateKeyReleased key model =
- model { keys = (delete key model.keys) }
-
-applyToTuples :: (a -> b -> c) -> (a, a) -> (b, b) -> (c, c)
-applyToTuples f (x, y) (a, b) = (f x a, f y b)
-
--- | updates cursor
-updateCursorPos :: Double -> Double -> Model -> Model
-updateCursorPos x y model =
- model
- { cursorPos = (x, y)
- , cursorDeltaPos = applyToTuples (-) model.cursorPos (x, y)
- }
-
-- | views the model
view :: GLFW.Window -> Model -> IO ()
view window model = do
@@ -371,15 +210,20 @@ view window model = do
GL.clearColor $= GL.Color4 1 0 1 1
GL.clear [GL.ColorBuffer, GL.DepthBuffer]
+ -- depth
+ GL.depthFunc $= Just GL.Less
+
-- apply transforms
let
- yaw = (L.rotate (L.axisAngle model.wprop.up model.camera.camYaw) model.camera.camReference)
+ pitch = model.camera.camPitch
+ yaw = model.camera.camYaw
+ forward = V3 (cos pitch * sin yaw) (sin pitch) (cos pitch * cos yaw)
viewMatrix =
L.lookAt
model.camera.camPos
- (model.camera.camPos + L.rotate (L.axisAngle (L.cross model.wprop.up yaw) model.camera.camPitch) yaw)
+ (model.camera.camPos - forward)
model.wprop.up
- projectionMatrix = L.perspective 1.5 (fromIntegral w / fromIntegral h) 0.1 100
+ projectionMatrix = L.perspective 1.5 (fromIntegral w / fromIntegral h) 0.01 10000
viewGLMatrix <- GL.newMatrix GL.RowMajor $ toGLMatrix viewMatrix :: IO (GL.GLmatrix GL.GLfloat)
viewLocation <- GL.get $ GL.uniformLocation model.program "u_view"
@@ -397,42 +241,3 @@ view window model = do
-- check for interrupts
GLFW.pollEvents
-
--- | draws objects
-drawObjects :: [Object] -> IO ([Object])
-drawObjects [] = return []
-drawObjects
- ((Object vao numVertices _ primitiveMode):objects) = do
- GL.bindVertexArrayObject $= Just vao
- GL.drawArrays primitiveMode 0 numVertices
- drawObjects objects
-
---------------------------------------------------------------------------------
--- interrupts
---------------------------------------------------------------------------------
-
--- | shuts down GLFW
-shutdownWindow :: GLFW.WindowCloseCallback
-shutdownWindow window = do
- GLFW.destroyWindow window
- GLFW.terminate
-
--- | resizes viewport with window
-resizeWindow :: GLFW.WindowSizeCallback
-resizeWindow _ _ _ = return ()
-
--- | handles key presses
-keyPressed :: Maybe (IORef Model) -> GLFW.KeyCallback
-keyPressed _ window GLFW.Key'Escape _ GLFW.KeyState'Pressed _ =
- shutdownWindow window
-keyPressed (Just modelRef) window key _ GLFW.KeyState'Pressed _ =
- modifyIORef' modelRef $ updateKeyPressed key
-keyPressed (Just modelRef) window key _ GLFW.KeyState'Released _ =
- modifyIORef' modelRef $ updateKeyReleased key
-keyPressed _ _ _ _ _ _ = return ()
-
--- | handles cursor position updates
-cursorPosHandler :: Maybe (IORef Model) -> GLFW.CursorPosCallback
-cursorPosHandler (Just modelRef) _ x y =
- modifyIORef' modelRef $ updateCursorPos x y
-cursorPosHandler Nothing _ _ _ = return ()