Ball in the Box (A C++&OpenGL game)

Ball in the Box is a simple game developed in C++ using OpenGL library during my free time, out of my interest to learn OpenGL. The latest version of it is 4.0. Since it is not in my present system, I will give you the 3.0 version’s source code. You are free to modify or copy or what-ever you like to do with this… 🙂

Before going into the code, let me give you a feel of my game:

Image

Image

Image

/*

File name : DisplayText.h

Author : Sreejith Sreekantan

Version : 3.0

Date : June 2012

*/

#ifndef __DisplayText_h__

#define __DisplayText_h__

#ifdef __APPLE__

#include <GLUT/glut.h>

#include <OpenGL/OpenGL.h>

#include <OpenGL/gl.h>

#else

#include <GL/glut.h>

#endif

#include

using namespace std;

namespace DisplayText {

void DisplayText(float posx, float posy, void* font, char string[]) {

glRasterPos2f(posx, posy);

while(*string) {

glutBitmapCharacter(font, *string);

string++;

}

}

void DisplayText(float posx, float posy, void* font, int value) {

int iTemp1=0, iTemp2 = value;

while(iTemp2>0) {

iTemp1++;

iTemp2 /= 10;

}

char *string = (char*)malloc(sizeof(char)*iTemp1+1);

sprintf(string, “%d”, value);

//clog << “string=” << *string << endl;

DisplayText(posx, posy, font, string);

}

}

#endif // __DisplayText_h__

/*

File name : BitB (Ball in the Box)

Author : Sreejith Sreekantan (krssreejith@gmail.com)

Version : 3.0

Date : June 2012

*/

#ifdef __APPLE__

#include <GLUT/glut.h>

#include <OpenGL/OpenGL.h>

#include <OpenGL/gl.h>

#else

#include <GL/glut.h>

#endif

#include “DisplayText.h”

#include

#include

#include

#include

using namespace std;

#define NAME_OF_GAME “Ball in the Box!”

// Game states

#define GAME_INIT 0

#define GAME_START 1

#define GAME_END 2

#define GAME_CLOSE 3

#define SCORE_OFFSET 5

#define SCREEN_WIDTH_PIX 120

#define SCREEN_HEIGHT_PIX 80

#define DASHBOARD_WIDTH_PIX SCREEN_WIDTH_PIX

#define DASHBOARD_HEIGHT_PIX 10

#define BALL_RADIUS 1.5

#define BALLSPEED_OFFSET 0.05

#define BOARD_WIDTH 5.0

#define BOARD_LENGTH 20.0

#define BOARD_HEIGHT 3

#define PLAYER_NAME_LEN 11

int iGameStatus;

int iScore;

int iScoreTemp=0;

GLfloat fBallSpeed = 0.01;

GLfloat fBoardSpeed = 4.0;

GLfloat afBallSpecular[] = {0.5, 0.0, 0.0, 1.0};

GLfloat afBallAmbient[] = {0.5, 0.0, 0.0, 1.0};

GLfloat afBallShininess[] = {50.0};

GLfloat fBallTransX = SCREEN_WIDTH_PIX/2;

GLfloat fBallTransY = SCREEN_HEIGHT_PIX/2;

GLfloat fBallTransXOffset = fBallSpeed;

GLfloat fBallTransYOffset = fBallSpeed;

GLfloat fBoardTransX = 0.0;

GLfloat fBoardTransY = 0.0;

GLfloat fBoardTransXOffset = fBoardSpeed;

char acPlayerName[PLAYER_NAME_LEN];

GLuint iSphereGenList;

GLuint iBoardGenList;

GLuint iDashboardGenList;

GLuint iGetNameGenList;

GLuint iShowScore;

time_t startTime;

