PDA

View Full Version : delay function



pbivens
01-05-2018, 05:53 PM
void delay(float secs)
{
float end = clock() / CLOCKS_PER_SEC + secs;
while ((clock() / CLOCKS_PER_SEC) < end);
}
void draw_button()
{
if (board[0][0] == 1)
{
glColor3f(0.5f, 0.5f, 0.0f);
glRectf(-90.0f, 90.0f, -10.0f, 10.0f);
delay(1);
glColor3f(1.0f, 1.0f, 0.0f);
glRectf(-90.0f, 90.0f, -10.0f, 10.0f);
}
}

I am drawing a square then I am drawing a dimmed square then I want to wait a second and then draw a undimmed square. well this code draws a square but then it does not draw a dimmed square or wait to draw a undimmed square.

Symbroson
01-06-2018, 02:20 AM
It seems like you forgot to render the screen after drawing a square - I don't know where exactly you call SwapBuffers, but before the delay there's none - so you'll never see the first square but the second one which will compleately overdraw the first.

I also suggest to change the Vertices of the second one so that the squares just overlap in a smaller area. Then you wouldnt need to render between them and the delay too. Depends on what you need it for

GClements
01-06-2018, 08:19 AM
glColor3f(0.5f, 0.5f, 0.0f);
glRectf(-90.0f, 90.0f, -10.0f, 10.0f);
delay(1);
glColor3f(1.0f, 1.0f, 0.0f);
glRectf(-90.0f, 90.0f, -10.0f, 10.0f);



This won't work, for a variety of reasons.

If you're using GLUT, you should draw the first square and use glutTimerFunc() to register a callback which will be invoked after one second. That callback should call glutPostRedisplay(), which will cause your display function to be called. That should draw the second square. Use a variable to keep track of which version of the square the display function should draw at any given time. Also, you should call glutSwapBuffers() at the end of your display function to ensure that what you draw is actually visible on screen.

Dark Photon
01-06-2018, 08:44 AM
pbivens, with OpenGL, in most cases you're drawing to an invisible buffer (term: "double-buffering"). Not only that, the drawing commands you call in your application aren't executed immediately; instead, they're recorded for execution later.

So sleeping in your application is not the way to force the execution of your draw commands and to display the result on-screen.

Instead, how you request that both of these be done is to call *SwapBuffers. If you're using GLUT, you should call glutSwapBuffers().

pbivens
01-06-2018, 01:51 PM
void delay(int v)
{
glColor3f(1.0f, 1.0f, 0.0f);
glRectf(-90.0f, 90.0f, -10.0f, 10.0f);
glutPostRedisplay();
glutTimerFunc(1000, delay, v);
}
void draw_button()
{
if (board[0][0] == 1)
{
delay(0);
glColor3f(0.5f, 0.5f, 0.0f);
glRectf(-90.0f, 90.0f, -10.0f, 10.0f);
glutSwapBuffers();
}
}

well I am working on my code as per gclements I have made some changes. but it still does not work however it does flicker when I hit the yellow square. thanks for all the help. I am close to solving this problem I just need a little help.

Dark Photon
01-06-2018, 05:07 PM
I suggest you don't draw anything in your timer callback. Draw everything in one "draw" function based on the current program state.

Also, you need to call glutPostRedisplay anytime you want a draw to occur. I don't know, but I suspect you want that to happen more than every 1 second (the rate that you're currently calling it, based on your timer callback interval).

For testing, just drop a glutPostRedisplay at the end of your init() and draw() functions so that it's just called as often as possible. Then after you get things working well, you can scale back and only request a redraw when it's needed if you want.

pbivens
01-06-2018, 05:26 PM
void delay(int v)
{
glColor3f(1.0f, 1.0f, 0.0f);
glRectf(-90.0f, 90.0f, -10.0f, 10.0f);
glutPostRedisplay();
glutTimerFunc(1000, delay, v);
glFlush();
}
void draw_button()
{
if (board[0][0] == 1)
{
glColor3f(0.5f, 0.5f, 0.0f);
glRectf(-90.0f, 90.0f, -10.0f, 10.0f);
glFlush();
}
}

