2014-11-21 58 views
1

http://pastebin.com/2CS1k1Zq如何獲得輸入遊戲循環在Haskell

在這場比賽中我需要得到步驟遊戲前進的每半秒左右,而偶爾讓輸入改變方向。這些與Haskell似乎無法做到的事情有沒有辦法做到?目前我有一個mv tread stall異常。

+1

可能重複http://stackoverflow.com/questions/19285691/how-do-i-write-a-game-loop-in- haskell) – 2014-11-21 16:43:06

+0

不,因爲我理解如何製作gameloop的基礎知識,我不明白的是你如何延遲你的遊戲或使其及時步入。還有如何獲得輸入。 – 2014-11-21 16:54:16

+0

你可能需要一個觀察者來檢查關鍵字。如何做到這一點取決於你的平臺,你可能需要做一些「FFI-ing」。一旦被覆蓋了,你的實際遊戲循環看起來就像是一個標準的Haskell遊戲循環。爲了使它可以播放,不要忘記延遲渲染部分(例如,使線程在遊戲步驟之間休眠,但要確保仍然可以輸入!)。如果你可以提到你的平臺,甚至標記它,這將是有益的(特別是因爲這似乎是一個控制檯遊戲)。 – MasterMastic 2014-11-21 17:10:39

回答

2

更新:在System.IO中找到hWaitForInput函數,它與waitFor基本相同。

以下是一些很大程度上基於this answer的代碼。

我所做的主要區別是等待按鍵的線程不直接執行getChar。在MVar中傳達的結果表示超時或按鍵已經發生。實際獲得角色是主線程的責任。這樣可以防止在讀取字符並將其放入MVar之間而導致char讀取線程中斷的情況下出現可能的競爭情況。

import Control.Concurrent 
import Control.Monad 
import Data.Maybe 
import System.IO 
import Control.Exception 

data Event = CharReady | TimedOut 

withRawStdin :: IO a -> IO a 
withRawStdin = bracket uncook restore . const 
    where 
    uncook = do 
     oldBuffering <- hGetBuffering stdin 
     oldEcho <- hGetEcho stdin 
     hSetBuffering stdin NoBuffering 
     hSetEcho stdin False 
     return (oldBuffering, oldEcho) 
    restore (oldBuffering, oldEcho) = do 
     hSetBuffering stdin oldBuffering 
     hSetEcho stdin oldEcho 

waitFor :: Int -> IO Event 
waitFor delay = do 
    done <- newEmptyMVar 
    withRawStdin . bracket (start done) cleanUp $ \_ -> takeMVar done 
    where 
    start done = do 
     t1 <- forkIO $ hLookAhead stdin >> putMVar done CharReady 
     t2 <- forkIO $ threadDelay delay >> putMVar done TimedOut 
     return (t1, t2) 
    cleanUp (t1, t2) = do 
     killThread t1 
     killThread t2 

loop state = do 
    if state <= 0 
    then putStrLn "Game over." 
    else do putStrLn $ "Rounds to go: " ++ show state 
      e <- waitFor 3000000 
      case e of 
       TimedOut -> do putStrLn "Too late!"; loop state 
       CharReady -> do c <- getChar -- should not block 
           if c == 'x' 
           then do putStrLn "Good job!"; loop (state-1) 
           else do putStrLn "Wrong key"; loop state 

main = loop 3 
的[我怎樣寫在Haskell遊戲循環?(
+0

Haskell新手在這裏,這幫助了我,謝謝。我嘗試使用hWaitForInput,但getChar變成阻塞,然後,不知道爲什麼。 – 2017-01-06 18:27:10