Implementing Screen - sinusinu/Flora GitHub Wiki

Normally, games have multiple "screen"s to do different works. (e.g. Title screen, Game screen, Settings screen...)
To make implementing screen a bit easier, Flora provides IScreen interface. Let's try this one!

Begin with Simple Program:

MyCore.cs

using Flora;
using Flora.Gfx;

namespace FloraTest {
    class MyCore : FloraCore {
        IScreen currentScreen = null;
        IScreen pendingScreen = null;

        public override void Prepare() {
            currentScreen = new ScreenA(this);
        }

        public override void Pause() {
            if (currentScreen != null) currentScreen.Pause();
        }

        public override void Resume() {
            if (currentScreen != null) currentScreen.Resume();
        }

        public override void Resize(int width, int height) {
            if (currentScreen != null) currentScreen.Resize(width, height);
        }

        public override void Render(float delta) {
            if (currentScreen != null) currentScreen.Render(delta);

            if (pendingScreen != null) {
                currentScreen.Cleanup();
                currentScreen = pendingScreen;
                pendingScreen = null;
            }
        }

        public override void Cleanup() {
            if (currentScreen != null) currentScreen.Cleanup();
        }

        public void SetScreen(IScreen newScreen) {
            pendingScreen = newScreen;
        }
    }
}

Now MyCore have currentScreen and pendingScreen variable, sets currentScreen to new ScreenA(this) on Prepare, and just passes all the functions to currentScreen.

Render code is a bit unusual; It switches the screen after the render is over, instead of switching it immediately. This is to preserve reference of current screen while render is being executed.

Finally, We expose SetScreen function for screens to set new screens.

ScreenA.cs

Create a new class file named ScreenA.cs. Fill it with this:

using Flora;
using Flora.Gfx;
using System;

namespace FloraTest {
    class ScreenA : IScreen {
        MyCore core;

        public ScreenA(MyCore core) {
            this.core = core;
            Console.WriteLine("Screen A created!");
        }

        public void Pause() {

        }

        public void Resume() {

        }

        public void Resize(int width, int height) {

        }

        public void Render(float delta) {
            Gfx.Begin();
            Gfx.End();

            core.SetScreen(new ScreenB(core));
        }

        public void Cleanup() {

        }
    }
}

You can see that IScreen interface have all the same functions with FloraCore except Prepare.

That's because Flora is supposed to be already initialized when any of IScreen-inheriting object is being constructed. So any preparation can be done in constructor, instead of having separate Prepare function.

It is important for screens to keep the reference of MyCore alive by passing it around - or there will be no way to change the screen.

For now, ScreenA sets current screen to ScreenB every Render call.

ScreenB.cs

Create a new class file named ScreenB.cs. Fill it with this:

using Flora;
using Flora.Gfx;
using System;

namespace FloraTest {
    class ScreenB : IScreen {
        MyCore core;

        public ScreenB(MyCore core) {
            this.core = core;
            Console.WriteLine("Screen B created");
        }

        public void Pause() {

        }

        public void Resume() {

        }

        public void Resize(int width, int height) {

        }

        public void Render(float delta) {
            Gfx.Begin();
            Gfx.End();

            core.SetScreen(new ScreenA(core));
        }

        public void Cleanup() {

        }
    }
}

Same deal as ScreenA, but ScreenB sets current screen to ScreenA every Render call.

Now if you launch this app, you will see two screens quickly switching between them via Console. Nothing is being drawn on screen yet because we draw nothing on it.

You can use IScreen this way to easily implement screens!

⚠️ **GitHub.com Fallback** ⚠️