well I have made some progress when I hit the square it blinks on and off and it continues to do so. I took the drawing routine out of the timer but it does not work at all.

pbivens
01-06-2018, 05:38 PM
well I finally solved this problem. here is the code I am using.


void delay(int v)
{
glColor3f(1.0f, 1.0f, 0.0f);
glRectf(-90.0f, 90.0f, -10.0f, 10.0f);
glutTimerFunc(1000, delay, v);
glFlush();
}
void draw_button()
{
if (board[0][0] == 1)
{
glColor3f(0.5f, 0.5f, 0.0f);
glRectf(-90.0f, 90.0f, -10.0f, 10.0f);
glFlush();
}

thanks for all the help [SOLVED]

pbivens
01-06-2018, 05:58 PM
I have made more progress.


void delay_one(int v)
{
glColor3f(1.0f, 1.0f, 0.0f);
glRectf(-90.0f, 90.0f, -10.0f, 10.0f);
glutTimerFunc(1000, delay_one, v);
glFlush();
}
void delay_two(int v)
{
glColor3f(1.0f, 0.0f, 0.0f);
glRectf(10.0f, 90.0f, 90.0f, 10.0f);
glutTimerFunc(1000, delay_two, v);
glFlush();
}
void delay_three(int v)
{
glColor3f(0.0f, 1.0f, 0.0f);
glRectf(-90.0f, -10.0f, -10.0f, -90.0f);
glutTimerFunc(1000, delay_three, v);
glFlush();
}
void delay_four(int v)
{
glColor3f(0.0f, 0.0f, 1.0f);
glRectf(10.0f, -10.0f, 90.0f, -90.0f);
glutTimerFunc(1000, delay_four, v);
glFlush();
}
void draw_button()
{
if (board[0][0] == 1)
{
glColor3f(0.5f, 0.5f, 0.0f);
glRectf(-90.0f, 90.0f, -10.0f, 10.0f);
glFlush();
}
if (board[0][1] == 1)
{
glColor3f(0.5f, 0.0f, 0.0f);
glRectf(10.0f, 90.0f, 90.0f, 10.0f);
glFlush();
}
if (board[1][0] == 1)
{
glColor3f(0.0f, 0.5f, 0.0f);
glRectf(-90.0f, -10.0f, -10.0f, -90.0f);
glFlush();
}
if (board[1][1] == 1)
{
glColor3f(0.0f, 0.0f, 0.5f);
glRectf(10.0f, -10.0f, 90.0f, -90.0f);
glFlush();
}
}

void onMouseButton(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
if (x >= 130 && x <= 370 && y <= 270 && y >= 30)
{
board[0][0] = 1;
}
if (x >= 430 && x <= 670 && y <= 270 && y >= 30)
{
board[0][1] = 1;
}
if (x >= 130 && x <= 370 && y <= 570 && y >= 330)
{
board[1][0] = 1;
}
if (x >= 430 && x <= 670 && y <= 570 && y >= 330)
{
board[1][1] = 1;
}
draw_button();
}
glFlush();
}

I am building a simon game. However when I press a square and another square it turns both squares off and on. I want to turn on and off one square at a time.

GClements
01-06-2018, 06:12 PM
First: the only place you should be calling OpenGL functions is during initialisation and from the display callback (whether in the display function itself or in other functions called from it). Other callbacks shouldn't call OpenGL functions, directly or indirectly. The display function needs to be able to draw the scene based upon the program state. Other functions simply modify that state.

So to change the display in response to events (keyboard, mouse, timer), you change some variables in response to those events (and if necessary, force a display update with glutPostRedisplay()). The display function just takes those variables into account when deciding what to draw.

pbivens
01-06-2018, 06:17 PM
I am going to work on this problem more.

pbivens
01-07-2018, 01:48 PM
I am building a simon game. However when I press a square and another square it turns both squares off and on. I want to turn on and off one square at a time.

thor4000
01-08-2018, 01:22 PM
Post your code, or at least the important parts.

