{-# LANGUAGE CPP #-}
{-# OPTIONS_HADDOCK hide #-}
{- | 
This FunGEn module contains some important game routines.
-}
{- 

FunGEN - Functional Game Engine
http://www.cin.ufpe.br/~haskell/fungen
Copyright (C) 2002  Andre Furtado <awbf@cin.ufpe.br>

This code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

-}


module Graphics.UI.Fungen.Game (
  Game, IOGame,
  -- ** creating
  createGame,
  -- ** IO utilities
  runIOGame, runIOGameM, liftIOtoIOGame, liftIOtoIOGame',
  -- ** game state
  getGameState, setGameState,
  getGameAttribute, setGameAttribute,
  -- ** game flags
  getGameFlags, setGameFlags,
  enableGameFlags, disableGameFlags,
  enableMapDrawing, disableMapDrawing,
  enableObjectsDrawing, disableObjectsDrawing,
  enableObjectsMoving, disableObjectsMoving,
  -- ** map operations
  drawMap, clearScreen, getTileFromIndex, getTileFromWindowPosition, setCurrentMapIndex,
  -- ** object operations
  getObjectManagers, setObjectManagers,
  drawAllObjects, drawObject, moveAllObjects, destroyObjects, destroyObject,
  getObjectsFromGroup, addObjectsToGroup, addObjectsToNewGroup, findObjectManager,findObject,
  getObjectName, getObjectGroupName, getObjectAsleep, getObjectSize,
  getObjectPosition, getObjectSpeed, getObjectAttribute,
  setObjectPosition, setObjectAsleep, setObjectSpeed, setObjectCurrentPicture, setObjectAttribute,
  replaceObject,
  reverseXSpeed, reverseYSpeed,
  -- ** collision detection
  objectsCollision, objectsFutureCollision,
  objectListObjectCollision, objectListObjectFutureCollision,
  objectTopMapCollision, objectBottomMapCollision, objectRightMapCollision, objectLeftMapCollision,
  pointsObjectCollision, pointsObjectListCollision,
  objectTopMapFutureCollision, objectBottomMapFutureCollision, objectRightMapFutureCollision, objectLeftMapFutureCollision,
  -- ** text operations
  printOnPrompt, printOnScreen, printText,
  -- ** random numbers
  randomFloat, randomInt, randomDouble,
  -- ** utilities
  showFPS,
  wait
) where

import Graphics.UI.Fungen.Types
import Graphics.UI.Fungen.Util
import Graphics.UI.Fungen.Loader
import Graphics.UI.Fungen.Text
import Graphics.UI.Fungen.Map
import Graphics.UI.Fungen.Objects
import Graphics.Rendering.OpenGL
import Graphics.UI.GLUT
import Control.Monad
import Data.IORef
import Text.Printf


-- | A game has the type @Game t s u v@, where 
--  
-- * t is the type of the game special attributes
-- 
-- * s is the type of the object special attributes
-- 
-- * u is the type of the game levels (state)
-- 
-- * v is the type of the map tile special attribute, in case we use a Tile Map as the background of our game
-- 
-- For a mnemonic, uh...
--
-- * t - /T/op-level game attribute type,
--
-- * s - /S/prite object attribute type,
--
-- * u - /U/pdating game state type,
--
-- * v - /V/icinity (map tile) attribute type.
-- 
-- Internally, a Game consists of:
--
-- * @gameMap       :: IORef (GameMap v)         -- a map (background)@
--
-- * @gameState     :: IORef u                   -- initial game state@
--
-- * @gameFlags     :: IORef GameFlags           -- initial game flags@
--
-- * @objManagers   :: IORef [(ObjectManager s)] -- some object managers@
--
-- * @textList      :: IORef [Text]              -- some texts@
--
-- * @quadricObj    :: QuadricPrimitive          -- a quadric thing@
--
-- * @windowConfig  :: IORef WindowConfig        -- a config for the main window@
--
-- * @gameAttribute :: IORef t                   -- a game attribute@
--
-- * @pictureList   :: IORef [TextureObject]     -- some pictures@
--
-- * @fpsInfo       :: IORef (Int,Int,Float)     -- only for debugging@
-- 
data Game t s u v = Game {
        forall t s u v. Game t s u v -> IORef (GameMap v)
gameMap       :: IORef (GameMap v), -- ^ a map (background)
        forall t s u v. Game t s u v -> IORef u
gameState     :: IORef u,           -- ^ initial game state
        forall t s u v. Game t s u v -> IORef GameFlags
gameFlags     :: IORef GameFlags,   -- ^ initial game flags
        forall t s u v. Game t s u v -> IORef [ObjectManager s]
objManagers   :: IORef [ObjectManager s], -- ^ some object managers
        forall t s u v. Game t s u v -> IORef [Text]
textList      :: IORef [Text],              -- ^ some texts
        forall t s u v. Game t s u v -> QuadricPrimitive
quadricObj    :: QuadricPrimitive,          -- ^ a quadric thing
        forall t s u v. Game t s u v -> IORef WindowConfig
windowConfig  :: IORef WindowConfig,        -- ^ a config for the main window
        forall t s u v. Game t s u v -> IORef t
gameAttribute :: IORef t,                   -- ^ a game attribute
        forall t s u v. Game t s u v -> IORef [TextureObject]
pictureList   :: IORef [TextureObject],     -- ^ some pictures
        forall t s u v. Game t s u v -> IORef (Int, Int, Float)
fpsInfo       :: IORef (Int,Int,Float)  -- only for debugging
        }

-- | IOGame is the monad in which game actions run. An IOGame action
-- takes a Game (with type parameters @t s u v@), performs some IO,
-- and returns an updated Game along with a result value (@a@):
--
-- @newtype IOGame t s u v a = IOG (Game  t s u v -> IO (Game t s u v,a))@
--
-- The name IOGame was chosen to remind that each action deals with a
-- Game, but an IO operation can also be performed between game
-- actions (such as the reading of a file or printing something in the
-- prompt).
newtype IOGame t s u v a = IOG (Game  t s u v -> IO (Game t s u v,a))

-- | Game flags: mapDrawing, objectsDrawing, objectsMoving
type GameFlags = (Bool,Bool,Bool)

----------------------------------
-- IOGame Monad definitions
----------------------------------
-- OBS.: all of this stuff is done to encapsulate Monad IO inside
--       Monad IOGame. Thanks to Jay Cox who suggested this solution.

bindST :: IOGame t s u v a -> (a -> IOGame t s u v b) -> IOGame t s u v b
bindST :: forall t s u v a b.
IOGame t s u v a -> (a -> IOGame t s u v b) -> IOGame t s u v b
bindST (IOG Game t s u v -> IO (Game t s u v, a)
x) a -> IOGame t s u v b
f =
   forall t s u v a.
(Game t s u v -> IO (Game t s u v, a)) -> IOGame t s u v a
IOG (Game t s u v -> IO (Game t s u v, a)
x forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> (\ (Game t s u v
s', a
v) -> let IOG Game t s u v -> IO (Game t s u v, b)
g = a -> IOGame t s u v b
f a
v in Game t s u v -> IO (Game t s u v, b)
g Game t s u v
s'))

unitST :: a -> IOGame t s u v a
unitST :: forall a t s u v. a -> IOGame t s u v a
unitST a
v = forall t s u v a.
(Game t s u v -> IO (Game t s u v, a)) -> IOGame t s u v a
IOG (\Game t s u v
s -> forall (m :: * -> *) a. Monad m => a -> m a
return (Game t s u v
s,a
v))

instance Functor (IOGame t s u v) where
  fmap :: forall a b. (a -> b) -> IOGame t s u v a -> IOGame t s u v b
fmap = forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM

instance Applicative (IOGame t s u v) where
  pure :: forall a. a -> IOGame t s u v a
pure  = forall a t s u v. a -> IOGame t s u v a
unitST
  <*> :: forall a b.
IOGame t s u v (a -> b) -> IOGame t s u v a -> IOGame t s u v b
(<*>) = forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
ap

instance Monad (IOGame t s u v) where
  >>= :: forall a b.
IOGame t s u v a -> (a -> IOGame t s u v b) -> IOGame t s u v b
(>>=) = forall t s u v a b.
IOGame t s u v a -> (a -> IOGame t s u v b) -> IOGame t s u v b
bindST

instance MonadFail (IOGame t s u v) where
  fail :: forall a. String -> IOGame t s u v a
fail String
s = forall a t s u v. IO a -> IOGame t s u v a
liftIOtoIOGame (forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
s)

runIOGame :: IOGame t s u v a -> Game t s u v -> IO (Game t s u v,a)  -- (a,Game t s u v) the state tuple
runIOGame :: forall t s u v a.
IOGame t s u v a -> Game t s u v -> IO (Game t s u v, a)
runIOGame (IOG Game t s u v -> IO (Game t s u v, a)
f) = Game t s u v -> IO (Game t s u v, a)
f

runIOGameM :: IOGame t s u v a -> Game t s u v -> IO ()
runIOGameM :: forall t s u v a. IOGame t s u v a -> Game t s u v -> IO ()
runIOGameM IOGame t s u v a
x Game t s u v
g = forall (f :: * -> *) a. Functor f => f a -> f ()
void (forall t s u v a.
IOGame t s u v a -> Game t s u v -> IO (Game t s u v, a)
runIOGame IOGame t s u v a
x Game t s u v
g)

liftIOtoIOGame      :: IO a -> IOGame t s u v a
liftIOtoIOGame :: forall a t s u v. IO a -> IOGame t s u v a
liftIOtoIOGame IO a
p    =
     forall t s u v a.
(Game t s u v -> IO (Game t s u v, a)) -> IOGame t s u v a
IOG forall a b. (a -> b) -> a -> b
$ \Game t s u v
s -> (do a
y <- IO a
p
                     forall (m :: * -> *) a. Monad m => a -> m a
return (Game t s u v
s,a
y))

liftIOtoIOGame'     :: (a -> IO ()) -> a -> IOGame t s u v ()
liftIOtoIOGame' :: forall a t s u v. (a -> IO ()) -> a -> IOGame t s u v ()
liftIOtoIOGame' a -> IO ()
p a
q =
     forall t s u v a.
(Game t s u v -> IO (Game t s u v, a)) -> IOGame t s u v a
IOG forall a b. (a -> b) -> a -> b
$ \Game t s u v
s -> (do a -> IO ()
p a
q
                     forall (m :: * -> *) a. Monad m => a -> m a
return (Game t s u v
s,()))

----------------------------------
-- get & set routines
----------------------------------

getMap :: IOGame t s u v (GameMap v)
getMap :: forall t s u v. IOGame t s u v (GameMap v)
getMap = forall t s u v a.
(Game t s u v -> IO (Game t s u v, a)) -> IOGame t s u v a
IOG ( \Game t s u v
game -> forall a. IORef a -> IO a
readIORef (forall t s u v. Game t s u v -> IORef (GameMap v)
gameMap Game t s u v
game) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \GameMap v
gm -> if forall t. GameMap t -> Bool
isMultiMap GameMap v
gm
                                                                then forall (m :: * -> *) a. Monad m => a -> m a
return (Game t s u v
game,forall t. GameMap t -> GameMap t
getCurrentMap GameMap v
gm)
                                                                else forall (m :: * -> *) a. Monad m => a -> m a
return (Game t s u v
game,GameMap v
gm))

getRealMap :: IOGame t s u v (GameMap v)
getRealMap :: forall t s u v. IOGame t s u v (GameMap v)
getRealMap = forall t s u v a.
(Game t s u v -> IO (Game t s u v, a)) -> IOGame t s u v a
IOG ( \Game t s u v
game -> forall a. IORef a -> IO a
readIORef (forall t s u v. Game t s u v -> IORef (GameMap v)
gameMap Game t s u v
game) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \GameMap v
gm -> forall (m :: * -> *) a. Monad m => a -> m a
return (Game t s u v
game,GameMap v
gm))

setRealMap :: GameMap v -> IOGame t s u v ()
setRealMap :: forall v t s u. GameMap v -> IOGame t s u v ()
setRealMap GameMap v
m = forall t s u v a.
(Game t s u v -> IO (Game t s u v, a)) -> IOGame t s u v a
IOG ( \Game t s u v
game -> forall a. IORef a -> a -> IO ()
writeIORef (forall t s u v. Game t s u v -> IORef (GameMap v)
gameMap Game t s u v
game) GameMap v
m forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *) a. Monad m => a -> m a
return (Game t s u v
game,()))


getGameState :: IOGame t s u v u
getGameState :: forall t s u v. IOGame t s u v u
getGameState = forall t s u v a.
(Game t s u v -> IO (Game t s u v, a)) -> IOGame t s u v a
IOG ( \Game t s u v
game -> forall a. IORef a -> IO a
readIORef (forall t s u v. Game t s u v -> IORef u
gameState Game t s u v
game) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \u
gs -> forall (m :: * -> *) a. Monad m => a -> m a
return (Game t s u v
game,u
gs))

setGameState :: u -> IOGame t s u v ()
setGameState :: forall u t s v. u -> IOGame t s u v ()
setGameState u
s = forall t s u v a.
(Game t s u v -> IO (Game t s u v, a)) -> IOGame t s u v a
IOG ( \Game t s u v
game -> forall a. IORef a -> a -> IO ()
writeIORef (forall t s u v. Game t s u v -> IORef u
gameState Game t s u v
game) u
s forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *) a. Monad m => a -> m a
return (Game t s u v
game,()))

getTextList :: IOGame t s u v [Text]
getTextList :: forall t s u v. IOGame t s u v [Text]
getTextList = forall t s u v a.
(Game t s u v -> IO (Game t s u v, a)) -> IOGame t s u v a
IOG ( \Game t s u v
game -> forall a. IORef a -> IO a
readIORef (forall t s u v. Game t s u v -> IORef [Text]
textList Game t s u v
game) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \[Text]
tl -> forall (m :: * -> *) a. Monad m => a -> m a
return (Game t s u v
game,[Text]
tl))

setTextList :: [Text] -> IOGame t s u v ()
setTextList :: forall t s u v. [Text] -> IOGame t s u v ()
setTextList [Text]
t = forall t s u v a.
(Game t s u v -> IO (Game t s u v, a)) -> IOGame t s u v a
IOG ( \Game t s u v
game -> forall a. IORef a -> a -> IO ()
writeIORef (forall t s u v. Game t s u v -> IORef [Text]
textList Game t s u v
game) [Text]
t forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *) a. Monad m => a -> m a
return (Game t s u v
game,()))

getGameFlags :: IOGame t s u v GameFlags
getGameFlags :: forall t s u v. IOGame t s u v GameFlags
getGameFlags = forall t s u v a.
(Game t s u v -> IO (Game t s u v, a)) -> IOGame t s u v a
IOG ( \Game t s u v
game -> forall a. IORef a -> IO a
readIORef (forall t s u v. Game t s u v -> IORef GameFlags
gameFlags Game t s u v
game) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \GameFlags
gf -> forall (m :: * -> *) a. Monad m => a -> m a
return (Game t s u v
game,GameFlags
gf))

setGameFlags :: GameFlags -> IOGame t s u v ()
setGameFlags :: forall t s u v. GameFlags -> IOGame t s u v ()
setGameFlags GameFlags
f = forall t s u v a.
(Game t s u v -> IO (Game t s u v, a)) -> IOGame t s u v a
IOG ( \Game t s u v
game -> forall a. IORef a -> a -> IO ()
writeIORef (forall t s u v. Game t s u v -> IORef GameFlags
gameFlags Game t s u v
game) GameFlags
f forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *) a. Monad m => a -> m a
return (Game t s u v
game,()))

