Create your own OpenGL game in 15 minutes!

Gaurav Prabhu K
13 min readApr 10, 2020

--

Image created using Canva

As a kid, I loved playing video games and computer games and I am sure you did too. Although I enjoyed playing them, I was always curious as to how can I create my own game! When I began my studies to be a Computer engineer I was finally introduced to the magical world of Computer Graphics! As a computer programmer, I enjoy the privilege of creating and playing my computer games! Here’s one of the very first games I and my friend created together. This is very simple and I am sure you will be able to create in less than 15 minutes!

About the game:

The game is called “Park the rocket”.

As the name says, you will be given a rocket in the game and you have to park it on a given surface without crashing into any obstacles!

The final output of the game

Requisites to create the game:

The game will be coded in the “C” programming language using the OpenGL library. I write this blog post with the understanding that you have installed the C compiler and OpenGL on your computer and also that you have a basic knowledge of Computer Graphics.

Psst… In case you need tutorials on Computer Graphics from the scratch or installing and setting up OpenGL on your computer, please mention it in the comment section and I will write blogs to help you with it.

Let us begin the code by importing the essential libraries.

#include<stdio.h>#include<time.h>#include<stdlib.h>#include<string.h>#include<GL/glut.h>

The GL/glut.h is the header file for importing the OpenGL library. The time.h is used to implement blinking later on.

Next, we will define all the global variables which we will use as flags for various purposes.

int SCREEN = 1;float xsize = 0.0, ysize = 127.0;GLfloat r = 100.0, cx = 700.0, cy = 700.0;GLint wreckFlag = 0;

The SCREEN flag is used to change the screen according to a certain action. This game has four screens:

  1. Front screen — Where we display the game details.
  2. Main/Game screen — Where we play the game.
  3. Congratulations screen — Shows up after completing the game without crashing into any obstacles.
  4. Game Over screen — Used to display the message “Game Over” if the rocket crashes into an obstacle.

The SCREEN values vary from 1 to 4 based on which screen we want to display for a particular action. The wreckFlag is used to determine whether the rocket is in shape or not (determine rocket crash). The other floating-point constants are used to draw the rocket and give the displacement to the rocket in the X and Y direction.

Let us begin by drawing our rocket and one of the obstacles (not the asteroid). If you look closely at the game image, you can see the Rocket in our game has been drawn using three shapes. A triangle for the top, a rectangle in the middle and the base is a trapezium.

//Rocket Coordinates//Coordinates of the Trianglefloat top[3][3] = {{ 30.0, 130.0 },{ 60.0, 130.0 },{ 45.0, 170.0 }};//Coordinates of the Squarefloat square[4][4] = {{ 30.0, 30.0 },{ 60.0, 30.0 },{ 60.0, 130.0 },{ 30.0, 130.0 }};//Coordinates of the Basefloat base[][5] = {{ 20.0, 10.0 },{ 70.0, 10.0 },{ 60.0, 30.0 },{ 30.0, 30.0 }};// Coordinates of the Obstaclefloat obstacle[4][4] = {{ 150.0, 350.0 },{ 150.0, 450.0 },{ 250.0, 450.0 },{ 250.0, 350.0 }};

Now we shall define a function that displays the first screen, which displays the name and project details. We shall define two functions to do the same, output and drawstring.

void output(int x, int y, char *string){int len, i;glRasterPos2f(x, y);len = (int)strlen(string);for (i = 0; i < len; i++){glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, string[i]);}}void drawstring(int x, int y, char *string, void *font){int len, i;glRasterPos2f(x, y);len = (int)strlen(string);for (i = 0; i < len; i++){glutBitmapCharacter(font, string[i]);}}

The drawstring function is used to display whatever string we want to display on the screen. Let us define the frontscreen function to display the game details when we start the game.

