Skip to content

Non Flickering Canvas GUI Tutorial

samnad edited this page Oct 2, 2020 · 6 revisions

Welcome to my tutorial! Today, we are going to make a fully working GUI that doesn't flicker with a mouse. First, we need to define the screen x and y size. Make these ints that are not in a method.

int screenX = 800;
int screenY = 640;

Second, define the pixel buffer. This will store all of the pixels you are setting until the screen is drawn. We also need one that will store the last frame's buffer to check against for the same pixel. We use (x * y) + x so that we can differentiate from pixel (3, 3) and (9, 1). If we only used x*y, those two coordinates would give the same pixel.

private static Color[] pixelBuffer = new Color[(screenX * screenY) + screenX];
private static Color[] pixelBufferOld = new Color[(screenX * screenY) + screenX];

We need to make an init method as well to initialize the canvas.

public static void init() {
    canvas = FullScreenCanvas.GetFullScreenCanvas();
    canvas.Mode = new Mode(screenX, screenY, ColorDepth.ColorDepth32);
}

Now that we've gotten everything initialized, let's make the first method. This one will set a pixel inside the buffer to a specific color. We will use this instead of the canvas.setPixel() method. Here, we check if the pixel location is outside of the screen dimensions, and if not, set the buffer at that location to that color.

public static void setPixel(int x, int y, Color c) {
    if (x > screenX || y > screenY) return;
    pixelBuffer[(x * y) + x] = c;
}

After that, we need to draw the screen. So let's make that method. I randomly picked Color.Orange for the starting pen color, but it doesn't matter at all.

public static void drawScreen() {
    Pen pen = new Pen(Color.Orange);
    for (int y = 0, h = screenY; y < h; y++)
    {
        for (int x = 0, w = screenX; x < w; x++)
        {
            if (!(pixelBuffer[(y * screenW) + x] == pixelBufferOld[(y * screenW) + x])) canvas.DrawPoint(pen, x, y);
        }
    }
    for (int i = 0, len = pixelBuffer.Length; i < len; i++)
    {
        pixelBuffer[i] = pixelBufferOld[i];
    }
}

Next, let's make a method to set all of the pixels on the screen to a certain color.

public static void clearScreen(Color c) {
    for (int i = 0, len = pixelBuffer.Length; i < len; i++)
    {
        pixelBuffer[i] = c;
    }
}

Ok. Now we can set pixels, clear the screen, and draw all the pixels! The last thing we need is an update method. This is where you put all the code to set the pixels. Using the setPixel method we made, you can make all kinds of methods, like rectangles, etc etc. Here's the update method. If you put this in a separate class like "DisplayDriver.cs", just put DisplayDriver.update(); in the run method in the kernel.cs.

public static void update() {
    clearScreen(Color.Blue);
    setPixel(1, 1, Color.Black);
    setPixel(1, 2, Color.Black);
    setPixel(2, 1, Color.Black);
    setPixel(2, 2, Color.Black);
    drawScreen();
}

Now we're done! Let me know if there are any issues or need help. I'll put the full code right below this. In the next tutorial, I'll show how to add a mouse to the GUI.

int screenX = 800;
int screenY = 640;
private static Color[] pixelBuffer = new Color[(screenX * screenY) + screenX];
private static Color[] pixelBufferOld = new Color[(screenX * screenY) + screenX];

public static void init() {
    canvas = FullScreenCanvas.GetFullScreenCanvas();
    canvas.Mode = new Mode(screenX, screenY, ColorDepth.ColorDepth32);
    Cosmos.System.MouseManager.ScreenWidth = Convert.ToUInt32(screenX);
    Cosmos.System.MouseManager.ScreenHeight = Convert.ToUInt32(screenY);
}
public static void drawScreen() {
    Pen pen = new Pen(Color.Orange);
    for (int y = 0, h = screenY; y < h; y++)
    {
        for (int x = 0, w = screenX; x < w; x++)
        {
            if (!(pixelBuffer[(y * screenW) + x] == pixelBufferOld[(y * screenW) + x])) canvas.DrawPoint(pen, x, y);
        }
    }
    for (int i = 0, len = pixelBuffer.Length; i < len; i++)
    {
        pixelBuffer[i] = pixelBufferOld[i];
    }
}
public static void clearScreen(Color c) {
    for (int i = 0, len = pixelBuffer.Length; i < len; i++)
    {
        pixelBuffer[i] = c;
    }
}
public static void setPixel(int x, int y, Color c) {
    if (x > screenX || y > screenY) return;
    pixelBuffer[(x * y) + x] = c;
}
public static void update() {
    clearScreen(Color.Blue);
    setPixel(1, 1, Color.Black);
    setPixel(1, 2, Color.Black);
    setPixel(2, 1, Color.Black);
    setPixel(2, 2, Color.Black);
    drawScreen();
}
Clone this wiki locally