The first iteration of tools and editor of Pepper Wars 0.5

I’m about to talk a little bit about what this editor is for and a bit about our framework architecture, if you’re not interested in that then you can just skip right down to the “editor and tools” section near the bottom.

Introduction to Pepper Wars 0.5 and Tall Order Games

If you’ve checked out my portfolio already then you might have seen one of my previous solo games, ‘Pepper Wars’. Pepper Wars is a PVP local multiplayer networked game, where two players fight with their armies to destroy the other army and or castle in order to win. There were multiple units, each with their own unique abilities.

It was similar to Advance Wars, Fire Emblem and Final Fantasy Tactics. All games that I’ve played and adored. It was fun to build (and my first time networking a game), but it didn’t have good replayability and was very confusing for people who hadn’t played games like it before.

I recruited a few very talented people from my University and together we started to build what I am code-naming ‘Pepper Wars 0.5’. Development began as of February 2017 and since then I have been building a SFML based framework with an editor and tools. Before I show you them, I’ll quickly go through our game architecture and answer some questions you might be wondering.

Software & tools used

Why not Unity, Unreal or another game engine?

This is one of the questions that I’ve been asked a lot when talking to people about this project – and it’s a completely fair question. I’ll outline my main reasons now and get them out the way.

  1. SFML is a 2D dedicated framework. It’s free, easy to pick up and can be extended to make any sort of 2dgame.
  2. A lot of our team members come from an XNA/MonoGame and SFML background.
  3. Some of us have also spent time modding games (including Dota2) where the scripting language used is Lua.
  4. We have full control over everything. We can design our systems from the ground up and if there’s a bug, or something sucks, it’s our fault and we can do something about it.
  5. Building a framework is time consuming, but it’s also fun, teaches you a lot and looks good on your CV.
  6. Our game has tools-driven workflow and mod-ability in mind. We want the designers to be a able to create lots of missions and have a lot of control over the game.
  7. We can use dear ImGui. I really like dear ImGui.
  8. We can use C++ and a ton of awesome C++ libs.

A brief overview of our games architecture

Our architecture is heavily inspired by many patterns outlined in “Game Coding Complete, 4th edition” by Mike McShaffry/David Graham and “Game Programming Patterns” by Robert Nystrom. These are both great books and I recommend them thoroughly – even if you’re not making games.

Actors and our component system

Actors are made up of a set of components. Components are not behavioural and contain only data (similar to a Entity-Component-System).

Game state, logic and view

The game state is a “Scene”. A scene is split into the “Logic” and the “Views”.

The logic directs the current game states direction by doing things like deciding on what unit has what turn, what scripts should be run and creating/ending certain game processes. Logic can be defined in C++ or Lua, but typically it will be defined in Lua.

The views are responsible for the way that the player perceives the game. For example, the “RenderView” is responsible for rendering every actor that has a “DrawComponent” and the “EditorView” is responsible for drawing whatever editor widgets are active, if any. Views are typically defined in C++, as they are a time critical part of the game but they can also be done in Lua, for things like the UI that may require a lot of time to edit/perfect.

Event system

The event system is how all of our games logic, view, processes and editor communicate without knowing about one another.

For example: When the game scene object is being imported and the actors are being generated, the “ActorManagerProcess” will listen for the “CreateActorEvent“. The CreateActorEvent holds a shared/smart pointer to an actor that has just been created. The actor manager, upon hearing that this event has been triggered, will now store a reference to the actor that has been created. When the “DestroyActorEvent” is triggered, the same ActorManagerProcess will remove its reference to that actor. Thus the ActorManagerProcess now has a internal collection of all active Actors on the scene (as well as keeping them in memory!).

This allows for decoupled behaviour between all of our processes/systems and scripts.

Also: Events can easily be serialized and sent down a network!

Game processes

A process is a lifetime object. By that, I mean that it has a beginning (initialize()), a life (update()) and an ending (onComplete()/onFail()). This exact pattern is covered in Game Coding Complete, so I don’t want to go into it too much.

A process, once started, can be completed or failed. Completion or failure can will sometimes have different behaviours. It can also have a child process, which is the process that takes over after its parent dies. It can also be paused, which means its update() will not run until it is unpaused.

A process in our application can be relevant to our current scene or it can be global. Essentially this means that some processes will run through the entire lifetime of the application (global) and some processes will run only for the lifetime of the scene.

An example of a global process would be networking or io and an example of a scene process would be script execution (as it’s actor-specific).

The editor and tools

At this point, you might be thinking “thank god, finally!” – so without further ado, here are the editor and tools that we have built for Pepper Wars. I’ve also included some features that we’re currently implementing and some ideas of what we’ll be looking at in the future.

[Editor] Tilesheet importing

The tilesheet importer allows the designer to import a spritesheet and split it up into it’s individual tiles.

A configured tilesheet as separated tiles.

Right now we’re working on a feature that will allow the designer to create default components for tiles that we import, so when they are painted into the map those components will be there. This stops the designer from having to manually edit each tiles data as it’s painted, making the workflow quicker and easier.

Tilesheets also help us keep a record of what large spritesheet textures have been brought into memory, so we can remove them from memory when the scene ends.

[Editor] Tilemaps

The tilemap editor allows the designers to create our in game maps.

Editing top tile layer and then moving it down the layer order.

