Upgrade to Pro — share decks privately, control downloads, hide ads and more …

FRP in games

elise_huard
November 04, 2015

FRP in games

Given at Codemesh 2015 http://www.codemesh.io/

elise_huard

November 04, 2015
Tweet

More Decks by elise_huard

Other Decks in Programming

Transcript

  1. FRP

  2. game :: RandomGen t => Signal (Bool, Bool, Bool, Bool)

    -> t -> SignalGen (IO ()) game directionKey randomGenerator = mdo randomNumber <- stateful (undefined, randomGenerator) nextRandom player <- transfer2 initialPlayer (movePlayer 10) directionKey gameOver' monster <- transfer3 initialMonster wanderOrHunt player randomNumber gameOver' gameOver <- memo (playerEaten <$> player <*> monster) gameOver' <- delay False gameOver return $ renderFrame win glossState <$> player <*> monster <*> gameOver
  3. start :: SignalGen (Signal a) -> IO (IO a) network

    <- start $ game directionKey randomGenerator fix $ \loop -> do readInput win directionKeySink join network threadDelay 20000 esc <- exitKeyPressed win unless esc loop
  4. (directionKey, directionKeySink) <- external (False, False, False, False) (l,r,u,d) <-

    (,,,) <$> keyIsPressed window Key'Left <*> keyIsPressed window Key'Right <*> keyIsPressed window Key'Up <*> keyIsPressed window Key'Down directionKeySink (l, r, u, d)
  5. player <- transfer2 initialPlayer movePlayer directionKey gameOver’ monster <- transfer3

    initialMonster wanderOrHunt player randomNumber gameOver’
  6. game :: RandomGen t => Signal (Bool, Bool, Bool, Bool)

    -> t -> SignalGen (IO ()) game directionKey randomGenerator = mdo player <- transfer2 initialPlayer (movePlayer 10) directionKey gameOver' randomNumber <- stateful (undefined, randomGenerator) nextRandom monster <- transfer3 initialMonster wanderOrHunt player randomNumber gameOver' gameOver <- memo (playerEaten <$> player <*> monster) gameOver' <- delay False gameOver return $ renderFrame win glossState <$> player <*> monster <*> gameOver
  7. generator :: Signal (SignalGen a) -> SignalGen (Signal a) playLevel

    :: Signal (Bool, Bool, Bool, Bool) -- event signals -> LevelNumber -- pattern match on level number -> Score -> Health -> SignalGen (Signal GameState, Signal Bool) -- in playGame main function (gameState, levelTrigger) <- switcher $ playLevel directionKey <$> levelCount' <*> score' <*> lives'
  8. SignalGen [Signal Bolt] let bolt direction range startPosition = stateful

    (Bolt startPosition direction range False) moveBolt mkShot shot currentPlayer = if hasAny shot then (:[]) <$> bolt (dirFrom shot) boltRange (position currentPlayer) else return [] newBolts <- generator (mkShot <$> shoot <*> player) bolts <- collection newBolts (boltIsAlive worldDimensions <$> monsters)
  9. collection :: (Signal [Signal Bolt]) -> Signal (Bolt -> Bool)

    -> SignalGen (Signal [Bolt]) collection source isAlive = mdo boltSignals <- delay [] (map snd <$> boltsAndSignals') -- add new bolt signals bolts <- memo (liftA2 (++) source boltSignals) let boltsAndSignals = zip <$> (sequence =<< bolts) <*> bolts -- filter out dead ones boltsAndSignals' <- memo (filter <$> ((.fst) <$> isAlive) <*> boltsAndSignals) return $ map fst <$> boltsAndSignals'
  10. prop_insideLimits move player@(Player (x,y) _ _) = (x > ((-worldWidth)

    `quot` 2 + playerSize `quot` 2)) && (x < (worldWidth `quot` 2 - playerSize `quot` 2)) && (y > ((-worldHeight) `quot` 2 + playerSize `quot` 2)) && (y < (worldHeight `quot` 2 - playerSize `quot` 2)) ==> not $ (\p -> outsideOfLimits (worldWidth, worldHeight) p playerSize) $ position $ movePlayer playerSpeed (worldWidth, worldHeight) move Nothing (False, False, False, False) Nothing player