A collection of samples showing potential ways to implement common game patterns using a scene graph in MonoGame.
See OWL
A basic scene with a white sprite tinted red. We offset the sprite relative to the container to create an orbit like effect.
using OWL.Graph;
namespace Examples.Basic.Scenes
{
class BasicScene : Scene
{
Sprite sprite;
Container container;
public BasicScene()
{
container = new Container();
container.SetPosition(400, 250);
AddChild(container);
sprite = new Sprite(Game1.White);
sprite.Width = 40;
sprite.Height = 40;
sprite.SetPosition(100, 0);
sprite.SetAnchor(0.5f);
sprite.Tint = Microsoft.Xna.Framework.Color.Red;
container.AddChild(sprite);
}
public override void Update(float deltaTime)
{
var speed = 3f;
container.Rotation += speed * deltaTime;
}
}
}
Trigger a pause scene using a scene stack. Scenes in the background pause because they are not at the top of the stack.
using OWL.Graph;
namespace Examples.SceneStack.Scenes
{
class MainScene : Scene
{
Sprite bg;
Motes motes;
public MainScene()
{
bg = new Sprite(Game1.White);
bg.Width = Game1.Device.Viewport.Width;
bg.Height = Game1.Device.Viewport.Height;
bg.Tint = Microsoft.Xna.Framework.Color.BlanchedAlmond;
AddChild(bg);
motes = new Motes(20);
AddChild(motes);
Delay(this, 2000f, () => OnPause?.Invoke());
}
public override void Update(float deltaTime)
{
base.Update(deltaTime);
motes.Update(deltaTime);
}
}
}
Load some frames for an animated sprite and display the loading progress.
protected override void LoadContent()
{
_spriteBatch = new SpriteBatch(GraphicsDevice);
_renderer = new Renderer(_graphics.GraphicsDevice, _spriteBatch);
// TODO: use this.Content to load your game content here
Assets = new Assets(Content, _graphics.GraphicsDevice);
// Load loading scene assets
Assets.Load("textures/logo_white_small", out Texture2D _);
// Create loading scene and add to stack
_loadingScene = new LoadingScene();
_stack.Push(_loadingScene);
// Loader progress callback
_loadingScene.OnLoaderProgress += (float progress) =>
{
_loadingScene.Load(progress);
};
// Complete callback
OnLoadingComplete += () =>
{
// Show main scene after short delay
Scene.Delay(_loadingScene, 1000f, () =>
{
_stack.Pop(); // Remove preloader scene from stack
var mainScene = _sceneManager.ShowMainScene(); // Show main scene
});
};
// Create asset list
_manifest = new List<ManifestItem>();
for (var i = 0; i <= 7; i++)
{
_manifest.Add(new ManifestItem
{
uri = @"textures/ammo_crate_00" + i,
name = @"ammo_crate_00" + i
});
}
_loadTotal = _manifest.Count;
// Why not give a small delay before loading too, just to make sure everything is ready
Scene.Delay(_loadingScene, 500f, () =>
{
_loading = true;
});
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
// TODO: Add your update logic here
float deltaTime = gameTime.ElapsedGameTime.Milliseconds;
_stack.Update(deltaTime);
// Load assets
if (_loading)
{
// Pop asset
var asset = _manifest[_manifest.Count - 1];
_manifest.RemoveAt(_manifest.Count - 1);
// Load file
Assets.Load(asset.uri, out Texture2D _);
// Calc progress
var progress = (_loadTotal - _manifest.Count) / (float)_loadTotal;
_loadingScene.OnLoaderProgress?.Invoke(progress);
// Finish loading
if (_manifest.Count == 0)
{
_loading = false;
OnLoadingComplete?.Invoke();
}
}
base.Update(gameTime);
}