椿の日記

たぶんプログラムの話をします

スレッドを使ってみる

ゲームプログラムでは、メインスレッドからコントローラ入力監視のスレッドを独立させ、短い周期でポーリングし、得られたデータをキューに突っ込んでメインスレッドから扱えるようにすると良いと思います。
とりあえずHaskellでやってみるんで、まずシングルスレッドでテストしてみます。

import Graphics.Win32.Key
import System.Win32.Process (sleep)

main :: IO ()
main = do
    val <- getAsyncKeyState $ fromIntegral vK_LBUTTON
    print val
    sleep 500
    main

実行するとこんな感じ。

0
0
0
1         // 押してすぐ離した
0
32769     // 押した。そのまま離さない
32768     // 押したまま
32768     // 押したまま
0         // 離した
0
0

1ビット目が「押したフラグ」で16ビット目が「押し続けているフラグ」らしい。
そしてフォークさせます。概念的には、入力スレッドは[Int]を伸ばしていき、表示スレッドは[Int]を丸ごと取得する形です。

import Graphics.Win32.Key
import System.Win32.Process (sleep)

import Control.Concurrent
import Control.Concurrent.MVar

addQueue :: MVar [Int] -> Int -> IO ()
addQueue queue val = modifyMVar_ queue (\xs -> return $ xs ++ [val] )

getQueue :: MVar [Int] -> IO [Int]
getQueue queue = modifyMVar queue (\xs -> return $ ([],xs) )

inputThread :: MVar [Int] -> IO ()
inputThread queue = do
    val <- getAsyncKeyState $ fromIntegral vK_LBUTTON
    addQueue queue $ fromIntegral val
    sleep 100
    inputThread queue

printThread :: MVar [Int] -> IO ()
printThread queue = do
    vals <- getQueue queue
    print vals
    sleep 500
    printThread queue

main :: IO ()
main = do
    queue <- newMVar []
    forkIO $ inputThread queue
    printThread queue

そして実行。

[0,0]
[0,0]
[0,32769]
[32768,32768]
[32768,32768]
[32768,0]
[0,32769]
[32768,32768]
[32768,32768]
[32768,0]
[0,0]

…ん?何故2個しか出てこない…? 入力スレッドは100ms間隔、出力スレッドは500ms間隔で指定しているはずですが…
何が原因なんだろう。