Raising the ground
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:
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
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:
- 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:
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 inmath.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) / numberRx = (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