Tutorial: You Spin Me Right Round

This tutorial is going to introduce a few more features of Nyx, and to do that, we’re going to make a spinning square that changes colors!

Setup

We’re going to start with the same code we had at the end of the previous tutorial with a small modification (not drawing a line). Here it is:

#include "nyx/nyx.hpp"

int main(int, char *[]) {
  auto engine = nyx::Engine();
  auto window = engine.create_window("Tutorial", 800, 600);
  auto ctx = window->create_context();

  do {
    engine.update();

    window->clear();

    engine.show();
  } while (engine.is_running);

  return 0;
}

Drawing a Square

Drawing a square is easy with Nyx! We’re going add a simple bit of code. Last tutorial, I mentioned that you often want to draw it outside the loop if it’s going to be static, but since this is going to eventually rotate, we’re going to have to redraw every frame, meaning we’re going to be clearing the Context each time. Here is that part of the code changed to our new needs of drawing a white, 100x100 square at the center of the screen:

int sq_w = 100;
int sq_h = 100;

do {
  engine.update();

  window->clear();

  ctx->clear();
  ctx->rectangle(
      (window->w / 2) - (sq_w / 2),
      (window->h / 2) - (sq_h / 2),
      sq_w,
      sq_h,
      nyx::Color(0xffffffff));

  engine.show();
} while (engine.is_running);

Easy! Context::rectangle() takes up to 6 parameters: an x, y, width, height, angle, and color. Angle is optional and you can just put a color where it goes instead. We’ll use the angle parameter in a second, but the above snippet doesn’t use it.

We are subtracting half the size of the square from the center point of the window so the center of the square is what’s actually at the center of the window. Like most libraries, squares/rectangles are drawn from the top left corner.

Now we want it to rotate. Let’s do that now by creating a new variable named angle that we will increment every frame:

int sq_w = 100;
int sq_h = 100;

double angle = 0.0;

do {
  engine.update();

  angle += 1.0;

  window->clear();

  ctx->clear();
  ctx->rectangle(
      (window->w / 2) - (sq_w / 2),
      (window->h / 2) - (sq_h / 2),
      sq_w,
      sq_h,
      angle,
      nyx::Color(0xffffffff));

  engine.show();
} while (engine.is_running);

This works, but there’s a problem. There isn’t any good way to decide how much to increment the angle each frame. As of now, it’s based on the framerate. The higher the framerate, the faster it will spin. Not to worry, there’s an easy fix.

Delta Time

Unless you’ve looked at the API already, you won’t know that Engine::update() actually returns a double value. This value is the delta time of the previous frame–how many seconds it between the last frame and this one. You can use this value to decide how much to change values between frames. Let’s use that now to make the square rotate 90 degrees per second:

int sq_w = 100;
int sq_h = 100;

double angle = 0.0;

do {
  double dt = engine.update();

  angle += 90.0 * dt;

  window->clear();

  ctx->clear();
  ctx->rectangle(
      (window->w / 2) - (sq_w / 2),
      (window->h / 2) - (sq_h / 2),
      sq_w,
      sq_h,
      angle,
      nyx::Color(0xffffffff));

  engine.show();
} while (engine.is_running);

If you run this now, you’ll see the square smoothly rotates around in a circle at ~1/4 turn per second. This is now completely independent of how fast the program runs because we are basing the rotation off how fast the program is running. Isn’t that cool?

This is a technique used widely throughout game development, and can be used any time you need a frame indepenedent way to move things around. Don’t forget that update gives you that dt, you don’t need to calculate it yourself!

Changing Color With Timers

Timers are built into Nyx, and can be used to call a snippet of code periodically. This snippet is taken in the form of a C++11 lambda, and there are many different timer types. Take a look at the API to see all of them, but in this tutorial, we are going to use the every timer.

every timers execute the code snippet given every N seconds, where N is a double that you provide. We want to change the color to something random each frame, which is going to be very easy with this technique. Here is the full code snippet, comments included where changes were made:

#include "nyx/nyx.hpp"

#include <stdlib.h>  // rand

// Moved square size up here and made it constant
const int SQ_W = 100;
const int SQ_H = 100;

int main(int, char *[]) {
  srand(time(NULL));  // Seed the random generator

  auto engine = nyx::Engine();
  auto window = engine.create_window("Tutorial", 800, 600);
  auto ctx = window->create_context();

  auto color = nyx::Color(0xffffffff);  // Start with the color white

  // Create a timer that executes the given function every 1.0 seconds
  engine.timers->every(1.0, [&]{
    // Set the color to a random color given 3 random values for r, g, and b
    color = nyx::Color(rand()%255, rand()%255, rand()%255);
  });

  double angle = 0.0;

  do {
    double dt = engine.update();

    angle += 90.0 * dt;

    window->clear();

    ctx->clear();
    ctx->rectangle(
        (window->w / 2) - (SQ_W / 2),
        (window->h / 2) - (SQ_H / 2),
        SQ_W,
        SQ_H,
        angle,
        color);  // Use the new color variable to
                 // determine the color

    engine.show();
  } while (engine.is_running);

  return 0;
}

If all is well, you should see the square rotating, and also changing colors every second. This concludes this tutorial.