Jump to content
  • Advertisement
Sign in to follow this  
nprz

OpenGL Weird bug that I can't find, help?

This topic is 5055 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have a couple bugs that I can't seem to find and I was hoping a couple eyes taking a look could help me find it :) The problems are the linewidth doesn't always work properly and the circle doesn't always translate to the correct position (and appears at 0,0 as a dotted circle). Thanks! There are three files (btw, it is a tic tac toe) board.h
// Tic Tac Toe Board Header
// Programmed by Nathan Prziborowski
// Date Last modified: December 14, 2004

enum spot { X, OH, UNOCCUPIED }; // Keep track of the status of each spot on the board
enum Command { UP = '8', DOWN = '2', LEFT = '4', RIGHT = '6', SELECT = '5', QUIT = 'q' }; 
const int BOARD_SIZE = 3;			 // this makes it easier to reference rather than writing 3 many times.


class Board
{
public:
	Board() { clear(); } // default constructor
	~Board() { }
	Board(const Board& in);
	bool move(int xpos, int ypos);
	void clear();
	friend bool operator ==(const Board& left, const Board& right); // this function needs access
	// to the private member variables of this class, so we declare as a friend.
	int gety() const { return cury; }
	int getx() const { return curx; }
	void sety(int iny) { cury = iny; }
	void setx(int inx) { curx = inx; }
	spot at(int inx, int iny) const { return game_board[inx][iny]; }
private:
	spot game_board[BOARD_SIZE][BOARD_SIZE];
	spot turn;						// is it X's turn or OH's turn
	int curx,cury;
};

board.cpp
// Tic Tac Toe Board
// Programmed by Nathan Prziborowski
// Date Last modified: December 14, 2004

#include <iostream>
#include <vector>
#include "board.h"

Board::Board(const Board& in) // copy constructor
{	// the purpose of the copy constructor is to make a deep-copy of the input class
	// into the target class. the in class should be constant and byref.
	// The meaning of deep-copy is to copy the data from all the member variables.
	
	// If I just put game_board = in.game_board, that would be a shallow copy,
	// if it were dynamic memory instead of static.

	for (int x = 0; x < BOARD_SIZE; ++x)
		for (int y = 0; y < BOARD_SIZE; ++y)
			game_board[x][y] = in.game_board[x][y]; // instead of making each spot unoccupied, 
													// copy what the other board was.
	turn = in.turn;
	curx = in.curx;
	cury = in.cury;
}

void Board::clear() // clear (does exactly what default constructor does)
{
	for (int x = 0; x < BOARD_SIZE; ++x)
		for (int y = 0; y < BOARD_SIZE; ++y)
			game_board[x][y] = UNOCCUPIED; // initialize each spot to be unoccupied.
	turn = X; // always start the game with X
	curx = BOARD_SIZE / 2;
	cury = BOARD_SIZE / 2;
}

bool Board::move(int xpos, int ypos)
{
	if (game_board[xpos][ypos] == UNOCCUPIED)	// don't move on a spot that is taken.
	{
		game_board[xpos][ypos] = turn;
		(turn == X) ? turn = OH : turn = X;		// this is shorthand for
												// if (turn == X)
												//		turn = OH;
												// else
												//		turn = X;
		return true;
	}
	return false;
}

bool operator ==(const Board& left, const Board& right)
{
	bool result = true;
	for (int x = 0; x < BOARD_SIZE; ++x)
		for (int y = 0; y < BOARD_SIZE; ++y)
			if (left.game_board[x][y] != right.game_board[x][y])
				result = false;
	if (left.turn != right.turn)
		result = false;

	return result;
}


driver.cpp
// Tic Tac Toe Main
// Programmed by Nathan Prziborowski
// Date Last modified: December 14, 2004

#include "board.h"
#include <iostream>
#include "GL/glut.h"
#include "windows.h"
#include "math.h"

void display(const Board& in, std::ostream& out);		// write the board out to the stream (file or cout)
char to_char(spot in);
void draw_board(const Board& ttt);
float windowheight,windowwidth;
int mousex,mousey;
int mainmenu; // handle for the menu.
void display();

Board tictactoe;

const int MY_CIRCLE_LIST = 1;
const int LINE_SIZE = 5;
const float PI = 3.14159265;

void buildCircle()
{
	GLint i;
	GLfloat cosine, sine;

	glDeleteLists(MY_CIRCLE_LIST, 1);
	glNewList(MY_CIRCLE_LIST, GL_COMPILE);
    glBegin(GL_LINE_LOOP);
		for(i = 0; i < 100; i+=2)
		{
			cosine=cos(i * 2 * PI / 100.0);
			sine=sin(i * 2 * PI / 100.0);
			glVertex2f(cosine*windowwidth/(BOARD_SIZE*2), sine*windowheight/(BOARD_SIZE*2));
        }
   glEnd();
   glEndList();
}

