I am tying to create a simple animation using haskell
gloss. I want that at the first 4 seconds, every rectangle will change its color to a darker one. The problem is that after a relatively long time of linking, nothing really happens -
All rectangles appear and they don't change color
This is the following code i used -
window :: Display
window = InWindow "Simon" (width, height) (offset, offset)
background :: Color
background = black
data SimonGame = Game {
rectangleGreen::Picture,
rectangleRed::Picture,
rectangleBlue::Picture,
rectanglYellow::Picture
} deriving Show
initialState :: SimonGame
initialState = Game
{ rectangleGreen = translate (-100) (0) $ color green $ rectangleSolid 60 60,
rectangleRed = translate (100) (0) $ color red $ rectangleSolid 60 60,
rectangleBlue = translate (0) (100) $ color blue $ rectangleSolid 60 60,
rectanglYellow = translate (0) (-100) $ color yellow $ rectangleSolid 60 60
}
render :: SimonGame -> Picture
render game = pictures
[ rectangleGreen game,
rectangleRed game,
rectangleBlue game,
rectanglYellow game
]
updateBoard :: Float-> SimonGame -> SimonGame
updateBoard 1.0 game = game {
rectangleGreen = translate (-100) (0) $ color (dark green) $ rectangleSolid 60 60,
rectangleRed = translate (100) (0) $ color red $ rectangleSolid 60 60,
rectangleBlue = translate (0) (100) $ color blue $ rectangleSolid 60 60,
rectanglYellow = translate (0) (-100) $ color yellow $ rectangleSolid 60 60
}
updateBoard 2.0 game = game {
rectangleGreen = translate (-100) (0) $ color green $ rectangleSolid 60 60,
rectangleRed = translate (100) (0) $ color (dark red) $ rectangleSolid 60 60,
rectangleBlue = translate (0) (100) $ color blue $rectangleSolid 60 60,
rectanglYellow = translate (0) (-100) $ color yellow $rectangleSolid 60 60
}
updateBoard 3.0 game = game {
rectangleGreen = translate (-100) (0) $ color green $ rectangleSolid 60 60,
rectangleRed = translate (100) (0) $ color red $ rectangleSolid 60 60,
rectangleBlue = translate (0) (100) $ color (dark blue) $rectangleSolid 60 60,
rectanglYellow = translate (0) (-100) $ color yellow $rectangleSolid 60 60
}
updateBoard 4.0 game = game {
rectangleGreen = translate (-100) (0) $ color green $ rectangleSolid 60 60,
rectangleRed = translate (100) (0) $ color red $ rectangleSolid 60 60,
rectangleBlue = translate (0) (100) $ color blue $rectangleSolid 60 60,
rectanglYellow = translate (0) (-100) $ color (dark yellow) $rectangleSolid 60 60
}
updateBoard _ game = game
main :: IO ()
main = animate window background frame
where
frame :: Float -> Picture
frame seconds = render $ updateBoard seconds initialState
Never equality-check on floating point numbers. (Or, if you do, always assume the result may be False
even if the numbers are conceptually equal.)
In your case, that's not even conceptually the case, because animate
is called on some finite points in time; why would these include any exact integral number of seconds?
One simple way to get around this is to look up the rounded-to-whole-seconds time.
updateBoard :: Int -> SimonGame -> SimonGame
updateBoard 1 game = game { ... }
updateBoard 2 game = game { ... }
...
main = animate window background frame
where
frame :: Float -> Picture
frame seconds = render $ updateBoard (floor seconds) initialState