The course editor

Volo’s course editor was made to share the joy of creating and flying time trial courses, based on the fun Martijn and I had creating the initial set of courses for v3.2 challenging each other, and later on discovering Youtube video’s of others playing these courses. We liked what we saw so much that we decided to create a course editor similar to how we created the initial courses in Unity and were very curious to see what you all could come up with. As it is one thing with Volo that caught our eye when watching countless Youtube video’s is that everyone plays the game differently. Everyone has a personal flying style and discovers different lines on the Volo mountain.

course_editor

The course editor is the first in a series of features that tries to let you share your flying experiences. The idea is that courses can help you learn someone else’s flying style and can let you see parts of the mountain that you might have missed, lines that you didn’t know existed. This idea also came from our experience after the first v3.0 video’s came online: we saw the mountain in a particular way and had our set of lines to fly but there were so many other lines that we didn’t see shown to us by other players.

Still we didn’t know if an idea like a course editor would work at all. So we created a relatively simple first version. Simple enough so that it could be built in a small amount of time but with enough features so that you wouldn’t miss anything essential. We then went on and released this version in v3.4 and waited for your reactions. If it wouldn’t be used at all it would’ve been a very clear that the course editor was not the right direction for Volo and that community-created content would need to take on a different form.

Judging by the forums people are actively creating courses and downloading courses from other players. This is absolutely wonderful! It means that we’ll most likely expand upon it and make a better version of the editor, one that contains more stuff and is easier to use.

One of the benefits of releasing the first version is all the feedback we got on what does and doesn’t work in the course editor. So, in the second version we’re considering adding:

  • Additional props that make flying more fun, like wind zones
  • Sharing courses through Volo (instead of using the forums, which was easy to implement, but cumbersome to use)
  • Better course management: turning courses off, turning other courses off while flying a course.
  • Remappable shortcuts so the course editor can be controlled with any kind of peripheral, not just the keyboard.

Hopefully this has given you some insight in how we approach building new features for Volo and more specifically how we approached building the course editor and how we plan to extend it further.

 

The technical side of the course editor is also interesting. It was our first venture into building more complex user interfaces with both 3D and 2D elements. Hopefully we can inspire other game developers with this when they face such a complex task.

The main requirements for the course editor were as follows:

  • A fully functional graphical interface. Whenever you change something, like highlighting a ring for example, the graphical interface should make that visible to you.
  • Building courses should be similar to our experience in Unity: fly through a world, place rings, move them around, rotate them etc. because that worked well for us.
  • Keyboard shortcuts for convenience.
  • Full undo/redo support. We want the course editor to remember every step you take so you can always reliably move backward and forward in time.

To implement this we’ve been looking at reactive programming and more specifically at how Facebook’s architecture for building user interfaces with React and Flux. As it turns out their approach makes it relatively easy to implement all our requirements. The core idea is to have one module, called a store, handling all the state changes and let all other modules depend on the state changes coming from the store. Let me clarify with a picture:

image00

The Store is our core module and is the only piece that knows how to change the state of the course editor. The state looks a bit like this:

{selectedRing: “4567”,

 highlightedRing: “1234”,

 rings: [{id: “1234”,

          transform: {position: [0, 50.5, -10.4], rotation: [0, 0, 0]},

         {id: “4567”,

          transform: {position: [0, 0, 0], rotation: [0, 0, 0]}]

}

Other modules can hand over requests to the store like: ‘I would like to select this ring’, then the store checks if the ring is available, stores the previous state onto the undo stack, and updates the current state so it contains the newly selected ring. If for some reason the ring does not exist or the ring is already selected the store just ignores the request because it made no sense.

Whenever the state is updated all the other modules react accordingly: the graphical user interface is re-rendered and the input module gets new information so it can decide how to react to keyboard input.

Having the state in one place and make all other modules derivatives of the state is absolutely lovely: we don’t have to worry about the GUI module and the input module maintaining state on their own by having to perform some coordination between the two. The GUI module and the input module are unaware of each other. They’re also unaware of the store in the sense that they’re only interested in state changes and can only interact with the store indirectly through the requests module. The store is unaware of any of the modules listening to its state changes, so when adding another module, for example an audio module that plays sounds whenever the state changes, we don’t have to change any of the existing components.

You notice the beauty of this model when you start seeing some of the more complex behaviour, like: you hover over a ring in the course editor, this gets translated to a highlight ring request, which in turn updates the state, which in turn re-renders both the ring itself as well as the GUI representation of the ring since they’re both dependent on the same state.

Undo/Redo is also easy to implement, the player presses Ctrl+Z and the input module triggers an undo action, the store reverts to the previous state (if there is any) and the whole GUI is re-rendered because the state was updated.

This architectural pattern proves to be incredibly useful but is still somewhat immature. Especially some things in our implementation of the pattern could be written much less verbose and more composable. I’m particularly interesting in how you would compose functionality between stores. Currently the course editor only has one store, making it somewhat monolithic. What if we could re-use existing parts from the course editor on some other part of the code?

 

That’s it for now folks, now you’ll have to wait for Martijn’s next What’s Happening blog post!