Vâng, đây là một phác thảo sơ bộ những gì tôi muốn làm:
import Graphics.UI.SDL.Time (getTicks)
import Control.Concurrent (threadDelay)
type Frame = [[Char]]
type Animation = [Frame]
displayFrame :: Frame -> IO()
displayFrame = mapM_ putStrLn
timeAction :: IO() -> IO Integer
timeAction act = do t <- getTicks
act
t' <- getTicks
return (fromIntegral $ t' - t)
addDelay :: Integer -> IO() -> IO()
addDelay hz act = do dt <- timeAction act
let delay = calcDelay dt hz
threadDelay $ fromInteger delay
calcDelay dt hz = max (frame_usec - dt_usec) 0
where frame_usec = 1000000 `div` hz
dt_usec = dt * 1000
runFrames :: Integer -> Animation -> IO()
runFrames hz frs = mapM_ (addDelay hz . displayFrame) frs
Rõ ràng là tôi đang sử dụng SDL đây hoàn toàn là getTicks
, bởi vì đó là những gì tôi đã sử dụng trước đó. Hãy thay thế bằng bất kỳ chức năng nào khác để có được thời gian hiện tại.
Đối số đầu tiên cho runFrames
là - như tên cho thấy - tốc độ khung hình trong hertz, tức là, khung hình trên giây. Chức năng runFrames
trước tiên chuyển đổi mỗi khung thành một hành động mà vẽ nó, sau đó đưa mỗi chức năng addDelay
, kiểm tra thời gian trước và sau khi chạy hành động, sau đó ngủ cho đến khi thời gian khung đã trôi qua.
Mã riêng của tôi trông khác một chút, vì tôi thường có một vòng lặp phức tạp hơn có thể thực hiện các công cụ khác, ví dụ, bỏ phiếu SDL cho sự kiện, xử lý nền, chuyển dữ liệu sang lần lặp tiếp theo, & c. Nhưng ý tưởng cơ bản là như nhau. Rõ ràng là điều tốt đẹp về cách tiếp cận này là, trong khi vẫn còn khá đơn giản, bạn sẽ có được tốc độ khung hình nhất quán khi có thể, với một phương tiện rõ ràng để xác định tốc độ mục tiêu.
Nguồn
2011-09-16 23:18:18
nếu bạn xóa màn hình, màn hình sẽ nhấp nháy. có một bộ phóng to ascii fractal cho haskell, kiểm tra nó. –