pbivens
01-08-2018, 03:15 PM
I have already posted my code above.

pbivens
01-21-2018, 02:06 PM
I am working on a simon game. I am using c++ and opengl.I am able to draw four buttons. When press a button with the mouse it turns off and on. however it also turns on and off the other buttons. I want it to turn on and off only a single button at a time. here is some of my code.


void delay_one(int v)
{
glColor3f(1.0f, 1.0f, 0.0f);
glRectf(-90.0f, 90.0f, -10.0f, 10.0f);
glutTimerFunc(1000, delay_one, v);
glFlush();
}
void delay_two(int v)
{
glColor3f(1.0f, 0.0f, 0.0f);
glRectf(10.0f, 90.0f, 90.0f, 10.0f);
glutTimerFunc(1000, delay_two, v);
glFlush();
}
void delay_three(int v)
{
glColor3f(0.0f, 1.0f, 0.0f);
glRectf(-90.0f, -10.0f, -10.0f, -90.0f);
glutTimerFunc(1000, delay_three, v);
glFlush();
}
void delay_four(int v)
{
glColor3f(0.0f, 0.0f, 1.0f);
glRectf(10.0f, -10.0f, 90.0f, -90.0f);
glutTimerFunc(1000, delay_four, v);
glFlush();
}
void draw_button()
{
if (board[0][0] == 1)
{
glColor3f(0.5f, 0.5f, 0.0f);
glRectf(-90.0f, 90.0f, -10.0f, 10.0f);
glFlush();
}
if (board[0][1] == 1)
{
glColor3f(0.5f, 0.0f, 0.0f);
glRectf(10.0f, 90.0f, 90.0f, 10.0f);
glFlush();
}
if (board[1][0] == 1)
{
glColor3f(0.0f, 0.5f, 0.0f);
glRectf(-90.0f, -10.0f, -10.0f, -90.0f);
glFlush();
}
if (board[1][1] == 1)
{
glColor3f(0.0f, 0.0f, 0.5f);
glRectf(10.0f, -10.0f, 90.0f, -90.0f);
glFlush();
}
}

let me know if you need more code.

GClements
01-22-2018, 02:45 AM
Starting another thread isn't going to help. And the fact that you shouldn't be calling OpenGL functions outside of the display callback isn't going to change.

pbivens
01-22-2018, 04:07 PM
well here is my display callback function


void RenderScene(void)
{
glClear(GL_COLOR_BUFFER_BIT);
Draw_Buttons();
glFinish();
draw_button();
}

I have done some research on display callback, I think that the display callback is what is used to display my game to the screen. let me know if I have a understanding of callbacks.

GClements
01-22-2018, 04:17 PM
I have done some research on display callback, I think that the display callback is what is used to display my game to the screen.
Correct. And the display callback is the only time you should be drawing anything. The other callbacks (mouse, keyboard, timer) should only be changing variables which affect the drawing performed by the display callback.

You should probably have an array of flags which indicate whether each button is "lit". The timer callback would change those flags (and call glutPostRedisplay), the display callback would read them to determine how to draw each button (dark or light).

pbivens
01-22-2018, 04:23 PM
cool I am glad that I understand display callback functions. here is my mouse callback


void onMouseButton(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
if (x >= 130 && x <= 370 && y <= 270 && y >= 30)
{
board[0][0] = 1;
}
if (x >= 430 && x <= 670 && y <= 270 && y >= 30)
{
board[0][1] = 1;
}
if (x >= 130 && x <= 370 && y <= 570 && y >= 330)
{
board[1][0] = 1;
}
if (x >= 430 && x <= 670 && y <= 570 && y >= 330)
{
board[1][1] = 1;
}
draw_button();
}
glFinish();
}

is this an array that you are talking about or something different?

GClements
01-23-2018, 02:39 AM
cool I am glad that I understand display callback functions. here is my mouse callback


draw_button();
}
glFinish();


Those two function calls don't belong there. After updating the board array, the function should simply call glutPostRedisplay().