getObjectManagers :: IOGame t s u v [ObjectManager s]
getObjectManagers :: forall t s u v. IOGame t s u v [ObjectManager s]
getObjectManagers = forall t s u v a.
(Game t s u v -> IO (Game t s u v, a)) -> IOGame t s u v a
IOG ( \Game t s u v
game -> forall a. IORef a -> IO a
readIORef (forall t s u v. Game t s u v -> IORef [ObjectManager s]
objManagers Game t s u v
game) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \[ObjectManager s]
om -> forall (m :: * -> *) a. Monad m => a -> m a
return (Game t s u v
game,[ObjectManager s]
om))

setObjectManagers :: [ObjectManager s] -> IOGame t s u v ()
setObjectManagers :: forall s t u v. [ObjectManager s] -> IOGame t s u v ()
setObjectManagers [ObjectManager s]
o = forall t s u v a.
(Game t s u v -> IO (Game t s u v, a)) -> IOGame t s u v a
IOG ( \Game t s u v
game -> forall a. IORef a -> a -> IO ()
writeIORef (forall t s u v. Game t s u v -> IORef [ObjectManager s]
objManagers Game t s u v
game) [ObjectManager s]
o forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *) a. Monad m => a -> m a
return (Game t s u v
game,()))

getQuadric :: IOGame t s u v QuadricPrimitive
getQuadric :: forall t s u v. IOGame t s u v QuadricPrimitive
getQuadric = forall t s u v a.
(Game t s u v -> IO (Game t s u v, a)) -> IOGame t s u v a
IOG ( \Game t s u v
game -> forall (m :: * -> *) a. Monad m => a -> m a
return (Game t s u v
game,forall t s u v. Game t s u v -> QuadricPrimitive
quadricObj Game t s u v
game) )

getPictureList :: IOGame t s u v [TextureObject]
getPictureList :: forall t s u v. IOGame t s u v [TextureObject]
getPictureList = forall t s u v a.
(Game t s u v -> IO (Game t s u v, a)) -> IOGame t s u v a
IOG ( \Game t s u v
game -> forall a. IORef a -> IO a
readIORef (forall t s u v. Game t s u v -> IORef [TextureObject]
pictureList Game t s u v
game) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \[TextureObject]
pl -> forall (m :: * -> *) a. Monad m => a -> m a
return (Game t s u v
game,[TextureObject]
pl))

getWindowConfig :: IOGame t s u v WindowConfig
getWindowConfig :: forall t s u v. IOGame t s u v WindowConfig
getWindowConfig = forall t s u v a.
(Game t s u v -> IO (Game t s u v, a)) -> IOGame t s u v a
IOG ( \Game t s u v
game -> forall a. IORef a -> IO a
readIORef (forall t s u v. Game t s u v -> IORef WindowConfig
windowConfig Game t s u v
game) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \WindowConfig
wc -> forall (m :: * -> *) a. Monad m => a -> m a
return (Game t s u v
game,WindowConfig
wc))

getGameAttribute :: IOGame t s u v t
getGameAttribute :: forall t s u v. IOGame t s u v t
getGameAttribute = forall t s u v a.
(Game t s u v -> IO (Game t s u v, a)) -> IOGame t s u v a
IOG ( \Game t s u v
game -> forall a. IORef a -> IO a
readIORef (forall t s u v. Game t s u v -> IORef t
gameAttribute Game t s u v
game) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \t
ga -> forall (m :: * -> *) a. Monad m => a -> m a
return (Game t s u v
game,t
ga))

setGameAttribute :: t -> IOGame t s u v ()
setGameAttribute :: forall t s u v. t -> IOGame t s u v ()
setGameAttribute t
ga = forall t s u v a.
(Game t s u v -> IO (Game t s u v, a)) -> IOGame t s u v a
IOG ( \Game t s u v
game -> forall a. IORef a -> a -> IO ()
writeIORef (forall t s u v. Game t s u v -> IORef t
gameAttribute Game t s u v
game) t
ga forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *) a. Monad m => a -> m a
return (Game t s u v
game,()))

