CG Project Report
CG Project Report
Project Report on
“Flappy Plane”
Submitted By-
Ishika Chhabra 102003511
Jatin 102003510
Tushar 102003513
Submitted to-
Ms. Kudratpreet Kaur
2
INTRODUCTION TO PROJECT
Airplane Run is an exciting and challenging game built using OpenGL and C++. Get
ready for a thrilling flying experience as you take control of an airplane soaring
through the sky. The objective of the game is to avoid obstacles like buildings and
clouds that come in your way while the airplane automatically moves forward and
experiences the force of gravity pulling it down.
The game features a dynamic gameplay where the airplane moves forward at a
constant speed, and you need to manoeuvre it skilfully to avoid collisions with the
obstacles. You can make the airplane go up by pressing a button, providing a way to
navigate through the challenging environments. But be careful, as the obstacles
become increasingly difficult to avoid as you progress, requiring quick reflexes and
strategic decision-making.
With immersive graphics powered by OpenGL, players will enjoy a visually stunning
experience as they navigate through beautifully rendered environments, including
cities, mountains, and clouds. The game also incorporates realistic physics, providing
a sense of authenticity to the flight dynamics of the airplane.
As you progress, you can challenge yourself to achieve high scores, unlock
achievements, and compete with friends or other players to see who can fly the
furthest without crashing. With its addictive gameplay, stunning visuals, and
challenging obstacles, Airborne Adventure is sure to provide an engaging gaming
experience for players of all ages.
3
COMPUTER GRAPHICS CONCEPTS USED
The Airplane Run project uses various computer graphics concepts to create a
visually appealing and interactive game. Some of these concepts include:
These functions can be used in Airplane Run to create a visually appealing and
interactive game.
5
USER DEFINED FUNCTIONS
6
void drawBg();
This function draws the background of the entire game. For example it sets the
ground colour and gives the screen its sky-blue colour.
void welcome();
Displays the welcome screen and all the buttons, namely Play, Instructions,
About, Exit.
void drawBuilding();
This function draws the entire building on the screen. It draws the building
base, the building structure and the windows on the building. Everything is drawn
with the help of polygons or rectangles.
void drawCloud();
This function draws the cloud onto the screen with the help of solid spheres.
bool cloudHit();
This function has a series of if-else statements to check if at any point the plane
is touching/overlapping/hitting the Clouds. If it is, then the function returns True, else
it returns False.
bool buildingHit();
This function has a series of if-else statements to check if at any point the plane
is touching/overlapping/hitting the building. If it is, then the function returns True,
else it returns False.
void printScore();
This function calculates and prints the score at the bottom of the screen when
a player is playing the game.
void display();
One of the main function that binds all the other functions together into a
common game logic. Calls other function as and when required by the game.
void moveJetU();
This function makes the jet translate in the positive y-axis by a fixed amount
so as to give the impression that the jet is flying upwards.
void moveJetD();
This function makes the jet translate in the negative y-axis by a fixed amount
so as to give the impression that the jet is falling downwards under the effect of
gravity.
7
CODE
#include<stdlib.h>
#include<gl/glut.h>
#include<time.h>
#include<stdio.h>
#include<math.h>
#pragma GCC diagnostic ignored "-Wwrite-strings"
#define BLOCKSPEED 0.025
#define BOOSTER_MAX 10
bool state;
int no_floors;
}building;
//-------------------declarations---------------
float bspd = BLOCKSPEED; // block speed
bool pause = false, lflag = true, wflag = true, gameEndStatus = false, instflag = false, abtflag = false,
start = false; //flags
float plane_mvmt = 0.0;//jet movement up or down
float score = 1;
char score_Str[20], slevel[20]; //score string and levelstring
int level = 1, buildColor; // initial level=1
building b; // building struct
Cloud s; // cloud struct
float booster = BOOSTER_MAX, boost = 0;
//plane bounds
//-------------function prototypes------------------
void keyPressed(unsigned char, int, int);
void mouse(int button, int state, int x, int y);
void printString(float x, float y, float z, void* font, char* string);//what does this do??
void buildingBlock();
void CloudBlock();
8
void init();
void drawJet();
void gameEnd();
void drawBg();
void welcome();
void drawBuilding();
void drawCloud();
bool cloudHit();
bool buildingHit();
void printScore();
void display();
void moveJetU();
void moveJetD();
void buildingBlock()
{
b.block_x = 50.0;
srand(time(0));
b.no_floors = rand() % 3 + 4;
buildColor = rand() % 3;
void CloudBlock()
{
s.block_x = 50.0;
srand(time(0));
s.block_y = (rand() % 30) + 50; //randomly generate block y cordinate
s.state = true;
b.state = false;
}
void drawJet()
{
//left tail wing
glColor3f(0.6, 0.6, 0.6);
glBegin(GL_POLYGON);
glVertex2f(5.5, 47.0);
glVertex2f(8.5, 47.0);
glVertex2f(5.5, 48.0);
glVertex2f(4.5, 48.0);
glEnd();
//tail
glColor3f(0.5, 0.5, 0.5);
glBegin(GL_POLYGON);
glVertex2f(4.7, 45.0);
glVertex2f(5.5, 51.0);
glVertex2f(7.0, 51.0);
glVertex2f(9.0, 45.0);
glEnd();
//body
glColor3f(0.5, 0.5, 0.5);
glBegin(GL_POLYGON);
10
glVertex2f(5.0, 48.0);
glVertex2f(11.0, 48.0);
glVertex2f(22.0, 46.5);
glVertex2f(22.0, 45.0);
glVertex2f(5.0, 45.0);
glEnd();
//dome
glColor3f(0.0, 0.0, 0.0);
glBegin(GL_POLYGON);
glVertex2f(13.0, 47.0);
glVertex2f(15.0, 48.5);
glVertex2f(17.0, 49.0);
glVertex2f(19.0, 48.0);
glVertex2f(21.0, 46.0);
glVertex2f(17.0, 46.0);
glVertex2f(15.0, 47.5);
glVertex2f(13.0, 47.0);
glEnd();
// front tip
glColor3f(0.4, 0.4, 0.4);
glBegin(GL_POLYGON);
glVertex2f(22.0, 45.0);
glVertex2f(22.3, 45.375);
glVertex2f(22.6, 45.75);
glVertex2f(22.3, 46.125);
glVertex2f(22.0, 46.5);
glEnd();
}
11
void drawString(float x, float y, float z, void* font,const char* string)
{
const char* c;
glRasterPos3f(x, y, z);
void gameEnd()
{
gameEndStatus = true;
glColor3f(0.3, 0.56, 0.84); //game end background screen
glBegin(GL_POLYGON);
glVertex3f(0.0, 0.0, 0.0);
glColor3f(0.137, 0.137, 0.556);
glVertex3f(100.0, 0.0, 0.0);
glColor3f(0.196, 0.196, 0.8);
glVertex3f(100.0, 100.0, 0.0);
glVertex3f(0.0, 100.0, 0.0);
glEnd();
glPushMatrix();
glScalef(0.8, 0.8, 0);
drawJet();
glPopMatrix();
glutPostRedisplay();
}
void drawBg()
{
glPushMatrix();
glColor3f(0.0, 0.48, 0.047); // green floor
glBegin(GL_POLYGON);
glVertex3f(0.0, 9.0, 0.0);
glVertex3f(100.0, 9.0, 0.0);
glColor3f(0.0, 0.3, 0.03);
glVertex3f(100.0, 10.0, 0.0);
glVertex3f(0.0, 10.0, 0.0);
glVertex3f(0.0, 9.0, 0.0);
glEnd();
// button 1 .. PLAY
glColor3f(0.196, 0.196, 0.8);
glRectf(39.5, 39.5, 60.5, 45.5);
// button 2 .. instructions
glColor3f(0.196, 0.196, 0.8);
glRectf(39.5, 29.5, 60.5, 35.5);
// button 3 .. ABOUT
glColor3f(0.196, 0.196, 0.8);
glRectf(39.5, 19.5, 60.5, 25.5);
// button 4 .. exit
glColor3f(0.196, 0.196, 0.8);
glRectf(39.5, 9.5, 60.5, 15.5);
glColor3f(0.8, 0.8, 0.8);
glRectf(40, 10, 60, 15);
glColor3f(0.137, 0.137, 0.556);
drawString(47, 11, 0, GLUT_BITMAP_HELVETICA_18, "EXIT");
14
glPushMatrix();
void drawBuilding()
{
glPushMatrix(); // 3D part
if (buildColor == 0)
glColor3f(0.1, 0.0, 0.0);
else if (buildColor == 1)
glColor3f(0.1, 0.1, 0.0);
else
glColor3f(0.0, 0.1, 0.1);
glTranslatef(b.block_x, b.no_floors * 10.0 + 10, 0.0);
glBegin(GL_POLYGON);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(5.0, 3.0, 0.0);
glVertex3f(20.0, 3.0, 0.0);
glVertex3f(20.0, -b.no_floors * 10.0, 0.0);
glVertex3f(0.0, -b.no_floors * 10.0, 0.0);
glEnd();
glPopMatrix();
if (buildColor == 0)
glColor3f(0.8, 0.0, 0.0);
else if (buildColor == 1)
glColor3f(0.8, 0.8, 0.0);
else
glColor3f(0.0, 0.8, 0.8);
if (buildColor == 0)
glColor3f(0.8, 0.0, 0.0);
else if (buildColor == 1)
glColor3f(0.8, 0.8, 0.0);
else
glColor3f(0.0, 0.8, 0.8);
void drawCloud()
{
glColor3f(1.0, 1.0, 1.0);
glTranslatef(s.block_x, s.block_y, 0.0);
glutSolidSphere(5, 100, 10);
glTranslatef(6, -3.0, 0.0);
glutSolidSphere(5, 100, 10);
glTranslatef(0, 6.0, 0.0);
glutSolidSphere(5, 100, 10);
glTranslatef(6, -3.0, 0.0);
glutSolidSphere(5, 100, 10);
}
bool cloudHit()
{
if (s.block_x < 13 && s.block_x> -5)
if (plane_mvmt - 3 + 50 > s.block_y - 3 && plane_mvmt - 3 + 50 < s.block_y + 3) // plane
front to cloud mid box1
return true;
bool buildingHit()
{
if (((int)b.block_x <= 8 && (int)b.block_x >= -7 && ((int)plane_mvmt + 50) - b.block_y <= 3))
//buildin back body to tail
17
return true;
else if (((int)b.block_x <= 10 && (int)b.block_x >= -5 && ((int)plane_mvmt + 50) - b.block_y
<= 0)) //body to tail
return true;
else if (((int)b.block_x <= 6 && (int)b.block_x >= -3 && ((int)plane_mvmt + 47) - b.block_y
<= 0)) //right wing
return true;
else if (((int)b.block_x <= 4 && (int)b.block_x >= -4 && ((int)plane_mvmt + 47) - b.block_y
<= 3)) // building back right wing
return true;
else
return false;
}
bool boundHit()
{
if (plane_mvmt + 50 >= 100 || plane_mvmt + 50 <= 18) // top and bottom boundary
return true;
else
return false;
}
void printScore()
{
glColor3f(1.0, 1.0, 0.0);//score
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//GameOver Checking
if (gameEndStatus == true)
{
gameEnd();
18
}
else if (wflag == true)//Welcome Screen
{
welcome();
}
else if (instflag == true)
{
glColor3f(0.3, 0.56, 0.84); // background
glBegin(GL_POLYGON);
glVertex3f(0.0, 0.0, 0.0);
glColor3f(0.137, 0.137, 0.556);
glVertex3f(100.0, 0.0, 0.0);
glColor3f(0.196, 0.196, 0.8);
glVertex3f(100.0, 100.0, 0.0);
glVertex3f(0.0, 100.0, 0.0);
glEnd();
glPushMatrix();
glScalef(0.8, 0.8, 0);
drawJet();
glPopMatrix();
glColor3f(0.137, 0.137, 0.556);
glRectf(20.0, 20.0, 80.0, 80.0);
glColor3f(0.8, 0.8, 0.8);
glRectf(21.0, 21.0, 79.0, 79.0);
19
drawString(23, 41, 0, GLUT_BITMAP_HELVETICA_18, " travelled,NITROS left,Atitude
and the LEVEL.");
drawString(23, 37, 0, GLUT_BITMAP_HELVETICA_18, "- As you reach distance multples
of 50 tour level ");
drawString(23, 33, 0, GLUT_BITMAP_HELVETICA_18, " increases as well as the speed
of the plane.");
drawString(33, 27, 0, GLUT_BITMAP_HELVETICA_18, " ENJOY PLAYING THE
GAME");
glutPostRedisplay();
}
else if (abtflag == true)
{
glColor3f(0.3, 0.56, 0.84); // background
glBegin(GL_POLYGON);
glVertex3f(0.0, 0.0, 0.0);
glColor3f(0.137, 0.137, 0.556);
glVertex3f(100.0, 0.0, 0.0);
glColor3f(0.196, 0.196, 0.8);
glVertex3f(100.0, 100.0, 0.0);
glVertex3f(0.0, 100.0, 0.0);
glEnd();
glPushMatrix();
glScalef(0.8, 0.8, 0);
drawJet();
glPopMatrix();
glColor3f(0.137, 0.137, 0.556);
glRectf(20.0, 20.0, 80.0, 80.0);
glColor3f(0.8, 0.8, 0.8);
glRectf(21.0, 21.0, 79.0, 79.0);
20
}
else if (pause == true)
{
drawBg();
glPushMatrix();
glScalef(0.8, 0.8, 0);
drawJet();
glPopMatrix();
glPushMatrix();
glColor3f(0.196, 0.196, 0.8);
glRectf(35.0, 40.0, 65.0, 60.0);
glColor3f(0.8, 0.8, 0.8);
glRectf(36.0, 41.0, 64.0, 59.0);
glPopMatrix();
glColor3f(0.137, 0.137, 0.556);
drawString(40, 55, 0, GLUT_BITMAP_HELVETICA_18, " GAME PAUSED");
drawString(37, 45, 0, GLUT_BITMAP_HELVETICA_18, " PRESS 'P' to continue");
glutPostRedisplay();
}
else if ((b.state == true && buildingHit() == true) || boundHit() == true)
{
gameEndStatus = true;
gameEnd();
}
else if (s.state == true && cloudHit() == true)
{
gameEndStatus = true;
gameEnd();
}
else
{
if ((int)score % 50 == 0 && lflag == true)// l-level
{
lflag = false;
level++;
bspd += 0.01;
}
else if ((int)score % 50 != 0 && lflag == false)
{
lflag = true;
}
glPushMatrix();
drawBg();
glPushMatrix();
glTranslatef(0.0, plane_mvmt, 0.0);
drawJet(); //code for jet
glPopMatrix();
21
if (booster <= BOOSTER_MAX && !boost) // booster charging
booster += 0.04;
if ((b.state == true && b.block_x < -10) || (s.state == true && s.block_x < -10)) //for
new building //building has gone outside the screen- state=true
{
srand(time(NULL));
int random = rand() % 2;//for random building or cloud
if (random == 0)
{
buildingBlock();
}
else
{
CloudBlock();
}
}
printScore();
}
glFlush();
glutSwapBuffers();
}
plane_mvmt += 0.03;
glutPostRedisplay();
}
}
void mouse(int button, int state, int x, int y) // takes input from mouse
{
int mx = x * 100 / SCREENW, my = (SCREENH - y) * 100 / SCREENH; // m = mouse cordinate
to graphics
/* mouse calculation//converting to screen coordinates-ortho values
SCREENSIZE ----> ORTHO
x(reqd val) ----> ???
*/
if (instflag || abtflag || gameEndStatus)
{
if (mx > 40 && mx < 60)
{
23
if (my > 5 && my < 10)
{
wflag = true;
if (instflag)
instflag = false;
else if (abtflag)
abtflag = false;
if (gameEndStatus)
{
wflag = true;
gameEndStatus = false;
plane_mvmt = 0;
start = false;
init();
bspd = BLOCKSPEED;//restarting the game
booster = BOOSTER_MAX;
score = 1;
level = 1;
glutPostRedisplay();
}
}
}
}
if (wflag == true)
{
if (mx > 40 && mx < 60)
{
if (my > 40 && my < 45)
{
start = true;
wflag = false;
}
else if (my > 30 && my < 35)
{
instflag = true;
wflag = false;
}
else if (my > 20 && my < 25)
{
abtflag = true;
wflag = false;
}
else if (my > 10 && my < 15)
{
exit(0);
}
}
}
24
else
{
if (button == GLUT_LEFT_BUTTON)
{
if (state == GLUT_DOWN)
glutIdleFunc(moveJetU);
void keyPressed(unsigned char key, int x, int y) // int x and y are mouse pos at time of press
{
if (key == 27)
{
exit(0);
}
else if (key == 'p' || key == 'P')
{
if (pause == true)
pause = false;
else
pause = true;
}
glutPostRedisplay();
}
void init()
{
srand(time(0));
int random = rand() % 2;
if (random == 0)
{
buildingBlock();
}
else
{
CloudBlock();
}
}
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(SCREENW, SCREENH);
glutInitWindowPosition(50, 50);
glutCreateWindow("Airplane Run!");
init();
glutDisplayFunc(display);
glutReshapeFunc(myReshape);
glutMouseFunc(mouse);
glutKeyboardFunc(keyPressed);
glutMainLoop();
return 0;
}
26
OUTPUT SCREENSHOTS
27
28
29
30