Getting a Board Game to Play on a Screen
Vassal Engine is a free Java application for building and playing digital board games. You take a physical game, scan or photograph its components, map out the rules as scripts, and suddenly you have a playable version on your computer. It has been around since 2001, it has a dedicated but stubborn community, and it powers a significant portion of the online wargaming world. The reason people still use it despite better-looking alternatives is that it does one thing and does it without requiring you to subscribe to anything or download proprietary software each time you want to play. Here is how I actually built my first module and what went wrong in the process. I started with Warhammer 40k, second edition, because it was a game my group wanted to play during a week when we could not get together in person. I needed the map, the miniatures represented as tokens, the combat tables, and the dice rolling mechanism. I went to vassalengine.org and downloaded the installer. The current version runs on Java 8 through 11 depending on your setup, and the site will tell you which one you need. You run the engine, create a new module, and you are presented with a blank board where you drag and drop game pieces onto.
The first thing I learned was that the documentation assumes you already know how things work. The module builder looks like a basic drawing program with a Properties panel that changes depending on what you click. If you select a counter and open Properties, you see fields for image, rotation, zoom scale, and then a long list of behaviors you can attach. Behaviors are the core concept. A behavior is a scriptable action that triggers when something happens, like a player clicking a unit or rolling a die. You do not code these from scratch. You pick from a menu of existing behaviors, and the engine inserts a template for you. I spent three days just mapping out the counters. Each unit on the board is an image file, usually a PNG with a transparent background. I scanned the unit cards at 300 DPI and converted them. I placed them on the board, set their coordinates, and then I attached the ClickBehavior so they would be selectable. That seemed straightforward. It was not. The first real problem hit me when I tried to build the combat phase. I wanted a button that both rolled a die and modified a unit stat based on the result. The engine has a DieBehavior and a MoveBehavior and a StackBehavior, but none of them combined what I needed. I ended up writing a custom Java behavior inside the module. That meant compiling a small class file and dropping it into the module directory. The compilation failed twice because the classpath was wrong. I fixed it by copying the Vassal.jar into my compile command with the -cp flag. After that, it worked. I still use that workaround today. If you need anything beyond the standard behaviors, you are going to hit this wall.
Now here is something most guides will not tell you. The dice rolling system in Vassal is not built for fairness if you are doing tournament play. It is built for convenience. When a player clicks a DieBehavior, it generates a random number, but the randomness comes from Java's Math.random() or SecureRandom depending on how the module author configured it. Neither is cryptographically secure. More importantly, there is no audit trail. If someone claims they rolled a different number, you cannot verify it. I had this happen once in a ranked game. A dispute over a six-sided roll broke down our match. The solution was to run an external dice roller alongside Vassal and log every result in a text file. I wrote a simple AutoHotkey script that intercepted the click and wrote the timestamp, player, and result to a log. It is a workaround that should not be necessary, but it is necessary if you care about integrity. Another counter-intuitive detail is how zoom and image quality interact. Vassal scales images based on a resolution setting in the module properties. If you set the resolution too low to improve performance, your counters look pixelated at higher zoom levels. If you set it too high, the engine becomes sluggish on older machines. The sweet spot for most 40k-scale modules is around 72 DPI with individual counter images at 600 by 600 pixels. The module file size will be larger, but the gameplay experience will not stutter. I learned this after a playtest where my opponent's machine choked at fourX zoom and we had to reduce the board visibility just to keep the game moving. Let me talk about the limitations, because they matter more than the tutorials suggest.
Get the Full Details

Vassal does not handle multiplayer well outside of its own chat system. The chat is basic and it has no message history retention between sessions. If your group wants to keep logs of what happened in each game, you have to export them manually. The export function creates a text file, but the format is inconsistent across versions. Some modules log actions by behavior name, others by custom text. You will spend time figuring out what your specific module recorded instead of just reading the log. The UI is unchanged for over a decade. It looks like Windows software from 2005. This is not a marketing complaint. It is a usability fact. New users will stare at the screen for twenty minutes before understanding that the Properties panel is where everything lives. There is no onboarding. The help files are text documents that assume familiarity with terms like "widget," "behavior," and "module type." If you are willing to push past that, it becomes manageable. If you are not, you will abandon it within the first hour. There is also the dependency issue. Vassal requires Java. If your system blocks Java downloads or uses a managed profile that restricts third-party executables, you cannot run it without administrative help. I have encountered this in corporate environments where IT policy prevents Java runtime installation. The alternative there is to run Vassal on a separate machine or use a containerized version, but that adds complexity that defeats the purpose of using it in the first place.
For people who want to try it, the download is at vassalengine.org. It is free. No account required. You install it, you open the Module Builder, and you start creating. The learning curve is steep but finite. A simple module like a hex-based wargame with counters and a single die roll can be built in a weekend if you follow the examples on the Vassal forums. A complex module with custom behaviors, multiple phases, and network play will take months. Be honest with yourself about which category your project falls into before you commit. If Vassal feels too limiting for what you need, alternatives exist. Tabletop Simulator on Steam offers physics-based play with a much wider community and easier scripting via Lua, but it requires a paid license and an internet connection to the Steam servers. Tabletopia operates similarly with a subscription model. For pure rule simulation without the physics layer, OpenBoardGame is an option, but its active development has stalled. None of these match Vassal's combination of zero cost, offline play, and deep rule customization. That is why it persists. I stopped maintaining my modules two years ago because the effort required to keep them compatible with new Java versions outweighed the benefit. The workaround was to freeze the module on Java 8 and ship the runtime with it, which is technically possible but annoying for users. If you build something now, plan for that maintenance burden from the start.