---
title: "Getting Started"
description: "Install NeoGameLib, write your first game, and learn the frame lifecycle."
canonical_url: "https://docs.ctrl-neo.dev/en/neogamelib/getting-started"
---
# Getting Started

## Install

Initialize your project with MonoGame first, then:

<code-group>

```bash [dotnet cli]
dotnet add package NeoGameLib
```

```xml [csproj]
<PackageReference Include="NeoGameLib" Version="0.3.2" />
```

</code-group>

Running the same `dotnet add` command again pulls the latest version.

## The minimum working game

Inherit `NeoGame` instead of `Game`:

```csharp
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

public class MyGame : NeoGame
{
    protected override void OnLoadContent(ContentManager cm)
    {
        // create and register a world
        WorldManager.CreateWorld("level1", world =>
        {
            NeoObject player = world.Instantiate("Player", new Transform(new Vector2(100, 100)));
            player.AddComponent(new NeoSpriteRenderer(RenderBus, cm.Load<Texture2D>("player")));
        });

        WorldManager.Load("level1");
    }

    protected override void OnUpdate(GameTime gameTime)
    {
        // runs after input + UI, before worlds, collisions and timers
    }

    protected override void OnDraw(SpriteBatch spriteBatch, GameTime gameTime)
    {
        // draws inside the main camera's world-space batch (identity when no camera exists)
    }

    protected override void OnDrawUI(SpriteBatch spriteBatch, GameTime gameTime)
    {
        // draws in plain window pixels, above every canvas
    }
}
```

In `Program.cs`, run your game the normal MonoGame way:

```csharp
using var game = new MyGame();
game.Run();
```

### The five lifecycle hooks

`NeoGame` seals MonoGame's own `Initialize`/`LoadContent`/`Update`/`Draw` and
exposes five virtual hooks instead:

<table>
<thead>
  <tr>
    <th>
      Hook
    </th>
    
    <th>
      Runs
    </th>
    
    <th>
      Typical use
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        OnInitialize()
      </code>
    </td>
    
    <td>
      once, after all buses exist and content has loaded
    </td>
    
    <td>
      one-time game setup
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        OnLoadContent(ContentManager)
      </code>
    </td>
    
    <td>
      once, after <code>
        Content
      </code>
      
       is ready (fires before <code>
        OnInitialize
      </code>
      
      )
    </td>
    
    <td>
      load assets, create/load worlds
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        OnUpdate(GameTime)
      </code>
    </td>
    
    <td>
      every frame, before worlds update
    </td>
    
    <td>
      frame-level logic
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        OnDraw(SpriteBatch, GameTime)
      </code>
    </td>
    
    <td>
      every frame, in the main camera's world batch
    </td>
    
    <td>
      custom world-space drawing
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        OnDrawUI(SpriteBatch, GameTime)
      </code>
    </td>
    
    <td>
      every frame, last, in window pixels
    </td>
    
    <td>
      debug overlays, screen-space drawing
    </td>
  </tr>
</tbody>
</table>

Buses and managers exist before `OnInitialize` and `OnLoadContent` run, so
component constructors that take a bus argument can be used in `OnLoadContent`
directly.

## The frame, in order

`NeoGame.Update` runs everything in a fixed order every frame:

1. **Input** — input maps refresh first; every later stage reads this frame's input.
2. **Viewport** — the letterboxed viewport (see `ViewportAspect`) is re-applied.
3. **UI update** — canvases lay out and handle their own logic.
4. **OnUpdate** — your game hook.
5. **Worlds** — every loaded world ticks: components get `OnStart` (first tick)
and `OnUpdate`, destroyed objects flush.
6. **Collisions** — the collider bus resolves pairs and fires `ICollision`
callbacks (so it sees positions from *this* frame's world update).
7. **Timers** — timer ticks run last.

`Draw` runs three passes: the world pass (once per enabled camera, sprites then
text), the UI pass (one batch per canvas), then `OnDrawUI` in raw window pixels.

## One design rule that makes everything else make sense

Every frame-loop in the library walks a **snapshot** of its list
(`PassSnapshot<T>`). That is the reason you can, from inside any callback
(`OnUpdate`, `OnCollision`, `OnDestroy`, a timer callback, `OnDraw`...),
safely:

- load/unload worlds
- destroy objects or add/remove components
- start/stop timers
- add/remove cameras, sprites, or canvases

Things you change mid-pass take effect **next tick**. When you write your own
loops over world objects or components, use `PassSnapshot<T>` and check
`IsAttached`/`IsDestroyed` per item — see
[Game Objects](https://docs.ctrl-neo.dev/3.game-objects#iterating-yourself-passsnapshot).


## Sitemap

See the full [sitemap](https://docs.ctrl-neo.dev/sitemap.md) for all pages.
