How to Make Awesome Water for a 2D Game
September 16th, 2014
By Peter Robinson
Three months ago, we decided to upgrade the graphics in Pirate Code. Since we’re an indie game developer, we needed to get the most benefit out of the time we spent on graphics. Time is our most precious resource. We determined that the elements that appeared the most in the game – and more importantly, in the screenshots – mattered the most. Since Pirate Code happens in an ocean, water matters most. We had other graphics we wanted to upgrade of course and we hired an excellent artist, Patrick Thompson, to handle it, but water was special. It was animated and needed to look alive. I knew it would probably take some special coding as well, so I decided to tackle it myself. When you’re an indie developer, you need to be able to wear any hat.
Things started off easy. Patrick drew up a few water tiles (11 actually) and they looked great! I knew I would have to animate them but I decided to throw them in the game and see what they looked like. The results were not good. The awesome water pattern repeated over and over looked like a marble floor. I hoped this would go away with animation so I started applying some Photoshop filters. I tried applying Ocean Wave to a tile systematically – increasing the amount by a certain amount each frame. At first I tried 15 frames but that looked choppy so I increased it to 30 frames. The animation smoothed out but looked weird. I tried other filters but nothing helped. Nothing looked like waves on the ocean.
I had other problems too. Dark tiles looked right on the open sea but terrible next to land. But light tiles, especially on the open sea, made the ocean look like it was glowing! In addition, the water patterns on the tiles, no matter how they were animated, looked so busy that it actually made it difficult to see the ships. I decided to try plain colored tiles – maybe with a slight gradient. This looked terrible! The ships looked like they were sitting on a rubber mat. To make matters worse the animations were lost on the plain color. I tried adding noise and using displacement maps simulate the waves on the water. I thought I had it! This looked like water. But from far away the waves disappeared – plus there was no way to animate the displacement map. Back to the drawing board.
I had spent nearly three weeks building water tiles day and night. I had nearly a dozen smoothly animated, ugly water tiles. I had carefully analyzed dozens of pictures of the ocean and read through every Photoshop tutorial on water I could find. Although I didn’t have any water to show for it, I had learned some important facts about the water I was trying to create.
- Water changes hue based on depth and the angle you look at it from. This might be because of the sand under shallow water. I can’t say for sure.
- Water changes brightness based on depth and the angle as well. I think this is largely due to reflection and the density of the water between the eye and the ocean floor.
- Water patterns don’t work because the pattern appears on the surface under the water. The only acceptable animation is actual ocean waves.
- Animations needed enough frames to play smoothly for several seconds before looping. Quickly looping or synchronized animations looked artificial.
All I had to do was meet these four requirements. I started with three and four. I needed waves and it was clear that Photoshop had no magic filter that was going to give me waves. I entertained the idea of hand drawing the waves but I couldn’t possibly get enough frames to smoothly animate for several seconds. Instead I found a free-to-use animated gif of waves. I nervously spent two days running each frame of the animation though filters and wrapping them around a hexagon tile. When I tested it I found at last what I had been looking for – beautifully crafted ocean waves, rising and falling in asymmetric harmony!
I was giddy.
But I wasn’t done! I still had to handle the hue and brightness changes. First to solve the hue I gradually set the blending color of each tile depending on it’s location on the map. Tiles lower down had a more purple hue while tiles at the top of the map appeared more green. This was easily done, but the brightness was a little harder. I created a solid white hexagon to go over each tile. I changed it’s openGL blending mode to be DST_COLOR and SRC_ALPHA (at full alpha this gives the same effect as increasing the saturation in Photoshop) and then based its transparency on its position on the map. Tiles further up were brighter and tiles at the bottom were darker.
The final results were better than I could have imagined! I later added the shallow water, transitions, and beaches. With the addition of new land, the cliffs now fade away as they disappear under the waves. I realize that most of these effects will go unnoticed by the average user, but the cumulative impact will create a world that players love to spend time in.
What do you think of the new water in Pirate Code? Let me know in the comments. And if you still haven’t played Pirate Code, what are you waiting for? Dive in! The water’s fine!