you must walk before you can run murder

This is a brief demo/walkthrough of the pixel-art ECS game engine, Murder. It's pretty fun and has a lot of features -- I'm going to focus on the steps necessary to get a simple character to walk around the map. Murder has a great built-in editor system that allows authors to fully customize their game dev environment to suit their needs -- I'm enjoying it and I hope you do too!

Many thanks to @isa and @saint11 for bringing Murder to us!

Resources

Last updated 9/26/2023 10:00PM EST. The Murder engine is developing rapidly so there's a good chance it might be out of date soon. I'm still working on this tutorial and will flesh it out with more reader-friendly details as time permits! Thanks for reading! - @ninjakohaku on discord

Prerequisites

This tutorial assumes basic familiarity with the following software:

Git is free to use, .NET 7 and Visual Studio 2022 Community are free for personal use, and Aseprite is well worth the investment if you're just now getting into game development.

This tutorial also assumes you're running Windows. This is largely because I don't have experience building the engine on other operating systems.

If you don't already have your own Git client, I highly recommend using Git for Windows, as it's a lot more user-friendly for first-timers, and it also gives you a command line called "bash" that you can use to follow along.

Cloning the Hello World repository

Screenshot showing the progress of 'git clone' procedure.

The first thing to do is get your hands on the Murder engine itself. What we're going to do is clone a copy of the "Hello World" project as it already has most of the pieces you need.

If you're using Git for Windows and installed the Explorer tools, just navigate to the folder you want to install to and right-click "Git Bash Here". This will open up a command-line terminal for running git.

From a command-line terminal, navigate to the folder you want to start the project, then type this to clone the project:

git clone --recurse-submodules https://github.com/isadorasophia/hellomurder
This project uses submodules. If you used some other way to clone the project, make sure to update your references like this:

git submodule update --init --recursive

Building and running the Editor

One of the best things about the Murder engine is that it comes with the source code for its own editing environment. If you need a new feature, you have the capability to edit it right there and then.

To build the game you can do one of the following, depending on whether you're running Visual Studio 2022 or dotnet at the terminal.

Build and Run using Visual Studio 2022:

Build and Run using dotnet:

cd src/HelloMurder.Editor dotnet build dotnet run

Running

Once you're in the editor, there's a number of things you can do. We're going to modify some code real quick but feel free to poke around.

Register the Inputs

The first thing we need to do is register some input bindings for the game controls to work. We'll do this by overriding the base IMurder class with our own custom Initialize() method.

As a side note: our code changes will take place entirely in the src/ folder. It's a good practice to avoid editing things in the murder/ folder. You're free to do whatever you want of course, but it's easier to incorporate murder/ updates through git if you don't have to contend with your own changes.
  1. Open the file src/HelloMurder/HelloMurderGame.cs. Add the lines of code highlighted in green below.
    using Microsoft.Xna.Framework.Input; using Murder; using Murder.Core.Input; using HelloMurder.Core; namespace HelloMurder { public class HelloMurderGame : IMurderGame { public string Name => "HelloMurder"; public void Initialize() { GamepadAxis[] stick = { GamepadAxis.LeftThumb, GamepadAxis.Dpad, }; Game.Input.RegisterAxes(MurderInputAxis.Movement, stick); Game.Input.Register(MurderInputAxis.Movement, new InputButtonAxis(Keys.W, Keys.A, Keys.S, Keys.D), new InputButtonAxis(Keys.Up, Keys.Left, Keys.Down, Keys.Right)); Game.Input.Register(InputButtons.LockMovement, Keys.LeftShift, Keys.RightShift); Game.Input.Register(InputButtons.LockMovement, Buttons.LeftTrigger, Buttons.RightTrigger); Game.Input.Register(InputButtons.Attack, Keys.Z); Game.Input.Register(InputButtons.Attack, Buttons.X); Game.Input.Register(InputButtons.Interact, Keys.Space); Game.Input.Register(InputButtons.Interact, Buttons.Y); } } }
    You may be wondering, "Where did this code come from?" The answer is -- the developers' Ludum Dare project, Neo City Express. It's a great reference for how to build a complete game in the Murder engine -- though work on the engine itself has proceeded really quickly since then and not everything will map to the current Murder engine in a 1:1 fashion.

Modifying the Input system

