Recently, I’ve been a huge proponent of Functional Programming. As technology improves, we are given more leverage to create applications with functional programming methodologies. ReasonML has become my functional language of choice, and with the new Reprocessing library, I was able to create a snake Snake game. So, let’s tell the story.
Once I got started, I began working on the core functionality of the snake game gameplay loop. In my mind, that is moving in all directions, eating food, extending the snake, and processing game over conditions (hitting obstacles and eating your own body).
At this stage, I planned out each functional requirement in a functional way. The most important thing I had to understand is that we are passing the state between each drawn frame of the game. For example, the position of the snake moves along the grid. I would have to update the position of the snake based on that grid each frame; the state of the game is then updated. This is just one example but applies to all the features I implemented. Once we were done, understanding what needed to be done, it was time to code.
The Coding Struggle
Coding at first was a struggle; I did not understand the library well and needed time to understand what the core functions of the library were. I also needed a refresher with the syntax of reasonML. These two hurdles slowed me down, but it got better toward the midpoint of the project. After I got past that issue, the next hurdle was coding the snake itself.
Although I understood conceptually how to make the entire snake (it’s just a list of point positions that follow each other); it did not translate well to code on my first attempt.
My first attempt was to simply have the snake move without a grid (that was a really bad idea). When adding a new body part, they would go to to the previous segments old position. This did not work, because the body part did not follow the snake fluidly, instead, they would just appear behind the snake at the old position, that never actually turned with the snake properly. The problem was that my implementation at the time had no grid, and the segments did not which direction to move after being added to the snake. The second implementation was much better.
In the second version, we added a grid; food obstacles, and the snake all existed on the grid. The snake would move on this grid, and we would log the direction of the snake’s segments went as well by comparing the new position to the old position. This allowed each segment to independently follow the previous segment. This is a true follower mechanic, which is exactly what is done in many old school RPG games. Now, the game started to take shape, and we could work on the most important part: collision detection.
Collision detection was easy with the grid; this allowed us to simply check if the grid cell is occupied. This also allowed us to create obstacles recursively that occupied their own individual cells. With that, we were able to accomplish all of our features (collision detection accounts for food, obstacles, and game over conditions).
I learned a lot working on this game. First of all, your first implementation may not be the best one; you may have to rethink your implementation for the success of the project. The next thing is that you should always plan out your code before writing anything; I could have saved a lot of time if I had gotten a better handle of what I actually needed to code. Programming is mainly logic, so get your logic right! But, the most important I learned is that you need to finish what you start; half-baked project means nothing to anyone. The finished version is always worth it, and it might just help someone else.
Stay tuned for most posts in the future.