Scrounge World Game
Clay Francisco & Zach Kamerling
Code Repository
Document Repository
Abstract. We discuss the idea of a web based real-time strategy game. Our main implementation points that separate this from most real-time strategy games is the client/server architecture combined with a fairly unique user interface. We attempt to highlight the benefits and difficulties of bringing a real-time strategy game to the web. We show that real-time and computationally expensive games can be made in the Haskell programming language and illustrate how painful it can be to make 3D games for browsers. Furthermore, we discuss what we plan to accomplish in the future to advance tablet gaming and the real-time strategy genre.
1 Introduction
First we discuss the history of RTS game architectures and UI's and how they have evolved over time. We discuss the benefits and complexities of the current model. In Section 2 we give a brief overview of the project and specify what it's composed of. Then we go on to explain the projects goals, its target audience, the server's architecture, and the client's architecture. We end by stating the current status of the project, what conclusions we can draw from our time working on it, and what we would like to do in the future.
1.1 The RTS Problem
Mobile games are a huge part of today's gaming market and yet are still missing a catalog of strategically rich RTS games. The current mobile market is choked with Tower Defense clones (for reasons I will examine later) that systemically replace creative gameplay with extreme graphic content (either cutesy or violent, sometimes even both). What I find most interesting is that the audience supports this kind of re-skinning of the same game i.e. guy “A” plays “Zombie Doom-Hut Defender”, while his 9 y.o. kid plays “Candy Monkey-Heart Protector” but underneath it all they are the exact same game, power-ups and all.
This may be good business but it's bad practice. The game designer in me just can't stand the blatant disregard for the game theme to game mechanics correlation. This is my main motivation for jumping into the mobile game design arena in general. Pen and Paper board games have a long and varied history that will continue on just fine without my help. Mobile strategy games need help though, and I am more than willing to lend a hand.
I must note here that turn-based strategy games have been successful on mobile devices and the genre is seeing a steady influx of creative exploration as people begin to re-imagine the board game paradigm. X-COMM, Aerena & Toribash are three great examples of turn-based strategy games changing the digital board game genre. Say good-bye to Majong and Othello clones.
2 Overview
2.1 Project Specification
Scrounge World is a client/server model RTS (real-time strategy) game implemented in Haskell, JavaScript, & CSS/HTML. The Haskell based server performs all game logic and sends packets of information to all players involved in the game. The client renders these packets of information and sends player commands to the server. The game is made for the web because we wanted it to be playable on as many platforms as possible. The server is made in Haskell to demonstrate the benefits of using a purely functional language to make a computationally expensive real-time game. Another aspect of the game is that other parties can modify it to create new experiences and tweak things how they desire.
2.2 Project Goals
We are using this project as a learning experience and we plan to market it in the future. Our hopes were to learn web development, game development, concurrency, parallelism, and advanced functional programming constructs. We also hope to change what people think is possible on mobile devices and demonstrate that a touch interface is viable for RTS games. With the modding capabilities and chance to play on many platforms, we believe we can create a diverse community of gamers who create and share experiences with one another.
2.3 Target Audience
RTS games typically only appeal to hardcore gamers. They require a player to balance their time and thoughts between economic growth, military expansion, intelligence gathering, and strategic maneuvers. In combat, players must also be able to quickly give commands to units to maximize their potential. Many units have special abilities that the player must utilize to gain an advantage.
Mobile games however have the exact opposite type of user. Mobile game players have notoriously short attention spans and need very low learning curves. Two concepts completely foreign to the RTS genre.
To make our RTS game successful, we'll need a UI that enables the player to quickly go from thought to action with as little effort as possible. RTS players spend all of their time navigating the battlefield, selecting units, and giving orders. They don't want to be fumbling around in menus searching for things while their opponent wipes them off the map. We designed a UI that we believe solves these problems and enables players to issue any command they wish within one or two seconds.
2.4 Server Architecture
There are extremely few large games written in the Haskell programming language. Certainly none that are similar to what we are trying to accomplish. This means no game engines were used on the server end and nearly all logic was written by hand. The only significant libraries used were for networking (websockets, stm, & blaze-builder) and array based data structures (vector, hashtables, repa).
The server code is divided up into several large components. There is a single module containing all data type declarations used by game logic called “Data.hs”. Nearly every module imports the “Data.hs” module. It's pointless to separate a games data into separate chunks when almost all pieces are interacting with one another at once. The simple act of a unit moving from point A to point B will touch nearly every chunk of data contained within the game. For this reason we don't think it's a great crime to include all data declarations in one module. By looking at a single module, you can get a good idea of how the game is structured and what all the pieces in play are. It also greatly simplifies importing.
The terrain in the game is procedurally generated and there is a module to specifically deal with that. “Terrain.hs” is responsible for generating random terrain using perlin noise and edge detection. A grid of perlin noise is generated, then layers are created by mapping ranges of values to specific integers. For instance, let 0 represent the water level, 1 represent sand, 2 represent dirt, 3 represent a ramp, and 4 represent a plateau. The perlin noise ranges from -1 to 1. So we can map values from -1 to -0.2 as water, -0.2 to -0.3 as sand, etc. We don't want units to travel between dirt and a plateau without using a ramp. So we use edge detection to find plateaus, then generate a ramp for each one to ensure units can access every plateau.
“Pathfinding.hs” is responsible for generating pathing data and finding paths using that data. After we have generated the terrain, we generate information for units to quickly navigate the world. To begin, we find every “corner” on the map. Let black represent tiles units cannot move through. Red represents corners on the map.
The previous diagram gives you a visual idea of how we identify corners. After every corner has been found, we perform a raytrace from every tile on the map to every corner. When this is done, every tile should know every corner it can “see”. Armed with this information, pathfinding using A* is trivial and extremely fast. It will take some time to compute visible corners and scales poorly for large maps, but the game-time benefits are awesome.
While “Pathfinding.hs” figures out where units should move, “Movers.hs” is actually responsible for moving a unit from point A to point B. When a unit moves, it may collide with walls and other units. To find nearby units, we use “Tree2D.hs” to construct a 2 dimensional tree every game frame that allows for fast lookups of nearby neighbors. When units bounding spheres are overlapping they push away from one another. Heavy units push lighter units around more and are pushed less by lighter units. If a unit would move into or through a wall, it is forced outside.
We now have the basic pieces required to get units moving around a map, but there's nobody to order them. “Competition.hs” is responsible for connecting players to the game, accepting messages from them (which are stored in a mailbox), and sending messages to the players. To create a competition, you simply state the port, the message decoder/deserializer you wish to use, and a list of teams with names & passes. When players connect to your server, they are automatically put into their respective teams and can now add messages to the mailbox. This module is very general purpose and could be used for any game with predefined teams.
We have the component for receiving and sending messages, but we haven't specified what those messages are. Every game frame (1/10th of a second), players need an update on the positions and attributes of units they can see. Since there can be hundreds of units visible to a player at any time, it's important that we save as many bits as possible when transferring information. Each unit is composed of a unique ID, a team #, an animation ID, a type ID, XYZ coordinates, and a facing angle. We cannot lose precision on a unit's ID because we don't know how many unique units a player will control throughout the game. We assume 4 bytes is enough to cover a player through any realistic match. For all other information we can either reduce the range/precision to save a lot of space. We know there will never be more than 255 teams, so it's safe to use just 1 byte for the units team. We can make the same assumption for the type ID and animation ID. To conserve space on the units XYZ coordinates, we have to know beforehand that the map won't exceed a certain size. For our game, we assume 1024
is the maximum size of any coordinate. This allows us to reduce precision from 32 to 16 bits. With 2 bytes a unit any occupy any of 64 (2^16 / 1024) different places between each tile. That's more than enough to fool the human eye.
2.5 Client Architecture
Basic Specifications:
- Client/Server model.
- Cross-browser/platform compatibility.
- JavaScript 2D client.
- 3 (+ 10) button UI layout (for touch devices).
Use Cases:
We are hoping that we will bring RTS fans to the mobile gaming market and introduce the mobile gaming audience to a more hard-core style of gameplay. There is, of course, the theory that “hard-core” games don't belong in the mobile arena because the audience will only support a 10 minute attention span. We are hoping that this doesn't hold true and that people will spend 20-30 minutes completing a round of our game. Only time will tell. Or maybe more research. I don't know how many people play Settlers of Catan on their phone but that's our market share either way.
Implementation Choices:
Excluding the flip-flopping about 2D and 3D graphics most of the game has been fairly static from early on. Game-play and UI design components have been completely independent of dimensional representation
Game Structure on Client:
PhaserState -- Phaser uses “states” to control application flow. You can think of states as being screens; Main Menu, Game Login, Options Menu, etc... States are used to manage asset loading.
PhaserGame – the game object that contains all of the current level data. This object is a global variable that is re-used for every level. However, Phaser does allow for multiple games to be created which would support a mini-game sort of functionality. We only have one game object though.
PhaserObjects – I won't go deeper into explaining the structure of Phaser except to say that it has all of your standard 2D engine bells and whistles. Support for touch, keyboard and mouse input handlers, sprite sheets, tile maps, animations like tweening, limited WebGL shaders, etc...
Logic flow from server listener:
ChefClass: Receives binary data from the server and parses it into game-readable event code. The ChefClass parses the data into messages called “cereal”.
2.6 UI Design
link to UI mock up/instructions
https://drive.google.com/?tab=mo&authuser=0#folders/0B1FaaEchU94Ya1F1T1p3RmVuUHM
When designing the UI we started by identifying the obstacles we had to overcome. Second, we developed a design that overcame said obstacles. Lastly, we are developing and will deploy our revolutionary design.
Through my research I found our 3 main obstacles on the mobile platform were/are:
1) limited AI capability for single player.
2) limited UI capabilities. The RTS genre relies heavily on complex hotkey setups.
3) limited/lo-fi assets do to decreased RAM size.
Obstacle 1: AI on a tablet.
People are spoiled. AIs nowadays are awesome. They often adhere strictly to the rules of the game and are truly an analog (if a poor one) for playing against a human opponent. It wasn't always like this.
In the early RTS days, most of your game AIs were pretty rudimentary. Many AIs were simply hard coded enemy factories that ceaselessly spewed units at you. As you progressed through the levels the enemy factory would simply go into over-drive and the mayhem would ensue. Eventually people caught on and weren't very happy with the situation. Apparently they didn't like that their enemy could “cheat” -nevermind the fact it can't think- but the game companies obliged as technology allowed. Which brings to our current day audience who expect a more complex play experience than gamers of old. One that truly is them versus a digital opponent not just a factory.
It wouldn't be unreasonable to assume that one of the reasons game companies are hesitant to tackle the
transition to mobile is because the AI constraints for single player mode might not be received well by
the younger audience of gamers. I am pretty sure this is why game companies have stuck to the TD genre. It thematically allows the AI to no longer have to consider economy or terrain-based combat. Which is HUGE! It allows the designers to revert back to the unit factories of old.
Obstacle 2: UI on a tablet.
This part just took sitting down and playing with an iPad to see what felt comfortable and what reasonably fit on the screen. Once that was accomplished (which was quite easy because much of this research was done for us) it was now a matter of sticking to the layout we had during game creation.
Which is actually an incredible difficult task but we did manage to design a fairly robust layout that should allow for 70-80% of the functionality provided by a full suite of hotkeys.
Basic UI mockup:
Obstacle 3: Assets on a tablet (and cross-platform compatibility).
Frankly this part has been a huge struggle. Figuring out what kind of 3D assets you can cram into the RAM of a mobile device is a real pain. After literally months of struggling with trying to scale down 3D model implementations and loaders I came to the conclusion that the only real way to get 3D assets into a browser game is to write your own model parser. You need the kind of per-vertex control only custom code can achieve in order to trim down model data to the most critical information. I am not ready to write our own model parser just yet so 2D is really the only option left. Hopefully our decision to move to 2D gives us the asset freedom we couldn't find with 3D. We need to be able to create enough graphical depth that terrain still feels as though it is on multiple levels. If we are successful in that regard I'm not worried about the quality of the graphics as most 2D games on mobile devices have been well received.
I think it's worth noting however that creating their own ultra-light model parser would be nothing for a AAA production company.
3 Status
On the server, we are currently able to make very basic mods that generate terrain and make some units for each team which can be ordered around. Players can connect to the game and see units moving around. The client is currently unable to send commands to those units so we simply have them ordered to move to the center of the map (assuming they can reach it).
Do to the indecision with the 2D/3D implementation choices we currently have 3 clients that are all in various states of functionality. Zach has an 2D Elm “view port” he uses to obverse unit behavior to troubleshoot the server code. I began the client in 3D so I have an implementation that is extremely un-performant do to the model loader I was using at the time. The implementation looks pretty and has all the foundational logic for screen panning, marquee select, unit spawning, and a few other basic dummy functions. I simply had to abandon it because I couldn't figure out how to make it performant shy of coding my own model loader from scratch (which the project time-line didn't allow for). The 2D implementation I am currently working on I have only been coding for just over a month. In that time I have almost caught up to the amount of work I completed on the 3D client in 4 months. The 2D client currently has all the bells and whistles of the 3D version but with better functionality for the event listeners.
4 Conclusions / Critique
If we were to do this project again, we would greatly simplify what we expected to accomplish. Originally, we planned on having 3D graphics, units shooting stuff at each other, and terrain would only be revealed to players as they discovered it. 3D graphics proved to be the most problematic. WebGL is very new technology with buggy model loaders. To get it working, we would have to implement our own model loader or stick to using static scenes. There are very few WebGL games with graphics beyond simple colored polygons, which makes for few examples. If we hadn't aimed for 3D we would have a lot more done at this point. We may have even met every other goal.
We wanted to have our unique UI implemented so we could show that a RTS game for tablets is feasible and comparable to the PC. Trying to get 3D working delayed us and we don't have the real innovation to show off. The server development came pretty close to the original goal. A few steps of the original plan were switched around and all terrain is visible to all players immediately. The modding support actually went better than expected. I believe with continued development, we could make a game that is easy for players to change and manipulate to their liking. Haskell's default laziness had an effect on performance and was annoying to deal with (as we anticipated), but adding a few deepseqs solved the problem.
5 Future Work
Getting a fully functioning client is top priority for the future as the UI might define the success of the project overall. This will allow us to really experiment and test out the design of the game. Once we have a working client, we can add in game features at will and see them in action. When we get something working that is fun, we will focus on making modding easy to do with plenty of documentation. Currently, games must be configured manually via text file, so in the future we'll need a coordinating server like “Battle.net” which can setup games for players. Once we have that infrastructure in place, we could market our game to the masses.