Next, we'll need to open up the Player Input controller.

  1. We'll need to make some modifications to the file src/HelloMurder/Systems/Player/PlayerInputSystem.cs.

    First, we'll need to comment out some code by placing two slash marks before it. This way it will be around in case we need to refer to it later.

    In Visual Studio you can type Ctrl+K, then Ctrl+C, to comment it out quickly.
  2. The code we need to edit is in the Update() method. Comment out the lines of code regarding _cachedInputSkill -- these refer to buttons we don't use yet. The text in green shows what needs to be added.

    public void Update(Context context) { _cachedInputAxis = Game.Input.GetAxis(InputAxis.Movement).Value; _lockMovement = Game.Input.Down(InputButtons.LockMovement); // _cachedInputSkill = // Game.Input.Down(InputButtons.Skill1) ? InputButtons.Skill1 : // Game.Input.Down(InputButtons.Skill2) ? InputButtons.Skill2 : // _cachedInputSkill; _cachedAttack = Game.Input.Down(InputButtons.Attack); if (Game.Input.Pressed(InputButtons.Interact)) { _interacted = true; Game.Input.Consume(InputButtons.Interact); } }
  3. The Murder engine is in active development, so there's a chance that the code we're editing might not be there. If so, no worries! Just move on to the next step if so.
  4. Once the file is updated, Save it.

Add the PlayerInputSystem

The PlayerInputSystem we just modified isn't attached to anything yet. We will now add it to the Characters feature.

  1. If the HelloMurder.Editor isn't already running, launch it by pressing F5 in Visual Studio, or start it with dotnet.

Features

  1. Click on the Features heading.
  2. Then click the Character feature.
  3. This will access the feature editor. Here, click Add System and add the PlayerInput system.
  4. Click Save Asset to save your changes to the Character feature.

About the asset workflow

The Murder engine has a Generator feature that adds resources to your project file for compilation. To make use of this feature we will add an Aseprite file directly into the project's resources/ folder.

If you don't have Aseprite, you could just use png files for each graphic. But with Aseprite, you gain three capabilities:

That's right -- if you start off with named loops, and then want to add/delete frames, modifications to the .aseprite file will be picked up by the Generator and reflected as soon as you reload them in the editor.

Building your sprites in Aseprite

You or an artist can use Aseprite to create animations for your character. To make the best use of Murder Engine's Agent feature, use the Aseprite's "loops" (F2) to assign names to the animation loops.

To build a walking character you will need some animation loops. There are two main categories of loops: idle loops, which show your character standing, and walk loops, which show your character walking.

The "starman" sample we will use in this demonstration has ten loops.Each loop begins with the "prefix" of "idle_" or "walk_" and ends with the "suffix" of "n", "ne", "e", "se", or "s", corresponding to the directions north, northeast, east, southeast, and south.

We don't need to worry about northwest, west, or southwest, because Murder Engine lets us flip the sprites when facing west.

Also, Murder Engine doesn't require five sprites; you can tell it to use different directions if you choose.

Screenshot of the Aseprite window showing 40 animation frames of a character

Add Sprites to the Atlas

For this demonstration we will use a sample .aseprite file named "starman".

  1. From the root folder of your project, locate the resources/images/ folder inside your hellomurder folder.
    There are also resources/ subfolders elsewhere in the project. Avoid those for now.
  2. Create a new characters/ folder inside the resources/images folder.
  3. Download this file into the new resources/images/characters/ folder: starman.aseprite
  4. From the menu, select Assets - Save All Assets.
  5. Click on the Atlas tab.
  6. Roll out the atlas heading.
  7. Click F3 or select Reload - Content and Atlas to run the Generator. (Note: This will discard changes to any unsaved assets.)

    Image of the HelloMurder.Editor showing the Atlas tab with the starman assets visible.

    The atlas heading will now populate with the frames from the Starman.aseprite file we just added.

Add a new player prefab

Now that we have graphics in the Atlas, we can now add a prefab for our little walking guy. Prefabs -- "pre-fabricated objects" -- are reusable components that will populate your world.

  1. In HelloMurder.Editor, click back to the Assets tab.
  2. Right-click the Prefabs folder and select Create New Prefab.

    Screenshot of the Create New Prefab dialog, showing the new prefab name as 'starman'

  3. The prefab creation menu will appear. Give it the name of "starman".

    Screenshot of the Assets tab, showing the new 'starman' prefab under the Prefabs heading

  4. The starman prefab now shows up under the Prefab menu, and HelloMurder.Editor will take us to the Prefab editor for our new prefab. If you look at the top of the bar you will see that the file has not been saved.

    Screenshot of the action bar for the Prefab Asset editor, showing (FILE NOT SAVED)

  5. Click Save Asset to save changes to our new prefab.

Eyedropper

Prefabs are used in the World Editor to populate our world. So one thing you will want to do for this new prefab is make sure it's shown in the entity picker. This will be useful later.

  1. Click on the eyedropper icon to turn the eyedropper white, then Save Asset.

    Screenshot of the eyedropper icon, li white

Components

In the Prefab editor, click the Select a component field, or the little button beside it, to add a component.

  1. Add a Position component.

    This basic component allows the engine to track this object's position in the world.

  2. Add an AgentComponent.

    Agents are objects that can be moved around by player input.

    The Speed determines the maximum speed of an agent, while Acceleration determines how fast it can reach maximum speed. Friction determines if the walking surface is slippery (0.0) or rough (1.0).

    For this demo, try the following settings at first:

  3. Add an AgentSpriteComponent.

    This component modifies the sprite of the agent based on its current Facing.

    The YSort determines how the sprite will be layered relative to other sprites at the same y-coordinate. (This is best determined experimentally with the debugging tools.)

    The animation determines which animation sequence will be used. The Idle Prefix is combined with a directional suffix to determine which loop of the animation will be shown when the character is standing still. The Walk Prefix will be combined with a Suffix to determine which loop will be shown when the character is walking.

    The Suffix field is a list of which suffix will be added when facing a given direction. If the Flip West option is set, then the sprite will be horizontally flipped when facing wast. This lets the artist cut back on the number of animations needed.

    The most common options are:

    For the demo, using the "starman" aseprite file, use the following settings:

  4. When you add the AgentSpriteComponent, a FacingComponent will be added as well.

    The Facing component keeps track of what direction the object is facing.

  5. Add a ColliderComponent.

    The Collider component keeps the object from overlapping other Collider objects.

    The Collider has a Layer mask to determine which layers will halt this object's progress.

    In order for a Collider to work, a Shape must be added. The most common shape used is a Box shape.

    For the demo, using the "starman" aseprite file, use the following settings:

  6. Add a PlayerComponent.

    The Player component is used by the PlayerInput system to identify the player to be controlled.

    In Unity and other games, objects could be given "tags," but as Murder is an ECS-based engine, it's common practice to add special-purpose Components that can be detected in the game scripts. This way new features can be added to players and enemies alike with a lot of additional coding.

  7. Click Save Asset.

Add the player to the world

  1. Click the World to show the worlds available.
  2. Right-click the Hello World world and select Duplicate. This will create "Hello World (1)" which we don't need right now, but it's there in case we need it.
  3. In the WorldAsset editor for Hello World, select the Room dropdown. Then click the trash can next to Player as we don't need that guy right now.
  4. Locate the Starman icon in the Entity Picker.

    (If it doesn't appear, then check back to the Eyedropper heading and make sure the eyedropper is turned on.)

    Screenshot of the WorldAsset Editor's Entity Picker, showing the 'starman' icon

  5. Click the Starman icon from the Entity Picker, and then move the mouse onto the map. As you move, the Starman graphic will follow your mouse cursor. Place him in the middle of the map, not touching the walled areas.
  6. Click Save Asset to save the map asset.

Screenshot of HelloMurder.Editor showing the WorldAsset Editor

Once the "starman" prefab is added to the WorldAsset, you can select it from the Room menu. If you do so, you will see that the asset received a new Component named PlacedInWorldComponent. This is normal! This component is used to track objects that have been placed in the world. Other components will be added to the objects during runtime, such as PrefabRefComponent, InCameraComponent, and IsSelectedComponent. These ECS components are how Murder Engine is able to update these objects in real-time.

Play and debug the game

Now start your game with F5 or by clicking Play!

Select New Game in the menu, and then you should see the Hello World map we just modified. You should be able to walk the Starman character around the map using the WASD keys, arrow keys, or gamepad.

Notice that he will not be able to walk over a wall because the colliders have been placed.

While playing the game with the Editor, you can access the game's Log Console by pressing F1.

You can show/hide the debugging tools by pressing F2. These debugging tools give you access to the components from the Editor, so that you can see how features work in the live game, and tweak them live.

Screenshot depicting the game and the debugging tools for the game. The 'Starman' character is selected, and the Position component is rolled out so that those values can be seen.

Next Steps

From here, the opportunities are up to you! The next step would probably be to rename the project to suit your own needs, add some enemies and game UI -- but that's beyond the scope of this quick peek under the hood of the Murder engine.

I hope this basic "walk"-through will give you an idea of how to use the Murder Engine for your own insidious ends. We're all learning how best to utilize it, so... have fun, everyone!

Thanks for reading!

- @ninjakohaku