Grocery Game

A grocery store role-playing game.

Full Speed Ahead, Painting Shelf Space

This week we’ll be showing off:

  • A shelf space painting prototype, and
  • Discussion of the technology behind the game and and some challenges encountered while implementing the shelf brush

If you’d like to play the game:

Subscribers of $5 or more on Patreon and other donors will also receive access to an Alpha version of the game.

Patreon PayPal Logo

Attention shoppers, we’ve got shelves!

Screenshot of Shelf Painting Prototype

Shelf space is painted with the S Shelves tool.

Challenges

By far, the biggest hurdle this last week was implementing procedural generation for shelves. The current solution is a somewhat convoluted application of Graph Theory and Linear Algebra.

Diagram Drawing of Shelf Graph

Diagram of the graph representation of a shelf area on the game world’s grid.

When the user paints shelf space in the world the game creates a graph representation for each discrete shelf area. An individual graph’s nodes are each painted square and its edges are the connections between neighboring squares. This abstraction allows the game to relatively quickly find unoccupied shelf space and makes it easier to reason about relationships between neighboring shelf squares.

Periodically, the game iterates over all unoccupied shelf space to fill with generated shelves. A library of shelf generation functions are abstracted into a collection of shelf Archetypes. Each archetype has properties limiting where and how the shelf it generates may be placed. For example, the Aisles archetype has a minimum size and a flag preferring that it be placed back-to-back to other aisle shelves.

Technical Odds & Ends

Ultralight and HTML GUIs in Games

The game’s UI also evolved this week:

Screenshot of Updated GUI

Using the nascent Ultralight library and reactive widgets with the lit-html and mobx JS libraries allows rapid iteration of new game experiences.

Heavily referencing Maxis’ GDC talk on HTML Game GUIs[1] inspired an interface with the game logic that has a very low surface area. The GUI posts JSON commands through a JS interop and the game responds to those commands with feedback about the action taken.

I might expand on this system in a later blog post.

D Lang and Templates

Landing on D was an adventure through the landscape of systems programming. In fact, Grocery Game went through prototyping iterations in three different languages.[2]

The game logic needs a systems language to stay fast, especially with the goal of a full agent-based simulation of people in the store. Trial end error eventually led to D. Its expressive C-family syntax and robust standard library were a big selling point. Later, the power of D’s template system has proved useful in keeping code readable and appropriately terse.

Take some of the game engine’s math helpers for example:

// Unit conversions
private import std.traits : isIntegral, isNumeric;
/// Converts km to meters
float kilometers(T) (T a) if (isIntegral!T) {
  return a * 1000.0f;
}
/// Converts cm to meters
float centimeters(T) (T a) if (isIntegral!T) {
  return a / 100.0f;
}
/// Converts mm to meters
float millimeters(T) (T a) if (isIntegral!T) {
  return a / 1000.0f;
}

/// Converts yd to meters
float yards(T) (T a) if (isNumeric!T) {
  return a / 1.094f;
}
/// Converts ft to meters
float feet(T) (T a) if (isNumeric!T) {
  return a / 3.281f;
}
/// Converts inches to meters
float inches(T) (T a) if (isNumeric!T) {
  return a / 39.37f;
}

These generic unit conversion functions are constrained with Traits afford elegant expressions, like this:

// Convert 4 yards to the game's metric system
auto width = 4.yards;

// Use `width` elsewhere...

What’s Next

Full speed ahead!

Full speed ahead with your shopping cart GIF

GIF via Giphy

Shading the World with Shaders

The game is looking very flat at the moment, but there is a plan to fix that:

Sketch of possible world shading for the game

Pictured is a sketch of how the game might look shaded with artificial sunlight.

Constructive Solid Geometry

At the moment, the game’s uses a house-made rudimentary procedural generation engine that takes a set of constraints as input and generates cuboids as output. The cuboids are then unceremoniously drawn with Raylib’s DrawCube function. It will probably become a bottleneck in the rendering pipeline to draw all of the cuboids like this, so the plan is to eventually generate a whole solid mesh from the cuboid output using CSG.

Agents, Shoppers, Staff, and Pathfinding

After a couple of other shelf type archetypes are implemented, agent-based modelling for store patrons and staff will be prototyped.

Citations

Alpha Access

If you’d like to play the game:

Subscribers of $5 or more on Patreon and other donors will also receive access to an Alpha version of the game.

Patreon PayPal Logo

Feedback

Let me know your thoughts and suggestions! What would you like to see in the game?

Written on October 8, 2020