void frontscreen(void){glClearColor(2.0,2.0,0.0,0.0);glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);glColor3f(0.7,0,1);drawstring(300,750,"DEPARTMENT OF COMPUTER SCIENCE ANDENGINEERING",GLUT_BITMAP_HELVETICA_18);glColor3f(1.7,0.0,0.0);drawstring(370,650,"A MINI PROJECT ON",GLUT_BITMAP_HELVETICA_18);glColor3f(0.5,0.0,9.0);drawstring(375,600,"\"PARK THE ROCKET\"",GLUT_BITMAP_HELVETICA_18);glColor3f(0,0.0,1);drawstring(425,550,"BY",GLUT_BITMAP_HELVETICA_18);glColor3f(0.5,0,0.5);drawstring(340,500,"GAURAV PRABHU K",GLUT_BITMAP_HELVETICA_18);drawstring(340,450,"GAUTHAM BHAT",GLUT_BITMAP_HELVETICA_18);glColor3f(3.9,0.0,0.0);drawstring(350,150,"PRESS 'n' or 'N' TOCONTINUE",GLUT_BITMAP_HELVETICA_18);glutSwapBuffers();glFlush();}

The frontscreen function displays the following screen:

The first screen displayed at the beginning of the game with game details

We shall now define the functions to draw the rocket, using the coordinates which we had defined earlier for the triangle, rectangle, and trapezium (polygon).

//Function to Draw Rocketvoid drawRocket(){//Draw TriangleglColor3f(1.0, 0.0, 0.0);glBegin(GL_TRIANGLES);glVertex2f(top[0][0] + xsize, top[0][1] + ysize);glVertex2f(top[1][0] + xsize, top[1][1] + ysize);glVertex2f(top[2][0] + xsize, top[2][1] + ysize);glEnd();//Draw SquareglColor3f(0.2, 0.2, 0.2);glBegin(GL_POLYGON);glVertex2f(square[0][0] + xsize, square[0][1] + ysize);glVertex2f(square[1][0] + xsize, square[1][1] + ysize);glVertex2f(square[2][0] + xsize, square[2][1] + ysize);glVertex2f(square[3][0] + xsize, square[3][1] + ysize);glEnd();//Draw BaseglColor3f(1.0, 0.0, 0.0);glBegin(GL_POLYGON);glVertex2f(base[0][0] + xsize, base[0][1] + ysize);glVertex2f(base[1][0] + xsize, base[1][1] + ysize);glVertex2f(base[2][0] + xsize, base[2][1] + ysize);glVertex2f(base[3][0] + xsize, base[3][1] + ysize);glEnd();glutSwapBuffers();glFlush();}//DrawRocket ends//Rocket wreckvoid rocketWreck(){glColor3f(1.0,0.0,0.0);glBegin(GL_POLYGON);glVertex2f( xsize, ysize);glVertex2f( xsize + 50.0 , ysize);glVertex2f( xsize + 30.0 , ysize + 30.0);glEnd();glColor3f(0.40,0.4,0.4);glBegin(GL_POLYGON);glVertex2f( xsize , ysize );glVertex2f( xsize + 20.0 , ysize);glVertex2f( xsize + 20.0, ysize + 70.0);glEnd();glColor3f(0.40,0.4,0.4);glBegin(GL_POLYGON);glVertex2f( ysize, ysize);glVertex2f( ysize + 10.0, xsize);glVertex2f( ysize + 10.0, xsize + 30.0);glEnd();glColor3f(1.0,0.0,0.0);glBegin(GL_POLYGON);glVertex2f( ysize, ysize);glVertex2f( ysize + 10.0, xsize);glVertex2f( ysize + 10.0, xsize + 30.0);glVertex2f( ysize , xsize + 30.0);glEnd();glFlush();}//Draw Flame Functionvoid drawFlame(){//RED FLAMEglColor3f(1.0, 0.0, 0.0);glBegin(GL_POLYGON);glVertex2f(20.0 + xsize, 10.0 + ysize);glVertex2f(70.0 + xsize, 10.0 + ysize);glVertex2f(70.0 + xsize, -10.0 + ysize);glVertex2f(60.0 + xsize, 0.0 + ysize);glVertex2f(50.0 + xsize, -10.0 + ysize);glVertex2f(30.0 + xsize, 0.0 + ysize);glVertex2f(20.0 + xsize, -10.0 + ysize);glEnd();//YELLOW FLAMEglColor3f(1.0, 1.0, 0.0);glBegin(GL_POLYGON);glVertex2f(25.0 + xsize, 10.0 + ysize);glVertex2f(55.0 + xsize, 10.0 + ysize);glVertex2f(55.0 + xsize, 0.0 + ysize);glVertex2f(40.0 + xsize, 5.0 + ysize);glVertex2f(35.0 + xsize, 0.0 + ysize);glVertex2f(30.0 + xsize, 5.0 + ysize);glVertex2f(25.0 + xsize, 0.0 + ysize);glEnd();glFlush();}

