module Interface.WindowUpdate ( updateWindowWithPlayerAction, updateWindowWithGravityDelay ) where import Core.Game import Core.Commands import Control.Monad.State import Control.Concurrent import Graphics.UI.Gtk import Data.IORef import Debug.Trace ------------------------------------------------------------------------------------------------------------------------- -- Updating of the Game Window with an action performed by the player and with an action performed periodically updateWindowWithPlayerAction :: DrawingArea -> MVar Game -> State Game Bool -> IO () updateWindowWithPlayerAction drawArea gameMVar move = do oldGame <- takeMVar gameMVar let newGame = execState move oldGame widgetQueueDraw drawArea putMVar gameMVar newGame return () updateWindowWithGravityDelay :: DrawingArea -> MVar Game -> IO () updateWindowWithGravityDelay drawArea gameMVar = do -- retrieve game state oldGame <- takeMVar gameMVar -- attempt to move brick down let (result,moveDownGame) = runState shift_brick_down oldGame -- if it is not possible to move brick down lock it in place and... newGame = if result then moveDownGame else execState lock_clear_next_brick moveDownGame -- calculate new delay newDelay = (calculateGravityDelay.getGravityFromGame) newGame -- save new game state putMVar gameMVar newGame -- create a new one-time update for the screen by calling oneself timeoutAdd (updateWindowWithGravityDelay drawArea gameMVar >> return False) newDelay return () ------------------------------------------------------------------------------------------------------------------------- -- Delay Calculations calculateGravityDelay :: Int -> Int calculateGravityDelay g | g > 0 = 1000 `div` g | otherwise = ((abs g) + 1) * 1000 calculateComputerPlayDelay :: Int calculateComputerPlayDelay = 10