Sportbedrijf Drachten is a foundation that aims to encourage healthy behavior to all residents of Smallingerland through sports and exercise. They have community sport coaches who motivate children to exercise. The foundation wanted a tool to for the coaches to help them achieve this goal.
8D Games facilitated a brainstorm. They came to the conclusion to achieve this, an app had to be made for iOS and Android. A coach could create missions in a back-end for the users. These mission are a collection of tasks. There had to be two types of tasks: Location- and Code-tasks. Location tasks are completed upon reaching a specified location. Code tasks are completed when a user entered a the correct corresponding code (usually received from a coach).
Everytime a user completed a task or a mission, the user had to receive points. These points can then be spent on cosmetics for a mascot. A cosmetic is unlocked using lootbox mechanics. A personal note: I don't find this dopamine explotation mechanic ethical, and especially for audiences such as children. After raising these conserns the product owner, and client still wanted to include this mechanic. So I included it.
We [an artist, a web programmer and I] had three weeks to create the app. I had the task to develop the iOS and Android app. This had to be done in Unity game-engine.
A question that arose when I wanted to develop the score tracking system: What is the best way to do this? The simplest thing is just to have a single integer. I had an under belly feeling that the app might be expanded (stonecoal English, because I have a poor sense of humor). This combined with the fact I have bad experiences with using the result instead of the source; I wanted to use a different approach. As suggested, tracking all sources of score invluences. All events are saved. Everytime the score is needed, it gets calculated based on all previous events. An event is completing a mission or spending some on lootboxes. You also are able to get additional points achieving
A user can earn points when completing achievements, tasks and mission. And lose points when buying lootboxes. Achievements are a result of tasks and missions, so this needn't to be tracked. To track only missions, tasks and items, everything can be updated and the score will update itsself. For example: When a new achievement has been added, it triggers automatically for everyone already completed its requirements. The biggest downside of this system is that it needs relatively an exreme amount of computation. After testing this, it didn't have a noticable impact on performance, so this was the system that I kept in place.
There are sixteen (16) unique items to achieve, and each have nine (9) different textures. In the customization screen, each item was depicted by an icon. So there had to be made a hundred forty four (144) icons. It was obvious to create a generator. My first attemt to keep the size of the app at a minimum was to generate them on the fly. This turned out to increase loading times by a lot (around a minute if you had all 144 items). The next thing was to include them in the project and load the icons if required. The size increase was less then I expected, and loading times were acceptable.
The first verion that was released was in July 2019. Before -spoiler alert- the first expension the app was called Missie0512. The image below renders as it was first released.
Less than a year had passed. Sportbedrijf Drachten and 8D Games saw success in the app. There was a need to expand the reach to other areas in The Netherlands. To get the most out of the app, they started a foundation called Move2Play.
The app and backend needed to support multiple organizations. And the foundation wanted a redesign of the app.
The new design had a lot of shadows and gradients in them. Instead of asking the artist to export every element, I made a component to create gradients without the need of textures. This became a component that has been used in many later projects. The code is below, The thing I would change, but hadn't had the time to do so, is changing relative positions to an angle. Instead of having to enter four (4) numbers, you only need to enter one (1).
public sealed class GradientUI : BaseMeshEffect { public Vector2 From = new Vector2(0, 0); public Vector2 To = new Vector2(1, 1); public SharedGradient Gradient; /// <inheritdoc /> public override void ModifyMesh(VertexHelper vh) { if (Gradient == null) return; var vertex = new UIVertex(); var min = new Vector2( 100000, 100000); var max = new Vector2(-100000, -100000); var matrix = transform.localToWorldMatrix; for (var i = 0; i < vh.currentVertCount; i++) { vh.PopulateUIVertex(ref vertex, i); Vector4 v = vertex.position; v.w = 1.0f; Vector2 position = matrix * v; min = Vector2.Min(min, position); max = Vector2.Max(max, position); } var delta = max - min; var from = min + Vector2.Scale(delta, From); var to = min + Vector2.Scale(delta, To); var offset = to - from; var sqrmagnitude = offset.sqrMagnitude; var gradient = Gradient.Value; if (gradient != null && sqrmagnitude > 0.000001f) { for (var i = 0; i < vh.currentVertCount; i++) { vh.PopulateUIVertex(ref vertex, i); Vector4 v = vertex.position; v.w = 1.0f; Vector2 position = matrix * v; var t = Vector2.Dot(position - from, offset) / sqrmagnitude; vertex.color *= gradient.Evaluate(Mathf.Clamp01(t)); vh.SetUIVertex(vertex, i); } } #if UNITY_EDITOR __start = from; __end = to; #endif } #if UNITY_EDITOR Vector2 __start; Vector2 __end; public void OnDrawGizmosSelected() => Debug.DrawLine(__start, __end); #endif }
At this time 8D Games did not have a web programmer. This meant I had to do it. The backend was written in PHP. I like to program in a data oriented and procedural manner. PHP and its frameworks give me too much friction in order to program effectively and efficiently. I estimated that it was cost effective to hire a web programmer when they wanted to use the existing code. If they wanted me to do it, based on the existic code and technoligies, the best option was to rewrite the backend using different technologies. 8D Games chose the latter.
After the web programmer left, an intern performed some research to find the best backend language for the company. The performed research concluded the language most suited for the company is Go. The Missie Master backend was going to be made in Go. The language isn't perfect, but for me, it is a huge improvement compared to what there was previously. It is also the backend language used for this website.
Over the years I worked for 8D Games, I knew management liked numbers, and tracking users. I added the possibility to expand the backend and app to track how many missions and tasks are completed. All this worked retroactively; missions completed before this feature was implemented could still be tracked, thanks to the score tracking in place. The development of the backend stayed within budget. From the foundation to the coaches who had to use the software were extremely happy.
It is 2021, new year, another expansion. This time a game is added to make sure users will keep using the app even if coaches haven't added new missions. It is heavily inspired from a game in Roblox: Obby Run. You can earn points traversing the courses with the customized character.
A notable feature in the game mode was the camera. It creates a some sort of mesh where the camera has a valid position. These points will then be interpolated to create a smooth transition when colliding into objects. This way there are no sudden jumps or cuts when playing the game and bumping into blocks.
This was a project on the larger end of the spectrum 8D Games does. If you want to like to know more about the systems in place, you can just send an email what you would like to know more about. And I'll try to answer the mail or update this page. Thank you for reading. Click here to go to the project page (external link)