In this game i need to get step the game forward every half a second or so while occasionally getting input to change direction. These too things seem impossible to do with haskell is there a way to do it? Currently I am having an mv tread stall exception.
Asked
Active
Viewed 631 times
1
-
1possible duplicate of [How do I write a game loop in Haskell?](http://stackoverflow.com/questions/19285691/how-do-i-write-a-game-loop-in-haskell) – Rein Henrichs Nov 21 '14 at 16:43
-
No because I understand the basics of how to make a gameloop what i dont understand is how you delay your game or make it step through in time. Also how to get input. – Kyle McKean Nov 21 '14 at 16:54
-
You're probably going to need an observer to check for keydowns. How to do it depends on your platform, you might need to do some "FFI-ing". Once that's covered, your actual game loop could look like a standard Haskell game loop. And to make it playable, don't forget to delay the rendering part (e.g. make the thread sleep between game-steps, but make sure you can still get input!). It would be helpful if you could mention your platform and even tag it (especially since this seems to be a console game). – MasterMastic Nov 21 '14 at 17:10
-
What is FFL ing? And i am running on a windows machine – Kyle McKean Nov 21 '14 at 18:35
-
I mean using the FFI (Foreign Function Interface). I suggest you learn what it is (within Haskell, of course). You could use it to import (impure) system calls (e.g. from the Win32 API) that will tell you when a key is pressed. – MasterMastic Nov 21 '14 at 19:31
-
@KyleMcKean By the way, when you're responding to someone in a comment that isn't to his question or answer, make sure to tag his name with a "@", like I did at the start of this comment. This will notify the person that you replied. So in this particular comment this isn't necessary because this is a comment to your question (but I did for demonstration). – MasterMastic Nov 21 '14 at 20:00
-
Sounds like this answer is relevant: http://stackoverflow.com/questions/9143041/block-until-keypress-or-given-time-of-day – ErikR Nov 21 '14 at 21:07
1 Answers
2
Update: Found the hWaitForInput function in System.IO which is essentially the same as waitFor.
Here is some code largely based on this answer.
The main difference I made is that the thread waiting for a key press does not perform the getChar directly. The result communicated in the MVar is an indication of timeout or that a key press has occurred. It is the responsibility of the main thread to actually get the character. This prevents a possible race condition in case the char reading thread is killed between getting the character and putting it into the MVar.
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 newbie here, this helped me, thank you. I tried using hWaitForInput but getChar becomes blocking then, don't know why. – Miloslav Číž Jan 06 '17 at 18:27