-- internal use only
getFpsInfo :: IOGame t s u v (Int,Int,Float)
getFpsInfo :: forall t s u v. IOGame t s u v (Int, Int, Float)
getFpsInfo = forall t s u v a.
(Game t s u v -> IO (Game t s u v, a)) -> IOGame t s u v a
IOG ( \Game t s u v
game -> forall a. IORef a -> IO a
readIORef (forall t s u v. Game t s u v -> IORef (Int, Int, Float)
fpsInfo Game t s u v
game) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \(Int, Int, Float)
fpsi -> forall (m :: * -> *) a. Monad m => a -> m a
return (Game t s u v
game,(Int, Int, Float)
fpsi))

-- internal use only
setFpsInfo :: (Int,Int,Float) -> IOGame t s u v ()
setFpsInfo :: forall t s u v. (Int, Int, Float) -> IOGame t s u v ()
setFpsInfo (Int, Int, Float)
f = forall t s u v a.
(Game t s u v -> IO (Game t s u v, a)) -> IOGame t s u v a
IOG ( \Game t s u v
game -> forall a. IORef a -> a -> IO ()
writeIORef (forall t s u v. Game t s u v -> IORef (Int, Int, Float)
fpsInfo Game t s u v
game) (Int, Int, Float)
f forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *) a. Monad m => a -> m a
return (Game t s u v
game,()))

----------------------------------
-- initialization of the game
----------------------------------
createGame :: GameMap v -> [ObjectManager s] -> WindowConfig -> u -> t -> FilePictureList -> IO (Game t s u v)
createGame :: forall v s u t.
GameMap v
-> [ObjectManager s]
-> WindowConfig
-> u
-> t
-> FilePictureList
-> IO (Game t s u v)
createGame GameMap v
gMap [ObjectManager s]
objectManagers WindowConfig
winConf u
gState t
gAttrib FilePictureList
filePicList = do
        IORef (GameMap v)
gM <- forall a. a -> IO (IORef a)
newIORef GameMap v
gMap
        IORef u
gS <- forall a. a -> IO (IORef a)
newIORef u
gState
        IORef GameFlags
gF <- forall a. a -> IO (IORef a)
newIORef (Bool
True,Bool
True,Bool
True)
        IORef [ObjectManager s]
gO <- forall a. a -> IO (IORef a)
newIORef [ObjectManager s]
objectManagers
        IORef [Text]
gT <- forall a. a -> IO (IORef a)
newIORef []
        let gQ :: QuadricPrimitive
gQ = Radius -> Slices -> Slices -> QuadricPrimitive
Sphere Radius
0 Slices
0 Slices
0
        IORef WindowConfig
gW <- forall a. a -> IO (IORef a)
newIORef WindowConfig
winConf
        IORef t
gA <- forall a. a -> IO (IORef a)
newIORef t
gAttrib
        [TextureObject]
picList <- FilePictureList -> IO [TextureObject]
loadPictures FilePictureList
filePicList
        IORef [TextureObject]
gP <- forall a. a -> IO (IORef a)
newIORef [TextureObject]
picList
        IORef (Int, Int, Float)
gFPS <- forall a. a -> IO (IORef a)
newIORef (Int
0,Int
0,Float
0.0)
        forall (m :: * -> *) a. Monad m => a -> m a
return (Game {
            gameMap :: IORef (GameMap v)
gameMap       = IORef (GameMap v)
gM,
            gameState :: IORef u
gameState     = IORef u
gS,
            gameFlags :: IORef GameFlags
gameFlags     = IORef GameFlags
gF,
            objManagers :: IORef [ObjectManager s]
objManagers   = IORef [ObjectManager s]
gO,
            textList :: IORef [Text]
textList      = IORef [Text]
gT,
            quadricObj :: QuadricPrimitive
quadricObj    = QuadricPrimitive
gQ,
            windowConfig :: IORef WindowConfig
windowConfig  = IORef WindowConfig
gW,
            gameAttribute :: IORef t
gameAttribute = IORef t
gA,
            pictureList :: IORef [TextureObject]
pictureList   = IORef [TextureObject]
gP,
            fpsInfo :: IORef (Int, Int, Float)
fpsInfo       = IORef (Int, Int, Float)
gFPS
            })

-- | loads all of the pictures used in the game
loadPictures :: [(FilePath,InvList)] -> IO [TextureObject]
loadPictures :: FilePictureList -> IO [TextureObject]
loadPictures FilePictureList
pathsAndInvLists = do
        [AwbfBitmap]
bmps <- [(String, Maybe ColorList3)] -> IO [AwbfBitmap]
loadBitmapList (forall a b. (a -> b) -> [a] -> [b]
map (String, InvList) -> (String, Maybe ColorList3)
pathAndInv2color3List FilePictureList
pathsAndInvLists)
        [TextureObject]
texBmList <- forall a (m :: * -> *).
(GeneratableObjectName a, MonadIO m) =>
Int -> m [a]
genObjectNames (forall (t :: * -> *) a. Foldable t => t a -> Int
length [AwbfBitmap]
bmps)
        [TextureObject] -> [AwbfBitmap] -> IO ()
texStuff [TextureObject]
texBmList [AwbfBitmap]
bmps
        forall (m :: * -> *) a. Monad m => a -> m a
return [TextureObject]
texBmList

----------------------------------
-- map routines
----------------------------------

-- | draws the background map
drawMap :: IOGame t s u v ()
drawMap :: forall t s u v. IOGame t s u v ()
drawMap = do
    GameMap v
m <- forall t s u v. IOGame t s u v (GameMap v)
getMap
    [TextureObject]
p <- forall t s u v. IOGame t s u v [TextureObject]
getPictureList
    ((Int, Int)
_,(Int
winWidth, Int
winHeight),String
_) <- forall t s u v. IOGame t s u v WindowConfig
getWindowConfig
    forall a t s u v. IO a -> IOGame t s u v a
liftIOtoIOGame forall a b. (a -> b) -> a -> b
$ forall t. GameMap t -> Point2D -> [TextureObject] -> IO ()
drawGameMap GameMap v
m (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
winWidth, forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
winHeight) [TextureObject]
p

-- | returns a mapTile, given its pixel position (x,y) in the screen
getTileFromWindowPosition :: (GLdouble,GLdouble) -> IOGame t s u v (Tile v)
getTileFromWindowPosition :: forall t s u v. Point2D -> IOGame t s u v (Tile v)
getTileFromWindowPosition (Radius
preX,Radius
preY) = do
       GameMap v
m <- forall t s u v. IOGame t s u v (GameMap v)
getMap
       if forall t. GameMap t -> Bool
isTileMap GameMap v
m
            then let (Radius
tileXsize,Radius
tileYsize) = forall t. GameMap t -> Point2D
getTileMapTileSize GameMap v
m
                     (Radius
scrollX,Radius
scrollY) = forall t. GameMap t -> Point2D
getTileMapScroll GameMap v
m
                     (Radius
x,Radius
y) = (Radius
preX forall a. Num a => a -> a -> a
+ Radius
scrollX,Radius
preY forall a. Num a => a -> a -> a
+ Radius
scrollY)
                     (Radius
sX,Radius
sY) = forall t. GameMap t -> Point2D
getTileMapSize GameMap v
m
                 in if Radius
x forall a. Ord a => a -> a -> Bool
>= Radius
sX Bool -> Bool -> Bool
|| Radius
y forall a. Ord a => a -> a -> Bool
>= Radius
sY
                        then forall a. HasCallStack => String -> a
error (String
"Game.getTileFromWindowPosition error: pixel " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show (Radius
x,Radius
y) forall a. [a] -> [a] -> [a]
++ String
" out of map range!")
                        else forall t s u v. (Int, Int) -> IOGame t s u v (Tile v)
getTileFromIndex (forall a. Enum a => a -> Int
fromEnum (Radius
yforall a. Fractional a => a -> a -> a
/Radius
tileXsize),forall a. Enum a => a -> Int
fromEnum (Radius
xforall a. Fractional a => a -> a -> a
/Radius
tileYsize)) -- (x,y) window orientation is different than index (x,y)!
            else forall a. HasCallStack => String -> a
error String
"Game.getTileFromWindowPosition error: game map is not a tile map!"

-- | returns a mapTile, given its index (x,y) in the tile map
getTileFromIndex :: (Int,Int) -> IOGame t s u v (Tile v)
getTileFromIndex :: forall t s u v. (Int, Int) -> IOGame t s u v (Tile v)
getTileFromIndex (Int
x,Int
y) = do
        GameMap v
m <- forall t s u v. IOGame t s u v (GameMap v)
getMap
        if forall t. GameMap t -> Bool
isTileMap GameMap v
m
            then let matrix :: TileMatrix v
matrix = forall t. GameMap t -> TileMatrix t
getTileMapTileMatrix GameMap v
m
                     (Int
mapX,Int
mapY) = forall a. [[a]] -> (Int, Int)
matrixSize TileMatrix v
matrix
                 in if Int
mapX forall a. Ord a => a -> a -> Bool
>= Int
x Bool -> Bool -> Bool
&& Int
mapY forall a. Ord a => a -> a -> Bool
>= Int
y Bool -> Bool -> Bool
&& Int
x forall a. Ord a => a -> a -> Bool
>= Int
0 Bool -> Bool -> Bool
&& Int
y forall a. Ord a => a -> a -> Bool
>= Int
0
                        then forall (m :: * -> *) a. Monad m => a -> m a
return ( TileMatrix v
matrix forall a. [a] -> Int -> a
!! (Int
mapX forall a. Num a => a -> a -> a
- Int
x) forall a. [a] -> Int -> a
!! Int
y)
                        else forall a. HasCallStack => String -> a
