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 SimpleCharacter
This will create a new folder named SimpleCharacter containing C# project named SimpleCharacter, and a code file named Class1.cs.
- Rename the file
Class1.cs
toCharacter.cs
-
Rename the class in the code to
Character
namespace SimpleCharacter; public class Character { }
-
In the
SimpleCharacter.csproj
file make sure theTargetFramework
isnet8.0
<TargetFramework>net8.0</TargetFramework>
-
In the
SimpleCharacter.csproj
file add aTargetExt
field below theTargetFramework
line<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 --prerelease
This will add the reference to the
SimpleCharacter.csproj
file<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 Avalonia
This will add the reference to the
SimpleCharacter.csproj
file (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
Assets
folder create a folder namedFrames
. - In the
Frames
folder copy the frame images from the sample Frames folder. - In the
Assets
folder create a file namedActions.json
-
Edit the
Actions.json
file 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.csproj
file add the assets as Avalonia resources<ItemGroup> <AvaloniaResource Include="Assets\**" /> </ItemGroup>
-
Edit the
Character.cs
file to implement theIAgent
interface.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.Agent
file in a bin folder. -
Run the nsquared agents application and open Settings, and then go to the
Add
button next to the character list -
This will open a file dialog. Find the
SimpleCharacter.Agent
file you built. -
The new SimpleCharacter will be selected