If you want the button state to change automatically after a given amount of timer, register a timer callback. As with the mouse callback, the timer callback should simply update the board array then call glutPostRedisplay(); it shouldn't attempt to draw anything itself.

pbivens
01-23-2018, 12:58 PM
well I tried the glutPostRedisplay but it made the buttons to not blink on and off. they just stayed static.

GClements
01-23-2018, 02:52 PM
well I tried the glutPostRedisplay but it made the buttons to not blink on and off. they just stayed static.
If you want the button state to change over time, you need to start a timer, and have the timer callback change the state and call glutPostRedisplay().

pbivens
01-23-2018, 04:49 PM
I finally solved my problem, thanks for all the help.

pbivens
01-23-2018, 06:44 PM
now I have to work on the AI for my game. I have to develop the computer player for my simon game. can I get a hint on how to proceed further.

pbivens
01-25-2018, 04:35 PM
well I am now working on the computer player in my game. right now one of my squares is dimmed, I want it to turn on and off and on again.


void draw_button()
{
if (board[0][0] == 1)
{
glColor3f(0.5f, 0.5f, 0.0f);
glRectf(-90.0f, 90.0f, -10.0f, 10.0f);
glutTimerFunc(1000, delay_one, 0);
board[0][0] = 0;
}
if (board[0][1] == 1)
{
glColor3f(0.5f, 0.0f, 0.0f);
glRectf(10.0f, 90.0f, 90.0f, 10.0f);
glutTimerFunc(1000, delay_one, 0);
board[0][1] = 0;
}
if (board[1][0] == 1)
{
glColor3f(0.0f, 0.5f, 0.0f);
glRectf(-90.0f, -10.0f, -10.0f, -90.0f);
glutTimerFunc(1000, delay_one, 0);
board[1][0] = 0;
}
if (board[1][1] == 1)
{
glColor3f(0.0f, 0.0f, 0.5f);
glRectf(10.0f, -10.0f, 90.0f, -90.0f);
glutTimerFunc(1000, delay_one, 0);
board[1][1] = 0;
}
}