error (String
"Game.getTileFromIndex error: tile index " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show (Int
x,Int
y) forall a. [a] -> [a] -> [a]
++ String
" out of map range!")
            else forall a. HasCallStack => String -> a
error String
"Game.getTileFromIndex error: game map is not a tile map!"

-- | paint the whole screen with a specified RGB color
clearScreen :: GLclampf -> GLclampf -> GLclampf -> IOGame t s u v ()
clearScreen :: forall t s u v. Float -> Float -> Float -> IOGame t s u v ()
clearScreen Float
r Float
g Float
b = forall a t s u v. IO a -> IOGame t s u v a
liftIOtoIOGame forall a b. (a -> b) -> a -> b
$ Float -> Float -> Float -> IO ()
clearGameScreen Float
r Float
g Float
b

-- | set the current map for a MultiMap
setCurrentMapIndex :: Int -> IOGame t s u v ()
setCurrentMapIndex :: forall t s u v. Int -> IOGame t s u v ()
setCurrentMapIndex Int
i = do
        GameMap v
m <- forall t s u v. IOGame t s u v (GameMap v)
getRealMap
        if forall t. GameMap t -> Bool
isMultiMap GameMap v
m
                then forall v t s u. GameMap v -> IOGame t s u v ()
setRealMap (forall t. GameMap t -> Int -> GameMap t
updateCurrentIndex GameMap v
m Int
i)
                else forall a. HasCallStack => String -> a
error String
"Game.setCurrentMapIndex error: you are not working with MultiMaps!"

----------------------------------
-- flags routines
----------------------------------

enableGameFlags :: IOGame t s u v ()
enableGameFlags :: forall t s u v. IOGame t s u v ()
enableGameFlags = forall t s u v. GameFlags -> IOGame t s u v ()
setGameFlags (Bool
True,Bool
True,Bool
True)

disableGameFlags :: IOGame t s u v ()
disableGameFlags :: forall t s u v. IOGame t s u v ()
disableGameFlags = forall t s u v. GameFlags -> IOGame t s u v ()
setGameFlags (Bool
False,Bool
False,Bool
False)

enableMapDrawing :: IOGame t s u v ()
enableMapDrawing :: forall t s u v. IOGame t s u v ()
enableMapDrawing = do
    (Bool
_,Bool
od,Bool
om) <- forall t s u v. IOGame t s u v GameFlags
getGameFlags
    forall t s u v. GameFlags -> IOGame t s u v ()
setGameFlags (Bool
True,Bool
od,Bool
om)

disableMapDrawing :: IOGame t s u v ()
disableMapDrawing :: forall t s u v. IOGame t s u v ()
disableMapDrawing = do
    (Bool
_,Bool
od,Bool
om) <- forall t s u v. IOGame t s u v GameFlags
getGameFlags
    forall t s u v. GameFlags -> IOGame t s u v ()
setGameFlags (Bool
False,Bool
od,Bool
om)

enableObjectsDrawing :: IOGame t s u v ()
enableObjectsDrawing :: forall t s u v. IOGame t s u v ()
enableObjectsDrawing = do
    (Bool
md,Bool
_,Bool
om) <- forall t s u v. IOGame t s u v GameFlags
getGameFlags
    forall t s u v. GameFlags -> IOGame t s u v ()
setGameFlags (Bool
md,Bool
True,Bool
om)

disableObjectsDrawing :: IOGame t s u v ()
disableObjectsDrawing :: forall t s u v. IOGame t s u v ()
disableObjectsDrawing = do
    (Bool
md,Bool
_,Bool
om) <- forall t s u v. IOGame t s u v GameFlags
getGameFlags
    forall t s u v. GameFlags -> IOGame t s u v ()
setGameFlags (Bool
md,Bool
False,Bool
om)

enableObjectsMoving :: IOGame t s u v ()
enableObjectsMoving :: forall t s u v. IOGame t s u v ()
enableObjectsMoving = do
    (Bool
md,Bool
od,Bool
_) <- forall t s u v. IOGame t s u v GameFlags
getGameFlags
    forall t s u v. GameFlags -> IOGame t s u v ()
setGameFlags (Bool
md,Bool
od,Bool
True)

disableObjectsMoving :: IOGame t s u v ()
disableObjectsMoving :: forall t s u v. IOGame t s u v ()
disableObjectsMoving = do
    (Bool
md,Bool
od,Bool
_) <- forall t s u v. IOGame t s u v GameFlags
getGameFlags
    forall t s u v. GameFlags -> IOGame t s u v ()
setGameFlags (Bool
md,Bool
od,Bool
False)

----------------------------------
-- objects routines
----------------------------------

-- | draws all visible objects
drawAllObjects :: IOGame t s u v ()
drawAllObjects :: forall t s u v. IOGame t s u v ()
drawAllObjects = do
    [ObjectManager s]
o <- forall t s u v. IOGame t s u v [ObjectManager s]
getObjectManagers
    QuadricPrimitive
q <- forall t s u v. IOGame t s u v QuadricPrimitive
getQuadric
    [TextureObject]
p <- forall t s u v. IOGame t s u v [TextureObject]
getPictureList
    forall a t s u v. IO a -> IOGame t s u v a
liftIOtoIOGame forall a b. (a -> b) -> a -> b
$ forall t.
[ObjectManager t] -> QuadricPrimitive -> [TextureObject] -> IO ()
drawGameObjects [ObjectManager s]
o QuadricPrimitive
q [TextureObject]
p

-- | draw one object
drawObject :: GameObject s -> IOGame t s u v ()
drawObject :: forall s t u v. GameObject s -> IOGame t s u v ()
drawObject GameObject s
o = do
    QuadricPrimitive
q <- forall t s u v. IOGame t s u v QuadricPrimitive
getQuadric
    [TextureObject]
p <- forall t s u v. IOGame t s u v [TextureObject]
getPictureList
    forall a t s u v. IO a -> IOGame t s u v a
liftIOtoIOGame forall a b. (a -> b) -> a -> b
$ forall t.
GameObject t -> QuadricPrimitive -> [TextureObject] -> IO ()
drawGameObject GameObject s
o QuadricPrimitive
q [TextureObject]
p

-- | changes objects position according to its speed
moveAllObjects :: IOGame t s u v ()
moveAllObjects :: forall t s u v. IOGame t s u v ()
moveAllObjects = do
    [ObjectManager s]
m <- forall t s u v. IOGame t s u v [ObjectManager s]
getObjectManagers
    let newManagers :: [ObjectManager s]
newManagers = forall t. [ObjectManager t] -> [ObjectManager t]
moveGameObjects [ObjectManager s]
m
    forall s t u v. [ObjectManager s] -> IOGame t s u v ()
setObjectManagers [ObjectManager s]
newManagers

-- | destroys objects from the game
destroyObjects :: [GameObject s] -> IOGame t s u v ()
destroyObjects :: forall s t u v. [GameObject s] -> IOGame t s u v ()
destroyObjects = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
(>>) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s t u v. GameObject s -> IOGame t s u v ()
destroyObject) (forall (m :: * -> *) a. Monad m => a -> m a
return ())

-- | destroys an object from the game
destroyObject :: GameObject s -> IOGame t s u v ()
destroyObject :: forall s t u v. GameObject s -> IOGame t s u v ()
destroyObject GameObject s
obj = do
    [ObjectManager s]
m <- forall t s u v. IOGame t s u v [ObjectManager s]
getObjectManagers
    let objName :: String
objName = forall t. GameObject t -> String
getGameObjectName GameObject s
obj
    String
mngName <- forall s t u v. GameObject s -> IOGame t s u v String
getObjectGroupName GameObject s
obj
    let newManagers :: [ObjectManager s]
newManagers = forall t.
String -> String -> [ObjectManager t] -> [ObjectManager t]
destroyGameObject String
objName String
mngName [ObjectManager s]
m
    forall s t u v. [ObjectManager s] -> IOGame t s u v ()
setObjectManagers [ObjectManager s]
newManagers

-- | returns the list of all objects from the group whose name is given
getObjectsFromGroup :: String -> IOGame t s u v [GameObject s]
getObjectsFromGroup :: forall t s u v. String -> IOGame t s u v [GameObject s]
getObjectsFromGroup String
mngName = do
        ObjectManager s
mng <- forall t s u v. String -> IOGame t s u v (ObjectManager s)
findObjectManager String
mngName
        forall (m :: * -> *) a. Monad m => a -> m a
return (forall t. ObjectManager t -> [GameObject t]
getObjectManagerObjects ObjectManager s
mng)

-- | adds an object to a previously created group
addObjectsToGroup :: [GameObject s] -> String -> IOGame t s u v ()
addObjectsToGroup :: forall s t u v. [GameObject s] -> String -> IOGame t s u v ()
addObjectsToGroup [GameObject s]
objs String
managerName = do
        -- manager <- findObjectManager managerName
        [ObjectManager s]
managers <- forall t s u v. IOGame t s u v [ObjectManager s]
getObjectManagers
        let newManagers :: [ObjectManager s]
newManagers = forall t.
[GameObject t] -> String -> [ObjectManager t] -> [ObjectManager t]
addObjectsToManager [GameObject s]
objs String
managerName [ObjectManager s]
managers
        forall s t u v. [ObjectManager s] -> IOGame t s u v ()
setObjectManagers [ObjectManager s]
newManagers

-- | adds an object to a new group
addObjectsToNewGroup :: [GameObject s] -> String -> IOGame t s u v ()
addObjectsToNewGroup :: forall s t u v. [GameObject s] -> String -> IOGame t s u v ()
addObjectsToNewGroup [GameObject s]
objs String
newMngName = do
        let newManager :: ObjectManager s
