 I'm very happy to be here, and thanks to the organizers for an amazing conference. And also, I love that the Ruby community is so open-minded that they'd invite someone to talk about a game in Haskell. So, well, let's decompose this into its component. So, again, more precisely, we're talking about a video game. So, a video game is an electronic game that uses human interaction to generate feedback and visual feedback on video devices like a TV monitor or a console screen or whatever. So that's what we're doing here. Has anyone here developed any kind of game before? A fair show of hands there. That's nice. So, let's talk about Haskell. So, Haskell is a programming language with the following components, following properties, sorry. It's purely functional, so it's all functions. It's statically typed. So, unlike Ruby, every value you see has a type. Every function has a type signature. And, thirdly, Haskell is lazy, and that means that expressions don't get evaluated necessarily right away. They get evaluated when the result is needed by the program. So, basically, it's very different from Ruby. Anyone here has done Haskell before? Still a number there. That's cool. But for the other ones, don't worry. I have included a fair amount of code in my presentation, but I've made sure it's fairly readable, and if you don't understand certain details, don't worry. If you get the general idea, it's fine. So, let's start. So, we need a number of building blocks, obviously, to build a game. To start with, we need some sort of interaction with the operating system. We need to ask for windows, a window or an application, rather, to work in a certain context. And then we also need to listen for, let's say, keyboard events or mouse events or whatever events you want to listen to. And I used a library called GLFW, which is actually C, but Haskell has nice bindings to it. And you can basically, more or less, see here, create a window, and you work within that context, pull events, and then you make some convenient functions to detect whether a certain key has been pressed, for instance. So, that's one building block we need. The next one is, I guess, a graphical tool. So, when I started with my first game in Haskell, I actually, I guess, made, I wouldn't say the mistake, but I started with working with OpenGL bindings directly, and that was fairly horrid. Fortunately, someone recommended Gloss to me, which is a really nice framework on top of OpenGL. And what it does, it actually pushes all the nasty sort of OpenGL side-effecting stuff well down the pipeline. And all you have to worry about is defining a nice data structure. So, first one, well, you can see right, a polygon with certain coordinates. I want to have it violet and put down, you know, up left on the screen. Second one, I want a circle that is light blue and put it on the right, for instance. And you run all that through display picture function, and it all runs as expected, and you have a shape to work with. Then, obviously, we need more than just, well, here's a nice drawing with, like, a circle and a square. We need a loop to make things move forward. So, we know that the human eye will perceive 24 frames per second as more or less flowing movements. Obviously, nowadays, we work more with 60, 70, 90, which is the more the refresh rate of your usual screen. So basically, what our loop needs to do is to present you with a different image every 20 milliseconds or something, and then you'll have something that seems to advance like a video. And our loop goes like this for the game. Pull input events, react to input and change the state, and then render a frame from the state. And then, if you don't exit, you start again. You loop, loop, loop, like that. Then, obviously, in that loop, you saw a state. You need to keep track of where you are in your game. Obviously, to get a coherent flow of events. The simplest way, sorry, to codify that in Haskell, you will use the types. The types are actually surprisingly expressive at showing the structure of, for instance, states. Like here, you see a very simple state data structure, which is the player with a certain position. Then here's the loop I was talking about with a little bit more code. So you create your window, then you loop with an initial state, your player in the middle, for instance. And then the thread delay is to get only 60 frames per second, because if you let it run away, it would just run, run, run, run, and overload your graphical pipeline and crash. So you let it just pause a little bit between each frame. You pull the events, you check the arrow keys, and you pass that into a function here, move player, which is a pure function, which will just say, well, I have the arrows there and the player here. Then I need to make it move forward a little bit, or whatever is needed. And then you render, render frame. And then you start again here. Unlike in Ruby, you can do recursion in Haskell. It's still recursion optimized, so you can do that. No problem. So this is the move player function. You'll notice another property of Haskell, which is to be able to pattern match. So your pattern match on the arrow keys, well, if your left arrow is depressed, then we will move the player left a bit and so on and so forth. And if none of the keys are depressed, then the player obviously stays in place. And so that's enough to start. We have a little demo here with just a black square. So with the building blocks we had so far, that's what we can do, which is already something. So a twist on this is that the simple sort of state handling we had before is okay when you have a very simple state like we have here. But when it becomes more complicated, it's actually nice to use a different paradigm, which is functional reactive programming, which allows you to decompose your states in a different way. So with functional reactive programming, we're going to work with streams of events through time or streams of values through time. So that's again our player, but we'll call this a player signal rather. And so we have a relationship between the arrows, the arrow signal and the player signal. And if your key is not depressed, then your player stays in place. But if, for instance, if you need to go left, then there's a relationship between those. And so you work with a network of all those signals interacting together. So this is our loop, slightly reworked. We capture our key signal in a sync, and then we'll work with this, which is a direction key signal. And our player becomes a transfer between the direction key with the direct story. It became, we express sorry, the dependency between the player signal and the direction key here. And we feed it the initial states and everything just unloops from there. And then at the end of the network, we do the same render frame function, but we unpack the signal to the current value. So it's like the boxes Choose was talking about. So we get the value of the signal box to render. And then the loop is like this. We feed the direction key sync with the output and then we delay a little bit again and then we continue like this. It's more or less the same, but it allows you to express your states with different components. Like if we have a tiny bit more complex game, we have player signal, a monster signal, a game over signal, then the external inputs are arrows and a random generator, for instance. And our player is dependent on the direction key and game over. Our monster is dependent on player, random number, and game over. And the very nice thing here is that what we worry about, the only thing we have to worry about is the function here, the red function here, which are pure functions. And so you don't have to worry about what's going on elsewhere. You just say, well, if I feed my player this input, then I should get this output, which is very easy to test, obviously. You just need to test whether that's coherent and then your whole game should work. And then you render frame with unboxing the player and the monster signal here. So what we did with Gloss before was drawing a little square or a little circle or something, and usually we want a spaceship or a landscape or something like that. And so we want to work with images rather than geometry. And fortunately, Gloss helps us again. We can just load a bitmap like this. And we call this a texture. And then we use a texture in our render frame function here. So, for instance, render player. We will just take that texture we loaded and move it to wherever we need it to be. And already things are looking up a little bit and our game starts looking like something we'd recognize a little bit more. So the player, well, the knight figure of my little game may or may not have been based on my daughter Alice on the left. So we have this bet that we're going to insert a picture in every presentation. So that was a picture. So if you see this, unfortunately, there's still something wrong with it. The knight is just basically shifting along. And it's a little bit wooden. You need something else to have it a little bit more lifelike. And that's where we need animations. So animations is a full-time job. It's a specialty. It's not something you can just improvise. What I've been doing is traditional animation, which is just simply using different pictures for every frame. But if you're doing this professionally, you're going to do interpolations. You're going to do skeletal animation. You're going to do motion capture. You're going to use specialized software to generate all the frames because it's not something you can just do, especially when it becomes more complicated. So I've been drawing all my assets, as I said. So to make the little lights walk a little bit better, I basically just made one foot lift or the other foot lift and the arms move a little bit. And that already creates a slightly better illusion of movement. Obviously, this means that suddenly, you have a combinatorial explosion of textures instead of having four, one for every direction. You now have 12 just to make it walk. And if you add cross-balls like a little bit later, you have four times that. So it's just a lot of drawing suddenly. So the thing is now your state changes a little bit in the fact that you have to not only keep track of the state of the game, where is your little man, but also which stage of the animation is it in. So in my very simple walking animation, I define a walk stage here, which becomes part of the state like this here. And then when I render the player, I have four stages. So it cycles between those. It goes through that walking motion every time. You should have had a video there. It'll come later, it's no problem. And then obviously we need some sounds. We need background music that will stick in our heads. We need little events to make it a little bit more attractive. And I used a library called ALUT, which is again bindings to a C library, which is doing its job very well and it's not too hard to use. And our state changes again because not only do we have graphical states, we also have a sound state to manage. And our render frame is now grouped within output function. Output function takes care of both render frame and the sound. Obviously for sound you don't really need 60 triggers a second. What you do is you trigger a sound and you let it play out. So originally I thought that I would need to start a thread next to the main loop to sort of have the sounds play, but it turns out that this is actually taking care for you. Like the graphical pipeline, there's a sound pipeline and so you just make sure your sounds are played at the right moment. Just once, not 60 times a second. And then things just play out. And here you load the sounds. So where do the sounds come from? I downloaded them from a site called Free Sound. But you can also buy sample packs, which are more professional, or if you're a musician, obviously you can make them yourself, which is even better. And the play sounds looks like this. You see it's actually also relatively expressive when you use a few functions. Like this function changes the background music and there's danger. At the end of game, which means when the monster eats the little dude, then you have a shriek and when the monster is hunting, then it's biting all the time. So demo here. Normally the sound is not working. Maybe I should turn it up. There isn't any sound. No, because it stopped playing. That's cool. I think we need to remove the stuff. So obviously that's not all you need. You also need a start screen. You need levels. And that's where it starts to get a little bit interesting with the functional reactive programming. Because you have signals all over. Actually you have several levels going on. You keep the state of your game at the upper level. Sorry, the general state at the upper level. Are you in a start screen or are you in a game? And are there high scores, for instance? And then the next level is we are in a game. So I started a network, a sub-network sort of which keeps track of the level number we are at. And that again starts a sub-network with lots of signals for the monster, the player, and everything. And everything like the render state and the sound state are just passed back up to the upper network. And here the rendering still happens. And I'm not going to show you that code because that would take more than one slide. So contrast is not great on this, but... So, yeah. So I wasn't saying it was a great game. Also... Also, one fortunate thing with Gloss is that the fonts support socks. Basically you have no fonts, you just have this. And that's a pull request I'm working on personally. I'd like that to improve. So, okay. So what are the lessons I learned from the whole process of getting to this? First, let's talk about Haskell. So Haskell has lots of nice things going. Like I said, the types allow you to really describe your state in a very nice, readable way. Pattern matching is really great to describe transitions from one state to the other. The result is fast. It's compiled down to an executable that runs fast. Okay, the downsides. Well, first off, the laziness is actually not suited for games. You don't want things to execute at the last possible minute. You want them to execute right now. And so you need to take care in Haskell to force that. There are data structures to allow you to do that. But you need to pay attention. And then it was insanely hard to get started because not many people have done this before. And so I had to troll the Internet to find a toolset that worked for me. And that wasn't easy. And I'm still working on the distribution aspect. I'm fairly sure that won't be too big a problem. I'm working on generating a backup from the game. And the next step will then be maybe a Debian package or a Windows executable. But there was a lot of stuff to solve, basically. So I wrote a book about documenting this. Like I said, I feel like I had to really work through a lot of crap to get through this point. And so I'm hoping that people can push this further because basically with this people can sort of say, well, that was very nice. Now I want my animations to be 12 times better than this and I'm going to make it work. So I'm hoping that having good explanations out there sort of will help that. Also, one other reason I wrote this book is because I think it's a fun way to sort of get deeper into Haskell and to understand it better. Because most examples are not that much fun, to be honest. So having a game is, I think, a nicer way to start. So that's me. Are these calls to the operating system non-blocking or how do you achieve these parallel computations? I'm sorry? How do you achieve parallel computations like sound and drawing at the same time? It would be easy to do that, but I didn't really need to do that here because like I said, OpenGL sort of takes things away under the hood and OpenALUT also takes things away under the hood so you don't really need to worry about multi-treading at this point. More questions for Elise? We have a few minutes for the next break. This side of the room, any questions? Hello, Elise. I didn't quite get whether you were learning Haskell at the same time when programming this game or did you have Haskell experience before that? I had been programming Haskell for about a year and I was consulting professionally. Now I'm not an expert so I still see the beginner's point of view in this one. Thank you. Nothing more? Okay, thank you.