Posts Tagged ‘Tabletop Simulator’
The Die is Cast
comments

The one feature that I knew I wanted for dice was rolling the dice directly on the map and watching them clatter about and bounce of the walls, floors, and miniatures. I wanted to avoid using the Unity physics primarily because it’s non-deterministic and, like most physics engines, a bit squirrely and unpredictable.

I spent a fair amount of time investigating other possibilities and I was getting close to a workable solution, but it was ultimately going to consume too much time and effort to develop a custom die-rolling system. I chose, instead, to go ahead and implement dice rolling with using the built-in physics. The Unity documentation specifically calls out scale as an issue with their physics engine. The presumption is that 1 unit = 1 meter and the physics are calculated using that scale. It’s not modifiable.

Fortunately, when I began the project, I knew that the scale of the map may one day be a factor and that day was today. I included a global scale factor that let’s me arbitrarily modify the overall scale of the world. I’ve been working at a scale of 40 (an entirely made-up test number). To get the physics simulation of the dice to look at all correct, I had to set the world scale down to 0.5. To get a true representation of 25mm figures, I’d need to set the scale to 0.025. Unfortunately, the physics simulations fall apart at that size.

The second issue with the smaller scale is that the font rendering in Unity does not like tiny fonts. Fonts that once rendered well, now are all blurry. For dynamic fonts, Unity uses OS specific font renderers and the Windows renderer does not like font sizes that small. I may have to create custom textures for the movement costs. Other than the text, I have a few issues still to resolve.

1) I’m determining the value of the roll by checking the orientation of the die when it comes to rest. Sometimes the simulation results in a “cocked die” that isn’t lying flat on the surface. Currently that is resulting in a value of 0, but it’s addressable. For dice that are really cattywampus, the die can just be re-rolled. For those that are pretty close to flat, I’ll have to adjust the calculations to allow for a greater range of orientations.

2) Sometimes the dice fall off of the table. Constructing an invisible box to contain the dice, or just an invisble plane, should be enough. It’s just on the to-do list.

3) At the moment, I’m only rolling six-sided dice. Determining the facing side of a d20 is significantly more involved. I have some work with pen-paper to figure out the best way to handle polyhedral dice. Worst case is a look-up table. For the standard six dice, this shouldn’t be too bad. It’s only eight if I included the d30 and d100.

Most importantly, rolling the dice is pretty fun. It has much of the same satisfaction of rolling real dice on a table. Take a look as I roll some dice. Lots of dice.

What you see is…
comments

Probably the most head-scratching, frustrating feature I’ve tackled so far has been calculating line-of-sight. It’s something that can’t work 90% of the time, or fail on some edge cases. It has to work 100%. And that’s the part that kept me busy with the graph paper checking the math.

My first approach was to “walk the squares” out from the miniature and test collision with any walls encountered. This “marching squares” algorithm was working well and as expected, but it failed on corner cases. As the LOS rays traversed across the map, there were cases wherein the ray would miss potentially visible squares by passing precisely through the corner and ignoring the squares on either side. I spent a while trying different solutions, but none of them were satisfactory.

I moved on to casting rays from the miniature through the end points of each wall section to the edges to check for collision. The rays were then sorted by angle and the collision points connected to form visibility triangles. When considered all together, these triangles formed the potential visibility. Again it was failing on the edges. This time, rather than a miss, I was getting early rejection. The ray was intersecting the end of the wall segment and stopping. It was working well enough, unless the miniature was standing in a doorway or narrow opening between walls.

I tried a few a few tweaks: shortening the walls slightly at the end of the segments, tweaking the angle of the rays. None of these solutions were 100%. Finally, I settled on splitting the rays—guaranteeing that one ray would collide with a wall and the other, if it was open on one end, would slip past. This has doubled my ray count, but it should be a negligible difference once optimizations are in place. A linear increase is far more desirable than an exponential or logarithmic one.