newManager = forall t. String -> [GameObject t] -> ObjectManager t
objectGroup String
newMngName [GameObject s]
objs
        [ObjectManager s]
managers <- forall t s u v. IOGame t s u v [ObjectManager s]
getObjectManagers
        forall s t u v. [ObjectManager s] -> IOGame t s u v ()
setObjectManagers (ObjectManager s
newManagerforall a. a -> [a] -> [a]
:[ObjectManager s]
managers)

-- | returns an object manager of the game, given its name (internal use)
findObjectManager :: String -> IOGame t s u v (ObjectManager s)
findObjectManager :: forall t s u v. String -> IOGame t s u v (ObjectManager s)
findObjectManager String
mngName = forall t. String -> [ObjectManager t] -> ObjectManager t
searchObjectManager String
mngName forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall t s u v. IOGame t s u v [ObjectManager s]
getObjectManagers

-- | returns an object of the game, given its name and is object manager name
findObject :: String -> String -> IOGame t s u v (GameObject s)
findObject :: forall t s u v. String -> String -> IOGame t s u v (GameObject s)
findObject String
objName String
mngName = do
    [ObjectManager s]
objectManagers <- forall t s u v. IOGame t s u v [ObjectManager s]
getObjectManagers
    let m :: ObjectManager s
m = forall t. String -> [ObjectManager t] -> ObjectManager t
searchObjectManager String
mngName [ObjectManager s]
objectManagers
    forall (m :: * -> *) a. Monad m => a -> m a
return (forall t. String -> ObjectManager t -> GameObject t
searchGameObject String
objName ObjectManager s
m)

-- | there is no need to search through the managers, because the name of an object is
-- never modified so the result of this function will always be safe.
getObjectName :: GameObject s -> IOGame t s u v String
getObjectName :: forall s t u v. GameObject s -> IOGame t s u v String
getObjectName GameObject s
o = forall (m :: * -> *) a. Monad m => a -> m a
return (forall t. GameObject t -> String
getGameObjectName GameObject s
o)

-- | because an object can have its group (manager) name modified, it is necessary
-- to search through the managers to find it, otherwise this functions won't be safe.
getObjectGroupName :: GameObject s -> IOGame t s u v String
getObjectGroupName :: forall s t u v. GameObject s -> IOGame t s u v String
getObjectGroupName GameObject s
o = do [ObjectManager s]
managers <- forall t s u v. IOGame t s u v [ObjectManager s]
getObjectManagers
                          let obj :: GameObject s
obj = forall t. GameObject t -> [ObjectManager t] -> GameObject t
findObjectFromId GameObject s
o [ObjectManager s]
managers
                          forall (m :: * -> *) a. Monad m => a -> m a
return (forall t. GameObject t -> String
getGameObjectManagerName GameObject s
obj)

-- | because an object can have its sleeping status modified, it is necessary
-- to search through the managers to find it, otherwise this functions won't be safe.
getObjectAsleep :: GameObject s -> IOGame t s u v Bool
getObjectAsleep :: forall s t u v. GameObject s -> IOGame t s u v Bool
getObjectAsleep GameObject s
o = do [ObjectManager s]
managers <- forall t s u v. IOGame t s u v [ObjectManager s]
getObjectManagers
                       let obj :: GameObject s
obj = forall t. GameObject t -> [ObjectManager t] -> GameObject t
findObjectFromId GameObject s
o [ObjectManager s]
managers
                       forall (m :: * -> *) a. Monad m => a -> m a
return (forall t. GameObject t -> Bool
getGameObjectAsleep GameObject s
obj)

-- | because an object can have its size modified, it is necessary
-- to search through the managers to find it, otherwise this functions won't be safe.
getObjectSize :: GameObject s -> IOGame t s u v (GLdouble,GLdouble)
getObjectSize :: forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectSize GameObject s
o = do [ObjectManager s]
managers <- forall t s u v. IOGame t s u v [ObjectManager s]
getObjectManagers
                     let obj :: GameObject s
obj = forall t. GameObject t -> [ObjectManager t] -> GameObject t
findObjectFromId GameObject s
o [ObjectManager s]
managers
                     forall (m :: * -> *) a. Monad m => a -> m a
return (forall t. GameObject t -> Point2D
getGameObjectSize GameObject s
obj)

-- | because an object can have its position modified, it is necessary
-- to search through the managers to find it, otherwise this functions won't be safe.
getObjectPosition :: GameObject s -> IOGame t s u v (GLdouble,GLdouble)
getObjectPosition :: forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectPosition GameObject s
o = do [ObjectManager s]
managers <- forall t s u v. IOGame t s u v [ObjectManager s]
getObjectManagers
                         let obj :: GameObject s
obj = forall t. GameObject t -> [ObjectManager t] -> GameObject t
findObjectFromId GameObject s
o [ObjectManager s]
managers
                         forall (m :: * -> *) a. Monad m => a -> m a
return (forall t. GameObject t -> Point2D
getGameObjectPosition GameObject s
obj)

-- | because an object can have its speed modified, it is necessary
-- to search through the managers to find it, otherwise this functions won't be safe.
getObjectSpeed :: GameObject s -> IOGame t s u v (GLdouble,GLdouble)
getObjectSpeed :: forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectSpeed GameObject s
o = do [ObjectManager s]
managers <- forall t s u v. IOGame t s u v [ObjectManager s]
getObjectManagers
                      let obj :: GameObject s
obj = forall t. GameObject t -> [ObjectManager t] -> GameObject t
findObjectFromId GameObject s
o [ObjectManager s]
managers
                      forall (m :: * -> *) a. Monad m => a -> m a
return (forall t. GameObject t -> Point2D
getGameObjectSpeed GameObject s
obj)

-- | because an object can have its attribute modified, it is necessary
-- to search through the managers to find it, otherwise this functions won't be safe.
getObjectAttribute :: GameObject s -> IOGame t s u v s
getObjectAttribute :: forall s t u v. GameObject s -> IOGame t s u v s
getObjectAttribute GameObject s
o = do [ObjectManager s]
managers <- forall t s u v. IOGame t s u v [ObjectManager s]
getObjectManagers
                          let obj :: GameObject s
obj = forall t. GameObject t -> [ObjectManager t] -> GameObject t
findObjectFromId GameObject s
o [ObjectManager s]
managers
                          forall (m :: * -> *) a. Monad m => a -> m a
return (forall t. GameObject t -> t
getGameObjectAttribute GameObject s
obj)

-- | changes the sleeping status of an object, given its new status
setObjectAsleep :: Bool -> GameObject s -> IOGame t s u v ()
setObjectAsleep :: forall s t u v. Bool -> GameObject s -> IOGame t s u v ()
setObjectAsleep Bool
asleep GameObject s
obj = forall s t u v.
GameObject s -> (GameObject s -> GameObject s) -> IOGame t s u v ()
replaceObject GameObject s
obj (forall t. Bool -> GameObject t -> GameObject t
updateObjectAsleep Bool
asleep)

-- | changes the position of an object, given its new position
setObjectPosition :: (GLdouble,GLdouble) -> GameObject s -> IOGame t s u v ()
setObjectPosition :: forall s t u v. Point2D -> GameObject s -> IOGame t s u v ()
setObjectPosition Point2D
pos GameObject s
obj = forall s t u v.
GameObject s -> (GameObject s -> GameObject s) -> IOGame t s u v ()
replaceObject GameObject s
obj (forall t. Point2D -> GameObject t -> GameObject t
updateObjectPosition Point2D
pos)

-- | changes the speed of an object, given its new speed
setObjectSpeed :: (GLdouble,GLdouble) -> GameObject s -> IOGame t s u v ()
setObjectSpeed :: forall s t u v. Point2D -> GameObject s -> IOGame t s u v ()
setObjectSpeed Point2D
speed GameObject s
obj = forall s t u v.
GameObject s -> (GameObject s -> GameObject s) -> IOGame t s u v ()
replaceObject GameObject s
obj (forall t. Point2D -> GameObject t -> GameObject t
updateObjectSpeed Point2D
speed)

-- | changes the current picture of a multitextured object
setObjectCurrentPicture :: Int -> GameObject s -> IOGame t s u v ()
setObjectCurrentPicture :: forall s t u v. Int -> GameObject s -> IOGame t s u v ()
setObjectCurrentPicture Int
n GameObject s
obj = do
        [TextureObject]
picList <- forall t s u v. IOGame t s u v [TextureObject]
getPictureList
        forall s t u v.
GameObject s -> (GameObject s -> GameObject s) -> IOGame t s u v ()
replaceObject GameObject s
obj (forall t. Int -> Int -> GameObject t -> GameObject t
updateObjectPicture Int
n (forall (t :: * -> *) a. Foldable t => t a -> Int
length [TextureObject]
picList forall a. Num a => a -> a -> a
- Int
1))

-- | changes the attribute of an object, given its new attribute
setObjectAttribute :: s -> GameObject s -> IOGame t s u v ()
setObjectAttribute :: forall s t u v. s -> GameObject s -> IOGame t s u v ()
setObjectAttribute s
a GameObject s
obj = forall s t u v.
GameObject s -> (GameObject s -> GameObject s) -> IOGame t s u v ()
replaceObject GameObject s
obj (forall t. t -> GameObject t -> GameObject t
updateObjectAttribute s
a)

-- | replaces an object by a new one, given the old object and the function that must be applied to it.
replaceObject :: GameObject s -> (GameObject s -> GameObject s) -> IOGame t s u v ()
replaceObject :: forall s t u v.
GameObject s -> (GameObject s -> GameObject s) -> IOGame t s u v ()
replaceObject GameObject s
obj GameObject s -> GameObject s
f = do
    String
managerName <- forall s t u v. GameObject s -> IOGame t s u v String
getObjectGroupName GameObject s
obj
    [ObjectManager s]
