Using Surfaces

Surfaces are essentially just Render Textures.  A Surface can be the target of rendering Graphics, and Otter uses a main Surface to render the entire game by default.  You can create your own Surfaces and render Graphics to them.  This is a quick example on how to get a Surface set up and rendering in a game.

using Otter;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SurfaceBasics {
  class Program {
    static void Main(string[] args) {
      // Create a Game.
      var game = new Game("Surface Example");

      // Create a Scene.
      var scene = new Scene();

      // Add the Entity that will control the Surface being used.
      scene.Add(new SurfaceController());

      // Add 100 Things to the Scene!
      for (int i = 0; i < 100; i++) {
        scene.Add(new Thing());

      // Start 'er up.

  class Thing : Entity {
    // The movement max speed of the Thing.
    public float MoveSpeed = 3;

    public Thing() {
      // Add a small randomly colored circle as the Graphic.
      var img = Image.CreateCircle(5, Color.Random);

    public override void Added() {

      // Look for the SurfaceController, and set this Entity to render to that Surface.
      // An Entity will default to rendering to whatever Surface is set to it's Surface field.
      Surface = GetEntity<SurfaceController>().DrawingSurface;

      // Randomly position the Thing in the Game's bounds.
      SetPosition(Rand.Float(Game.Width), Rand.Float(Game.Height));

    public override void Update() {

      // Randomly move the Thing around.
      X += Rand.Float(-MoveSpeed, MoveSpeed);
      Y += Rand.Float(-MoveSpeed, MoveSpeed);

  class SurfaceController : Entity {
    // The Surface to be used by the Things to draw onto.
    public Surface DrawingSurface;

    // The movement speed.
    public float MoveSpeed = 4;
    // The speed at which the DrawingSurface will be scaled.
    public float ScaleSpeed = 0.02f;

    public override void Added() {
      // Create a Surface that is the size of the Game window.
      DrawingSurface = new Surface(Game.Width, Game.Height);

      // Set the fill color to a nice off black color.
      DrawingSurface.FillColor = Color.Shade(0.1f);

      // Add the Surface to the list of Graphics to be rendered.

      // Center the origin but don't move it.

    public override void Update() {

      // Toggle the auto clear flag and watch the magic.
      if (Input.KeyPressed(Key.Space)) {
        DrawingSurface.AutoClear = !DrawingSurface.AutoClear;

      // Change the color/tint of the Surface to a random color!
      if (Input.KeyPressed(Key.Return)) {
        DrawingSurface.Color = Color.Random;
      // Reset the color/tint of the Surface.
      if (Input.KeyPressed(Key.R)) {
        DrawingSurface.Color = Color.White;

      // Move the Entity around with WASD to see the Surface move as well.
      if (Input.KeyDown(Key.W)) {
        Y -= MoveSpeed;
      if (Input.KeyDown(Key.A)) {
        X -= MoveSpeed;
      if (Input.KeyDown(Key.S)) {
        Y += MoveSpeed;
      if (Input.KeyDown(Key.D)) {
        X += MoveSpeed;

      // Scale the Surface because it's funny looking.
      if (Input.KeyDown(Key.Up)) {
        DrawingSurface.ScaleY += ScaleSpeed;
      if (Input.KeyDown(Key.Down)) {
        DrawingSurface.ScaleY -= ScaleSpeed;
      if (Input.KeyDown(Key.Left)) {
        DrawingSurface.ScaleX -= ScaleSpeed;
      if (Input.KeyDown(Key.Right)) {
        DrawingSurface.ScaleX += ScaleSpeed;

This example will render a bunch of small circles to a surface that can be squashed and stretched and moved around with the arrow keys, and the W, A, S, and D keys respectively.

Check out what happens when the space bar is pressed.  The Surface will no longer clear itself before rendering so all of the circles will actually be permanently drawn to the Surface.

Also pressing the Enter key will change the color of the Surface to a random color.  As you will notice the entire Surface and its contents are tinted to that color.  Press R to reset the color back to white.