Building a Simple Character
In order to build a new character for nsquared agents you will need to build a .NET 8.0 assembly that contains a class that implements the IAgent interface.
You will also need to have some images for the animated frames of the character. In this example we are using a small set of images to create a simple clippy character. These frames can be found in the sample Frames folder.
Step-by-Step creating a simple nsquared agent character
-
Start by creating a new C# class library project named SimpleCharacter.
dotnet new classlib --name SimpleCharacterThis will create a new folder named SimpleCharacter containing C# project named SimpleCharacter, and a code file named Class1.cs.
- Rename the file
Class1.cstoCharacter.cs -
Rename the class in the code to
Characternamespace SimpleCharacter; public class Character { } -
In the
SimpleCharacter.csprojfile make sure theTargetFrameworkisnet8.0<TargetFramework>net8.0</TargetFramework> -
In the
SimpleCharacter.csprojfile add aTargetExtfield below theTargetFrameworkline<TargetExt>.Agent</TargetExt> -
Add a package reference to the nsquared.agents NuGet package, from PowerShell you can do this with the following command.
dotnet add package nsquared.agents.api --prereleaseThis will add the reference to the
SimpleCharacter.csprojfile<ItemGroup> <PackageReference Include="naquared.agents.api" /> </ItemGroup> -
Add a package reference to the Avalonia NuGet package, from PowerShell you can do this with the following command.
dotnet add package AvaloniaThis will add the reference to the
SimpleCharacter.csprojfile (the version might be different as it will pull the latest version.)<ItemGroup> <PackageReference Include="Avalonia" Version="11.2.3" /> </ItemGroup> - In the SimpleCharacter folder create a new folder named
Assets. - In the new
Assetsfolder create a folder namedFrames. - In the
Framesfolder copy the frame images from the sample Frames folder. - In the
Assetsfolder create a file namedActions.json -
Edit the
Actions.jsonfile and put the following json to define two actions and two states.{ "ActionItems": [ { "Name": "Show", "Return": null, "Frames": [ { "SoundEffect": null, "Duration": 10, "ExitBranch": -1, "Images": [ { "Filename": "0000", "OffsetX": 0, "OffsetY": 0 } ], "Mouths": [], "Branches": [] } ], "Reverse": false, "ActionMenuSelected": null }, { "Name": "Idle", "Return": null, "Frames": [ { "SoundEffect": null, "Duration": 10, "ExitBranch": -1, "Images": [ { "Filename": "0000", "OffsetX": 0, "OffsetY": 0 } ], "Mouths": [], "Branches": [] }, { "SoundEffect": null, "Duration": 10, "ExitBranch": -1, "Images": [ { "Filename": "0045", "OffsetX": 0, "OffsetY": 0 } ], "Mouths": [], "Branches": [] }, { "SoundEffect": null, "Duration": 10, "ExitBranch": -1, "Images": [ { "Filename": "0046", "OffsetX": 0, "OffsetY": 0 } ], "Mouths": [], "Branches": [] }, { "SoundEffect": null, "Duration": 10, "ExitBranch": 9, "Images": [ { "Filename": "0047", "OffsetX": 0, "OffsetY": 0 } ], "Mouths": [], "Branches": [] }, { "SoundEffect": null, "Duration": 10, "ExitBranch": 9, "Images": [ { "Filename": "0048", "OffsetX": 0, "OffsetY": 0 } ], "Mouths": [], "Branches": [] }, { "SoundEffect": null, "Duration": 10, "ExitBranch": -1, "Images": [ { "Filename": "0049", "OffsetX": 0, "OffsetY": 0 } ], "Mouths": [], "Branches": [ { "BranchTo": 8, "Probability": 3 } ] }, { "SoundEffect": null, "Duration": 15, "ExitBranch": 8, "Images": [ { "Filename": "0050", "OffsetX": 0, "OffsetY": 0 } ], "Mouths": [], "Branches": [ { "BranchTo": 7, "Probability": 98 }, { "BranchTo": 6, "Probability": 2 } ] }, { "SoundEffect": null, "Duration": 10, "ExitBranch": 9, "Images": [ { "Filename": "0051", "OffsetX": 0, "OffsetY": 0 } ], "Mouths": [], "Branches": [] }, { "SoundEffect": null, "Duration": 10, "ExitBranch": -1, "Images": [ { "Filename": "0052", "OffsetX": 0, "OffsetY": 0 } ], "Mouths": [], "Branches": [] }, { "SoundEffect": null, "Duration": 10, "ExitBranch": -1, "Images": [ { "Filename": "0053", "OffsetX": 0, "OffsetY": 0 } ], "Mouths": [], "Branches": [] }, { "SoundEffect": null, "Duration": 10, "ExitBranch": -1, "Images": [ { "Filename": "0000", "OffsetX": 0, "OffsetY": 0 } ], "Mouths": [], "Branches": [] } ], "Reverse": false, "ActionMenuSelected": null } ], "States": { "Showing": [ "Show" ], "IdlingLevel1": [ "Idle" ] } } -
In the
SimpleCharacter.csprojfile add the assets as Avalonia resources<ItemGroup> <AvaloniaResource Include="Assets\**" /> </ItemGroup> -
Edit the
Character.csfile to implement theIAgentinterface.using nsquared.agents; namespace SimpleCharacter; public class Character : IAgent { public string Name { get => "SimpleCharacter"; set => throw new NotImplementedException(); } public string AssemblyName { get => "SimpleCharacter"; set => throw new NotImplementedException(); } public Uri ActionsFileUri => new Uri($"avares://{AssemblyName}/Assets/Actions.json"); public string AudioFilesPath => $"{Name}.Assets.Audio."; public string FrameAssetPath => $"avares://{AssemblyName}/Assets/Frames/"; public string IconPath => $"avares://{AssemblyName}/Assets/Icon.ico"; } -
Build the SimpleCharacter project. It should build the
SimpleCharacter.Agentfile in a bin folder. -
Run the nsquared agents application and open Settings, and then go to the
Addbutton next to the character list
-
This will open a file dialog. Find the
SimpleCharacter.Agentfile you built.
-
The new SimpleCharacter will be selected
