nsquared agents

Downloads and guides for the nsquared agents desktop characters.

View on GitHub

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.

The full source code for this example

Step-by-Step creating a simple nsquared agent character

  1. 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.

  2. Rename the file Class1.cs to Character.cs
  3. Rename the class in the code to Character

     namespace SimpleCharacter;
     public class Character
     {
    
     }
    
  4. In the SimpleCharacter.csproj file make sure the TargetFramework is net8.0

     <TargetFramework>net8.0</TargetFramework>
    
  5. In the SimpleCharacter.csproj file add a TargetExt field below the TargetFramework line

     <TargetExt>.Agent</TargetExt>
    
  6. 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>
    
  7. 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>
    
  8. In the SimpleCharacter folder create a new folder named Assets.
  9. In the new Assets folder create a folder named Frames.
  10. In the Frames folder copy the frame images from the sample Frames folder.
  11. In the Assets folder create a file named Actions.json
  12. 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"
             ]
         }
     }
    

    More information on the schema for the Actions.json file.

  13. In the SimpleCharacter.csproj file add the assets as Avalonia resources

     <ItemGroup>
         <AvaloniaResource Include="Assets\**" />
     </ItemGroup>
    
  14. Edit the Character.cs file to implement the IAgent 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";
     }
    
    
  15. Build the SimpleCharacter project. It should build the SimpleCharacter.Agent file in a bin folder.

  16. Run the nsquared agents application and open Settings, and then go to the Add button next to the character list

    Add character

  17. This will open a file dialog. Find the SimpleCharacter.Agent file you built.

    Select SimpleCharacter.Agent file

  18. The new SimpleCharacter will be selected

    SimpleCharacter selected

The full source code for this example