In order to prevent the player from “peeking around corners,” the line-of-sight is only reset when the player drops the miniature and movement is restricted to those squares that are visible. There is still a slight issue. When a visibility triangle intersects a square, that entire square is visible. So the player can sometimes see slightly around corners.  I have a couple of avenues to address this issue. Real-time shadows and render-to-texture are cleverly disabled in the free version of Unity, so with an upgrade to the Pro version this may no longer be a problem. Additionally, I have the triangles calculated. Those calculation are accurate and could be used to create a stencil, either for rejecting pixels at render, or for creating a projection mask for the spot light that hovers over the miniature.

I am contemplating revealing a 2D map for any squares that the player has already seen, but are not currently visible. This help prevent the player from getting lost. I only hope that it doesn’t spoil the dungeon feel that is achieved by only rendering part of the map. I’m also calculating visibility for 360 degrees around the player and not considering miniature facing. It will be trivial to do so and will likely be an option.

There are number of optimizations remaining. Primarily the walls for collision testing need to be sorted by proximity to the player. As it stands now, the routine runs at framerate for smaller maps, but slows to a crawl on large maps. For now, it is functional and, as I like to say, “I’ll burn that bridge when I come to it.”

Unity-LOS-debug from C. Lewis Pinder on Vimeo.

Unity-LOS from C. Lewis Pinder on Vimeo.

New Miniatures
comments

As some of you know, I’ve had trouble finding the aesthetic that I want—particularly for the miniatures. I tried a number of approaches, but I never achieved the dynamic poses and “chunky” look of old school miniatures. A few weeks ago, my brother sent me a care package with some of our old gaming gear. In the dice pouch of the package were a few Ral Partha miniatures from 1979. These were definitely the look I’m going for.

Ral Partha miniatures.

I picked two of minis (a dwarf with a torch and an ogre with a large club). I took a ton of reference photos and built a rough representation in 3DSMax .

Rough meshes in 3DSMax.

Dwarf in Sculptris.

That mesh was then imported into Sculptris for detailing. Sculptris was a lucky find. While Z-brush is the “industry standard” for sculpting, the UI was apparently designed by a blind man describing it to a deaf person. I’ve never been able to overcome the dreadful interface to produce anything useful in Z-brush. I’ve tried Mudbox, which is a huge usability improvement, but I’ve given enough money to Autodesk already. Sculptris is both simple and free.

Ogre in Sculptris.

Once in Sculptris, I sculpted in the details and then exported back out to 3DSMax to render the new high-res mesh into a normal map for the original lo-res representation. I’m definitely getting closer to the look and feel of miniatures, but I obviously cannot blatantly lift all the designs from Ral Partha. I ordered some more generic plastic figures from Amazon and they look to be a good basis to add custom details.

Lo-res Minis with normal maps.

Along the way, I wound up writing a custom mesh exporter/importer. Unity’s default support for FBX files is nice, but it carries with it a lot of overhead I don’t need. Worst of all, to convert the 3DSMax z-up models into Unity’s y-up coordinates, the FBX exporter adds a 90 degree rotation to the model’s transform. Carrying around the transform was polluting all of the rotation code for the miniatures in game. Additionally, Unity insists on applying a 0.1 scale on all FBX model imports. This can be changed, but it’s on a per model basis and a new default can’t be set.
I’m not reinventing a perfectly good wheel just to do it. I’ll be setting up groups of vertices in the future to allow the players to change the colors on the painted miniatures and I don’t won’t to try to piggy-back that on an FBX export.

Next up, we’ll talk about line-of-sight visibility and how that kept me up at night.

Where I Split Walls
comments

I’ve been doing quite a bit of work over the last month, but I’ve neglected to post any updates on my progress. In honor of today being Tabletop Day, I’ll get back to writing updates. Rather than overwhelm you with a single post on all the changes and new features, I’ll break them down and post each individually as I write them up.

The first change was in the map structure itself. Originally I was storing the map in a rather naive fashion, knowing all along I would have to update it at some point. The original method stored the grid squares as either open or as a wall. This worked fine for test purposes, and made maps much easier to mockup. Unfortunately, anyone who’s ever mapped a dungeon during play realizes that the walls are most frequently represented as a line along the grid lines—not in a square, but between them.

