I've always had a little bit of an urge to try out game development. It wasn't something I associated with Haskell in the past. But recently, I started learning a bit about game architecural patterns. I stumbled on some ideas that seemed "Haskell-esque". I learned about the Entity-Component-System model, which suits typeclasses rather than object-oriented design.

So I've decided to do a few articles on writing a basic game in Haskell. We'll delve more into these architectural ideas later in the series. But to start, we have to learn a few building blocks! The first couple weeks will focus on the basics of the Gloss library. This library has some simple tools for creating 2D graphics that we can use to make a game. Frequent readers of this blog will note a lot of commonalities between Gloss and the Codeworld library we studied a while back. In this first part, we'll learn some basic combinators.

If you're looking for some more practical usages of Haskell, we have some tools for you! Download our Production Checklist to learn many interesting libraries you can use! You can also read our Haskell Web Skills series to go a bit more in depth!

## A Basic Gloss Tutorial

The get started with the Gloss library, let's draw a simple picture using the `display`

function. All this does is make a full screen window with a circle in the middle.

```
-- Always imported
import Graphics.Glass
main :: IO ()
main = display FullScreen white (Circle 80)
```

All the arguments here are pretty straightforward. The program opens a full screen window and displays a circle against a white background. We can make the window smaller by using `InWindow`

instead of `FullScreen`

for the `Display`

type. This takes a window "name", as well as dimensions for the size and offset of the window.

```
windowDisplay :: Display
windowDisplay = InWindow "Window" (200, 200) (10, 10)
main :: IO ()
main = display windowDisplay white (Circle 80)
```

The primary argument here is this last one, a `Picture`

using the `Circle`

constructor. We can draw many different things, including circles, lines, boxes, text, and so on. The `Picture`

type also allows for translation, rotation, and aggregation of other pictures.

## Animating

We can take our drawing to the next level by using the `animate`

function. Instead of only drawing a static picture, we'll take the animation time as an input to a function. Here's how we can provide an animation of a growing circle:

```
main = animate windowDisplay white animationFunc
animationFunc :: Float -> Picture
animationFunc time = Circle (2 * time)
```

## Simulating

The next stage of our program's development is to add a model. This allows us to add state to our animation so that it is no longer merely a function of the time. For our next example, we'll make a pendulum. We'll keep two pieces of information in our model. These are the current angle ("theta") and the derivative of that angle ("dtheta"). The `simulate`

function takes more arguments than `animate`

. Here's the skeleton of how we use it. We'll go over the new arguments one-by-one.

```
type Model = (Float, Float)
main = simulate
displayWindow
white
simulationRate
initialModel
drawingFunc
updateFunc
where
simulationRate :: Int
simulationRate = 20
initialModel :: Model
initialModel = (0,0)
drawingFunc :: Model -> Picture
drawingFunc (theta, dtheta) = …
updateFunc :: ViewPort -> Float -> Model -> Model
updateFunc _ dt (theta, dtheta) = ...
```

The first extra argument (`simulationRate`

) tells us how many model steps per second. Then we have our initial model. Then there's a function taking the model and telling us how to draw the picture. We'll fill this in to draw a line at the appropriate angle.

```
drawingFunc :: Model -> Picture
drawingFunc (theta, dtheta) = Line [(0, 0), (50 * cos theta, 50 * sin theta)]
```

Finally, we have an updating function. This takes the view-port, which we won't use. It also takes the amount of time for this simulation step (`dt`

). Then it takes a current model. It uses these to determine the new model. We can fill this in with a little bit of trigonometry. Then we'll have a working pendulum simulation!

```
updateFunc :: ViewPort -> Float -> Model -> Model
updateFunc _ dt (theta, dtheta) = (theta + dt * dtheta, dtheta - dt * (cos theta))
```

## Playing a Game

The final element we need to make a playable game is to accept user input. The `play`

function provides us what we need here. It looks like the `simulate`

function except for an extra function for handling input. We're going to make a game where the user can move a circle around with the arrow keys. We'll add an extra mechanic where the circle keeps trying to move back towards the center. Here's the skeleton:

```
type World = (Float, Float)
main :: IO ()
main = play
windowDisplay
white
20
(0, 0)
drawingFunc
inputHandler
updateFunc
drawingFunc :: World -> Picture
drawingFunc (x, y) = ...
inputHandler :: Event -> World -> World
inputHandler event (x, y) = ...
updateFunc :: Float -> World -> World
updateFunc dt (x, y) = ...
```

Our `World`

will represent the current location of our circle. The drawing function will draw a simple circle, translated by this amount.

```
drawingFunc :: World -> Picture
drawingFunc (x, y) = translate x y (Circle 20)
```

Now for our input handler, we only care about a few inputs. We'll read the up/down/left/right arrows, and adjust the coordinates:

```
inputHandler :: Event -> World -> World
inputHandler (EventKey (SpecialKey KeyUp) Down _ _) (x, y) = (x, y + 10)
inputHandler (EventKey (SpecialKey KeyDown) Down _ _) (x, y) = (x, y - 10)
inputHandler (EventKey (SpecialKey KeyRight) Down _ _) (x, y) = (x + 10, y)
inputHandler (EventKey (SpecialKey KeyLeft) Down _ _) (x, y) = (x - 10, y)
inputHandler _ w = w
```

Finally, let's write our "update" function. This will keep trying to move the circle's coordinates towards the center of the frame:

```
updateFunc :: Float -> World -> World
updateFunc _ (x, y) = (towardCenter x, towardCenter y)
where
towardCenter :: Float -> Float
towardCenter c = if abs c < 0.25
then 0
else if c > 0
then c - 0.25
else c + 0.25
```

And that's it, we have our miniature game!

## Conclusion

Hopefully this article gave you a good, quick overview on the basics of the Gloss library. Next week, we'll start making a more complicated game with a more interesting model!

We have other resources for the more adventurous Haskellers out there! Download our Production Checklist and read our Haskell Web Skills Series!