Skip to content

Setting up your first project

David Zhao edited this page Feb 13, 2019 · 36 revisions

Setting up your first project

This tutorial is designed to get you started with a new project using osu-framework. It is not meant to be a guide for contribution to the osu-framework project.

Targeting desktop platforms

You can find this code and more to help you get started in SampleGame and SampleGame.Desktop

Create a new WinExe project.

In Visual Studio or Rider, simply set the project type to "Windows Application" when creating a new solution. You can verify whether or not you have succeeded by opening the .csproj file generated by the solution in your preferred editor and checking that the <OutputType>Exe</OutputType> tag exists.

In dotnet CLI, dotnet new console will create a new project in the current directory with the same project name.

Install the nuget package.

You can find the nuget package at https://www.nuget.org/packages/ppy.osu.Framework/

From dotnet CLI: dotnet add package ppy.osu.Framework

You can also add the package from the NuGet GUI. In rider, you can find this in Tools > Nuget > Manage NuGet Packages for Solution.

Create a new game class that derives osu.Framework.Game.

The following code creates a cube with a rigid body container.

namespace AwesomeGame
{
    public class AwesomeGame : Game
    {
        RigidBodySimulation sim;
        
        [BackgroundDependencyLoader]
        private void load()
        {
            Child = sim = new RigidBodySimulation { RelativeSizeAxes = Axes.Both };
            
            RigidBodyContainer<Drawable> rbc = new RigidBodyContainer<Drawable>
            {
                Child = new Box
                {
                    Anchor = Anchor.Centre,
                    Origin = Anchor.Centre,
                    Size = new Vector2(150, 150),
                    Colour = Color4.Tomato,
                },
                Position = new Vector2(500, 500),
                Size = new Vector2(200, 200),
                Rotation =  45,
                Colour = Color4.Tomato,
                Masking = true,
            };
            
            sim.Add(rbc);            
        }
    }
}

In your main() method, create a new instance of your game.

[STAThread]
public static void Main()
{
   using (Game game = new AwesomeGame())
   using (GameHost host = Host.GetSuitableHost(@"awesome-game"))
      host.Run(game);
}

Testing

Setting up a test browser

osu-framework has a visual testing framework that is meant to help provide tests that can be verified both visually and systematically via NUnit. To start using visual tests, you will need to create a TestBrowser and add it to your game. In order for your test browser to discover tests, you will need to specify a namespace in which for the browser to look in when constructing it.

namespace AwesomeGame.VisualTests
{
    public class AwesomeGameTestRunner : AwesomeGame
    {
         [BackgroundDependencyLoader]
         private void load()
         {
             Child = new DrawSizePreservingFillContainer
             {
                 Children = new Drawable[]
                 {
                     new TestBrowser("AwesomeGame"), //Specify the namespace to discover tests from
                     new CursorContainer(),
                 },
             };
         }

         public override void SetHost(GameHost host)
         {
             base.SetHost(host);
             host.Window.CursorState |= CursorState.Hidden;
         }
    }
}

Note that in order for you to be able to run the visual tests, you will have to switch your game type to visual tests. To do that, you can either create your visual tests in a separate project and run them as a build configuration, or simply apply build configuration pre-processor checks in your entry point to run the appropriate game.

For the purpose of our demo, we will simply switch our game type to our VisualTestRunner instead.

namespace AwesomeGame
{
    class Program
    {
        [STAThread]
        public static void Main()
        {
            using (GameHost host = Host.GetSuitableHost(@"AwesomeGame"))
            using (Game game = new VisualTestRunner())
            //using (Game game = new AwesomeGame())
                host.Run(game);
        }
    }
}

Adding tests to the test browser

Now that our test browser is discovering tests from the specified namespace, we can start adding tests! To do so, create a new class that derives TestCase with the TestFixture attribute. From here, we can add steps to this test of various types:

  • AddStep creates a step that runs a method. Completes successfully if no exceptions are caught.
  • AddRepeatStep creates a step that runs a method a specified amount of times. Completes successfully if no exceptions are caught.
  • AddToggleStep toggles a flag.
  • AddUntilStep adds a step that attempts to run until a condition becomes true, or fails when it times out.
  • AddWaitStep adds a step that waits a specified amount of time before continuing to the next step.
  • AddSliderStep adds a step that creates a slider-bar that adjusts a set value.
  • AddAssert creates a step that fails if the specified value does not return true.

Example Test

The following code adds a simple cube to the visual test browser that we created above. The cube has a rigid body attached, and should drop to the bottom of the screen when created. From here, we can choose to check the behavior of the cube by asserting that the cube eventually reaches the bottom via AddAssert.

namespace AwesomeGame.VisualTests
{
    [TestFixture]
    public class RigidCubeTest : TestCase
    {
        private RigidBodySimulation sim;

        [Test]
        public void AwesomeTestName()
        {
            AddStep("Drop a cube", DropCube);
        }

        private void DropCube()
        {
            Child = sim = new RigidBodySimulation { RelativeSizeAxes = Axes.Both };
            
            RigidBodyContainer<Drawable> rbc = new RigidBodyContainer<Drawable>
            {
                Child = new Box
                {
                    Anchor = Anchor.Centre,
                    Origin = Anchor.Centre,
                    Size = new Vector2(150, 150),
                    Colour = Color4.Tomato,
                },
                Position = new Vector2(500, 500),
                Size = new Vector2(200, 200),
                Rotation =  45,
                Colour = Color4.Tomato,
                Masking = true,
            };
            
            sim.Add(rbc);
        }
    }
}

Appendix

Setup Attribute

The Setup NUnit attribute marks a method as a setup method that runs as a step before every group of tests in a test method. The steps created by this attribute gets added to the visual test browser as well.

BackgroundDependencyLoader Attribute

The BackgroundDependencyLoader attribute denotes a method to be the load method of a Drawable. You can specify a type in the method parameters to attempt to grab an object of that type that has been cached.

Further Reading

For information on how to load your own resources such as textures and audio, please read Setting Up Compiled Resource Stores.

For more information regarding dependency injection via the BackgroundDependencyLoader attribute, please read Dependency Injection

For additional reading on visual tests, please refer to Dynamic Compilation and Visual Testing

Clone this wiki locally