To represent this, I have split the walls, storing half in each square. A wall running horizontally, for example, would be stored as a wall running east-west with the north facing half in the upper squares and the south facing half in the lower squares. As line-of-sight is coming on line this has the added benefit of only rendering the side of the wall that is visible.

What, on the surface, is a rather simple change in representation has the knock-on effect of requiring significant additional artwork and the added logic for determining which wall piece is necessary: currently it requires twelve wall pieces when you account for straight walls, end caps, inside corner and outside corners. Thirteen pieces if you include that I have two middle wall pieces to create a 10′ span of wall with 5′ squares.

Next up, miniatures.

AFK
comments

I’ve wrapped up work on some other projects (The Borderlands and Apollo Zero) and I’m back at the keyboard. When we last left off, I’d just finished putting together a small level based on the Hirst Arts gothic dungeon. It was good to get some hands-on (even if they were virtual hands) experience building a dungeon based on practical models. However, as often happens, I ran into some issues with my implementation and took a different approach.

On Prototypes
Everyone certainly has their own approach to prototyping, but for me—in the early stages—it’s involves a great deal of create, tweak, and restart. At each stage, I start anew. Borrowing pieces of code that worked, but willing to toss away whole pieces that don’t quite fit the bill. Such was the case for this stage of the prototype. read more

Test Dungeon
comments

I’ve finally had a break on some of the projects I’m involved in which has allowed me put together a test dungeon. Having never built any practical tabletop terrain for miniatures, I decided to recreate the sample gothic dungeon from Hirst Arts.

 

Hirst Basic Gothic Dungeon

This will give me the opportunity to test solutions to number of necessary features: read more

Feature Creep
comments

We’re all familiar with feature creep, the adding of features to software until you’ve either bloated the program or significantly deviated from the original intent. Even this early in the process, I suddenly found myself recognizing this happening. While working on some new artwork as I begin adding terrain templates and costs, I realized I was targeting the wrong aesthetic.

First it was lighting. I was considering, as I worked with the art, the effects of torches and other motivated light sources. How was I going represent lighting in the world when, for example, the character is carrying a torch or lantern?

Second it was the miniature. I modeled a quick miniature and rigged it to a skeleton so that I could not only pose it, but do some simple animation.

Lastly, it was the materials. I was thinking in terms of real world materials: stone, marble and the like. read more

Now With Pathfinding
comments

Movement with pathfinding.Pathfinding is finally working on the map. After spending some time with a recursive function that just didn’t want to return, I have a functioning shortest-path algorithm implemented. Surprising, I had the most difficulty with moving the miniature off the grid. You’ll notice in the video that not only is it successfully finding its way around the hole in the floor, but you can also drag the miniature over the hole and it solves the path as soon as it’s on the other side.

I’ve spent some time considering different methods of movement, in particular, setting waypoints and evaluating movement at the end of the turn. After picking up and moving the mini around the map countless times, I’m currently inclined to not do waypoints. Picking up the mini and setting it down until all the moves are expended feels the most natural to me, the most like moving a real miniature. If the player really has made a mistake and needs to reset the move, the GM could undo the action and allow the player to redo some or all of the move. read more

What Makes You Special?
comments

There are a number of virtual tabletops for gaming available: Roll20, Tabletop Forge, and RPGTable Online. I was recently asked, what will make your product different from what’s already available? It’s a fair question to ask and a good question to answer. From time to time, it’s important to “justify” your work. To make sure that what you’re doing is unique and addresses existing needs.

So let’s take a look and see what’s the difference between what I’m offering versus other in this space. read more

Movement With Cost
comments

Movement with costI picked up some VFX work, so I’ve been away from the project for a few days. Now I’m back and working on movement again. I’ve made quite a few changes behind the scenes and added some features up front.

On the back-end, the grid and movement have been completely abstracted to separate classes with support for arbitrary grid size and distance. I’ve also added a main game loop rather than lazily attaching the logic to the camera which is what I had done. read more