void comp_buttons()
{
srand(time(NULL));

// int num = rand() % 4 + 1;

int num = 1;

if (num == 1)
{
board[0][0] = 1;
}

I will work on my game some more. I have resolved my previous problem so I will eventually resolve this problem as well.

pbivens
01-26-2018, 03:30 PM
int num = 2;

if (num == 1)
{
board[0][0] = 1;
}
if (num == 2)
{
board[0][1] = 1;
glColor3f(0.5f, 0.0f, 0.0f);
glRectf(10.0f, 90.0f, 90.0f, 10.0f);
glutTimerFunc(1000, delay_one, 0);
glColor3f(1.0f, 0.0f, 0.0f);
glRectf(10.0f, 90.0f, 90.0f, 10.0f);
board[0][1] = 0;
}

I am still trying to get a rectangle to dim and then undim its color.I am using glutTimerFunc to wait a small period of time. I am also thinking about using glutIdleFunc to wait a period of time.

GClements
01-27-2018, 04:36 AM
if (num == 2)
{
board[0][1] = 1;
glColor3f(0.5f, 0.0f, 0.0f);
glRectf(10.0f, 90.0f, 90.0f, 10.0f);
glutTimerFunc(1000, delay_one, 0);
glColor3f(1.0f, 0.0f, 0.0f);
glRectf(10.0f, 90.0f, 90.0f, 10.0f);
board[0][1] = 0;
}

I am still trying to get a rectangle to dim and then undim its color.I am using glutTimerFunc to wait a small period of time. I am also thinking about using glutIdleFunc to wait a period of time.
glutTimerFunc() isn't a "wait" function. It registers a callback which will be executed at a given point in the future, then returns immediately.

Your display() function should be doing something like:


if (board[0][1] = 0)
glColor3f(0.5f, 0.0f, 0.0f); // dim
else
glColor3f(1.0f, 0.0f, 0.0f); // bright
glRectf(10.0f, 90.0f, 90.0f, 10.0f);

// draw everything else

glutSwapBuffers();


The mouse/keyboard callback does e.g.


board[0][1] = 1;
glutTimerFunc(1000, timer, 0);
glutPostRedisplay();


The timer() function does:


board[0][1] = 0;
glutPostRedisplay();


To summarise:

The input event changes the button state, starts a timer, and requests a redraw (which, because of the change to the button state, will draw the button in the pressed state). When the timer expires, the timer callback will revert the button state and request a redraw (which will draw the button in the default state).

This isn't specific to OpenGL; this is how GUI programming works in general. In particular, you cannot wait in the middle of handling an event. You have to arrange for a timer event to be generated in the future, return to allow event processing to continue, then handle the timer event when it occurs.

pbivens
01-27-2018, 02:43 PM
is there I can use as a wait function?

pbivens
01-27-2018, 04:07 PM
I have almost solved my problem. I got a rectangle to turn off by itself. I just want it turn on by itself as well.


void delay(int v)
{
board[0][0] = 1;
glutPostRedisplay();
glutTimerFunc(1000, delay, 1);
}

void draw_button()
{
if (board[0][0] == 1)
{
glColor3f(0.5f, 0.5f, 0.0f);
glRectf(-90.0f, 90.0f, -10.0f, 10.0f);
board[0][0] = 0;
}
if (board[0][1] == 1)
{
glColor3f(0.5f, 0.0f, 0.0f);
glRectf(10.0f, 90.0f, 90.0f, 10.0f);
board[0][1] = 0;
}
if (board[1][0] == 1)
{
glColor3f(0.0f, 0.5f, 0.0f);
glRectf(-90.0f, -10.0f, -10.0f, -90.0f);
board[1][0] = 0;
}
if (board[1][1] == 1)
{
glColor3f(0.0f, 0.0f, 0.5f);
glRectf(10.0f, -10.0f, 90.0f, -90.0f);
board[1][1] = 0;
}
}

the problem is in the delay function.

pbivens
01-28-2018, 12:52 PM
can I please get some more help, I have almost solved my problem.

GClements
01-28-2018, 01:49 PM
I have almost solved my problem. I got a rectangle to turn off by itself. I just want it turn on by itself as well.


void delay(int v)
{
board[0][0] = 1;
glutPostRedisplay();
glutTimerFunc(1000, delay, 1);
}


The delay() function shouldn't be having the timer re-execute it; at least, not in its current form.

You can either have multiple functions where each sets a specific state then triggers the next function via glutTimerFunc(), or a single function which sets the next state each time it's called. In the latter case, you need something like:


#define NUM_STATES 10 /* or whatever */
int state = 0;
void delay(int v)
{
state++;
glutPostRedisplay();
if (state < NUM_STATES);
glutTimerFunc(1000, delay, 1);
}

Then the display() function would use the value of state to determine the button colours at any given time. E.g. if the intent is to light the buttons in a pre-determined sequence, one approach would be to have an array:


#define NUM_STATES 8
static const int buttons[NUM_STATES] = {1,0,2,0,3,0,4,0};
void display(void)
{
int button = state<NUM_STATES ? buttons[state] : 0;

if (button == 1)
glColor3f(1.0,0,0);
else
glColor3f(0.5,0,0);
glRectf( ... ); /* draw button 1 */

if (button == 2)
/* and so on */
}

The timer callback sets the variables to record the current state, requests a redraw, and if the sequence hasn't finished starts a timer for the next point in the sequence. The display callback draws the "board" for the current state. The details depend upon exactly what you're trying to achieve.

Really, most of this isn't anything to do with OpenGL, it's general programming concepts.

pbivens
01-28-2018, 02:21 PM
thanks for the help, I will work on my code more. is there any tutorials I can look at that will help?

pbivens
01-29-2018, 03:31 PM
well I got my code to blink off and on one of my rectangles, I want it to blink on and off only once.

pbivens
02-01-2018, 07:26 PM
well I finally solved my square problems. thanks for all the help

pbivens
02-11-2018, 06:11 PM
well I am working on my simon game, I am making the AI for my game. this problem is quite difficult, any input on how I should proceed?