Using View - sinusinu/Flora GitHub Wiki

⚠️ Currently View might have some implementation error because I can't figure things out - If you have a problem, a little help would be greatly appreciated!

What if you want to have a "camera" so you can move, scale, and/or rotate the screen?

or you want to have a fixed-size drawing screen regardless of window size/display resolution?

Flora provides a simple way to do that: View. Let's take a look!

Begin with Drawing Textures (get your test.png ready!):

MyCore.cs

using Flora;
using Flora.Gfx;
using Flora.Util;

namespace FloraTest {
    class MyCore : FloraCore {
        Texture texture;
        View view;

        public override void Prepare() {
            texture = new Texture(PathUtils.Relative("test.png"));

            view = new View(1920, 1080, true);
            Gfx.SetView(view);
        }

        public override void Pause() {
            
        }

        public override void Resume() {
            
        }

        public override void Resize(int width, int height) {
            
        }

        public override void Render(float delta) {
            Gfx.Begin();
            Gfx.Clear(0, 0, 0);
            Gfx.Draw(texture, 0, 0);
            Gfx.End();
        }

        public override void Cleanup() {
            texture.Dispose();
        }
    }
}

new View(1920, 1080, true); creates a View with size of 1920 * 1080, letterboxed.

Newly created View must be applied to Gfx by calling Gfx.SetView(view).

View does not need to be disposed.

After applying the view, you can draw just like you did previously; but the texture will be drawn a bit differently.

How does the View work?

Without View, Flora uses top-left origin, and only the area from (0, 0) to (window width, window height) can be seen.

With View, Flora uses center origin, and area of size given when creating View can be seen.
Think of it as if there is an infinitely large surface, and you are looking a part of it through the camera.

Visible area of the View is always at least of given size at its creation. If letterBox was set to true, outside the region of given size won't be drawn, enforcing the given aspect ratio. It is good for hiding not-to-be-seen offscreen junks, but the empty areas might be distracting.

View metrics

View provides some metrics that can be useful for positioning some elements.

Continue with above program:

using Flora;
using Flora.Gfx;
using Flora.Util;

namespace FloraTest {
    class MyCore : FloraCore {
        Texture texture;
        View view;

        public override void Prepare() {
            texture = new Texture(PathUtils.Relative("test.png"));

            view = new View(1920, 1080, false);  // letterBox set to false
            Gfx.SetView(view);
        }

        public override void Pause() {
            
        }

        public override void Resume() {
            
        }

        public override void Resize(int width, int height) {
            
        }

        public override void Render(float delta) {
            Gfx.Begin();
            Gfx.Clear(0, 0, 0);
            Gfx.Draw(texture, view.visibleLeft, view.visibleTop, view.visibleWidth, view.visibleHeight);
            Gfx.End();
        }

        public override void Cleanup() {
            texture.Dispose();
        }
    }
}

This will draw texture full screen, regardless of window size.
If you can't resize the window, check out the Application Configuration.

View.visibleLeft and View.visibleTop gives current most top-left visible position.
These values will be updated in sync when you move the view.

View.visibleWidth and View.visibleHeight gives current visible width and height.
If letterBox is true, it will be same as the given size on creation. if false, it will give you a 'stretched' size.

Now what can you do with this View?

Move

Continue with above program:

using Flora;
using Flora.Gfx;
using Flora.Util;
using System;

namespace FloraTest {
    class MyCore : FloraCore {
        Texture texture;
        View view;

        float tmp = 0f;

        public override void Prepare() {
            texture = new Texture(PathUtils.Relative("test.png"));

            view = new View(1280, 720, false);
            Gfx.SetView(view);
        }

        public override void Pause() {
            
        }

        public override void Resume() {
            
        }

        public override void Resize(int width, int height) {
            
        }

        public override void Render(float delta) {
            tmp += delta * MathF.PI;

            view.positionX = MathF.Cos(tmp) * 300f;
            view.positionY = MathF.Sin(tmp) * 300f;

            Gfx.Begin();
            Gfx.Clear(0, 0, 0);
            Gfx.Draw(texture, -view.visibleWidth / 2f, -view.visibleHeight / 2f, view.visibleWidth, view.visibleHeight);
            Gfx.End();
        }

        public override void Cleanup() {
            texture.Dispose();
        }
    }
}

Now texture will move in circle.

Note that the texture is being drawn on position -view.visibleWidth / 2f, -view.visibleHeight / 2f because view.visibleLeft and view.visibleTop gets updated with moving view and using that value here will make texture look like it's not moving.

Scale

Continue with above program:

using Flora;
using Flora.Gfx;
using Flora.Util;
using System;

namespace FloraTest {
    class MyCore : FloraCore {
        Texture texture;
        View view;

        float tmp = 0f;

        public override void Prepare() {
            texture = new Texture(PathUtils.Relative("test.png"));

            view = new View(1280, 720, false);
            Gfx.SetView(view);
        }

        public override void Pause() {
            
        }

        public override void Resume() {
            
        }

        public override void Resize(int width, int height) {
            
        }

        public override void Render(float delta) {
            tmp += delta * MathF.PI;

            view.zoom = MathF.Sin(tmp) + 1f;

            Gfx.Begin();
            Gfx.Clear(0, 0, 0);
            Gfx.Draw(texture, -view.visibleWidth / 2f, -view.visibleHeight / 2f, view.visibleWidth, view.visibleHeight);
            Gfx.End();
        }

        public override void Cleanup() {
            texture.Dispose();
        }
    }
}

Now texture will zoom in/out.

View.zoom accepts positive value, and initial zoom is 1f.

Rotate

Continue with above program:

using Flora;
using Flora.Gfx;
using Flora.Util;
using System;

namespace FloraTest {
    class MyCore : FloraCore {
        Texture texture;
        View view;

        float tmp = 0f;

        public override void Prepare() {
            texture = new Texture(PathUtils.Relative("test.png"));

            view = new View(1280, 720, false);
            Gfx.SetView(view);
        }

        public override void Pause() {
            
        }

        public override void Resume() {
            
        }

        public override void Resize(int width, int height) {
            
        }

        public override void Render(float delta) {
            tmp += delta * MathF.PI * 45f;

            view.rotation = tmp;

            Gfx.Begin();
            Gfx.Clear(0, 0, 0);
            Gfx.Draw(texture, -view.visibleWidth / 2f, -view.visibleHeight / 2f, view.visibleWidth, view.visibleHeight);
            Gfx.End();
        }

        public override void Cleanup() {
            texture.Dispose();
        }
    }
}

Now texture will rotate.

View.rotate is a degree angle, so 180f will be upside-down and 360f will be the same as 0f.

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