Lila Games Player Journey Explorer
A browser-based gameplay analytics tool that transforms raw player telemetry into an interactive experience for understanding player movement, combat and map behaviour.
Lila Games, sent me this as the first-round assignment for a Product Engineering role. As part of the application process, I was given five days of production gameplay telemetry from LILA BLACK, along with minimap images for three maps and documentation explaining the data format and coordinate system. The task was to turn this raw telemetry into a browser-based tool that could help a Level Designer understand how players actually move through the game.
I already have a detailed article here
The Problem
The raw gameplay data contained a large amount of information about player movement and gameplay events, but raw telemetry is difficult to reason about directly.
A Level Designer shouldn't have to inspect thousands of rows of player coordinates to understand whether a particular area of a map is being used. They shouldn't have to manually correlate timestamps with player positions to understand where fights happened. The useful information is already present in the telemetry, but it needs to be transformed into something that makes those patterns visible.
The questions I wanted the product to help answer were fairly straightforward. Where are players actually moving? Where are players spending most of their time? Where are fights happening? Where are players dying? Which areas of the map appear to be underutilized? How does a match unfold over time?
The assignment therefore wasn't simply about displaying player coordinates. It was about designing an interface that could turn telemetry into something a Level Designer could investigate.
Starting With The Data
I deliberately started by understanding the data before designing the interface.
The assignment provided gameplay telemetry in Parquet format, along with documentation explaining the schema and coordinate system. I first explored how matches, players, timestamps and gameplay events were represented and how those pieces of information related to one another.
This was important because the visualization would only be useful if the underlying interpretation was correct. The assignment also highlighted several areas that required particular attention, including coordinate mapping, timestamps, bot detection and the representation of gameplay events.
These weren't just implementation details. Getting any of them wrong could lead to a visually convincing application that was actually showing incorrect information. That became one of the guiding principles of the project: understand what the data actually says before deciding what the product should show.
Turning Coordinates Into A Map
One of the first major roadblocks was coordinate mapping.
The player movement data was represented using game-world coordinates, while the provided minimaps were 1024 × 1024 images. The two coordinate systems weren't directly interchangeable, so simply plotting the raw X and Y values onto the image produced incorrect positions.
I therefore had to determine how the game-world coordinate space corresponded to each individual minimap. Since the three maps had different coordinate ranges and alignments, I treated each map separately and established the required origin and scale values for the transformation.
The general flow became:
Game World Coordinates
↓
Map-specific transformation
↓
Minimap Coordinates
↓
Canvas Position
I then validated the transformation by checking whether the resulting player positions actually aligned with recognizable areas of the map.
This was one of the most important parts of the project because every visualization depends on it. A player path that is technically rendered but geographically incorrect would make every subsequent analysis misleading.
Deciding What The Product Should Show
Once I understood the data, I started thinking about the experience from the perspective of a Level Designer.
The assignment required player journeys, gameplay events, filtering, playback and heatmaps. But I didn't want these to feel like a collection of unrelated features.
I wanted the product to answer questions progressively. A designer could first select a map and match, then observe how players moved through the environment. They could then look at specific events such as kills, deaths or loot and understand where those events occurred. Finally, heatmaps could provide a higher-level view of the same behaviour and reveal broader spatial patterns.
That led me towards three interconnected layers of exploration:
- Player journeys
- Gameplay events
- Spatial heatmaps
The timeline then became the common interaction connecting them.
Designing The Player Journey View
The player journey is the central part of the application.
Instead of displaying every movement event as an individual point, I wanted to show the path players took through the map. This makes it much easier to understand routes, areas of concentration and the relationship between different parts of the map.
Human players and bots are visually distinguished so that a Level Designer can understand who is contributing to a particular movement pattern.
The journey can also be viewed over time using the playback controls. Rather than seeing a match as a static collection of paths, the designer can watch the match unfold and understand how player behaviour changes as the game progresses.
This was an important product decision because movement without time provides only part of the story. A static path tells you where a player went, but playback helps explain when and in what sequence those movements happened.
Making Gameplay Events Understandable
Player movement alone doesn't explain what is happening inside a match.
A path can tell you that a player moved through an area, but it doesn't tell you whether they found loot there, encountered another player, got killed, or died to the storm.
I therefore treated gameplay events as another layer of information on top of the player journeys.
The tool distinguishes events such as:
- Player kills
- Player deaths
- Bot kills
- Killed by bot
- Loot
- Storm deaths
Each event has its own visual representation, allowing the designer to understand not only where players moved but what happened when they reached different parts of the map.
This also made it possible to connect individual events to the timeline and investigate them in the context of the wider match.
Heatmaps As A Different Way Of Looking At The Data
The next question was how to move from individual player behaviour to broader patterns.
A Level Designer may not necessarily care about the exact path taken by one player. They may instead want to know whether a particular part of the map consistently attracts players or whether combat repeatedly occurs in a specific area.
For this, I created three heatmap modes:
- High Traffic
- Kill Zones
- Death Zones
High Traffic highlights areas where player movement is concentrated. Kill Zones show where combat results in kills, while Death Zones highlight areas associated with player deaths.
The important part wasn't simply generating a heatmap. It was giving each heatmap a clear question behind it.
Instead of asking the designer to interpret a generic density visualization, the interface allows them to switch between different behavioural lenses. This makes the same underlying telemetry useful for answering different design questions.
Filtering The Investigation
A dataset covering multiple days, maps and matches can quickly become overwhelming.
Filtering therefore became a fundamental part of the experience rather than an optional feature.
The tool allows the user to narrow the analysis by:
- Map
- Date
- Match
This lets a designer move between broad and specific questions.
They can look at a particular map across multiple matches to understand recurring behaviour, or isolate one match when investigating a specific gameplay sequence.
The idea was to make exploration feel progressive rather than forcing the user to process the entire dataset at once.
Another Roadblock: Understanding Bots
Bot representation introduced another interesting ambiguity.
The telemetry contained bot-related information, but not every situation provided the same level of detail. Some matches contained explicit bot participants with movement data, while other gameplay events could indicate interactions with bots without providing a corresponding bot journey.
My first instinct could have been to infer the missing movement data, but that would have meant creating information that wasn't actually present in the source data.
Instead, I chose to preserve the distinction.
When bot movement data exists, it is visualized as a bot journey. When only a bot-related event exists, the event is still represented without inventing a corresponding path.
This was a small but important product decision because analytics tools need to distinguish between what the data proves and what the system merely assumes.
Choosing The Technology
I wanted the final application to be fast to build, easy to iterate on and simple to deploy.
I chose React and TypeScript for the frontend because the application contains several interconnected states. The selected map, date, match, active visualization, playback position, filters and event selections all need to update the interface together.
Vite provided a lightweight development and build environment, while Tailwind CSS allowed me to iterate quickly on the interface without introducing unnecessary styling complexity.
For the visualization layer, I used React Konva. The application needed to render player paths, event markers, heatmaps and other elements on top of a map image, making a canvas-based rendering approach more appropriate than trying to represent thousands of visual elements using standard HTML.
Python was used for the data-processing stage, particularly for reading the Parquet files, transforming the telemetry and generating the data structure consumed by the frontend.
The technology choices were therefore driven by the problem rather than by a desire to use a particular stack.
Why I Chose Preprocessing
Another architectural decision was whether the application should process the raw Parquet files at runtime.
I decided against it.
The dataset was static for the purpose of this assignment, so there was little value in introducing a backend just to process data that wasn't changing. Instead, I built a preprocessing pipeline that converts the raw telemetry into lightweight JSON files that the frontend can consume.
The resulting architecture is intentionally simple:
Parquet Files
↓
Python Processing
↓
Coordinate Transformation
↓
Processed JSON
↓
React Application
↓
Interactive Visualization
This allowed the deployed application to remain client-side and avoided the need for a database or API layer.
The tradeoff is that adding new telemetry requires running the preprocessing pipeline again and redeploying the application. For this particular use case, I considered that a reasonable tradeoff in exchange for a simpler architecture and a faster development cycle.
Designing For The Actual User
One of the most important things I took away from the assignment was the distinction between building for a developer and building for a Level Designer.
A developer might be comfortable looking at raw coordinates, event IDs and timestamps. A Level Designer shouldn't need to understand any of that.
The interface therefore focuses on visual relationships.
A player path is more useful than a list of coordinates. A kill marker on a map is more useful than a row in a database. A heatmap showing a recurring combat zone is more useful than manually counting events.
This influenced the overall design philosophy.
The product should make the answer visible rather than make the user calculate it themselves.
From Building The Tool To Using The Tool
Once the Explorer became usable, I stopped looking at it primarily as a developer and started using it as if I were investigating a map.
This was where the project became much more interesting.
The visualization made certain patterns immediately noticeable. Player movement appeared to concentrate around compounds, while some connecting areas showed considerably less activity. Combat events also appeared to cluster around particular areas instead of being evenly distributed across the map.
Those observations led to more interesting questions.
-
Are compounds naturally acting as the primary destinations for players?
-
Are some parts of the map underutilized because they don't offer enough incentives?
-
Are repeated combat hotspots intentionally designed engagement areas?
-
Or are players being funnelled into these locations because the alternatives aren't attractive enough?
The tool doesn't automatically answer all of these questions.
Instead, it makes them easier to ask.
That was an important distinction for me. The goal of the visualization wasn't to replace the Level Designer's judgment. It was to give them a better starting point for that judgment.
What I Learned
The biggest lesson from the project was that building a data visualization product is not simply about displaying data.
The difficult part is deciding what the data should help the user understand.
A raw telemetry dataset can contain millions of useful observations, but exposing all of them doesn't necessarily create a useful product. The product becomes valuable when those observations are transformed into interactions and visualizations that correspond to real questions.
I also learned how quickly technical details can become product decisions.
Coordinate mapping initially looked like an engineering problem, but it directly affected whether the entire product could be trusted. Bot detection looked like a data-cleaning problem, but it affected how users interpreted player behaviour. Playback initially looked like a UI feature, but it became an important part of understanding how spatial behaviour changes throughout a match.
The boundaries between engineering, data and product thinking became much less distinct as the project progressed.
What I Would Explore Next
The current version is primarily designed for exploring individual matches and understanding the behaviour captured within them.
The next opportunity would be moving from individual match exploration towards comparative analysis.
I would be interested in exploring:
- Comparing player journeys across multiple matches
- Identifying recurring routes and movement patterns
- Comparing kill and death hotspots across different dates
- Overlaying multiple matches to identify persistent areas of activity
- Measuring how player behaviour changes after map or gameplay changes
- Exploring live or continuously updated telemetry
These additions would change the product from a match exploration tool into a broader level-design analytics system.
The most interesting direction would be connecting the telemetry more directly to game-design decisions. Instead of simply showing that an area has low traffic, the product could help designers investigate why that might be happening and compare the behaviour before and after a map change.
That would turn the tool from a visualization layer into a feedback loop for level design.
The Conclusion
I built the Player Journey Explorer in phases over three days, gradually moving from understanding the raw telemetry to building the visualization and then refining the experience around how a Level Designer would actually use it. Each phase introduced a new problem to solve, from processing the Parquet data and figuring out coordinate mapping to rendering player journeys, gameplay events, filters, playback and heatmaps.
What I enjoyed most was how quickly the project moved between product thinking and engineering. A technical roadblock would often lead to a product decision, and a product question would force me to rethink how the data should be represented. Rather than trying to build everything at once, I kept the scope focused and built the tool step by step, validating each part before moving on.
Over those three days, I ended up with a lightweight browser-based Player Journey Explorer built using React, TypeScript, Vite, React Konva, Tailwind CSS and Python-based data preprocessing. It was one of those projects where the process of figuring things out was just as enjoyable as the final product, especially because I could see the tool becoming more useful with every iteration.
P.S: I was rejected after the first round of Technical Interview, but will keep an eye on future opportunities for sure :)