oldManagers <- forall t s u v. IOGame t s u v [ObjectManager s]
getObjectManagers
    let objectId :: Integer
objectId = forall t. GameObject t -> Integer
getGameObjectId GameObject s
obj
        newManagers :: [ObjectManager s]
newManagers = forall t.
(GameObject t -> GameObject t)
-> Integer -> String -> [ObjectManager t] -> [ObjectManager t]
updateObject GameObject s -> GameObject s
f Integer
objectId String
managerName [ObjectManager s]
oldManagers
    forall s t u v. [ObjectManager s] -> IOGame t s u v ()
setObjectManagers [ObjectManager s]
newManagers

reverseXSpeed :: GameObject s -> IOGame t s u v ()
reverseXSpeed :: forall s t u v. GameObject s -> IOGame t s u v ()
reverseXSpeed  GameObject s
o = do (Radius
vX,Radius
vY) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectSpeed GameObject s
o
                      forall s t u v. Point2D -> GameObject s -> IOGame t s u v ()
setObjectSpeed (-Radius
vX,Radius
vY) GameObject s
o

reverseYSpeed :: GameObject s -> IOGame t s u v ()
reverseYSpeed :: forall s t u v. GameObject s -> IOGame t s u v ()
reverseYSpeed GameObject s
o = do (Radius
vX,Radius
vY) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectSpeed GameObject s
o
                     forall s t u v. Point2D -> GameObject s -> IOGame t s u v ()
setObjectSpeed (Radius
vX,-Radius
vY) GameObject s
o

-----------------------
-- collision routines
-----------------------

-- | checks the collision between an object and the top of the map
objectTopMapCollision :: GameObject s -> IOGame t s u v Bool
objectTopMapCollision :: forall s t u v. GameObject s -> IOGame t s u v Bool
objectTopMapCollision GameObject s
o = do
    Bool
asleep <- forall s t u v. GameObject s -> IOGame t s u v Bool
getObjectAsleep GameObject s
o
    if Bool
asleep
        then forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
        else do GameMap v
m <- forall t s u v. IOGame t s u v (GameMap v)
getMap
                (Radius
_,Radius
pY) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectPosition GameObject s
o
                (Radius
_,Radius
sY) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectSize GameObject s
o
                let (Radius
_,Radius
mY) = forall t. GameMap t -> Point2D
getMapSize GameMap v
m
                forall (m :: * -> *) a. Monad m => a -> m a
return (Radius
pY forall a. Num a => a -> a -> a
+ Radius
sYforall a. Fractional a => a -> a -> a
/Radius
2 forall a. Ord a => a -> a -> Bool
> forall a b. (Real a, Fractional b) => a -> b
realToFrac Radius
mY)

-- | checks the collision between an object and the top of the map in the next game cicle
objectTopMapFutureCollision :: GameObject s -> IOGame t s u v Bool
objectTopMapFutureCollision :: forall s t u v. GameObject s -> IOGame t s u v Bool
objectTopMapFutureCollision GameObject s
o = do
    Bool
asleep <- forall s t u v. GameObject s -> IOGame t s u v Bool
getObjectAsleep GameObject s
o
    if Bool
asleep
        then forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
        else do GameMap v
m <- forall t s u v. IOGame t s u v (GameMap v)
getMap
                (Radius
_,Radius
pY) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectPosition GameObject s
o
                (Radius
_,Radius
vY) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectSpeed GameObject s
o
                (Radius
_,Radius
sY) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectSize GameObject s
o
                let (Radius
_,Radius
mY) = forall t. GameMap t -> Point2D
getMapSize GameMap v
m
                forall (m :: * -> *) a. Monad m => a -> m a
return (Radius
pY forall a. Num a => a -> a -> a
+ Radius
sYforall a. Fractional a => a -> a -> a
/Radius
2 forall a. Num a => a -> a -> a
+ Radius
vY forall a. Ord a => a -> a -> Bool
> forall a b. (Real a, Fractional b) => a -> b
realToFrac Radius
mY)

-- | checks the collision between an object and the bottom of the map
objectBottomMapCollision :: GameObject s -> IOGame t s u v Bool
objectBottomMapCollision :: forall s t u v. GameObject s -> IOGame t s u v Bool
objectBottomMapCollision GameObject s
o = do
    Bool
asleep <- forall s t u v. GameObject s -> IOGame t s u v Bool
getObjectAsleep GameObject s
o
    if Bool
asleep
        then forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
        else do (Radius
_,Radius
pY) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectPosition GameObject s
o
                (Radius
_,Radius
sY) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectSize GameObject s
o
                forall (m :: * -> *) a. Monad m => a -> m a
return (Radius
pY forall a. Num a => a -> a -> a
- Radius
sYforall a. Fractional a => a -> a -> a
/Radius
2 forall a. Ord a => a -> a -> Bool
< Radius
0)

-- | checks the collision between an object and the bottom of the map in the next game cicle
objectBottomMapFutureCollision :: GameObject s -> IOGame t s u v Bool
objectBottomMapFutureCollision :: forall s t u v. GameObject s -> IOGame t s u v Bool
objectBottomMapFutureCollision GameObject s
o = do
    Bool
asleep <- forall s t u v. GameObject s -> IOGame t s u v Bool
getObjectAsleep GameObject s
o
    if Bool
asleep
        then forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
        else do (Radius
_,Radius
pY) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectPosition GameObject s
o
                (Radius
_,Radius
sY) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectSize GameObject s
o
                (Radius
_,Radius
vY) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectSpeed GameObject s
o
                forall (m :: * -> *) a. Monad m => a -> m a
return (Radius
pY forall a. Num a => a -> a -> a
- Radius
sYforall a. Fractional a => a -> a -> a
/Radius
2 forall a. Num a => a -> a -> a
+ Radius
vY forall a. Ord a => a -> a -> Bool
< Radius
0)

-- | checks the collision between an object and the right side of the map
objectRightMapCollision :: GameObject s -> IOGame t s u v Bool
objectRightMapCollision :: forall s t u v. GameObject s -> IOGame t s u v Bool
objectRightMapCollision GameObject s
o = do
    Bool
asleep <- forall s t u v. GameObject s -> IOGame t s u v Bool
getObjectAsleep GameObject s
o
    if Bool
asleep
        then forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
        else do GameMap v
m <- forall t s u v. IOGame t s u v (GameMap v)
getMap
                (Radius
pX,Radius
_) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectPosition GameObject s
o
                (Radius
sX,Radius
_) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectSize GameObject s
o
                let (Radius
mX,Radius
_) = forall t. GameMap t -> Point2D
getMapSize GameMap v
m
                forall (m :: * -> *) a. Monad m => a -> m a
return (Radius
pX forall a. Num a => a -> a -> a
+ Radius
sXforall a. Fractional a => a -> a -> a
/Radius
2 forall a. Ord a => a -> a -> Bool
> forall a b. (Real a, Fractional b) => a -> b
realToFrac Radius
mX)

-- | checks the collision between an object and the right side of the map in the next game cicle
objectRightMapFutureCollision :: GameObject s -> IOGame t s u v Bool
objectRightMapFutureCollision :: forall s t u v. GameObject s -> IOGame t s u v Bool
objectRightMapFutureCollision GameObject s
o = do
    Bool
asleep <- forall s t u v. GameObject s -> IOGame t s u v Bool
getObjectAsleep GameObject s
o
    if Bool
asleep
        then forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
        else do GameMap v
m <- forall t s u v. IOGame t s u v (GameMap v)
getMap
                (Radius
pX,Radius
_) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectPosition GameObject s
o
                (Radius
sX,Radius
_) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectSize GameObject s
o
                (Radius
vX,Radius
_) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectSpeed GameObject s
o
                let (Radius
mX,Radius
_) = forall t. GameMap t -> Point2D
getMapSize GameMap v
m
                forall (m :: * -> *) a. Monad m => a -> m a
return (Radius
pX forall a. Num a => a -> a -> a
+ Radius
sXforall a. Fractional a => a -> a -> a
/Radius
2 forall a. Num a => a -> a -> a
+ Radius
vX forall a. Ord a => a -> a -> Bool
> forall a b. (Real a, Fractional b) => a -> b
realToFrac Radius
mX)

-- | checks the collision between an object and the left side of the map
objectLeftMapCollision :: GameObject s -> IOGame t s u v Bool
objectLeftMapCollision :: forall s t u v. GameObject s -> IOGame t s u v Bool
objectLeftMapCollision GameObject s
o = do
    Bool
asleep <- forall s t u v. GameObject s -> IOGame t s u v Bool
getObjectAsleep GameObject s
o
    if Bool
asleep
        then forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
        else do (Radius
pX,Radius
_) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectPosition GameObject s
o
                (Radius
sX,Radius
_) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectSize GameObject s
o
                forall (m :: * -> *) a. Monad m => a -> m a
return (Radius
pX forall a. Num a => a -> a -> a
- Radius
sXforall a. Fractional a => a -> a -> a
/Radius
2 forall a. Ord a => a -> a -> Bool
< Radius
0)

-- | checks the collision between an object and the left side of the map in the next game cicle
objectLeftMapFutureCollision :: GameObject s -> IOGame t s u v Bool
objectLeftMapFutureCollision :: forall s t u v. GameObject s -> IOGame t s u v Bool
objectLeftMapFutureCollision GameObject s
o = do
    Bool
asleep <- forall s t u v. GameObject s -> IOGame t s u v Bool
getObjectAsleep GameObject s
o
    if Bool
asleep
        then forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
        else do (Radius
pX,Radius
_) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectPosition GameObject s
o
                (Radius
sX,Radius
_) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectSize GameObject s
o
                (Radius
vX,Radius
_) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectSpeed GameObject s
o
                forall (m :: * -> *) a. Monad m => a -> m a