void fnDisplay() {

glLoadIdentity();

gluLookAt(0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

if (iGameStatus == GAME_INIT){

glPushMatrix();

glCallList(iGetNameGenList);

glColor3f(0.75, 0.0, 0.0);

DisplayText::DisplayText(SCREEN_WIDTH_PIX/2-8, SCREEN_HEIGHT_PIX/2, GLUT_BITMAP_HELVETICA_18, acPlayerName);

glPopMatrix();

}

else if (iGameStatus == GAME_START) {

iScore = ((time(NULL) – startTime)/SCORE_OFFSET);

if(iScore > 0 && iScore % (SCORE_OFFSET*2) == 0 && iScore != iScoreTemp) {

fBallTransX *= 1.025;

fBallTransY *= 1.025;

fBoardTransX *= 1.025;

fBoardTransY *= 1.025;

iScoreTemp = iScore;

clog << “Speed incremented:” << fBallTransX << “,” << fBallTransY << endl;

}

//clog << “iScore=” << iScore << endl;

glPushMatrix();

glTranslatef(fBallTransX, fBallTransY, 0.0);

glCallList(iSphereGenList);

glPopMatrix();

glPushMatrix();

glTranslatef(fBoardTransX, fBoardTransY, 0.0);

glCallList(iBoardGenList);

glPopMatrix();

glPushMatrix();

glCallList(iDashboardGenList);

glColor3f(1.0, 1.0, 1.0);

DisplayText::DisplayText(10.0, SCREEN_HEIGHT_PIX+5, GLUT_BITMAP_HELVETICA_18, acPlayerName);

DisplayText::DisplayText(SCREEN_WIDTH_PIX-10, SCREEN_HEIGHT_PIX+5, GLUT_BITMAP_HELVETICA_12, iScore);

glPopMatrix();

}

else if (iGameStatus == GAME_END){

glPushMatrix();

glCallList(iShowScore);

glColor3f(0.75, 0.0, 0.0);

DisplayText::DisplayText(SCREEN_WIDTH_PIX/2-8, SCREEN_HEIGHT_PIX/2, GLUT_BITMAP_HELVETICA_18, iScore);

glPopMatrix();

}

else if (iGameStatus == GAME_CLOSE){

exit(0);

}

glFlush();

}

void fnReshape(int w, int h) {

glViewport(0, 0, w, h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

glOrtho(0, SCREEN_WIDTH_PIX, 0, SCREEN_HEIGHT_PIX+DASHBOARD_HEIGHT_PIX, 0.5, 2);

glMatrixMode(GL_MODELVIEW);

}

void fnIdle() {

//clog << “fnIdle():” << endl;

bool flag_x_offset_changed = false;

bool flag_y_offset_changed = false;

if (fBallTransX == SCREEN_WIDTH_PIX || fBallTransX == 0) {

fBallTransXOffset *= -1; // inverse x direction

flag_x_offset_changed = true;

}

if (fBallTransY == SCREEN_HEIGHT_PIX) {

fBallTransYOffset *= -1; // inverse y direction

flag_y_offset_changed = true;

}

if ((fBallTransX+BALL_RADIUS) >= fBoardTransX &&

(fBallTransX-BALL_RADIUS) <= (fBoardTransX + BOARD_LENGTH) &&

(fBallTransY-BALL_RADIUS) <= BOARD_HEIGHT &&

(fBallTransY) >= BOARD_HEIGHT) // if ball is hit by the board

{

fBallTransYOffset *= -1; // inverse y direction

iScore += SCORE_OFFSET;

flag_y_offset_changed = true;

}

if (fBallTransY == 0) {

glutIdleFunc(NULL);

iGameStatus = GAME_END;

clog << “Game status changed to GAME_END” << endl;

}

fBallTransX += fBallTransXOffset;

fBallTransY += fBallTransYOffset;

if (!flag_x_offset_changed) {

if (fBallTransX > SCREEN_WIDTH_PIX) {

fBallTransX = SCREEN_WIDTH_PIX;

}

else if (fBallTransX < 0) {

fBallTransX = 0.0;

}

}

if (!flag_y_offset_changed) {

if (fBallTransY > SCREEN_HEIGHT_PIX) {

fBallTransY = SCREEN_HEIGHT_PIX;

}

else if (fBallTransY < 0) {

fBallTransY = 0.0;

}

}

glutPostRedisplay();

}

void fnSpecial(int key, int x, int y) {

//clog << “fnSpecial():” << “key=” << key << ” x=” << x << ” y=” << y << endl;

switch (key) {

case 100: // left arrow key

if (fBoardTransX > 0.0 && iGameStatus == GAME_START) {

fBoardTransX -= fBoardTransXOffset;

}

break;

case 102: // right arrow key

if ( (fBoardTransX + BOARD_LENGTH) < SCREEN_WIDTH_PIX && iGameStatus == GAME_START) {

fBoardTransX += fBoardTransXOffset;

}

break;

//case 101: // up arrow key

//case 103: // down arrow key

default:

break;

}

glutPostRedisplay();

}

int iTemp =0;

void fnKeyboard(unsigned char key, int x, int y) {

clog << “fnKeyboard():” << “key=” << key << “(int)key=” << (int)key << ” x=” << x << ” y=” << y << endl;

switch (key) {

case 13: // if enter key pressed

if ( acPlayerName[0] != ” && iGameStatus == GAME_INIT) {

fBallTransX = SCREEN_WIDTH_PIX/2;

fBallTransY = SCREEN_HEIGHT_PIX/2;

fBallTransXOffset = fBallSpeed;

fBallTransYOffset = fBallSpeed;

glutIdleFunc(fnIdle);

iScore = 0;

startTime = time(NULL);

clog << “startTime=” << startTime << endl;

iGameStatus = GAME_START;

clog << “Game status changed to GAME_START” << endl;

}

else if (iGameStatus == GAME_END) {

iGameStatus = GAME_CLOSE;

clog << “Game status changed to GAME_CLOSE” << endl;

}

break;

case 8: // if backspace key pressed

if (iTemp >= 0 && iGameStatus == GAME_INIT) {

acPlayerName[–iTemp] = ”;

}

break;

case 27: // if escape key is pressed

if (iGameStatus == GAME_END) {

iGameStatus = GAME_INIT;

fnKeyboard(13, x, y);

return;

}

default:

if ( (key >= ‘a’ || key >= ‘A’) &&

(key <= ‘z’ || key <= ‘Z’) &&

iTemp < PLAYER_NAME_LEN-1 &&

iGameStatus == GAME_INIT

)

{

acPlayerName[iTemp++] = key;

acPlayerName[iTemp] = ”;

clog << “iTemp=” << iTemp << endl;

}

break;

}

glutPostRedisplay();

}

void init() {

//clog << “init():” << endl;

iGameStatus = GAME_INIT;

GLfloat light0_position[] = {-1.0, -1.0, -1.0, 0.0};

glLightfv(GL_LIGHT0, GL_POSITION, light0_position);

iBoardGenList = glGenLists(1);

glNewList(iBoardGenList, GL_COMPILE);

glEnable (GL_LINE_STIPPLE);

glLineStipple (1, 0x0F0F);

glColor3f(0.5, 0.75, 0.75);

glBegin(GL_LINES);

glVertex2d(0.0, BOARD_HEIGHT);

glVertex2d(BOARD_LENGTH, BOARD_HEIGHT);

glEnd();

glDisable(GL_LINE_STIPPLE);

glEndList();

iSphereGenList = glGenLists(1);

glNewList(iSphereGenList, GL_COMPILE);

glEnable(GL_LIGHTING);

glEnable(GL_LIGHT0);

glMaterialfv(GL_FRONT, GL_SPECULAR, afBallSpecular);

glMaterialfv(GL_FRONT, GL_AMBIENT, afBallAmbient);

glMaterialfv(GL_FRONT, GL_SHININESS, afBallShininess);

glutSolidSphere(BALL_RADIUS, 10, 10);

glDisable(GL_LIGHT0);

glDisable(GL_LIGHTING);

glEndList();

iDashboardGenList = glGenLists(1);

glNewList(iDashboardGenList, GL_COMPILE);

glColor3f(0.0, 0.5, 0.5);

glBegin(GL_POLYGON);

glVertex2d(0, SCREEN_HEIGHT_PIX);

glVertex2d(0, SCREEN_HEIGHT_PIX+DASHBOARD_HEIGHT_PIX);

glVertex2d(SCREEN_WIDTH_PIX, SCREEN_HEIGHT_PIX+DASHBOARD_HEIGHT_PIX);

glVertex2d(SCREEN_WIDTH_PIX, SCREEN_HEIGHT_PIX);

glEnd();

glColor3f(1.0, 1.0, 1.0);

DisplayText::DisplayText(1.0, SCREEN_HEIGHT_PIX+5, GLUT_BITMAP_HELVETICA_12, “Player:”);

DisplayText::DisplayText(SCREEN_WIDTH_PIX-20, SCREEN_HEIGHT_PIX+5, GLUT_BITMAP_HELVETICA_12, “Score:”);

glEndList();

iGetNameGenList = glGenLists(1);

glNewList(iGetNameGenList, GL_COMPILE);

glColor3f(0.0, 0.5, 0.5);

glBegin(GL_POLYGON);

glVertex2d(20, SCREEN_HEIGHT_PIX/2-20);

glVertex2d(20, SCREEN_HEIGHT_PIX/2+20);

glVertex2d(SCREEN_WIDTH_PIX-20, SCREEN_HEIGHT_PIX/2+20);

glVertex2d(SCREEN_WIDTH_PIX-20, SCREEN_HEIGHT_PIX/2-20);

glEnd();

glColor3f(0.8, 0.8, 0.8);

DisplayText::DisplayText(23.0, SCREEN_HEIGHT_PIX/2+10, GLUT_BITMAP_HELVETICA_18,

“Enter your name and press enter to continue.”);

glBegin(GL_POLYGON);

glVertex2d(SCREEN_WIDTH_PIX/2-20, SCREEN_HEIGHT_PIX/2-7);

glVertex2d(SCREEN_WIDTH_PIX/2-20, SCREEN_HEIGHT_PIX/2+7);

glVertex2d(SCREEN_WIDTH_PIX/2+20, SCREEN_HEIGHT_PIX/2+7);

glVertex2d(SCREEN_WIDTH_PIX/2+20, SCREEN_HEIGHT_PIX/2-7);

glEnd();

glEndList();

iShowScore= glGenLists(1);

glNewList(iShowScore, GL_COMPILE);

glColor3f(0.0, 0.5, 0.5);

glBegin(GL_POLYGON);

glVertex2d(20, SCREEN_HEIGHT_PIX/2-20);

glVertex2d(20, SCREEN_HEIGHT_PIX/2+20);

glVertex2d(SCREEN_WIDTH_PIX-20, SCREEN_HEIGHT_PIX/2+20);

glVertex2d(SCREEN_WIDTH_PIX-20, SCREEN_HEIGHT_PIX/2-20);

glEnd();

glColor3f(0.8, 0.8, 0.8);

DisplayText::DisplayText(30.0, SCREEN_HEIGHT_PIX/2+10, GLUT_BITMAP_HELVETICA_18,

“Your present score is”);

DisplayText::DisplayText(23.0, SCREEN_HEIGHT_PIX/2-17, GLUT_BITMAP_HELVETICA_18,

“Press enter to exit or escape to continue..”);

glBegin(GL_POLYGON);

glVertex2d(SCREEN_WIDTH_PIX/2-20, SCREEN_HEIGHT_PIX/2-7);

glVertex2d(SCREEN_WIDTH_PIX/2-20, SCREEN_HEIGHT_PIX/2+7);

glVertex2d(SCREEN_WIDTH_PIX/2+20, SCREEN_HEIGHT_PIX/2+7);

glVertex2d(SCREEN_WIDTH_PIX/2+20, SCREEN_HEIGHT_PIX/2-7);

glEnd();

glEndList();

glLineWidth(BOARD_WIDTH);

glClearColor(0.5, 0.5, 0.5, 1.0);

glEnable(GL_BLEND);

glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

}

int main(int argc, char **argv) {

glutInit(&argc, argv);

glutInitDisplayMode(GLUT_SINGLE);

glutInitWindowSize(600, 400);

glutInitWindowPosition(100, 100);

glutCreateWindow(NAME_OF_GAME);

init();

glutDisplayFunc(fnDisplay);

glutReshapeFunc(fnReshape);

//glutIdleFunc(fnIdle);

glutSpecialFunc(fnSpecial);

glutKeyboardFunc(fnKeyboard);

glutMainLoop();

}

Not a big deal.. I know.. but a beginner in OpenGL will find it useful.. 🙂