Aidan Aidan - 1 month ago 6
C++ Question

How to output variable numbers in OpenGL?

I'm writing a game in OpenGL where there are 3 large boxes and 1 small box. The small box is hidden under one of the large boxes, and the user has to press A, B, or C to reveal where the small box is. I want to keep track of how many guesses the user has made, rounds played, etc, but I'm not entirely sure how to output incremented numbers in OpenGL. I want to increment the numbers every time something pertaining to the numbers happens, but I just cannot figure it out. Can someone point me in the right direction? Thank you so much!

main.cpp:

#include "Box.h"
#include "Font.h"
#include "Camera.h"
#include "Time.h"
#include <vector>
using namespace std;

#include "vgl.h"
using namespace glm;
#define SPACEBAR_KEY 32
#define ESCAPE_KEY 033

vector<Box * > boxes;
Camera* camera;
Font* font;
int numGenerator, guesses, totalGuesses, rounds, averageGuesses;
bool win;

void closeApp()
{
delete camera;
delete font;



for (auto it = boxes.begin(); it != boxes.end(); ++it)
delete (*it);


}

void startNewGame()
{
rounds++;
win = false;
guesses = 0;
numGenerator = rand() % 3;

boxes[1]->Visible = true;
boxes[2]->Visible = true;
boxes[3]->Visible = true;

if (numGenerator == 0)
{
boxes[0]->Position = vec3(0.0f, -3.0f, 0.0f);
}
else if (numGenerator == 1)
{
boxes[0]->Position = vec3(0.0f, 0.0f, 0.0f);
}
else
{
boxes[0]->Position = vec3(0.0f, 3.0f, 0.0f);
}

}

void keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case ESCAPE_KEY: // ASCII Escape Key Code
closeApp();
exit(EXIT_SUCCESS);
break;
case 'a':
boxes[1]->Visible = false;
if (boxes[0]->Position != vec3(0.0f, -3.0f, 0.0f))
{
guesses++;
totalGuesses++;
}
else
{
win = true;
}
glutPostRedisplay();
break;
case 'b':
boxes[2]->Visible = false;
if (boxes[0]->Position != vec3(0.0f, 0.0f, 0.0f))
{
guesses++;
totalGuesses++;
}
else
{
win = true;
}
glutPostRedisplay();
break;
case 'c':
boxes[3]->Visible = false;
if (boxes[0]->Position != vec3(0.0f, 3.0f, 0.0f))
{
guesses++;
totalGuesses++;
}
else
{
win = true;
}
glutPostRedisplay();
break;
case 'r':
startNewGame();
glutPostRedisplay();
break;
}
}



void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
font->printText("Guessing Game!", 260, 500, 20);
font->printText("Press 1, 2, or 3 to make one of the boxes disappear!", 10, 480, 15);
font->printText("Try to find the small cube! Press 'r' to restart!", 30, 460, 15);
if (win)
{
font->printText("You win!", 20, 200, 30);
}
font->printText("Guesses: ", 20, 350, 15);
font->printText("Rounds played: ", 20, 330, 15);
font->printText("Total guesses: ", 20, 310, 15);
font->printText("Average guesses: ", 20, 290, 15);



boxes[0]->Draw(camera->ProjectionMatrix, camera->ViewMatrix);
boxes[1]->Draw(camera->ProjectionMatrix, camera->ViewMatrix);
boxes[2]->Draw(camera->ProjectionMatrix, camera->ViewMatrix);
boxes[3]->Draw(camera->ProjectionMatrix, camera->ViewMatrix);


glutSwapBuffers();
}

void init()
{
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_CULL_FACE);

srand(time(NULL));

font = new Font();

camera = new Camera();
camera->ViewMatrix = glm::lookAt(glm::vec3(0, 0, 20), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));


VertexBufferData vertexBufferData = VertexBufferData("Data\\Models\\Objects.xml");

boxes.push_back(new Box(vertexBufferData, glm::vec3(0.0f, 0.0f, 0.0f), "data/images/wood.bmp", "Data\\Shaders\\Vertex.shader", "Data\\Shaders\\Fragment.shader", vec3(0.4f, 0.4f, 0.4f), true));
boxes.push_back(new Box(vertexBufferData, glm::vec3(0.0f, -3.0f, 0.0f), "data/images/ground.tga", "Data\\Shaders\\Vertex.shader", "Data\\Shaders\\Fragment.shader", vec3(1.0f, 1.0f, 1.0f), true));
boxes.push_back(new Box(vertexBufferData,glm::vec3(0.0f, 0.0f, 0.0f), "data/images/metal.bmp", "Data\\Shaders\\Vertex.shader", "Data\\Shaders\\Fragment.shader", vec3(1.0f, 1.0f, 1.0f), true));
boxes.push_back(new Box(vertexBufferData, glm::vec3(0.0f, 3.0f, 0.0f), "data/images/brick.bmp", "Data\\Shaders\\Vertex.shader", "Data\\Shaders\\Fragment.shader", vec3(1.0f, 1.0f, 1.0f), true));

startNewGame();
}



int main(int argc, char** argv)
{
glutInit(&argc, argv);

glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(1024, 768);
glutInitContextProfile(GLUT_CORE_PROFILE);
glutCreateWindow("Satterwhite_Project_5");


if (glewInit())
{
cerr << "Unable to init glew" << endl;
exit(EXIT_FAILURE);
}

init();
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}

Answer

You have a font->printText method, which is a great deal, so printing strings is not an issue for you! It means, that you just need to prepare the string with numbers and then print it with printText.

One simple way to do it in C++ is to use string streams. In your display function, instead of font->printText("Guesses: ", 20, 350, 15);, write:

std::stringstream ss;
ss << "Guesses: " << guesses;
font->printText(ss.str().c_str(), 20, 350, 15);

and do the same for all the rest numbers.

Don't forget to include <sstream> for stringstream class.