Here, in the above code, we have also defined a function drawFlame. This function draws the flame emanating from the base of the rocket when the rocket is moving.

We shall now draw the asteroids, stars, and earth.

void drawObstacle(){int i,j;glLoadIdentity();glPushMatrix();glLoadIdentity();glColor3f(1.0,0.0,0.0);glTranslated(600.0,600.0,0.0);glutSolidSphere(10.0,10.0,10.0);glPopMatrix();glEnd();glFlush();//Draw STARSglColor4f(1.0,1.0,1.0,-10.0);glPointSize(3.0);glBegin(GL_POINTS);glVertex2f(300.0,300.0);glVertex2f(600.0,600.0);glVertex2f(10.0,300.0);glVertex2f(300.0,50.0);glVertex2f(200.0,20.0);glVertex2f(15.0,250.0);glVertex2f(210.0,30.0);glVertex2f(20.0,30.0);glVertex2f(30.0,90.0);glVertex2f(240.0,80.0);glVertex2f(250.0,570.0);glVertex2f(260.0,260.0);glVertex2f(470.0,850.0);glVertex2f(280.0,440.0);glVertex2f(90.0,230.0);glVertex2f(60.0,20.0);glVertex2f(80.0,20.0);glVertex2f(40.0,50.0);glVertex2f(60.0,80.0);glVertex2f(90.0,170.0);glVertex2f(20.0,100.0);glVertex2f(470.0,105.0);glVertex2f(280.0,100.0);glVertex2f(90.0,110.0);glVertex2f(60.0,120.0);glVertex2f(80.0,125.0);glVertex2f(40.0,50.0);glVertex2f(60.0,100.0);glVertex2f(90.0,107.0);glVertex2f(20.0,125.0);glVertex2f(470.0,400.0);glVertex2f(280.0,400.0);glVertex2f(90.0,410.0);glVertex2f(60.0,420.0);glVertex2f(80.0,525.0);glVertex2f(40.0,500.0);glVertex2f(60.0,400.0);glVertex2f(90.0,407.0);glVertex2f(20.0,525.0);glVertex2f(470.0,600.0);glVertex2f(280.0,600.0);glVertex2f(90.0,610.0);glVertex2f(60.0,620.0);glVertex2f(80.0,625.0);glVertex2f(40.0,600.0);glVertex2f(60.0,600.0);glVertex2f(90.0,607.0);glVertex2f(20.0,625.0);glVertex2f(800.0,500.0);glVertex2f(810,400.0);glVertex2f(820.0,410.0);glVertex2f(800,520.0);glVertex2f(800.0,525.0);glVertex2f(850.0,300.0);glVertex2f(870.0,500.0);glVertex2f(890.0,507.0);glVertex2f(820.0,325.0);glVertex2f(900.0,500.0);glVertex2f(900.0,400.0);glVertex2f(900.0,310.0);glVertex2f(660.0,520.0);glVertex2f(800.0,325.0);glVertex2f(900.0,500.0);glVertex2f(700.0,400.0);glVertex2f(600.0,407.0);glVertex2f(900.0,525.0);glEnd();//STARS END//DRAW EARTHglColor3f(0.0,0.0,1.0);glBegin(GL_POLYGON);for (j = 0; j < 101;j++){float theta = 2.0f*3.1416*(float)j / (float)101;float x = r*cos(theta);float y = r*sin(theta);glVertex2f(x+cx, y+cy);}glEnd();//ICE CAP 1glColor3f(0.6,0.6,0.6);glBegin(GL_POLYGON);glVertex2f(700.0, 800.0);glVertex2f(740.0, 790.0);glVertex2f(740.0, 780.0);glVertex2f(660.0, 760.0);glVertex2f(680.0, 785.0);glVertex2f(670.0, 790.0);//glVertex2f(glEnd();//LAND 1glColor3f(0.6,0.4,0.12);glBegin(GL_POLYGON);glVertex2f(800.0, 700.0);glVertex2f(785.0, 650.0);glVertex2f(775.0, 680.0);glVertex2f(760.0, 620.0);glVertex2f(750.0, 630.0);glVertex2f(745.0, 665.0);glVertex2f(740.0, 715.0);glVertex2f(750.0, 720.0);glVertex2f(745.0, 730.0);glVertex2f(755.0, 735.0);glVertex2f(770.0, 730.0);glVertex2f(765.0, 740.0);glVertex2f(775.0, 720.0);glEnd();//LAND 2glColor3f(0.6,0.4,0.12);glBegin(GL_POLYGON);glVertex2f(680.0, 670.0);glVertex2f(660.0, 650.0);glVertex2f(635.0, 630.0);glVertex2f(635.0, 630.0);glVertex2f(630.0, 630.0);glVertex2f(610.0, 650.0);glVertex2f(610.0, 675.0);glVertex2f(620.0, 685.0);glVertex2f(600.0, 700.0);glVertex2f(630.0, 740.0);glVertex2f(650.0, 710.0);glVertex2f(670.0, 680.0);glEnd();//VIEWPORT 1glColor3f(0.0, 0.0, 0.0);glBegin(GL_LINE_LOOP);glVertex2f(obstacle[0][0], obstacle[0][1]);glVertex2f(obstacle[1][0], obstacle[1][1]);glVertex2f(obstacle[2][0], obstacle[2][1]);glVertex2f(obstacle[3][0], obstacle[3][1]);glEnd();//VIEWPORT 2glColor3f(0.0, 0.0, 0.0);glBegin(GL_LINE_LOOP);glVertex2f(obstacle[0][0] + 170.0, obstacle[0][1] + 270.0);glVertex2f(obstacle[1][0] + 170.0, obstacle[1][1] + 270.0);glVertex2f(obstacle[2][0] + 170.0, obstacle[2][1] + 270.0);glVertex2f(obstacle[3][0] + 170.0, obstacle[3][1] + 270.0);glEnd();//VIEWPORT 3glColor3f(0.0, 0.0, 0.0);glBegin(GL_LINE_LOOP);glVertex2f(500.0, 250.0);glVertex2f(500.0, 350.0);glVertex2f(600.0, 350.0);glVertex2f(600.0, 250.0);glEnd();//VIEWPORT 4glColor3f(0.0, 0.0, 0.0);glBegin(GL_LINE_LOOP);glVertex2f(250.0, 125.0);glVertex2f(250.0, 300.0);glVertex2f(350.0, 300.0);glVertex2f(350.0, 125.0);glEnd();//ASTROID 1glColor3f(1.0, 0.0, 0.0);glBegin(GL_POLYGON);glVertex2f(160.0, 150.0 + 200.0 );glVertex2f(160.0, 160.0 + 200.0 );glVertex2f(150.0, 170.0 + 200.0 );glVertex2f(150.0, 220.0 + 200.0 );glVertex2f(160.0, 230.0 + 200.0 );glVertex2f(150.0, 240.0 + 200.0 );glVertex2f(170.0, 250.0 + 200.0 );glVertex2f(230.0, 250.0 + 200.0 );glVertex2f(250.0, 230.0 + 200.0 );glVertex2f(240.0, 210.0 + 200.0 );glVertex2f(250.0, 170.0 + 200.0 );glVertex2f(230.0, 150.0 + 200.0 );glVertex2f(210.0, 160.0 + 200.0 );glVertex2f(200.0, 150.0 + 200.0 );glEnd();//ASTROID 2glColor3f(1.0, 0.0, 0.0);glBegin(GL_POLYGON);glVertex2f(340.0, 320.0 + 300.0);glVertex2f(320.0, 330.0 + 300.0);glVertex2f(320.0, 340.0 + 300.0);glVertex2f(330.0, 350.0 + 300.0);glVertex2f(320.0, 360.0 + 300.0);glVertex2f(320.0, 370.0 + 300.0);glVertex2f(350.0, 370.0 + 300.0);glVertex2f(320.0, 380.0 + 300.0);glVertex2f(320.0, 410.0 + 300.0);glVertex2f(330.0, 420.0 + 300.0);glVertex2f(340.0, 420.0 + 300.0);glVertex2f(350.0, 410.0 + 300.0);glVertex2f(360.0, 420.0 + 300.0);glVertex2f(410.0, 420.0 + 300.0);glVertex2f(420.0, 410.0 + 300.0);glVertex2f(420.0, 380.0 + 300.0);glVertex2f(410.0, 370.0 + 300.0);glVertex2f(420.0, 360.0 + 300.0);glVertex2f(420.0, 340.0 + 300.0);glVertex2f(410.0, 320.0 + 300.0);glVertex2f(390.0, 320.0 + 300.0);glVertex2f(380.0, 330.0 + 300.0);glVertex2f(370.0, 320.0 + 300.0);glVertex2f(360.0, 330.0 + 300.0);glVertex2f(350.0, 330.0 + 300.0);glEnd();glFlush();//ASTROID 3glColor3f(1.0, 0.0, 0.0);glBegin(GL_POLYGON);glVertex2f(160.0 + 350.0, 150.0 + 100.0);glVertex2f(150.0 + 350.0, 220.0 + 100.0);glVertex2f(150.0 + 350.0, 240.0 + 100.0);glVertex2f(170.0 + 350.0, 250.0 + 100.0);glVertex2f(230.0 + 350.0, 250.0 + 100.0);glVertex2f(250.0 + 350.0, 230.0 + 100.0);glVertex2f(240.0 + 350.0, 210.0 + 100.0);glVertex2f(250.0 + 350.0, 170.0 + 100.0);glVertex2f(230.0 + 350.0, 150.0 + 100.0);glVertex2f(210.0 + 350.0, 160.0 + 100.0);glVertex2f(200.0 + 350.0, 150.0 + 100.0);glEnd();//HILLOCKglColor3f(1.0, 1.0, 0.0);glBegin(GL_POLYGON);glVertex2f( 250.0, 125.0 );glVertex2f( 260.0, 265.0 );//glVertex2f( 260.0, 145.0 );glVertex2f( 320.0, 280.0 );glVertex2f( 330.0, 280.0 );glVertex2f( 340.0, 260.0 );glVertex2f( 350.0, 125.0 );glEnd();//DRAW LANDING BASEglColor3f(0.30,0.2,0.7);glBegin(GL_POLYGON);glVertex2f(700.0, 125.0);glVertex2f(750.0, 170.0);glVertex2f(850.0, 170.0);glVertex2f(900.0, 125.0);glEnd();glFlush();//SURFACEglColor3f(1.0,1.0,0.0);glBegin(GL_POLYGON);glVertex2f(0.0, 0.0);glVertex2f(0.0, 125.0);glVertex2f(1200.0,125.0);glVertex2f(1200.0,0.0);glEnd();glFlush();}

Now let us define the functions to display the game over and congratulations screen. Again, these two functions make use of drawstring function to display the text.

//Function to display GAMEOVER messagevoid gameOver(){xsize = 0.0, ysize = 127.0;glClearColor(1.0,1.0,1.0,1.0);glColor3f(1.0,0.0,0.0);drawstring(400,500," ****GAME OVER****",GLUT_BITMAP_TIMES_ROMAN_24);glFlush();Sleep(500);glColor3f(1.0,1.0,0.0);drawstring(400,500," ****GAME OVER****",GLUT_BITMAP_TIMES_ROMAN_24);glFlush();Sleep(500);glColor3f(0.0,0.0,1.0);drawstring(400,200," Press \'y\' OR \'Y\' to PLAYAGAIN",GLUT_BITMAP_TIMES_ROMAN_24);drawstring(400,100," Press \'q\' OR \'Q\' toQUIT",GLUT_BITMAP_TIMES_ROMAN_24);glFlush();Sleep(1000);glutPostRedisplay();}//CONGRATULATIONS functionvoid Congratulations(){xsize = 0.0, ysize = 127.0;glClearColor(1.0,1.0,1.0,1.0);glColor3f(1.0,0.0,0.0);drawstring(400,500," ****CONGRATULATIONS****",GLUT_BITMAP_TIMES_ROMAN_24);glFlush();Sleep(500);glColor3f(1.0,1.0,0.0);drawstring(400,500," ****CONGRATULATIONS****",GLUT_BITMAP_TIMES_ROMAN_24);glFlush();Sleep(500);glColor3f(0.0,0.0,1.0);
drawstring(400,200," Press \'y\' OR \'Y\' to PLAY
AGAIN",GLUT_BITMAP_TIMES_ROMAN_24);drawstring(400,100," Press \'q\' OR \'Q\' toQUIT",GLUT_BITMAP_TIMES_ROMAN_24);glFlush();Sleep(1000);glutPostRedisplay();}

Game Over screen:

The screen that tells the user that the Game is Over

Congratulations Method:

The screen that congratulates the user for successful completion of the game

So far we have defined all the necessary functions to draw the elements that exist in our game. Now it is time to implement the control and logic part of the game.

Controlling the Rocket:

The games make use of “W”, “S”, “D” and “A” keys to move Up, Down, Right and Left respectively. If “W” or “S” are pressed, then we add or subtract the Y-displacement to the existing Rocket coordinates to move it up or down. Similarly, if “D” or “A” is pressed, then we shall add or subtract X-displacement to move the Rocket Sideways.

Crash Detection:

For every X and/or Y displacement added or removed to the rocket, we see whether or not the new coordinates of the rocket intersect with the coordinates of the obstacle and asteroid. This is done by drawing an imaginary square box that holds the asteroid and checking whether the coordinates of the rocket intersect with the coordinates of the imaginary box. Now I know, that this does not give us accurate results, but if you draw the asteroid closely associated with the imaginary box, you don’t have to worry much about the accuracy. You can definitely improve the accuracy comparing the coordinates of the obstacle and asteroid.

//myInit Functionvoid myInit(){glClearColor(1.0, 1.0, 1.0, 1.0);gluOrtho2D(0.0, 1000.0, 0.0, 900.0);}//Display Functionvoid display(){glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);glMatrixMode(GL_PROJECTION);if(SCREEN == 1){glClearColor(1.0, 1.0, 1.0, 1.0);glClear(GL_COLOR_BUFFER_BIT);frontscreen();}glLoadIdentity();if(SCREEN==2){glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);glClearColor(0.0, 0.0, 0.0, 0.0);drawObstacle();drawRocket();}glLoadIdentity();if( SCREEN == 3){if( wreckFlag == 0){wreckFlag = 1;rocketWreck();drawObstacle();Sleep(2000);glClear(GL_COLOR_BUFFER_BIT);}gameOver();}glLoadIdentity();if( SCREEN == 4){Congratulations();}}//Display function Ends//Keyboard Functionvoid myKeyboard(unsigned char btn, int x, int y){int i, j, id;if (btn == 'n' || btn == 'N'){SCREEN = 2;glutPostRedisplay();}if( btn == 'y' || btn == 'Y'){SCREEN = 2;}//Move UPif (btn == 'w' || btn == 'W'){ysize += 5.0;drawRocket();drawFlame();drawObstacle();glutPostRedisplay();glutSwapBuffers();//glutPostRedisplay();}//Move DOWNif (btn == 's' || btn == 'S'){ysize -= 5.0;drawRocket();drawFlame();glutSwapBuffers();glutPostRedisplay(); }//Move RIGHTif (btn == 'd' || btn == 'D'){xsize += 5.0;drawRocket();drawFlame();glutSwapBuffers();glutPostRedisplay();}//Move LEFTif (btn == 'a' || btn == 'A'){xsize -= 5.0;drawRocket();drawFlame();glutSwapBuffers();glutPostRedisplay();}//QUITif (btn == 'q' || btn == 'Q')exit(0);//***********************************************************COLLISION**********************************************************if( base[1][0] + ysize < 125.0){SCREEN = 3;//glutSwapBuffers();}if ( top[0][0] + ysize >= 800.0){SCREEN = 3;//glutPostRedisplay();}if( base[0][0] + xsize < 0.0){SCREEN = 3;//glutSwapBuffers();}if( base[1][0] + xsize > 900.0){SCREEN = 3;//glutSwapBuffers();}//OBSTACLE 1//LEFT EDGEif( (top[1][0] + xsize == 150.0) && (top[1][1] + ysize >= 350.0 && top[1][1] +ysize <= 450.0) ){SCREEN = 3;//glutSwapBuffers();}if( (base[1][0] + xsize == 150.0) && (base[1][1] + ysize >= 350.0 && base[1][1] +ysize <= 450.0) ){SCREEN = 3;//glutSwapBuffers();}//TOP EDGEif( (base[1][1] + ysize <= 450.0 && base[1][1] + ysize >= 350.0) && (base[1][0] +xsize >= 150.0 && base[1][0] + xsize <= 250.0) ){SCREEN = 3;//glutSwapBuffers();}//BOTTOM EDGEif ( (top[2][1] + ysize >= 350.0 && top[2][1] + ysize <= 450.0) && ( top[2][0] +xsize >= 150.0 && top[2][0] + xsize <= 250.0)){SCREEN = 3;glutPostRedisplay();}//RIGHT EDGEif (base[0][0] + xsize == 250.0 && (base[0][1] + ysize >= 350.0 && base[0][1] +ysize <= 450.0 )){SCREEN = 3;//glutSwapBuffers();}if (top[0][0] + xsize == 250.0 && ( top[0][1] + ysize >= 350.0 && top[0][1] +ysize <= 450.0 )){SCREEN = 3;//glutSwapBuffers();}//OBSTACLE 2//LEFT EDGEif( (top[1][0] + xsize == 320.0) && (top[1][1] + ysize >= 620.0 && top[1][1] +ysize <= 720.0) ){SCREEN = 3;//glutSwapBuffers();}if( (base[1][0] + xsize == 320.0) && (base[1][1] + ysize >= 620.0 && base[1][1] +ysize <= 720.0) ){SCREEN = 3;//glutSwapBuffers();}//TOP EDGEif( (base[1][1] + ysize <= 720.0 && base[1][1] + ysize >= 620.0) && (base[1][0] +xsize >= 320.0 && base[1][0] + xsize <= 420.0) ){SCREEN = 3;//glutSwapBuffers();}//BOTTOM EDGEif ( (top[2][1] + ysize >= 620.0 && top[2][1] + ysize <= 720.0) && ( top[2][0] +xsize >= 320.0 && top[2][0] + xsize <= 420.0)){SCREEN = 3;//glutSwapBuffers();}//RIGHT EDGEif (base[0][0] + xsize == 420.0 && (base[0][1] + ysize >= 620.0 && base[0][1] +ysize <= 720)){SCREEN = 3;//glutSwapBuffers();}if (top[0][0] + xsize == 420.0 && ( top[0][1] + ysize >= 620.0 && top[0][1] +ysize <= 720.0 )){SCREEN = 3;//glutSwapBuffers();}//OBSTACLE 3//LEFT EDGEif( (top[1][0] + xsize == 500.0) && (top[1][1] + ysize >= 250.0 && top[1][1] +ysize <= 350.0) ){SCREEN = 3;//glutSwapBuffers();}if( (base[1][0] + xsize == 500.0) && (base[1][1] + ysize >= 250.0 && base[1][1] +ysize <= 350.0) ){SCREEN = 3;//glutSwapBuffers();}//TOP EDGEif( (base[1][1] + ysize <= 350.0 && base[1][1] + ysize >= 250.0) && (base[1][0] +xsize >= 500.0 && base[1][0] + xsize <= 600.0) ){SCREEN = 3;//glutSwapBuffers();}//BOTTOM EDGEif ( (top[2][1] + ysize >= 350.0 && top[2][1] + ysize <= 250.0) && ( top[2][0] +xsize >= 500.0 && top[2][0] + xsize <= 600.0)){SCREEN = 3;//glutSwapBuffers();}//RIGHT EDGEif ( base[0][0] + xsize == 600.0 && (base[0][1] + ysize >= 250.0 && base[0][1] +ysize <= 350 )){SCREEN = 3;//glutSwapBuffers();}if (top[0][0] + xsize == 420.0 && ( top[0][1] + ysize >= 620.0 && top[0][1] +ysize <= 720.0 )){SCREEN = 3;//glutSwapBuffers();}//HILLOCK COLLISIONif( (base[1][0] + xsize >= 250.0 && base[1][0] + xsize <= 350.0) && (base[1][1] +ysize <= 300.0 && base[1][1] + ysize >= 125.0) ){SCREEN = 3;//glutSwapBuffers();}if( (base[0][0] + xsize <= 350.0 && base [0][0] + xsize >= 250.0) && ( base[0][1]+ ysize >= 125.0 && base[0][1] + ysize <= 300.0) ){SCREEN = 3;//glutSwapBuffers();}//COLLISIN ENDS//LANDINGif( (base[1][0] + xsize >= 750.0 && base[1][0] + xsize <= 850.0) && (base[1][1] +ysize <=170.0)){SCREEN = 4;glutSwapBuffers();}glutSwapBuffers();glutPostRedisplay();}

In the end, we shall define the main function and call the relevant functions such as setting up the window size and glutKeyboardFunc for keyboard controls inside it.

int main(int argc, char **argv){glutInit(&argc, argv);glutInitDisplayMode(GLUT_SINGLE);glutInitWindowSize(1200, 900);glutInitWindowPosition(0, 0);glutCreateWindow("Park The Rocket");glutDisplayFunc(display);myInit();glutKeyboardFunc(myKeyboard);glutMainLoop();return 0;}

Replay and Quit:

After the game is completed either successfully or with a crash, you can replay the game by pressing “Y” or “y” or you can quit the game by clicking on “Q” or “q”. This is done by setting proper values for the SCREEN flag.

Image created using Canva

You have finally created your very own game using OpenGL in C programming language.

Suggestions for improvement:

There is always a scope for improvement for every project. You can improve this current project in the following ways:

  1. Code improvement by writing the code in Object Oriented way by using C++.
  2. Implement Audio/Sounds to the game (Add funny sounds during the crash if possible).
  3. Implement more levels.
  4. Keep track of time and score the gameplay based on the time lapsed and maybe also create a leader board based on these scores.

--

--

Gaurav Prabhu K

A keen learner | Tech Geek | Computer Enthusiast | Computer Programmer | Website: https://codeb7.github.io/gp-portfolio/