I am able move my sprite from the center to the right border. but it moves very quickly, I want it to move slowly and one sprite width at a time. just like in space invaders.
As you wish. If I did not mess something up, here is my analysis why your Sprites are moving to fast:
You are using:
move_right++;
I guess move_right should represent your x-position. So you increase your position value every time you call your move function. Now there are 2 questions to me:
How often is your function called?
How much do you increase your value when using the operator ++?
This is important since both influence the time dependent position of your object. The answer to question 1 is expected to be 1 time per second (glutTimerFunction with 1000ms delay). The answer to question 2 is probably “by 1” like for integers (not sure here since I never tested it on floats … 7 years cpp and I am not sure xD).
So if your function is called once per second you end up at your limit of 9.0 after 9 seconds. Sounds quiet slow and this is probably what you want to happen. So if it is faster than that, one answer to the questions must be wrong. Since I doubt that the ++ operator is doing something unexpected here your function must be called more often than expected.
So check your code for the calls to move():
void move(int v)
{
move_right++;
if (move_right >= 9.0f)
{
move_right = 9.0f;
}
drawScene_bug_two(move_right, 10.0f);
glutPostRedisplay();
glutTimerFunc(1000, move, 0); // call to move after a delay of 1 second
}
void drawScene() {
glClear(GL_COLOR_BUFFER_BIT);
bullet();
drawScene_bug_one(-2.0f, 10.0f);
move(0); // call to move
glutTimerFunc(1000, move, 0); // call to move after a delay of 1 second
coll_bug_one();
erase_sprite();
drawScene_ship_one();
glutSwapBuffers();
}
So every time you call drawScene move is called twice. This doubles your increment of your position to 2 per drawScene() call. I guess you are calling drawScene more often than just once. Now your average movement speed per second is: 1 * 2 * numberOfTimesDrawSceneIsCalledPerSecond.
Additionally your move function is calling itself again (delayed) and here lies the major problem! If you were calling move just a single time from outside, your sprites position would be increased by 1 every second. If you would call drawScene just a single time your position would already be increased by 2 every second since you called move twice and every call to move triggers another delayed call. So basically your move function is a “accelerate by 1” function. If you call drawScene multiple times you will accelerate even more.
So the easiest fix would be to remove the calls to move from drawScene and call it only once before entering your main loop.
I think a better and more flexible approach is to use STL chrono lib instead of the glutTimerFunc. Just measure the time that has passed since the last call to move in your drawScene function. If it is more than 1000ms, call move and restart the counter.
well here is my updated code using glutTimerFunc, it pauses for a second and then accelerates to the edge of the screen.[/QUOTE]
Well the problem is probably that drawScene is called more than once per second. So every time you call drawScene you start a new timer that should call move after a second. Lets say drawScene is called 10 times a second. Then nothing will happen for a second because no timer has triggered yet. After the second 10 timers will call move one after each other over the period of the next second. Result is a movement speed of 10 in second number 2. As I said, I think the glutTimerFunc is the wrong tool for your use case.
What you need to do is the following: Write a function which gives you the passed time since your program started as an integer value. You will find a lot of examples in the internet. The funtion interface might look like this:
int GetElapsedTime()
{
// ... some STL chrono magic to return the elapsed time in milliseconds
}
Now before you enter your main loop, declare a variable and initialize it as follows:
int refTime = GetElapsedTime();
Then put the following lines into your drawScene function:
I hope I did not mess anything up but I think you get the intention. You will only call move if the time difference between your refTime and the current time is bigger than one second. Additionally you will now add one second to your refTime so that the condition is only fulfilled after another second has passed. If that works you can also remove the unnecessary parameter from your move function interface.
some STL chrono magic to return the elapsed time in milliseconds
Please do not do this. I know that Chrono seems like magic to a lot of people, but it really isn’t. And if you learn it, you’ll never, ever, have to ask the question, “what units is this time delta in again?”
The first rule of std::chrono is never stop using chrono. That is, if you want to have a function return the current time since the clock’s epoch milliseconds, you do it by returning a tick count in milliseconds:
See how much more readable that is? You never have to guess that GetTime returns milliseconds; it tells you what it returns. Even better, if you want to change GetTime to provide microsecond-accuracy, you can, and all the rest of the code will still work.
int time()
{
using namespace std::chrono;
auto now = high_resolution_clock::now();
auto millis = duration_cast<milliseconds>(now.time_since_epoch()).count();
cout << millis << endl;
return millis;
}
well here is my chrono code, how do I incorporate this into my game code.
Your code is doing that. I’m saying you shouldn’t be doing that. An integer is a typeless quantity. If you see a naked integer somewhere in your code, you have no idea if that’s in seconds, milliseconds, microseconds, etc.
Time durations should always have a unit attached to them.
[QUOTE=Alfonse Reinheart;1292003]Please do not do this. I know that Chrono seems like magic to a lot of people, but it really isn’t. And if you learn it, you’ll never, ever, have to ask the question, “what units is this time delta in again?”
[/QUOTE]
You are right, chrono is no magic, I just wrote this comment, because I was too lazy to google the right source code . Regarding your statements concerning units: I totally get your point and (partially) agree.
The problem here is, that the TO seems to be quiet new to C++/OGL. All the chrono related commands really bloat the code, since they are usually quiet long. So I think it would be easier for the TO to work with data types which he already knows. In my point of view the best solution would be to write a timer class which handles the chrono stuff inside and provides functions to get the elapsed time in some common time units
int GetElapsedSeconds() const;
int GetElapsedMilliseconds() const;
int GetElapsedMicroeconds() const;
Additionally you use a reset function to restart the timer. Using this with the TOs original problem you get something like:
That’s at least how I handle timed events most of the time. Properly named functions ensure that you won’t mess up the units and the class itself hides all the chrono work.
@pbivens: Does it work now as expected? If yes, you should think about the advise of Alfonse (since he has a valid point) and if or how you want to include it. It would make the code a little bit more complicated, but adds another layer of security. I think the best thing would be if you start with object oriented programming and write a timer class. It’s additional work, but it makes your life much easier.
The problem here is, that the TO seems to be quiet new to C++/OGL.
But that’s the perfect time to learn how to do these things right. Would you suggest that a new C++ user avoid std::vector<int> when creating a dynamic array, knowing that they will have to deal with delete[] complexity? Would you suggest a new C++ user avoid std::array<int, 10> and instead use an int var[10];, knowing that they have to deal with the fact that it decays into a pointer, can’t be compared to other arrays, can’t be directly copied, and other C-style array issues?
I would hope not. The standard library has an excellent tool for times that is simple to use and pretty much impossible to break. And the more widely you use that tool, the more powerful and safe your code gets. It may be more verbose in places, but I’m pretty sure that new users can handle that. Don’t underestimate them.
Properly named functions ensure that you won’t mess up the units and the class itself hides all the chrono work.
[QUOTE=Alfonse Reinheart;1292031]But that’s the perfect time to learn how to do these things right. Would you suggest that a new C++ user avoid std::vector<int> when creating a dynamic array, knowing that they will have to deal with delete[] complexity? Would you suggest a new C++ user avoid std::array<int, 10> and instead use an int var[10];, knowing that they have to deal with the fact that it decays into a pointer, can’t be compared to other arrays, can’t be directly copied, and other C-style array issues?
I would hope not. The standard library has an excellent tool for times that is simple to use and pretty much impossible to break. And the more widely you use that tool, the more powerful and safe your code gets. It may be more verbose in places, but I’m pretty sure that new users can handle that. Don’t underestimate them.
Is just a self-documenting. And thanks to auto, you don’t even have to remember the longer name.
This is self-documenting too: timer.GetTime() >= 1000ms. It’s also much shorter.[/QUOTE]
You are probably right. I have never put that much thoughts in using the chrono lib because it wasn’t necessary. I like your suggestions about the GetTime function. I think I will change my own code in favor of this solution. The TO should do this as well.
What do you mean by “resetting” your timer? That is, what do you want to happen? Are you trying to pause the timer or something? Do you want your object to go back to the first position (FYI: that’s not controlled by the timer; it’s controlled by things that read from the timer)?