return (Radius
pX forall a. Num a => a -> a -> a
- Radius
sXforall a. Fractional a => a -> a -> a
/Radius
2 forall a. Num a => a -> a -> a
+ Radius
vX forall a. Ord a => a -> a -> Bool
< Radius
0)

-- | checks the collision between two objects
objectsCollision :: GameObject s -> GameObject s -> IOGame t s u v Bool
objectsCollision :: forall s t u v. GameObject s -> GameObject s -> IOGame t s u v Bool
objectsCollision GameObject s
o1 GameObject s
o2 = do
    Bool
asleep1 <- forall s t u v. GameObject s -> IOGame t s u v Bool
getObjectAsleep GameObject s
o1
    Bool
asleep2 <- forall s t u v. GameObject s -> IOGame t s u v Bool
getObjectAsleep GameObject s
o2
    if Bool
asleep1 Bool -> Bool -> Bool
|| Bool
asleep2
                then forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
                else  do (Radius
p1X,Radius
p1Y) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectPosition GameObject s
o1
                         (Radius
p2X,Radius
p2Y) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectPosition GameObject s
o2
                         (Radius
s1X,Radius
s1Y) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectSize GameObject s
o1
                         (Radius
s2X,Radius
s2Y) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectSize GameObject s
o2

                         let aX1 :: Radius
aX1 = Radius
p1X forall a. Num a => a -> a -> a
- Radius
s1Xforall a. Fractional a => a -> a -> a
/Radius
2
                             aX2 :: Radius
aX2 = Radius
p1X forall a. Num a => a -> a -> a
+ Radius
s1Xforall a. Fractional a => a -> a -> a
/Radius
2
                             aY1 :: Radius
aY1 = Radius
p1Y forall a. Num a => a -> a -> a
- Radius
s1Yforall a. Fractional a => a -> a -> a
/Radius
2
                             aY2 :: Radius
aY2 = Radius
p1Y forall a. Num a => a -> a -> a
+ Radius
s1Yforall a. Fractional a => a -> a -> a
/Radius
2

                             bX1 :: Radius
bX1 = Radius
p2X forall a. Num a => a -> a -> a
- Radius
s2Xforall a. Fractional a => a -> a -> a
/Radius
2
                             bX2 :: Radius
bX2 = Radius
p2X forall a. Num a => a -> a -> a
+ Radius
s2Xforall a. Fractional a => a -> a -> a
/Radius
2
                             bY1 :: Radius
bY1 = Radius
p2Y forall a. Num a => a -> a -> a
- Radius
s2Yforall a. Fractional a => a -> a -> a
/Radius
2
                             bY2 :: Radius
bY2 = Radius
p2Y forall a. Num a => a -> a -> a
+ Radius
s2Yforall a. Fractional a => a -> a -> a
/Radius
2

                         forall (m :: * -> *) a. Monad m => a -> m a
return (Radius
bX1 forall a. Ord a => a -> a -> Bool
< Radius
aX2 Bool -> Bool -> Bool
&& Radius
aX1 forall a. Ord a => a -> a -> Bool
< Radius
bX2 Bool -> Bool -> Bool
&& Radius
bY1 forall a. Ord a => a -> a -> Bool
< Radius
aY2 Bool -> Bool -> Bool
&& Radius
aY1 forall a. Ord a => a -> a -> Bool
< Radius
bY2)

-- | checks the collision between two objects in the next game cicle
objectsFutureCollision :: GameObject s -> GameObject s -> IOGame t s u v Bool
objectsFutureCollision :: forall s t u v. GameObject s -> GameObject s -> IOGame t s u v Bool
objectsFutureCollision GameObject s
o1 GameObject s
o2 = do
    Bool
asleep1 <- forall s t u v. GameObject s -> IOGame t s u v Bool
getObjectAsleep GameObject s
o1
    Bool
asleep2 <- forall s t u v. GameObject s -> IOGame t s u v Bool
getObjectAsleep GameObject s
o2
    if Bool
asleep1 Bool -> Bool -> Bool
|| Bool
asleep2
                then forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
                else do (Radius
p1X,Radius
p1Y) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectPosition GameObject s
o1
                        (Radius
p2X,Radius
p2Y) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectPosition GameObject s
o2
                        (Radius
v1X,Radius
v1Y) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectSpeed GameObject s
o1
                        (Radius
v2X,Radius
v2Y) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectSpeed GameObject s
o2
                        (Radius
s1X,Radius
s1Y) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectSize GameObject s
o1
                        (Radius
s2X,Radius
s2Y) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectSize GameObject s
o2

                        let aX1 :: Radius
aX1 = Radius
p1X forall a. Num a => a -> a -> a
- Radius
s1Xforall a. Fractional a => a -> a -> a
/Radius
2 forall a. Num a => a -> a -> a
+ Radius
v1X
                            aX2 :: Radius
aX2 = Radius
p1X forall a. Num a => a -> a -> a
+ Radius
s1Xforall a. Fractional a => a -> a -> a
/Radius
2 forall a. Num a => a -> a -> a
+ Radius
v1X
                            aY1 :: Radius
aY1 = Radius
p1Y forall a. Num a => a -> a -> a
- Radius
s1Yforall a. Fractional a => a -> a -> a
/Radius
2 forall a. Num a => a -> a -> a
+ Radius
v1Y
                            aY2 :: Radius
aY2 = Radius
p1Y forall a. Num a => a -> a -> a
+ Radius
s1Yforall a. Fractional a => a -> a -> a
/Radius
2 forall a. Num a => a -> a -> a
+ Radius
v1Y

                            bX1 :: Radius
bX1 = Radius
p2X forall a. Num a => a -> a -> a
- Radius
s2Xforall a. Fractional a => a -> a -> a
/Radius
2 forall a. Num a => a -> a -> a
+ Radius
v2X
                            bX2 :: Radius
bX2 = Radius
p2X forall a. Num a => a -> a -> a
+ Radius
s2Xforall a. Fractional a => a -> a -> a
/Radius
2 forall a. Num a => a -> a -> a
+ Radius
v2X
                            bY1 :: Radius
bY1 = Radius
p2Y forall a. Num a => a -> a -> a
- Radius
s2Yforall a. Fractional a => a -> a -> a
/Radius
2 forall a. Num a => a -> a -> a
+ Radius
v2Y
                            bY2 :: Radius
bY2 = Radius
p2Y forall a. Num a => a -> a -> a
+ Radius
s2Yforall a. Fractional a => a -> a -> a
/Radius
2 forall a. Num a => a -> a -> a
+ Radius
v2Y
                        forall (m :: * -> *) a. Monad m => a -> m a
return (Radius
bX1 forall a. Ord a => a -> a -> Bool
< Radius
aX2 Bool -> Bool -> Bool
&& Radius
aX1 forall a. Ord a => a -> a -> Bool
< Radius
bX2 Bool -> Bool -> Bool
&& Radius
bY1 forall a. Ord a => a -> a -> Bool
< Radius
aY2 Bool -> Bool -> Bool
&& Radius
aY1 forall a. Ord a => a -> a -> Bool
< Radius
bY2)

objectListObjectCollision :: [GameObject s] -> GameObject s -> IOGame t s u v Bool
objectListObjectCollision :: forall s t u v.
[GameObject s] -> GameObject s -> IOGame t s u v Bool
objectListObjectCollision [] GameObject s
_ = forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
objectListObjectCollision (GameObject s
a:[GameObject s]
as) GameObject s
b = do
        Bool
col <- forall s t u v. GameObject s -> GameObject s -> IOGame t s u v Bool
objectsCollision GameObject s
a GameObject s
b
        if Bool
col
                then forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
                else forall s t u v.
[GameObject s] -> GameObject s -> IOGame t s u v Bool
objectListObjectCollision [GameObject s]
as GameObject s
b

objectListObjectFutureCollision :: [GameObject s] -> GameObject s -> IOGame t s u v Bool
objectListObjectFutureCollision :: forall s t u v.
[GameObject s] -> GameObject s -> IOGame t s u v Bool
objectListObjectFutureCollision [] GameObject s
_ = forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
objectListObjectFutureCollision (GameObject s
a:[GameObject s]
as) GameObject s
b = do
        Bool
col <- forall s t u v. GameObject s -> GameObject s -> IOGame t s u v Bool
objectsFutureCollision GameObject s
a GameObject s
b
        if Bool
col
                then forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
                else forall s t u v.
[GameObject s] -> GameObject s -> IOGame t s u v Bool
objectListObjectFutureCollision [GameObject s]
as GameObject s
b

pointsObjectCollision :: GLdouble -> GLdouble -> GLdouble -> GLdouble -> GameObject s -> IOGame t s u v Bool
pointsObjectCollision :: forall s t u v.
Radius
-> Radius
-> Radius
-> Radius
-> GameObject s
-> IOGame t s u v Bool
pointsObjectCollision Radius
p1X Radius
p1Y Radius
s1X Radius
s1Y GameObject s
o2 = do
        Bool
asleep <- forall s t u v. GameObject s -> IOGame t s u v Bool
getObjectAsleep GameObject s
o2
        if Bool
asleep
                then forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
                else do (Radius
p2X,Radius
p2Y) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectPosition GameObject s
o2
                        (Radius
s2X,Radius
s2Y) <- forall s t u v. GameObject s -> IOGame t s u v Point2D
getObjectSize GameObject s
o2

                        let aX1 :: Radius
aX1 = Radius
p1X forall a. Num a => a -> a -> a
- Radius
s1Xforall a. Fractional a => a -> a -> a
/Radius
2
                            aX2 :: Radius
aX2 = Radius
p1X forall a. Num a => a -> a -> a
+ Radius
s1Xforall a. Fractional a => a -> a -> a
/Radius
2
                            aY1 :: Radius
