-- | -- Copyright : (c) Ivan Perez & Henrik Nilsson, 2014. -- License : See LICENSE file. -- Maintainer : Ivan Perez -- -- Objects as signal functions. -- -- Live objects in the game take user input and the game universe and define -- their state in terms of that. They can remember what happened (see Yampa's -- Arrow combinators, which hide continuations), change their behaviour (see -- switches in Yampa). -- -- They cannot affect other objects, but they can kill themselves (see -- 'harakiri'). Should you need to spawn new game elements upon events, you -- might want to change 'harakiri' to something more general. module ObjectSF where -- External imports import FRP.Yampa -- Internal imports import Data.IdentityList import Input import Objects -- | Objects are defined as transformations that take 'ObjectInput' signals and -- return 'ObjectOutput' signals. type ObjectSF = SF ObjectInput ObjectOutput -- | In order to determine its new output, an object needs to know the user's -- desires ('userInput'), whether there have been any collisions -- ('collisions'), and the presence of any pre-existing objects -- ('knownObjects'). -- -- The reason for depending on 'Collisions' is that objects may ``die'' when -- hit. -- -- The reason for depending on 'Objects' is that objects may choose to follow -- other objects. -- -- TODO: Would it be possible to depend on the specific object SFs internally -- and remove the explicit 'knownObjects'? I guess so, so long as it's possible -- to always provide the same input to those SFs that they will have in the -- game: because they are different instances, we need the exact same input to -- guarantee the exact same behaviour. data ObjectInput = ObjectInput { userInput :: Controller , collisions :: Collisions , knownObjects :: Objects } -- | What we can see about each live object at each time. It's a snapshot of -- the object. data ObjectOutput = ObjectOutput { outputObject :: Object -- ^ The object's state (position, shape, etc.). , harakiri :: Event () -- ^ Whether the object has died (killed itself). } -- | Handy function to create an object that is currently alive. livingObject :: Object -> ObjectOutput livingObject o = ObjectOutput o noEvent -- | List of identifiable objects. Used to work with dynamic object -- collections. type ObjectSFs = IL ObjectSF extractObjects :: Functor f => SF (f ObjectOutput) (f Object) extractObjects = arr (fmap outputObject) -- | A list of object outputs type ObjectOutputs = [ObjectOutput]