Raising the ground

Fredy Acuña
8 min readMay 15, 2020

--

To read this blog I recommend you to be familiar with C programming language and (not mandatory) basics about SDL2. The main goal of this blog is not to give you a copy and paste code, instead it will guide you along the way until you get results by your own merit, also if you find any issues/mistakes/room for improvement please leave a response, thanks for reading.

You will create a program that displays an isometric grid receiving a file with coordinates in it

Your program should be executed using this syntax:

./program file

Note: The file will contain this information:

120 60 40 60 20 -20 -80 -120
40 20 30 30 -10 -40 -90 -110
20 30 10 06 -6 -20 -26 -90
00 -6 10 10 -6 -20 -20 -40
-20 -20 -18 -14 -40 -20 -20 -30
-10 -10 -10 -10 -8 -20 -20 -30
20 10 10 10 10 04 10 -10
30 24 24 22 20 18 14 16

Contents

To create this program you will follow these simple steps:

1) Receive data from a file in C
2) Create 2D grid with SDL2
3) Convert 3D grid into 2D isometric grid
4) Handle user input keys
5) Add rotation to grid

1. Receive data from file

To create it try implementing this structure or logic in your C main program:

to get the file name you need:

int main (int argc, char *argv[])

where argc parameter is the count of total command line arguments passed to executable on execution (including name of executable as first argument), and argv parameter is the array of character string of each command line argument passed to executable on execution. After that you need to open the file.

To work with files you need to declare a pointer of type file. This declaration is needed for communication between the file and the program, to open it you need fopen() (this function is defined in the stdio.h header file)

FILE *file_pointer; file_pointer = fopen("file_name","mode"); /* Mode will be r */

Note: If you open a file in some point you also need to close it, for that you’ll use fclose() , these functions are defined in the stdio.h header file.

Next step is to parse file information and store it. For that you can use getline() and strtok() functions or a derivative of these.

getline(char **buffer, size_t *n, FILE *stream);char *strtok(char *str, const char *delim);

Note: These functions are also included in stdio.h library.

getline() will read your file line per line, while strtok() split those lines in order to store them in the struct or array.

Note: remember to reserve memory for the information to be allocated.

Store the file information only on Z axis, X and Y axis will be used to store different coordinates that will be seen soon…

This is the structure that your array or struct will look like:

where rows, columns and data are represented this way in the file:

After you copy the data into the array or struct you should close the file.

2. Create 2D grid with SDL2

Before you create an isometric grid you need to understand how to create a grid like this:

First install SDL2 library in your computer, after that try creating a SDL2 window:

this window has 1280 x 720 size when executing

Note: Use SDL_Init(), SDL_CreateWindow(), SDL_CreateRenderer() to create it

Then you should use an infinite loop to keep your program running, else your program will open and close instantaneously.

Inside that infinite loop you may find the first SDL_SetRenderDrawColor() that sets the window background color and the second SDL_SetRenderDrawColor() that will paint the next illustration (in this case the graphs that you will create).

SDL_RenderClear() that will clean the window content and SDL_RenderPresent() that will update the screen content. All that will be happening constantly in the infinite loop, If you do not do that, your infinite loop will insert information over and over making a little mess

After you implement all above logic, you need to implement the key inputs, what’s the reason?
to close your program, because as your program is, it will not close because is doing and infinite loop. For it you will use SDL_PollEvent() function:

Implementing above code in your code will let you close your program with the exit button, also with it you can handle keyboard, mouse or joystick inputs from the user, for more info read this.

Now, if you want to test your program you can compile it and execute it:

$ gcc -Wall -Werror -Wextra -pedantic *.c -l $(sdl2-config --cflags --libs) -o program
$ ./program file

Note: -l flag will allow your program to compile with SDL2 library and if your program compiles, open the file, create and close the window, you are doing it well.

Draw simple grid

For this you will use SDL_RenderDrawPoint() and SDL_RenderDrawLine().
To draw the grid with no formulas or complex math.

To draw you have to understand that your window is like a Cartesian plane where the X axis points to the right, but the Y axis points down and the origin of the plane is in the top left

to plot that point I used SDL_RenderDrawPoint(renderer, 160, 120)

Note: If the window has a size of 1280 x 768 it means that your window X axis has 1280 distance while the Y axis has a distance of 768 both of them starting from 0

Once you have that clear try to follow the next steps:

  1. Create horizontal points.

2. Create multiple points in your screen:

Note: If you have more than one SDL_RenderDrawPoint() try making a nested loop and use just one SDL_RenderDrawPoint() function inside that nested loop, learn this will make you able to control easily the X and Y axis in your grid

3. Now that you know how to create points, try to connect the points horizontally:

4. Once you reach that point try to connect the points in a vertical way:

5. Congrats:

3. Convert 3D grid into 2D isometric grid

Once you know how to create a simple grid, it is time to store those coordinates into your array or struct, the logic should be alike to this one:

where row and col are the number of lines that you want to draw (Example: 8x7 grid, 8 = row, 7 = col)

After you store the variables in the array or struct, you have all 3D coordinates, but what if I tell you that you cannot graph 3D grids in SDL2?

SDL_RenderDrawLine() only receive X and Y axis, so Z axis is out of sign.
To solve this you need to convert 3D coordinates into 2D coordinates, you can do it applying this formula:

Wx = inc * X - inc * Y;
Wy = (1 - inc) * X +
(1 - inc) * Y - Z;

where inc it’s how much inclination will your grid have?

It’s time to implement the formula in your program:

The nested loop will iterate over the rows and columns in your pointer or struct, and the formula will be applied to every X, Y and Z, reducing those 3 values into 2 values (Wx and Wy). with those two arguments you will be ready to display an isometric grid.

4. Handle keys

As told before, in your function handle_keys() you can receive inputs from the user, so try to receive arrow keys from the user:

Note: Use macros to make your code more clear like SDL_SCANCODE_LEFT

If everything is OK you may have something like this:

5. Add rotation to grid

As shown in the previous image you will create a rotate_grid function that will move your isometric grid making it interactive, for that you need to:

  • Use the M_PI macro defined in math.h standard library
  • Add -m flag to you compile command to be able to use the math library

Here is the formula:

a = Angle * PI / 180
Rx = x * cos(a) - y * sin(a)
Ry = x * sin(a) + y * cos(a)

Note: Angle will be 1 to move left and -1 to move right, X and Y you already have them in your struct or array

Note: The formula is incomplete. To complete it implement your X and Y screen axis like this:

Cx = SCREEN_WIDTH (1280) / number
Cy = SCREEN_HEIGHT (720) / number
Rx = (X - Cx) * cos(a) - (Y - Cy) * sin(a) + Cx;
Ry = (X - Cx) * sin(a) + (Y - Cy) * cos(a) + Cy;

try changing number until you find the perfect one

when you finish to implement everything you will have something like this:

What’s rest it to compile your program and execute it.

$ gcc -Wall -Werror -Wextra -pedantic *.c -lm $(sdl2-config --cflags --libs) -o program
$ ./program file

--

--