Movement works now.
- Movement works. Keys are read out by KeyCode thus independent from Keyboard-Layout On a normal quertz-layout they map like so: * e, s, d, f for movement * r, w for rotation * space/caps for up/down
This commit is contained in:
parent
55a873022b
commit
f3b218c44e
@ -17,7 +17,10 @@ executable Pioneers
|
|||||||
random >=1.0.1 && <1.1,
|
random >=1.0.1 && <1.1,
|
||||||
random >=1.0.1 && <1.1,
|
random >=1.0.1 && <1.1,
|
||||||
text >=0.11.3 && <0.12,
|
text >=0.11.3 && <0.12,
|
||||||
stm >=2.4.2 && <2.5
|
stm >=2.4.2 && <2.5,
|
||||||
|
transformers >=0.3.0 && <0.4,
|
||||||
|
List >=0.5.1 && <0.6,
|
||||||
|
List >=0.5.1 && <0.6
|
||||||
ghc-options: -Wall
|
ghc-options: -Wall
|
||||||
other-modules:
|
other-modules:
|
||||||
Map.Coordinates,
|
Map.Coordinates,
|
||||||
|
159
src/Main.hs
159
src/Main.hs
@ -6,7 +6,7 @@ import Graphics.UI.Gtk (AttrOp((:=)))
|
|||||||
import qualified Graphics.UI.Gtk.OpenGL as GtkGL
|
import qualified Graphics.UI.Gtk.OpenGL as GtkGL
|
||||||
|
|
||||||
import Graphics.Rendering.OpenGL as GL
|
import Graphics.Rendering.OpenGL as GL
|
||||||
import qualified Graphics.UI.Gtk.Gdk.Events as Event
|
import qualified Graphics.UI.Gtk.Gdk.EventM as Event
|
||||||
import qualified Data.Array.IArray as A
|
import qualified Data.Array.IArray as A
|
||||||
|
|
||||||
import Map.Coordinates
|
import Map.Coordinates
|
||||||
@ -21,6 +21,9 @@ import Prelude as P
|
|||||||
import Control.Monad
|
import Control.Monad
|
||||||
import Control.Concurrent
|
import Control.Concurrent
|
||||||
import Control.Concurrent.STM
|
import Control.Concurrent.STM
|
||||||
|
import System.IO.Unsafe (unsafePerformIO)
|
||||||
|
import GHC.Conc.Sync (unsafeIOToSTM)
|
||||||
|
import Control.Monad.IO.Class (liftIO)
|
||||||
|
|
||||||
data ProgramState = PS { keysPressed :: IntSet
|
data ProgramState = PS { keysPressed :: IntSet
|
||||||
, px :: GLfloat
|
, px :: GLfloat
|
||||||
@ -29,14 +32,18 @@ data ProgramState = PS { keysPressed :: IntSet
|
|||||||
, heading :: GLfloat
|
, heading :: GLfloat
|
||||||
, pitch :: GLfloat
|
, pitch :: GLfloat
|
||||||
, dx :: GLfloat
|
, dx :: GLfloat
|
||||||
|
, dy :: GLfloat
|
||||||
, dz :: GLfloat
|
, dz :: GLfloat
|
||||||
, dheading :: GLfloat
|
, dheading :: GLfloat
|
||||||
, dpitch :: GLfloat }
|
, dpitch :: GLfloat }
|
||||||
|
deriving (Show)
|
||||||
|
|
||||||
animationWaitTime = 3 :: Int
|
animationWaitTime = 3 :: Int
|
||||||
canvasWidth = 640 :: Int
|
canvasWidth = 1024 :: Int
|
||||||
canvasHeight = 480 :: Int
|
canvasHeight = 768 :: Int
|
||||||
|
deltaV = 0.10
|
||||||
|
deltaH = 0.5
|
||||||
|
deltaP = 0.15
|
||||||
|
|
||||||
-- TODO: Put render-stuff in render-module
|
-- TODO: Put render-stuff in render-module
|
||||||
|
|
||||||
@ -79,7 +86,7 @@ drawSphere = do
|
|||||||
(Sphere 1.0 48 48)
|
(Sphere 1.0 48 48)
|
||||||
|
|
||||||
-- OpenGL polygon-function for drawing stuff.
|
-- OpenGL polygon-function for drawing stuff.
|
||||||
display :: TVar ProgramState -> PlayMap -> IO ()
|
display :: MVar ProgramState -> PlayMap -> IO ()
|
||||||
display state t =
|
display state t =
|
||||||
let
|
let
|
||||||
tiles = P.map (prepareRenderTile t) (A.assocs t)
|
tiles = P.map (prepareRenderTile t) (A.assocs t)
|
||||||
@ -91,7 +98,7 @@ display state t =
|
|||||||
, pz = pz
|
, pz = pz
|
||||||
, pitch = pitch
|
, pitch = pitch
|
||||||
, heading = heading }
|
, heading = heading }
|
||||||
<- readTVarIO state
|
<- readMVar state
|
||||||
loadIdentity
|
loadIdentity
|
||||||
GL.rotate pitch (Vector3 1.0 0.0 0.0 :: Vector3 GLfloat)
|
GL.rotate pitch (Vector3 1.0 0.0 0.0 :: Vector3 GLfloat)
|
||||||
GL.rotate heading (Vector3 0.0 1.0 0.0 :: Vector3 GLfloat)
|
GL.rotate heading (Vector3 0.0 1.0 0.0 :: Vector3 GLfloat)
|
||||||
@ -104,6 +111,50 @@ display state t =
|
|||||||
mapM_ renderTile tiles
|
mapM_ renderTile tiles
|
||||||
return ()
|
return ()
|
||||||
|
|
||||||
|
updateCamera :: MVar ProgramState -> IO ()
|
||||||
|
updateCamera state = do
|
||||||
|
ps@PS { dx = dx
|
||||||
|
, dy = dy
|
||||||
|
, dz = dz
|
||||||
|
, px = px
|
||||||
|
, py = py
|
||||||
|
, pz = pz
|
||||||
|
, pitch = pitch
|
||||||
|
, heading = heading
|
||||||
|
, dpitch = dpitch
|
||||||
|
, dheading = dheading }
|
||||||
|
<- takeMVar state
|
||||||
|
|
||||||
|
d@((dx,dy,dz),(heading',pitch')) <-
|
||||||
|
if any (/= 0.0) [dx,dy,dz,dpitch,dheading] then
|
||||||
|
preservingMatrix $ do
|
||||||
|
putStrLn $ unwords $ P.map show [dx,dy,dz,dpitch,dheading]
|
||||||
|
loadIdentity
|
||||||
|
|
||||||
|
-- in direction of current heading and pitch
|
||||||
|
rotate (-heading) (Vector3 0.0 1.0 0.0 :: Vector3 GLfloat)
|
||||||
|
rotate (-pitch) (Vector3 1.0 0.0 0.0 :: Vector3 GLfloat)
|
||||||
|
|
||||||
|
-- perform motion
|
||||||
|
translate (Vector3 (-dx) (-dy) (-dz))
|
||||||
|
|
||||||
|
|
||||||
|
-- get changes in location components
|
||||||
|
mat <- get (matrix Nothing) :: IO (GLmatrix GLfloat)
|
||||||
|
comps <- getMatrixComponents ColumnMajor mat
|
||||||
|
putStrLn $ show $ comps
|
||||||
|
let [dx', dy', dz', _] = drop 12 comps
|
||||||
|
(heading', pitch') = (heading + dheading, pitch + dpitch)
|
||||||
|
return ((dx',dy',dz'),(heading',pitch'))
|
||||||
|
else
|
||||||
|
return ((0,0,0),(heading, pitch))
|
||||||
|
putMVar state ps { px = px + dx
|
||||||
|
, py = py + dy
|
||||||
|
, pz = pz + dz
|
||||||
|
, pitch = pitch'
|
||||||
|
, heading = heading'
|
||||||
|
}
|
||||||
|
|
||||||
--Adjust size to given dimensions
|
--Adjust size to given dimensions
|
||||||
reconfigure :: Int -> Int -> IO (Int, Int)
|
reconfigure :: Int -> Int -> IO (Int, Int)
|
||||||
reconfigure w h = do
|
reconfigure w h = do
|
||||||
@ -133,17 +184,77 @@ reshape dims = do
|
|||||||
matrixMode $= Modelview 0
|
matrixMode $= Modelview 0
|
||||||
loadIdentity
|
loadIdentity
|
||||||
|
|
||||||
|
keyEvent state press = do
|
||||||
|
code <- Event.eventHardwareKeycode
|
||||||
|
val <- Event.eventKeyVal
|
||||||
|
mods <- Event.eventModifier
|
||||||
|
name <- Event.eventKeyName
|
||||||
|
liftIO $ do
|
||||||
|
ps@PS { keysPressed = kp
|
||||||
|
, dx = dx
|
||||||
|
, dy = dy
|
||||||
|
, dz = dz
|
||||||
|
, px = px
|
||||||
|
, py = py
|
||||||
|
, pz = pz
|
||||||
|
, pitch = pitch
|
||||||
|
, heading = heading
|
||||||
|
, dpitch = dpitch
|
||||||
|
, dheading = dheading }
|
||||||
|
<- takeMVar state
|
||||||
|
-- Only process the key event if it is not a repeat
|
||||||
|
(ps',ret) <- if (fromIntegral code `member` kp && not press) ||
|
||||||
|
(fromIntegral code `notMember` kp && press)
|
||||||
|
then let
|
||||||
|
accept a = return (a, True)
|
||||||
|
deny a = return (a, False)
|
||||||
|
in do
|
||||||
|
-- keep list of pressed keys up2date
|
||||||
|
ps <- if not press
|
||||||
|
then return ps { keysPressed = fromIntegral code `IS.delete` kp }
|
||||||
|
else return ps { keysPressed = fromIntegral code `IS.insert` kp }
|
||||||
|
putStrLn $ unwords [name , show val, show code, show ps] -- trace (unwords [name , show val]) -- debugging
|
||||||
|
-- process keys
|
||||||
|
case press of
|
||||||
|
-- on PRESS only
|
||||||
|
True
|
||||||
|
| code == 9 -> Gtk.mainQuit >> deny ps
|
||||||
|
| code == 26 -> accept $ ps { dz = dz + deltaV }
|
||||||
|
| code == 40 -> accept $ ps { dz = dz - deltaV }
|
||||||
|
| code == 39 -> accept $ ps { dx = dx + deltaV }
|
||||||
|
| code == 41 -> accept $ ps { dx = dx - deltaV }
|
||||||
|
| code == 65 -> accept $ ps { dy = dy - deltaV }
|
||||||
|
| code == 66 -> accept $ ps { dy = dy + deltaV }
|
||||||
|
| code == 25 -> accept $ ps { dheading = dheading - deltaH }
|
||||||
|
| code == 27 -> accept $ ps { dheading = dheading + deltaH }
|
||||||
|
| otherwise -> deny ps
|
||||||
|
-- on RELEASE only
|
||||||
|
False
|
||||||
|
| code == 26 -> accept $ ps { dz = dz - deltaV }
|
||||||
|
| code == 40 -> accept $ ps { dz = dz + deltaV }
|
||||||
|
| code == 39 -> accept $ ps { dx = dx - deltaV }
|
||||||
|
| code == 41 -> accept $ ps { dx = dx + deltaV }
|
||||||
|
| code == 65 -> accept $ ps { dy = dy + deltaV }
|
||||||
|
| code == 66 -> accept $ ps { dy = dy - deltaV }
|
||||||
|
| code == 25 -> accept $ ps { dheading = dheading + deltaH }
|
||||||
|
| code == 27 -> accept $ ps { dheading = dheading - deltaH }
|
||||||
|
| otherwise -> deny ps
|
||||||
|
else return (ps, False)
|
||||||
|
putMVar state ps'
|
||||||
|
return ret
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = do
|
main = do
|
||||||
! terrain <- testmap
|
! terrain <- testmap
|
||||||
-- create TVar using unsafePerformIO -> currently no other thread -> OK
|
-- create TVar using unsafePerformIO -> currently no other thread -> OK
|
||||||
state <- newTVarIO $ PS { keysPressed = IS.empty
|
state <- newMVar $ PS { keysPressed = IS.empty
|
||||||
, px = 7.5
|
, px = 7.5
|
||||||
, py = 20
|
, py = 20
|
||||||
, pz = 15
|
, pz = 15
|
||||||
, heading = 0
|
, heading = 0
|
||||||
, pitch = 60
|
, pitch = 60
|
||||||
, dx = 0
|
, dx = 0
|
||||||
|
, dy = 0
|
||||||
, dz = 0
|
, dz = 0
|
||||||
, dheading = 0
|
, dheading = 0
|
||||||
, dpitch = 0}
|
, dpitch = 0}
|
||||||
@ -207,6 +318,7 @@ main = do
|
|||||||
|
|
||||||
-- Setup the animation
|
-- Setup the animation
|
||||||
Gtk.timeoutAddFull (do
|
Gtk.timeoutAddFull (do
|
||||||
|
updateCamera state
|
||||||
Gtk.widgetQueueDraw canvas
|
Gtk.widgetQueueDraw canvas
|
||||||
return True)
|
return True)
|
||||||
Gtk.priorityDefaultIdle animationWaitTime
|
Gtk.priorityDefaultIdle animationWaitTime
|
||||||
@ -224,34 +336,25 @@ main = do
|
|||||||
--Wrench them together
|
--Wrench them together
|
||||||
|
|
||||||
Gtk.set window [ Gtk.containerBorderWidth := 10,
|
Gtk.set window [ Gtk.containerBorderWidth := 10,
|
||||||
Gtk.containerChild := vbox,
|
|
||||||
Gtk.windowTitle := "Pioneer" ]
|
|
||||||
Gtk.set button [ Gtk.buttonLabel := "Hello World" ]
|
|
||||||
Gtk.set exitButton [ Gtk.buttonLabel := "Quit" ]
|
|
||||||
Gtk.set vbox [
|
|
||||||
Gtk.containerChild := canvas,
|
Gtk.containerChild := canvas,
|
||||||
Gtk.containerChild := button,
|
Gtk.windowTitle := "Pioneer" ]
|
||||||
Gtk.containerChild := exitButton,
|
|
||||||
Gtk.containerChild := label
|
|
||||||
]
|
|
||||||
|
|
||||||
|
------
|
||||||
|
-- Events
|
||||||
|
--
|
||||||
Gtk.afterClicked button (putStrLn "Hello World")
|
Gtk.afterClicked button (putStrLn "Hello World")
|
||||||
Gtk.afterClicked exitButton Gtk.mainQuit
|
Gtk.afterClicked exitButton Gtk.mainQuit
|
||||||
Gtk.onDestroy window Gtk.mainQuit
|
Gtk.onDestroy window Gtk.mainQuit
|
||||||
|
|
||||||
|
Gtk.on window Gtk.keyPressEvent $ keyEvent state True
|
||||||
|
|
||||||
|
Gtk.on window Gtk.keyReleaseEvent $ keyEvent state False
|
||||||
|
|
||||||
-- "reshape" event handler
|
-- "reshape" event handler
|
||||||
Gtk.onConfigure canvas $ \ (Event.Configure _ _ _ w h) -> do
|
Gtk.on canvas Gtk.configureEvent $ Event.tryEvent $ do
|
||||||
(w', h') <- reconfigure w h
|
(w, h) <- Event.eventSize
|
||||||
{- texW <- Gtk.pixbufGetWidth pb
|
(w', h') <- liftIO $ reconfigure w h
|
||||||
texH <- Gtk.pixbufGetHeight pb
|
liftIO $ Gtk.labelSetText label $ unwords ["Width:",show w',"Height:",show h']
|
||||||
texBPS <- Gtk.pixbufGetBitsPerSample pb
|
|
||||||
texRS <- Gtk.pixbufGetRowstride pb
|
|
||||||
texNCh <- Gtk.pixbufGetNChannels pb-}
|
|
||||||
Gtk.labelSetText label $ unwords ["Width:",show w',"Height:",show h'{- ,
|
|
||||||
"TexW:",show texW,"TexH:",show texH,
|
|
||||||
"BPS:",show texBPS,"RS:",show texRS,
|
|
||||||
"NCh:",show texNCh-}]
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
Gtk.widgetShowAll window
|
Gtk.widgetShowAll window
|
||||||
|
@ -50,8 +50,8 @@ parseTemplate (r:rs) t =
|
|||||||
(case T.head t of
|
(case T.head t of
|
||||||
'~' -> (0, Water)
|
'~' -> (0, Water)
|
||||||
'S' -> (0, Sand)
|
'S' -> (0, Sand)
|
||||||
'G' -> (fromIntegral (r `mod` 3) / 3,Grass)
|
'G' -> (fromIntegral (r `mod` 3)/2.0,Grass)
|
||||||
'M' -> (fromIntegral (r `mod` 3 + 2) / 3, Mountain)
|
'M' -> (fromIntegral (r `mod` 3 + 2)/2.0, Mountain)
|
||||||
_ -> error "invalid template format for map"
|
_ -> error "invalid template format for map"
|
||||||
):parseTemplate rs (T.tail t)
|
):parseTemplate rs (T.tail t)
|
||||||
parseTemplate [] _ = error "out of randoms.."
|
parseTemplate [] _ = error "out of randoms.."
|
||||||
|
Loading…
Reference in New Issue
Block a user