我正在尝试使用Haskell在SDL 2中绘制随机定位的矩形。IO monad真的让我抓狂,我无法让它工作。我已经准备好了SDL 2的样板代码和RectangleObject
的自定义数据类型,我想做的就是在main
函数中随机生成矩形,然后在appLoop
函数中绘制它们。
我得到的错误:
BadRandomRectangles.hs:17:61-85: error:
• Couldn't match expected type: [RectangleObject]
with actual type: IO [RectangleObject]
• In the fourth argument of ‘GameState’, namely
‘(createRandomRectangles 10)’
In the expression:
GameState
(V2 10 10) (V2 40 40) (V2 1 1) (createRandomRectangles 10)
In an equation for ‘gameState’:
gameState
= GameState
(V2 10 10) (V2 40 40) (V2 1 1) (createRandomRectangles 10)
|
17 | let gameState = GameState (V2 10 10) (V2 40 40) (V2 1 1) (createRandomRectangles 10) in
| ^^^^^^^^^^^^^^^^^^^^^^^^^
字符串
我的代码是:
{-# LANGUAGE OverloadedStrings #-}
import SDL
import System.Random
import Control.Monad (unless, replicateM)
import Foreign.C.Types (CInt)
data RectangleObject = RectangleObject { rectPosn :: V2 CInt, rectDim :: V2 CInt };
data GameState = GameState { posn :: V2 CInt, dim :: V2 CInt, vel :: V2 CInt, objects :: [RectangleObject] };
main :: IO ()
main = do
initializeAll
window <- createWindow "Rectangles" (defaultWindow { windowInitialSize = V2 640 480 })
renderer <- createRenderer window (-1) defaultRenderer
let gameState = GameState (V2 10 10) (V2 40 40) (V2 1 1) (createRandomRectangles 10) in
appLoop renderer gameState
destroyRenderer renderer
destroyWindow window
quit
appLoop :: Renderer -> GameState -> IO ()
appLoop renderer gameState = do
events <- pollEvents
clear renderer
rendererDrawColor renderer $= V4 0 0 0 255
-- Get the RectangleObjects from the game state and draw them
let objs = objects gameState
mapM_ (\(RectangleObject posn dim) -> fillRect renderer (Just $ Rectangle (P $ posn) dim)) objs
-- Fill a rectangle of size 1280x720 with black color
fillRect renderer (Just $ Rectangle (P $ V2 0 0) (V2 1280 720))
rendererDrawColor renderer $= V4 255 0 0 255
fillRect renderer (Just $ Rectangle (P $ posn gameState) (dim gameState))
present renderer
SDL.delay 16
unless qPressed (appLoop renderer (updateGameState vGameState))
updateGameState :: GameState -> GameState
updateGameState (GameState posn dim vel objs) =
GameState (posn + vel) dim vel objs
createRandomRectangles :: Int -> IO [RectangleObject]
createRandomRectangles n = replicateM n generateRandomRectangle
generateRandomRectangle :: IO RectangleObject
generateRandomRectangle = do
x <- randomRIO (1, 10)
y <- randomRIO (1, 10)
w <- randomRIO (1, 10)
h <- randomRIO (1, 10)
return $ RectangleObject (V2 x y) (V2 w h)
型
1条答案
按热度按时间brgchamk1#
你的主要问题是,在这段代码中:
字符串
表达式
createRandomRectangles 10
的类型是IO [RectangleObject]
,但GameState
对象中的第四个字段是纯[RectangleObject]
。将其重写为:
型
你的
main
函数应该进行类型检查。在你的代码中仍然有一些未定义的变量(
qPressed
和vGameState
)和渲染器中的一些逻辑错误(例如,你画了随机矩形,然后用一个黑色矩形覆盖它们来擦除它们)。而且,随机矩形太小了,它们只是在左上角显示为小光点。在做了一些调整之后,下面的代码似乎可以工作,甚至看起来像“游戏”。祝你好运!
型