Features include:

  • Painting and erasing individual tiles from an imported spritesheet.
  • Ability to select individual tiles as actors and edit their components, id and data.
  • Ability to fill neighbour tiles so you don’t have to paint everything.
  • (To do) Define pathing data for the pathfinder to use.
  • (To do) Allow importing of a .tmx file from the popular tile map editor, Tiled.
  • (To do) Define and preview light sources.

[Editor] Actor and component editing

The actor editor allows the designer to create an actor that is saved for later importing (in the scenario designer, in a script, etc). It allows you to edit the actor data (name, id, active) as well as adding, removing and editing components.

Creating a basic actor that has a position and sprite.

Actors are exported in JSON, which means they can also be edited directly inside the file if necessary.

Later, when the command line is complete – this can also be an environment for running scripts against our actor.

[Editor] Level & Scenario designer

The scenario designer allows our designers to customise levels and scenarios inside the game without having to touch the underlying code or markup files.

After importing our tilemap, we’re importing some of our actors and moving them around.

Features include:

  • Import and create a copy of a tilemap that has been created.
  • Import (or create) actors and edit their components, scripts and data.
  • (Todo) Align actors to the tile grid.
  • (Todo) Customise pathing data for the pathfinder, overriding the tilemap data.
  • (Todo, Lua) Customise the scenario specific settings, (e.g. type of scenario, conditions and scripts).

[Editor] Animation editing & importing

The animation editor allows the designer to create reusable animations for the game. While editing the animation component, to add an animation you just point to a saved animation file that we’ve created.

Defining and testing animations in the animation editor

Features include:

  • Ability to manually define each frame of the animation from the sprite sheet.
  • Change the order that the frames are played in without editing the sprite itself.
  • Test the animation in a controlled environment, where no other actors or logic will interfere.
  • Change and test different frame rates
  • Change the texture without breaking code in other scripts.
  • (Todo) Use the splitter tool to automatically figure out each frame of the animation.

[Runtime Tool] Process list & editor

When we talked about the architecture of our game, I mentioned that we have processes that run in the background of the game. These processes can be completed, failed, paused and unpaused.

Completing (or failing) the tilemap process tidies up the tilemap actors.

Testing these processes can be difficult without writing certain trigger code or a command line argument to edit that specific process, so we created a tool that keeps a track of all alive game processes and allows you to edit their state during the games runtime. This helps us debug the scene and figure out what processes are causing the problem, if any.

[Runtime Tool] Actor hierarchy tracker & editor

Filtering out all of the tile actors on the scene, by specifying that we want to see all actors without a tile component.

This is much the same as the actor editor mentioned before, but instead of editing an actor to save to a file – this tool allows you to edit and view all actors that are available on the scene. There are even options to filter actors by their name, as well as the components that they do and do not have.

If an animation isn’t playing correctly, or an actor isn’t doing something it’s supposed to – you can simply open the actor hierarchy tracker tool, find the actor that you’re looking at and view its current components and data. This allows you to track down bugs and strange behaviours in an easier manner.

[Runtime Tool] Event log & tracker

This simple tool is incredibly useful for understanding what is going on in the current game loop, as well as debugging behaviours and finding errors.

It simply keeps a log of all of the last four-hundred events that have been triggered in the game, with options to filter out events so you can see if the event you’re expecting to be triggered is actually being triggered and listened too.

Here you can see the ‘CreateActorEvent’ being triggered for each actor we load in the scenario.

Another feature that we’ll be adding later is the ability to view the event data in JSON.

[Runtime Tool] Logger

Our logger is a simple tool that displays the last one-hundred logger messages and allows the user to filter them by their categories. Messages can be sorted into the categories ‘Debug’, ‘System’ and ‘Error’.

[TO-DO, Runtime Tool] Network log

The network log just records incoming and outgoing packets from the client and the server and holds a record of them in the log.

We will also be able to hover over an entry in the log, which will show the packet data in JSON. There will also be filter options to help find certain logs.

[TO-DO, Runtime Tool] LUA based command line

A command line would be great for editing, debugging and trying new things out in an empty scene. Our commands will all be done in LUA syntax, as we are embedding Lua as our games scripting language. A small set of features that we could do through our command line:

  • Anything we can do inside of a Lua script, including moving the actor, changing the animation, etc.
  • Create blank actor & load actor from a file.
  • Run script against actor.
  • Open and close network sessions to specific IPs.
  • Generate packets and events.

Conclusion on the editor and tools so far

Editors and tools are awesome! This is the first project I’ve ever done that has required a full tool set. A few final thoughts:

  • I need to spend a bit of time thinking about the UI design of the editor. So far, other people that have used them have found them quite un-intuitive, so I’ll probably redo all of the interfaces before handing it out to team members or consumers. I’ll also need to write a guide.
  • It’s amazing how much code has been reusable in the editor. Designing it has shown me a lot of great examples of good abstraction and code re-usability. Something I’ll discuss further in a system design / architecture post.
  • I’ve spent longer on them then I’d like, but honestly I’m having quite a lot of fun making them – and I think there’s a good argument for having a full set of easy to use tools that speed up the games development – especially if you’re planning on having a mission creator / mod-ability in the game release.
  • I need to figure out what’s up with my compile time. Currently taking 2 full minutes for compilation on a project that’s relatively small. (Yet another argument for Lua.)

Comments

Be the first to post a comment.

Leave a Comment

Your email address will not be published. Required fields are marked *

*

*