aY1 = Radius
p1Y forall a. Num a => a -> a -> a
- Radius
s1Yforall a. Fractional a => a -> a -> a
/Radius
2
                            aY2 :: Radius
aY2 = Radius
p1Y forall a. Num a => a -> a -> a
+ Radius
s1Yforall a. Fractional a => a -> a -> a
/Radius
2

                            bX1 :: Radius
bX1 = Radius
p2X forall a. Num a => a -> a -> a
- Radius
s2Xforall a. Fractional a => a -> a -> a
/Radius
2
                            bX2 :: Radius
bX2 = Radius
p2X forall a. Num a => a -> a -> a
+ Radius
s2Xforall a. Fractional a => a -> a -> a
/Radius
2
                            bY1 :: Radius
bY1 = Radius
p2Y forall a. Num a => a -> a -> a
- Radius
s2Yforall a. Fractional a => a -> a -> a
/Radius
2
                            bY2 :: Radius
bY2 = Radius
p2Y forall a. Num a => a -> a -> a
+ Radius
s2Yforall a. Fractional a => a -> a -> a
/Radius
2
                        forall (m :: * -> *) a. Monad m => a -> m a
return (Radius
bX1 forall a. Ord a => a -> a -> Bool
< Radius
aX2 Bool -> Bool -> Bool
&& Radius
aX1 forall a. Ord a => a -> a -> Bool
< Radius
bX2 Bool -> Bool -> Bool
&& Radius
bY1 forall a. Ord a => a -> a -> Bool
< Radius
aY2 Bool -> Bool -> Bool
&& Radius
aY1 forall a. Ord a => a -> a -> Bool
< Radius
bY2)

pointsObjectListCollision :: GLdouble -> GLdouble -> GLdouble -> GLdouble -> [GameObject s] -> IOGame t s u v Bool
pointsObjectListCollision :: forall s t u v.
Radius
-> Radius
-> Radius
-> Radius
-> [GameObject s]
-> IOGame t s u v Bool
pointsObjectListCollision Radius
_ Radius
_ Radius
_ Radius
_ [] = forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
pointsObjectListCollision Radius
p1X Radius
p1Y Radius
s1X Radius
s1Y (GameObject s
o:[GameObject s]
os) = do
        Bool
col <- forall s t u v.
Radius
-> Radius
-> Radius
-> Radius
-> GameObject s
-> IOGame t s u v Bool
pointsObjectCollision Radius
p1X Radius
p1Y Radius
s1X Radius
s1Y GameObject s
o
        if Bool
col
                then forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
                else forall s t u v.
Radius
-> Radius
-> Radius
-> Radius
-> [GameObject s]
-> IOGame t s u v Bool
pointsObjectListCollision Radius
p1X Radius
p1Y Radius
s1X Radius
s1Y [GameObject s]
os

-----------------------------------------------
--              TEXT ROUTINES                --
-----------------------------------------------
-- | prints a string in the prompt
printOnPrompt :: Show a => a -> IOGame t s u v ()
printOnPrompt :: forall a t s u v. Show a => a -> IOGame t s u v ()
printOnPrompt = forall a t s u v. (a -> IO ()) -> a -> IOGame t s u v ()
liftIOtoIOGame' forall a. Show a => a -> IO ()
print

-- | prints a string in the current window
printOnScreen :: String -> BitmapFont -> (GLdouble,GLdouble) -> GLclampf -> GLclampf -> GLclampf -> IOGame t s u v ()
printOnScreen :: forall t s u v.
String
-> BitmapFont
-> Point2D
-> Float
-> Float
-> Float
-> IOGame t s u v ()
printOnScreen String
text BitmapFont
font Point2D
pos Float
r Float
g Float
b = do
        [Text]
t <- forall t s u v. IOGame t s u v [Text]
getTextList
        forall t s u v. [Text] -> IOGame t s u v ()
setTextList ((String
text,BitmapFont
font,Point2D
pos,Float
r,Float
g,Float
b) forall a. a -> [a] -> [a]
: [Text]
t)

-- | internal use of the engine
printText :: IOGame t s u v ()
printText :: forall t s u v. IOGame t s u v ()
printText = do
        [Text]
t <- forall t s u v. IOGame t s u v [Text]
getTextList
        forall a t s u v. IO a -> IOGame t s u v a
liftIOtoIOGame forall a b. (a -> b) -> a -> b
$ [Text] -> IO ()
putGameText [Text]
t
        forall t s u v. [Text] -> IOGame t s u v ()
setTextList []

-----------------------------------------------
--     RANDOM NUMBER GENERATOR ROUTINES      --
-----------------------------------------------
randomInt :: (Int,Int) -> IOGame t s u v Int
randomInt :: forall t s u v. (Int, Int) -> IOGame t s u v Int
randomInt (Int
x,Int
y) = forall a t s u v. IO a -> IOGame t s u v a
liftIOtoIOGame forall a b. (a -> b) -> a -> b
$ (Int, Int) -> IO Int
randInt (Int
x,Int
y)

randomFloat :: (Float,Float) -> IOGame t s u v Float
randomFloat :: forall t s u v. (Float, Float) -> IOGame t s u v Float
randomFloat (Float
x,Float
y) = forall a t s u v. IO a -> IOGame t s u v a
liftIOtoIOGame forall a b. (a -> b) -> a -> b
$ (Float, Float) -> IO Float
randFloat (Float
x,Float
y)

randomDouble :: (Double,Double) -> IOGame t s u v Double
randomDouble :: forall t s u v. Point2D -> IOGame t s u v Radius
randomDouble (Radius
x,Radius
y) = forall a t s u v. IO a -> IOGame t s u v a
liftIOtoIOGame forall a b. (a -> b) -> a -> b
$ Point2D -> IO Radius
randDouble (Radius
x,Radius
y)

-----------------------------------------------
--           DEBUGGING ROUTINES              --
-----------------------------------------------

-- | shows the frame rate (or frame per seconds) 
showFPS :: BitmapFont -> (GLdouble,GLdouble) -> GLclampf -> GLclampf -> GLclampf -> IOGame t s u v ()
showFPS :: forall t s u v.
BitmapFont
-> Point2D -> Float -> Float -> Float -> IOGame t s u v ()
showFPS BitmapFont
font Point2D
pos Float
r Float
g Float
b = do
        (Int
framei,Int
timebasei,Float
fps) <- forall t s u v. IOGame t s u v (Int, Int, Float)
getFpsInfo
        Int
timei <- forall t s u v. IOGame t s u v Int
getElapsedTime
        let frame :: Float
frame = forall a. Enum a => Int -> a
toEnum (Int
framei forall a. Num a => a -> a -> a
+ Int
1) :: Float
            timebase :: Float
timebase = forall a. Enum a => Int -> a
toEnum Int
timebasei :: Float
            time :: Float
time = forall a. Enum a => Int -> a
toEnum Int
timei :: Float
        if Int
timei forall a. Num a => a -> a -> a
- Int
timebasei forall a. Ord a => a -> a -> Bool
> Int
1000
                then forall t s u v. (Int, Int, Float) -> IOGame t s u v ()
setFpsInfo (Int
0,Int
timei,Float
frameforall a. Num a => a -> a -> a
*forall a. Enum a => Int -> a
toEnum Int
1000forall a. Fractional a => a -> a -> a
/(Float
timeforall a. Num a => a -> a -> a
-Float
timebase))
                else forall t s u v. (Int, Int, Float) -> IOGame t s u v ()
setFpsInfo (Int
framei forall a. Num a => a -> a -> a
+ Int
1,Int
timebasei,Float
fps)
        forall t s u v.
String
-> BitmapFont
-> Point2D
-> Float
-> Float
-> Float
-> IOGame t s u v ()
printOnScreen (forall r. PrintfType r => String -> r
printf String
"%.1f" Float
fps) BitmapFont
font Point2D
pos Float
r Float
g Float
b

-- | get the elapsed time of the game
getElapsedTime :: IOGame t s u v Int
getElapsedTime :: forall t s u v. IOGame t s u v Int
getElapsedTime = forall a t s u v. IO a -> IOGame t s u v a
liftIOtoIOGame forall a b. (a -> b) -> a -> b
$ forall t a (m :: * -> *). (HasGetter t a, MonadIO m) => t -> m a
get IO Int
elapsedTime

-- | delay for N  seconds while continuing essential game functions
wait :: Int -> IOGame t s u v ()
wait :: forall t s u v. Int -> IOGame t s u v ()
wait Int
delay = do
        forall t s u v. IOGame t s u v ()
printText                                   -- force text messages to be printed (is not working properly!)
        (Int
framei,Int
timebasei,Float
fps) <- forall t s u v. IOGame t s u v (Int, Int, Float)
getFpsInfo
        forall t s u v. (Int, Int, Float) -> IOGame t s u v ()
setFpsInfo (Int
framei,Int
timebasei forall a. Num a => a -> a -> a
+ Int
delay,Float
fps) -- helps FPS info to be displayed correctly (if requested)
        Int
startTime <- forall t s u v. IOGame t s u v Int
getElapsedTime

        forall t s u v. Int -> Int -> IOGame t s u v ()
waitAux Int
delay Int
startTime

waitAux :: Int -> Int -> IOGame t s u v ()
waitAux :: forall t s u v. Int -> Int -> IOGame t s u v ()
waitAux Int
delay Int
startTime = do
        Int
presentTime <- forall t s u v. IOGame t s u v Int
getElapsedTime
        if Int
presentTime forall a. Num a => a -> a -> a
- Int
startTime forall a. Ord a => a -> a -> Bool
> Int
delay
                then forall (m :: * -> *) a. Monad m => a -> m a
return ()
                else forall t s u v. Int -> Int -> IOGame t s u v ()
waitAux Int
delay Int
startTime