spot is_over(const Board& ttt) // not a class function because if the size changes
			   // this I don't know what the creator would want as the requirements to win.
{ // A lot of checking to see if there is a winner.
	for (int x = 0; x < BOARD_SIZE; ++x) // check horizontal win.
	{
		if (ttt.at(x,0) == ttt.at(x,1) &&
			ttt.at(x,1) == ttt.at(x,2) &&
			ttt.at(x,0) != UNOCCUPIED)
			return ttt.at(x,0); // this guy won.
	}

	for (int y = 0; y < BOARD_SIZE; ++y) // check vertical win
	{
		if (ttt.at(0,y) == ttt.at(1,y) &&
			ttt.at(1,y) == ttt.at(2,y) &&
			ttt.at(0,y) != UNOCCUPIED)
			return ttt.at(0,y); // this guy won.
	}

	// diagonal win
	if (ttt.at(0,0) == ttt.at(1,1) && 
		ttt.at(1,1) == ttt.at(2,2) &&
		ttt.at(1,1) != UNOCCUPIED)
		return ttt.at(1,1);

	if (ttt.at(0,2) == ttt.at(1,1) &&
		ttt.at(1,1) == ttt.at(2,0) &&
		ttt.at(1,1) != UNOCCUPIED)
		return ttt.at(1,1);

	return UNOCCUPIED;
}

void mouse(int button, int state, int x, int y)
{
	
	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
	{ // store the down window
		mousex = x / (windowwidth / BOARD_SIZE);
		mousey = (windowheight - y) / (windowheight / BOARD_SIZE);
	}
	
	if (button == GLUT_LEFT_BUTTON && state == GLUT_UP)
	{ // determine if the current position and the down position were in the same box.
	  // if so, choose that spot for a move.
		int newx = x / (windowwidth / BOARD_SIZE);
		int newy = (windowheight - y) / (windowheight / BOARD_SIZE);

		if (mousex == newx &&
		   mousey == newy)
		{
			tictactoe.move(newx,newy);
		}
	}
}

void keyboard(unsigned char key, int x, int y)
{
	if (key == ' ')
	{
		tictactoe.clear();
	}
}

void init() 
{
	// initialize viewing system
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	buildCircle();
	
	gluPerspective(45.0, 1.0, 1.0, 100.0);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(0,0,0, 0,0,-1, 0,1,0);
	
	glEnable(GL_BLEND);	// Antialiasing
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glEnable(GL_LINE_SMOOTH);
	
	// initialize background color to white
	glClearColor(1,1,1,0);
}

void reshape(int width, int height) 
{
	GLfloat nRange = 50.0f;
	
	windowheight = height;
	windowwidth = width;
	
	if (height == 0)
		height = 1;
	
	glViewport(0, 0, width, height);
	
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	glOrtho(0, windowwidth, 0, windowheight, -1, 1);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(0,0,0, 0,0,-1, 0,1,0);
	
	buildCircle(); // circle size changes with the size of the window.
}

void main_menu(int value) 
{
	if (value == 0)
	{
		glDeleteLists(MY_CIRCLE_LIST, 1);
		exit(1);
	}
	else if (value == 1)
	{
		tictactoe.clear();
	}
}

int main(int argc, char **argv) 
{
	// initialize glut 
	glutInit(&argc, argv);
	
	// set window size
	glutInitWindowSize(300,300);
	
	// establish glut display parameters
	glutInitDisplayMode(GLUT_DOUBLE  | GLUT_RGB );
	
	// create window
	glutCreateWindow("Tic Tac Toe");
	
	// register callback functions
	glutDisplayFunc(display);
	glutReshapeFunc(reshape); 
	glutMouseFunc(mouse); 
	glutKeyboardFunc(keyboard);
	
	// initalize opengl parameters
	init();
	
	mainmenu = glutCreateMenu(main_menu);
	glutAddMenuEntry("Quit", 0);
	glutAddMenuEntry("Clear",1);
	
	glutAttachMenu(GLUT_RIGHT_BUTTON);
	
	glutMainLoop();
	
	return 0;           
}

