Rapid, Scalable Game development using Functional Reactive Programming

Ray Shulang Lei

Imperative vs Functional programming

Imperative Example: Count all numbers that can be divided exactly by 5 from 1 to 150.

			int sum = 0;
			for (int i = 0; i < 150; i++)
			{
				if (i % 5 == 0)
				  sum += i;
			}
			printf(sum);
		

Functional Example: Count all numbers that can be divided exactly by 5 from 1 to 150.

			show $ length [x | x <- [1..150], x `mod` 5 == 0]
		

Advantages of functional programming

Pitfalls of functional programming

Problems of imperative programming in Game development

Great! Let's just use Functional programming for games then, easy:

            GameLoop( 
                Players(), AIs(), Trees(), Guns(), Bullets(), ... )
		

I got it, give me one more chance, I can still do it, boss!

            gameState = [playerPosition, playerSpeed, 
                        gamepadIO, playerIsColliding, ... ]
            t = currentTime()
            GameLoop( 
                Players(gameState, t), AIs(gameState, t), 
                Trees(gameState, t), Guns(gameState, t), 
                Bullets(gameState, t), ... )
		

Functional Reactive programming to the rescue!

Definiation of FRP - functions react to an input signal and returns an updated signal.

A signal is a type value related to continuous time:
 Signal a = Time -> a
A signal function is a function from Signal to Signal:
 SF a b = Signal a -> Signal b
You can't touch the signals without using sigal functions.
Signal function combinators composite function(s) to a Signal Function: You can't touch the signal functions without using combinators.

Nice! we can now do:

signal(position, speed, mouseXY) 
    -> PlayerFunction 
        -> signal(position, speed, mouseXY)
        

But what about gamepads buttons, collisions etc.?

An event is a type to represent discrete events such as a mouse click:

data Event a = NoEvent | Event a

Looks like we are almost there:

signal(position, speed, mouseXY), event(gamepad, collision) 
  -> PlayerFunction 
    -> signal(position, speed, mouseXY)
        

But but but, what if my player dies? How do I remove and spawn?

Also, how does my object know if it is colliding with each other?

The last piece of the puzzle: Switches!

Switch switches from one subordinate signal function into another when a switching event occurs.
            switch :: SF a (b, Event c) -> 
              (c -> SF a b) -> SF a b
          

What is this non-sense? What are these strange symbols stand for?

It's haskell...I know. It says a switch will take an activated signal function with a trigger event, and another signal function as input. If the trigger event occurs, it applies the second signal function, else it applies the original signal function.

The big picture

We use switches to route events and switch on/off game objects for spawn/kill.

Conclusion


Q:What framework can I start to use FRP for game dev?
A:My presentation is based on the Yampa framework in Haskell

Q:How well is this method perform?
A:Paul Hudak made a game "PaddleBall" with 17 lines of code in FAL

Q:Is there example of complex game out there made with FRP?
A:Check out Frag, a first personal shooter game

Reference