{-# LANGUAGE Arrows #-} -- | This module defines the game as a big Signal Function that transforms a -- Signal carrying a Input 'Controller' information into a Signal carrying -- 'GameState'. -- -- There is no randomness in the game, the only input is the user's. -- 'Controller' is an abstract representation of a basic input device with -- position information and a /fire/ button. -- -- The output is defined in 'GameState', and consists of basic information -- (points, current level, etc.) and a universe of objects. -- -- Objects are represented as Signal Functions as well ('ObjectSF'). This -- allows them to react to user input and change with time. Each object is -- responsible for itself, but it cannot affect others: objects can watch -- others, depend on others and react to them, but they cannot /send a -- message/ or eliminate other objects. However, if you would like to -- dynamically introduce new elements in the game (for instance, falling -- powerups that the player must collect before they hit the ground) then it -- might be a good idea to allow objects not only to /kill themselves/ but -- also to spawn new object. -- -- This module contains two sections: -- -- - A collection of gameplay SFs, which control the core game loop, carry -- out collision detection, , etc. -- -- - One SF per game object. These define the elements in the game universe, -- which can observe other elements, depend on user input, on previous -- collisions, etc. -- -- You may want to read the basic definition of 'GameState', 'Controller' and -- 'ObjectSF' before you attempt to go through this module. -- module Objects.Walls where -- External imports import Prelude hiding (id, (.)) import Control.Category (id, (.)) import Data.List import Data.Maybe import Debug.Trace import FRP.Yampa import FRP.Yampa.Extra import FRP.Yampa.Switches -- General-purpose internal imports import Data.Extra.Ord import Data.Extra.VectorSpace import Physics.Oscillator import Physics.TwoDimensions.Collisions as Collisions import Physics.TwoDimensions.Dimensions import Physics.TwoDimensions.GameCollisions import Physics.TwoDimensions.Shapes import Physics.TwoDimensions.PhysicalObjects -- Internal iports import Constants import GameState import Input import Objects import ObjectSF -- * Walls -- | Walls. Each wall has a side and a position. -- -- NOTE: They are considered game objects instead of having special treatment. -- The function that turns walls into 'Shape's for collision detection -- determines how big they really are. In particular, this has implications in -- ball-through-paper effects (ball going through objects, potentially never -- coming back), which can be seen if the FPS suddently drops due to CPU load -- (for instance, if a really major Garbage Collection kicks in. One potential -- optimisation is to trigger these with every SF iteration or every rendering, -- to decrease the workload and thus the likelyhood of BTP effects. objSideRight :: ObjectSF objSideRight = objWall "rightWall" RightSide (gameWidth, 0) -- | See 'objSideRight'. objSideLeft :: ObjectSF objSideLeft = objWall "leftWall" LeftSide (0, 0) -- | See 'objSideRight'. objSideTop :: ObjectSF objSideTop = objWall "topWall" TopSide (0, 0) -- | See 'objSideRight'. objSideBottom :: ObjectSF objSideBottom = objWall "bottomWall" BottomSide (0, gameHeight) -- | Generic wall builder, given a name, a side and its base -- position. objWall :: ObjectName -> Side -> Pos2D -> ObjectSF objWall name side pos = arr $ \(ObjectInput ci cs) -> Object { objectName = name , objectKind = Side side , objectPos = pos , objectVel = (0,0) , canCauseCollisions = False , collisionEnergy = 0 }