void draw_sprite(int x, int y)
{
	spot ins = tictactoe.at(x,y);
	float xleft = x * windowwidth / BOARD_SIZE;
	float xright = (x + 1) * windowwidth / BOARD_SIZE;
	float ytop = ((y + 1) * windowheight / BOARD_SIZE);
	float ybottom = (y * windowheight / BOARD_SIZE);
	float ocenterx = (x * windowwidth / BOARD_SIZE) + (windowwidth / (2 * BOARD_SIZE));
	float ocentery = ((y * windowheight / BOARD_SIZE) + (windowheight / (2 * BOARD_SIZE)));

	switch (ins)
	{
	case X:
		glLineWidth(LINE_SIZE);
		glColor3f(0.0f,0.0f,1.0f);
		glPushMatrix();
		glBegin(GL_LINES);
		glVertex2f(xleft, ytop);
		glVertex2f(xright, ybottom);
		glVertex2f(xleft, ybottom);
		glVertex2f(xright, ytop);
		glEnd();
		glPopMatrix();
		glLineWidth(1);
		break;
	case OH:
		glPushMatrix();
		glTranslatef(ocenterx, ocentery, 0);
		glLineWidth(LINE_SIZE);
		glColor3f(1.0f,0.0f,0.0f);
		glCallList(MY_CIRCLE_LIST);
		glLineWidth(1);
		glPopMatrix();
		break;
	default: // nothing really
		break;
	}
}

void draw_board()
{
	int x,y;
	glLineWidth(1);
	glColor3f(0, 0, 0);
	glBegin(GL_LINES);
		for (x = 1; x < BOARD_SIZE; ++x)
		{
			glColor3f(0,0,0);
			glVertex2f(x * windowwidth / BOARD_SIZE, 0);
			glVertex2f(x * windowwidth / BOARD_SIZE, windowheight);
		}
		for (y = 1; y < BOARD_SIZE; ++y)
		{
			glVertex2f(0, y * windowheight / BOARD_SIZE);
			glVertex2f(windowwidth, y * windowheight / BOARD_SIZE);
		}

		for (x = 0; x < BOARD_SIZE; ++x)
			for (y = 0; y < BOARD_SIZE; ++y)
				draw_sprite(x, y);
	glEnd();
}

void display() 
{
	float adjustx = 0;
	float adjusty = 0;
	int x = 0;
	
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glShadeModel(GL_SMOOTH);
	
	glLoadIdentity();
	gluLookAt(0,0,0, 0,0,-1, 0,1,0);
	
	draw_board();
	
	glutPostRedisplay();
	
	// flush buffer
	glutSwapBuffers();
	Sleep(50);
}


Share this post


Link to post
Share on other sites
Advertisement
I think I found a few problems

Problem (1)

The code in driver.cpp:

void draw_sprite(int x, int y)
{
spot ins = tictactoe.at(x,y);
float xleft = x * windowwidth / BOARD_SIZE;
float xright = (x + 1) * windowwidth / BOARD_SIZE;
float ytop = ((y + 1) * windowheight / BOARD_SIZE);
float ybottom = (y * windowheight / BOARD_SIZE);
float ocenterx = (x * windowwidth / BOARD_SIZE) + (windowwidth / (2 * BOARD_SIZE));
float ocentery = ((y * windowheight / BOARD_SIZE) + (windowheight / (2 * BOARD_SIZE)));


You need to cast BOARD_SIZE to a float. i.e. (float)(BOARD_SIZE)

Problem (2)

(This isn't really a problem)

The for-loop in buildCircle() should read

for(i = 0; i < 100; ++i) not for(i = 0; i < 100; i+=2)

otherwise you are drawing 50 points instead of a 100 which is confusing


Happy bug hunting!

Share this post


Link to post
Share on other sites
That was a toughy to debug!
void draw_board()
{
int x,y;
glLineWidth(1);
glColor3f(0, 0, 0);
glBegin(GL_LINES);
for (x = 1; x < BOARD_SIZE; ++x)
{
glColor3f(0,0,0);
glVertex2f(x * windowwidth / BOARD_SIZE, 0);
glVertex2f(x * windowwidth / BOARD_SIZE, windowheight);
}
for (y = 1; y < BOARD_SIZE; ++y)
{
glVertex2f(0, y * windowheight / BOARD_SIZE);
glVertex2f(windowwidth, y * windowheight / BOARD_SIZE);
}

for (x = 0; x < BOARD_SIZE; ++x)
for (y = 0; y < BOARD_SIZE; ++y)
draw_sprite(x, y);
glEnd();
}

Your sprites are drawn within a begin-end pair, so calling glBegin again to render an 'X' is invalid. Move the glEnd() call above the sprite drawing loop.

A couple of additional points:
  1. Your init function should neither set the projection matrix nor build the circle display list. Leave that to the reshape function.

  2. You should not be calling glutPostRedisplay(); from inside your display function. Instead call it only when the window needs repainting - after the board has been cleared or a move has been made.

  3. Listen to your compiler warnings. You have unused variables that you may as well get rid of


Enigma

Share this post


Link to post
Share on other sites
Thanks for the help. Learning OpenGL through modifying projects isn't the right method but my professor never told us how to use it, so that was the quickest way to do a project a week. Also he never returned our work, so we had no idea what was right or wrong.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!