timebased sleep, 0 FPS issue.

E607ff029c51f19bc6b6b7002dec7023
0
fdmfdm 101 Dec 29, 2012 at 20:00

hi there,
i have been trying to get my game at roughly 60 FPS , a bit more or does not matter, but it was running at 150 FPS, which worked fine for using the frames as time, but i wanted to get a more steady speed, by putting in a sleep function at the end of the frame with as sleeptime 1000/60-elapsed time.
for this i used :

long long milliseconds_now() {
static LARGE_INTEGER s_frequency;
static BOOL s_use_qpc = QueryPerformanceFrequency(&s_frequency);
if (s_use_qpc) {
LARGE_INTEGER now;
QueryPerformanceCounter(&now);
return (1000LL * now.QuadPart) / s_frequency.QuadPart;
} else {
return GetTickCount();
}
}

long long start = milliseconds_now();

long long elapsed = milliseconds_now() - start;
printf (“time: %f\n”, elapsed );
Sleep(((1000/60)-elapsed));

i found this code on the internet, as i could not find a good place to get the codes for getting the elapsed time, and i honestly dont know if there is something wrong with this code or not, but as soon as i put this in i had a issue so now and then of the game running with 0 FMS
i got no errors, and it started, but just did nothing.

can anyone tell me what i did wrong, or point me at a place where i can learn this better?, as i want my game to work with frames as the time, and therefor i need a roughly steady FPS :)
thanks a lot for helping :)

24 Replies

Please log in or register to post a reply.

24b3b99366e625a41cf83bd7f4c085c7
0
jbadams 102 Dec 30, 2012 at 07:11

@fdmfdm

point me at a place where i can learn this better

Try “Fix Your Timestep!

E607ff029c51f19bc6b6b7002dec7023
0
fdmfdm 101 Dec 30, 2012 at 12:08

i tried that one, but they give as ultimate code:

    double t = 0.0;
    const double dt = 0.01;

    double currentTime = hires_time_in_seconds();
    double accumulator = 0.0;

    State previous;
    State current;

    while ( !quit )
    {
         double newTime = time();
         double frameTime = newTime - currentTime;
         if ( frameTime > 0.25 )
              frameTime = 0.25;   // note: max frame time to avoid spiral of death
         currentTime = newTime;

         accumulator += frameTime;

         while ( accumulator >= dt )
         {
              previousState = currentState;
              integrate( currentState, t, dt );
              t += dt;
              accumulator -= dt;
         }

         const double alpha = accumulator / dt;

         State state = currentState*alpha + previousState * ( 1.0 - alpha );

         render( state );
    }

but never explain what is what,
like it uses hires_time_in_seconds , which microsoft visual studio 2010 does not know:

1>c:\myprojects\template\devmaster_intro-to-c-tmpl83.00c_oct14\game.cpp(505): error C3861: ‘hires_time_in_seconds’: identifier not found

same goes with state, time, currentTime, accumulator and dt
now the problem here is that i need to know how long the program took for the last frame, so that i can sleep the rest of the 1/60th second.
i have read that entire tutorial, and altough the text itself is quite easy to follow, but does not explain much about the variables used in it :(

i might have to add (altough i think its quite clear now XD) that im quite new to C++, and altough i followed multiple tutorials, this is the first time im making an entire game with the need of controlling the time

A638aa42130293f319eda7fa4ba121f4
0
fireside 141 Dec 30, 2012 at 17:52

It looks overly complicated to me. I know I did something like this in java. Basically, I got the time right before render, kept it in temp variable for currentTime, but before that, kept another variable for last loop time and put the value in there, subtract and sleep if it’s less than 1/60 th of a second. so it’s something like
lastTime = currentTime;
currentTime = getTime();
sleepTime = 1/60 - (currentTime - lastTime);
if(sleepTime > 0) Sleep(sleepTime);

A8433b04cb41dd57113740b779f61acb
0
Reedbeta 167 Dec 30, 2012 at 17:56

@fdmfdm

but never explain what is what, like it uses hires_time_in_seconds , which microsoft visual studio 2010 does not know

This is pseudocode; it’s not supposed to be copy/pasted. The author is assuming you’re smart enough to adapt the idea of this code to your own project. :) For instance, hires_time_in_seconds() is just a placeholder for however you measure time in your language/API/OS. In your case, you’d write a function that would use QueryPerformanceCounter and convert the result to seconds as a double. (BTW, most advanced articles on programming are like this: you usually cannot just copy/paste others’ code into your own project and expect it to work, because they’ve made different design decisions or called things different names from you. You must adapt their code to your project.)

Anyway, trying to maintain a stable framerate by calculating the remaining time and sleeping is actually not a good approach. The problem is that “sleep” is not a precise operation. The OS will wake up your app at some point later, but you can’t rely on it being at the time you requested - it will be whenever the OS decides to give you another time-slice.

A better approach is to use your graphics API to wait for the next screen vsync. The details depend on what API you’re using, but hopefully there is a way to do this. It will use some internal graphics HW / OS magic to do a better job of syncing your program to 60 Hz (or whatever the screen refresh rate is, but 60 Hz is the most common) than you could likely do by yourself. Then you’d use QueryPerformanceCounter or whatever to measure the time at the start of each frame, subtract from the previous frame’s result to get the time elapsed, and run your game by that amount of time, either using a fixed timestep or not.

E607ff029c51f19bc6b6b7002dec7023
0
fdmfdm 101 Dec 30, 2012 at 20:02

@Reedbeta

This is pseudocode; it’s not supposed to be copy/pasted.

i had figured out that much, but as i dont know the actual codes for it, i did not get much further :)

but more on the topic, i did read something about vsync somewhere, but they said it was a bad idea because it could be turned off?
and you say it depends on what API i use, do you mean there is no standart time-calculator in c++
i know many people use libraries made by others (as i do with the library given with the template of the tutorials im following here made by IGAD), but i expected to be some standard timecalculator, that is not perfect, but given with the normal libraries.

if not, is there a way to find what does what?
the system i use now, which solved the issue of 0FPs, but gives a very rough 60 FPS:

long long milliseconds_now() {
static LARGE_INTEGER s_frequency;
static BOOL s_use_qpc = QueryPerformanceFrequency(&s_frequency);
if (s_use_qpc) {
LARGE_INTEGER now;
QueryPerformanceCounter(&now);
return (1000LL * now.QuadPart) / s_frequency.QuadPart;
} else {
return GetTickCount();
}
}

main()
{
long long start = milliseconds_now();

long long elapsed = milliseconds_now() - start;
if((elapsed>0)&(elapsed<1000/60))
{
Sleep ((1000/60)-elapsed);
}
}

this usually gives about 57, but sometimes goes down under 40, and sometimes gives up to 62, which does proof your point of it not bieing the time i told it :D

1 last thing,
i dont know QueryPerformanceCounter, so i googled it, and i found :

http://msdn.microsoft.com/en-us/library/windows/desktop/ms644904(v=vs.85).aspx

here they gave this piece of code:

BOOL WINAPI QueryPerformanceCounter(
_Out_ LARGE_INTEGER *lpPerformanceCount
);

in which if i understand it right, lpPerformanceCount, is the variable where they put the total counts, but what i was wondering here, is that in seconds(or rather, mseconds? for if it is not in seconds, it is no use to me XD
and the idea here is to use this time to make a Delta time, to get the speed, not matter what the time is?
my question here is, is it needed to sync with vsync if i can me the speed dependent of the ammount of frames/second ?

a quick summary to make sure i am not mistaken:
Dont use sleep to get a fixed framerate, as it is not precise enough.
use vsync to get the framerate (59 in my case (small question here, any idea why my default is 59? always wondered that))
and then i use QueryPerformanceCounter to make sure my games runs at the right speed.

A8433b04cb41dd57113740b779f61acb
0
Reedbeta 167 Dec 30, 2012 at 21:16

BTW, you can use [ code ] … [ /code ] tags around your code to preserve the formatting on the forum.

Yes, a lot of graphics drivers these days have the option to force vsync on or off for an application, regardless of what the application actually asks for. That’s a bit unfortunate, but it’s not such a big deal because your game has to deal with different refresh rates anyway. (If your game is locked to 60 Hz and someone runs it on a monitor that refreshes at 75 Hz, it’s going to look terrible.) Anyway, the way to ask for vsync depends on what graphics API you’re using (Direct3D, OpenGL, etc). There is no standard way to do it in C++, because this doesn’t have anything to do with the language - it has to do with the graphics API.

As for QueryPerformanceCounter, you already have the code to use it; it’s in your milliseconds_now() function (didn’t you notice that?). Obviously if you have the time in milliseconds then you can easily convert to seconds if you need to.

A638aa42130293f319eda7fa4ba121f4
0
fireside 141 Dec 30, 2012 at 21:40

I think it’s usually better to time animation sequences and let the game run as fast as it wants. I don’t notice as much stutter that way. The only time I’ve stopped frames was with a browser app because it needed a pause for other things in the browser to be working. Since I had to have a pause, I used it also as a buffer for when the computer was working harder on a particular loop.

E607ff029c51f19bc6b6b7002dec7023
0
fdmfdm 101 Dec 30, 2012 at 21:48

hehehe nope did not notice that :)
it was yesterday when i tried to figure it out, and forgot it while sleeping :)

but i should be using direct3d if im not mistaken, so ill check the internet for that :)

and fireside, the issue with running it as fast as it wants, is that everything will run faster, unless you adjust the speed according to the framerate.

and thanks for all the help :) this time issue really was the biggest problem i faced so far, because of my lack of knowledge on the subject XD
working on the background and collision detector with the map at the moment, but ill check this timer tomorrow (or if i can this evening/night) to see if i catch any problems :)
thanks again

ps. i’ll do that code thing next time :)

A638aa42130293f319eda7fa4ba121f4
0
fireside 141 Dec 30, 2012 at 22:09

and fireside, the issue with running it as fast as it wants, is that everything will run faster, unless you adjust the speed according to the framerate.

No, because you are adjusting animations and distances using a timer instead of using the framerate as a timer. It sounds complicated, but it really isn’t. Unity uses this method. I think a lot of engines do. You are just taking the time from the last frame and factoring it into animations. It has the added advantage of making animations more asynchronous because you aren’t suddenly stopping everything and then dropping all the frames at that loop, and you aren’t basically punishing people who have fast computers.

B5262118b588a5a420230bfbef4a2cdf
0
Stainless 151 Dec 30, 2012 at 22:21

In general using sleep for timing is very rare these days.

Most platforms now work on a timed event system.

The model is

Setup a timer at the require framerate
Release back to host
Event fires and control passes back to game
Game draws/updates and returns

XNA uses a separate update / draw cycle. The update method is going to be be called at the required frame rate, the draw method might not

Most other systems I work on use call backs. You register a timer callback and set the timer off

You cannot be sure to have a system clock with the required accuracy, hell the granularity on some systems is 100ms so when you query the system timer your max framerate is 10fps

I would look for other techniques, otherwise your code is not portable

E607ff029c51f19bc6b6b7002dec7023
0
fdmfdm 101 Dec 31, 2012 at 00:04

@fireside

No, because you are adjusting animations and distances using a timer instead of using the framerate as a timer. It sounds complicated, but it really isn’t. Unity uses this method. I think a lot of engines do. You are just taking the time from the last frame and factoring it into animations. It has the added advantage of making animations more asynchronous because you aren’t suddenly stopping everything and then dropping all the frames at that loop, and you aren’t basically punishing people who have fast computers.

i actually meant that with adjusting speed according to the framerate :)

btw a small question that is offtopic, but no need to make another topic if someone here can explain this to me,
i have read in the tutorial i was following that a warning of a int going to float or the other way around is bad,
not my physics are working fine as i have them now, so should i worry about these warnings or just take them out by telling the compiler i know its happening?

A638aa42130293f319eda7fa4ba121f4
0
fireside 141 Dec 31, 2012 at 02:09

If you go from float to int, the decimal portion will be dropped, which can be inaccurate. For instance 1.999 would end up being 1 as an int. I prefer to round in that situation. A simple way is to add .5 to it before the conversion. Use a typecast to eliminate the warning. It’s kind of bad form and it pays to eliminate them. If you have more than one, write a function. Take warnings seriously, especially when you are new. It’s a good time to do a little more study and learn a bit more. There may be a rounding function in the standard library, also. I haven’t used c++ in a while.

B5262118b588a5a420230bfbef4a2cdf
0
Stainless 151 Dec 31, 2012 at 10:40

going from float to int sometimes is a requirement.

If you are working on opengles, there is a known issue with aliasing. If you draw a sprite at pixel x = 10.1 it will look different than if you draw it at pixel 10

Use casts to get rid of the warning and think about what you are doing each time.

E607ff029c51f19bc6b6b7002dec7023
0
fdmfdm 101 Dec 31, 2012 at 12:00

im working on directRd and i have seen no problems with aliasing, so at least thats not a issue,
but are you guys saying its best to recheck all the warnings to see if it is really needed to make that conversion, and if it is use a cast (im guessing a cast is like putting (int) before the variable)?
as you can see under here there are quite some warnings,
now the & warnings will be gone in seconds :D, but the others, is this ammount a issue?
(dont worry about the error, just put that in to get the warnings, did not know how to see them otherwise :D)

warnings:

1>c:\myprojects\template\devmaster_intro-to-c-tmpl83.00c_oct14\game.cpp(254): warning C4244: ‘+=’ : conversion from ‘float’ to ‘int’, possible loss of data

1>c:\myprojects\template\devmaster_intro-to-c-tmpl83.00c_oct14\game.cpp(283): warning C4244: ‘+=’ : conversion from ‘float’ to ‘int’, possible loss of data

1>c:\myprojects\template\devmaster_intro-to-c-tmpl83.00c_oct14\game.cpp(285): warning C4554: ‘&’ : check operator precedence for possible error; use parentheses to clarify precedence

1>c:\myprojects\template\devmaster_intro-to-c-tmpl83.00c_oct14\game.cpp(302): warning C4554: ‘&’ : check operator precedence for possible error; use parentheses to clarify precedence

1>c:\myprojects\template\devmaster_intro-to-c-tmpl83.00c_oct14\game.cpp(303): warning C4244: ‘argument’ : conversion from ‘int’ to ‘float’, possible loss of data

1>c:\myprojects\template\devmaster_intro-to-c-tmpl83.00c_oct14\game.cpp(308): warning C4244: ‘=’ : conversion from ‘int’ to ‘float’, possible loss of data

1>c:\myprojects\template\devmaster_intro-to-c-tmpl83.00c_oct14\game.cpp(309): warning C4244: ‘=’ : conversion from ‘int’ to ‘float’, possible loss of data

1>c:\myprojects\template\devmaster_intro-to-c-tmpl83.00c_oct14\game.cpp(312): warning C4244: ‘=’ : conversion from ‘double’ to ‘float’, possible loss of data

1>c:\myprojects\template\devmaster_intro-to-c-tmpl83.00c_oct14\game.cpp(313): warning C4244: ‘=’ : conversion from ‘double’ to ‘float’, possible loss of data

1>c:\myprojects\template\devmaster_intro-to-c-tmpl83.00c_oct14\game.cpp(314): warning C4244: ‘=’ : conversion from ‘double’ to ‘float’, possible loss of data

1>c:\myprojects\template\devmaster_intro-to-c-tmpl83.00c_oct14\game.cpp(315): warning C4244: ‘=’ : conversion from ‘double’ to ‘float’, possible loss of data

1>c:\myprojects\template\devmaster_intro-to-c-tmpl83.00c_oct14\game.cpp(335): warning C4554: ‘&’ : check operator precedence for possible error; use parentheses to clarify precedence

1>c:\myprojects\template\devmaster_intro-to-c-tmpl83.00c_oct14\game.cpp(376): warning C4244: ‘=’ : conversion from ‘float’ to ‘int’, possible loss of data

1>c:\myprojects\template\devmaster_intro-to-c-tmpl83.00c_oct14\game.cpp(377): warning C4244: ‘=’ : conversion from ‘float’ to ‘int’, possible loss of data

1>c:\myprojects\template\devmaster_intro-to-c-tmpl83.00c_oct14\game.cpp(378): warning C4244: ‘=’ : conversion from ‘float’ to ‘int’, possible loss of data

1>c:\myprojects\template\devmaster_intro-to-c-tmpl83.00c_oct14\game.cpp(379): warning C4244: ‘=’ : conversion from ‘float’ to ‘int’, possible loss of data

1>c:\myprojects\template\devmaster_intro-to-c-tmpl83.00c_oct14\game.cpp(457): warning C4244: ‘=’ : conversion from ‘int’ to ‘float’, possible loss of data

1>c:\myprojects\template\devmaster_intro-to-c-tmpl83.00c_oct14\game.cpp(462): warning C4244: ‘argument’ : conversion from ‘int’ to ‘float’, possible loss of data

1>c:\myprojects\template\devmaster_intro-to-c-tmpl83.00c_oct14\game.cpp(462): warning C4244: ‘argument’ : conversion from ‘int’ to ‘float’, possible loss of data

1>c:\myprojects\template\devmaster_intro-to-c-tmpl83.00c_oct14\game.cpp(463): warning C4244: ‘argument’ : conversion from ‘float’ to ‘int’, possible loss of data

1>c:\myprojects\template\devmaster_intro-to-c-tmpl83.00c_oct14\game.cpp(463): warning C4244: ‘argument’ : conversion from ‘float’ to ‘int’, possible loss of data

1>c:\myprojects\template\devmaster_intro-to-c-tmpl83.00c_oct14\game.cpp(473): warning C4244: ‘=’ : conversion from ‘int’ to ‘float’, possible loss of data

1>c:\myprojects\template\devmaster_intro-to-c-tmpl83.00c_oct14\game.cpp(474): warning C4244: ‘=’ : conversion from ‘int’ to ‘float’, possible loss of data

1>c:\myprojects\template\devmaster_intro-to-c-tmpl83.00c_oct14\game.cpp(487): warning C4244: ‘argument’ : conversion from ‘float’ to ‘int’, possible loss of data

1>c:\myprojects\template\devmaster_intro-to-c-tmpl83.00c_oct14\game.cpp(487): warning C4244: ‘argument’ : conversion from ‘float’ to ‘int’, possible loss of data

1>c:\myprojects\template\devmaster_intro-to-c-tmpl83.00c_oct14\game.cpp(508): error C2065: ‘a’ : undeclared identifier

1>c:\myprojects\template\devmaster_intro-to-c-tmpl83.00c_oct14\game.cpp(508): error C2146: syntax error : missing ‘;’ before identifier ‘i’

1>c:\myprojects\template\devmaster_intro-to-c-tmpl83.00c_oct14\game.cpp(518): warning C4244: ‘=’ : conversion from ‘float’ to ‘int’, possible loss of data
under here my code untill this point, still need to clean some things as i was converting from max and min x/y values to tilecollision, so thats not finished yet.

// Template, major revision 3
// IGAD/NHTV - Jacco Bikker - 2006-2009


#include "string.h"
#include "surface.h"
#include "stdlib.h"
#include "template.h"
#include "game.h"



using namespace Tmpl8;

// sprites

Sprite poppetje( new Surface("assets/poppetje.BMP"), 1);
Sprite bullet( new Surface("assets/bullet.BMP"), 1);
Sprite bubble1( new Surface("assets/bubble1.BMP"), 1);


//background
Surface* tileSet[9];
int landTile[11][40] = {{2, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,1},
{6, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6},
{6, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6},
{6, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6},
{6, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6},
{6, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6},
{6, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6},
{6, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6},
{6, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6},
{6, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6},
{3, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,4}};
   int floory = 640;


// player variables
float xplayer = 320;
float yplayer = 200;
float dyplayer;
int xspeed = 3;
int playerheigth = 30;
int playertilex1;
int playertilex2;
int playertiley1;
int playertiley2;
bool left;
bool right;
bool up;
bool down;


// bullet variables
float xbullet[6];
float ybullet[6];
float x1bullet[6];
float y1bullet[6];
float x2bullet[6];
float y2bullet[6];
float dxbullet[6];
float dybullet[6];
float speed = 10;
float steps[6];
int bullet1[6]; // 1 is false 2 is true
int i=0;
bool shot = false;
int shotbreak = 0;
int shoottime = 10;


// bubble variables
int bubble1x[6]; //= 100;
int bubble1y[6]; //= 50;
int drawbubble[6]; //= true;
float bubble1dy[6]; //= 1;
float bubble1ddy[6]; //= 0.1;
float bubble1ddx[6]; //= 0.1;
float bubble1dx[6]; //= 1;
float maxyspeed[6]; //= 12;
float maxxspeed[6];
int bubblecount;
float bubbledist;
int bubbledistcount;
float bubbledistfix;
float bubblefraction;
float bubblexdist;
float bubbleydist;
int bubbleradius[6];
int bubbledoubler[6];

// collision variables
int distance;

//level variables
int deadbubblecount;
int bubblestokill;
int lvl;


// timer variables




long long milliseconds_now() {
    static LARGE_INTEGER s_frequency;
    static BOOL s_use_qpc = QueryPerformanceFrequency(&s_frequency);
    if (s_use_qpc) {
        LARGE_INTEGER now;
        QueryPerformanceCounter(&now);
        return (1000LL * now.QuadPart) / s_frequency.QuadPart;
    } else {
        return GetTickCount();
    }
}





void Game::Init()
{

// background
  tileSet[0] = new Surface( "assets/background1.BMP" );
   tileSet[1] = new Surface( "assets/background2.BMP" );
   tileSet[2] = new Surface( "assets/background3.BMP" );
   tileSet[3] = new Surface( "assets/background4.BMP" );
   tileSet[4] = new Surface( "assets/background5.BMP" );
   tileSet[5] = new Surface( "assets/background6.BMP" );
   tileSet[6] = new Surface( "assets/background7.BMP" );
   tileSet[7] = new Surface( "assets/background8.BMP" );


// bullet inits
bullet1[0]=1;
bullet1[1]=1;
bullet1[2]=1;
bullet1[3]=1;
bullet1[4]=1;
bullet1[5]=1;

// bubbles inits
bubble1x[0]=100; 
bubble1x[1]=200;
bubble1x[2]=300;

bubble1y[0]=50;
bubble1y[1]=50;
bubble1y[2]=50;

drawbubble[0]=2;
drawbubble[1]=2;
drawbubble[2]=2;

bubble1dy[0]=1;
bubble1dy[1]=1;
bubble1dy[2]=1;

bubble1ddy[0]=0.1;
bubble1ddy[1]=0.1;
bubble1ddy[2]=0.1;
bubble1ddy[3]=0.1;
bubble1ddy[4]=0.1;
bubble1ddy[5]=0.1;

bubble1ddx[0]=0.00;
bubble1ddx[1]=0.00;
bubble1ddx[2]=0.00;
bubble1ddx[3]=0.00;
bubble1ddx[4]=0.00;
bubble1ddx[5]=0.00;

bubble1dx[0]=1;
bubble1dx[1]=1;
bubble1dx[2]=1;

maxyspeed[0]=12;
maxyspeed[1]=12;
maxyspeed[2]=12;
maxyspeed[3]=12;
maxyspeed[4]=12;
maxyspeed[5]=12;


bubblestokill = 3;

maxxspeed[0] = 5;
maxxspeed[1] = 5;
maxxspeed[2] = 5;
maxxspeed[3] = 5;
maxxspeed[4] = 5;
maxxspeed[5] = 5;

bubbleradius[0] = 20;
bubbleradius[1] = 20;
bubbleradius[2] = 20;
bubbleradius[3] = 20;
bubbleradius[4] = 20;
bubbleradius[5] = 20;

bubbledoubler[0] = 0;
bubbledoubler[1] = 0;
bubbledoubler[2] = 0;
bubbledoubler[3] = 0;
bubbledoubler[4] = 0;
bubbledoubler[5] = 0;

// lvl inits
lvl = 1;

}
int mousex, mousey;
void Game::MouseMove( unsigned int x, unsigned int y )
{
    mousex = x;
    mousey = y;
}


void Game::Tick( float a_DT )
{

long long start = milliseconds_now();

//background
 m_Screen->Clear( 0 );
   for (int indexX = 0; indexX <= 39; indexX++)
    {
        for (int indexY = 0; indexY <= 10; indexY++)
        {
            int tile = landTile[indexY][indexX];
            tileSet[tile]->CopyTo( m_Screen, indexX * 20, indexY * 60 );
        }
    }

 // bubblecalculator


while (bubblecount<bubblestokill)
{
if(drawbubble[bubblecount]==2)
{
/*
if ((bubble1dy[bubblecount] < 0.01) & (bubble1dy[bubblecount] > -0.01))
{
bubble1dy[bubblecount] = 0;
}
*/



bubble1y[bubblecount] += bubble1dy[bubblecount];
bubble1dy[bubblecount] += bubble1ddy[bubblecount];

// to prevent alls from jumping straight up and down
if ((bubble1dx[bubblecount] < 1) &  (bubble1dx[bubblecount] > 0))
{
bubble1dx[bubblecount] += bubble1ddx[bubblecount];
}
if ((bubble1dx[bubblecount] < 0) &  (bubble1dx[bubblecount] > -1))
{
bubble1dx[bubblecount] -= bubble1ddx[bubblecount];
}

if ((bubble1dy[bubblecount] >maxyspeed[bubblecount]))
{
bubble1dy[bubblecount] = maxyspeed[bubblecount];
}
if ((bubble1dy[bubblecount] <-maxyspeed[bubblecount]))
{
bubble1dy[bubblecount] = -maxyspeed[bubblecount];
}


if (bubble1y[bubblecount] < 20)
{
bubble1y[bubblecount] = 40 - bubble1y[bubblecount];
bubble1dy[bubblecount]= -bubble1dy[bubblecount];
}

bubble1x[bubblecount] += bubble1dx[bubblecount];

if(((bubble1x[bubblecount]> (780 - 2 * bubbleradius[bubblecount]) )& (bubble1dx[bubblecount] > 0))|| ((bubble1x[bubblecount] <20) & bubble1dx[bubblecount] <0))
{
bubble1dx[bubblecount] = -bubble1dx[bubblecount];
}

if (bubble1y[bubblecount] > (floory- 2*bubbleradius[bubblecount]))
{
bubble1y[bubblecount]= floory - 2*bubbleradius[bubblecount];
bubble1dy[bubblecount] = -bubble1dy[bubblecount];
}

bubble1.Draw(bubble1x[bubblecount],bubble1y[bubblecount], m_Screen);
}
while(bubbledistcount<bubblestokill)
{
if (bubbledistcount!=bubblecount)
{
if(drawbubble[bubblecount] == 2 & drawbubble[bubblecount] == 2)
bubbledist = sqrtf((((bubble1x[bubbledistcount]+bubbleradius[bubbledistcount] )-(bubble1x[bubblecount]+bubbleradius[bubblecount]))*(((bubble1x[bubbledistcount]+bubbleradius[bubbledistcount])-(bubble1x[bubblecount]+bubbleradius[bubblecount])))+(((bubble1y[bubbledistcount]+bubbleradius[bubbledistcount])-(bubble1y[bubblecount]+bubbleradius[bubblecount]))*((bubble1y[bubbledistcount]+bubbleradius[bubbledistcount])-(bubble1y[bubblecount]+bubbleradius[bubblecount])))));
if (bubbledist<(bubbleradius[bubblecount]+bubbleradius[bubbledistcount]))
{
bubbledistfix = bubbleradius[bubblecount]+bubbleradius[bubbledistcount]-bubbledist;
bubblefraction = bubbledistfix / bubbledist;
bubblexdist =(bubble1x[bubbledistcount]+bubbleradius[bubbledistcount])-(bubble1x[bubblecount]+bubbleradius[bubblecount]);
bubbleydist =(bubble1y[bubbledistcount]+bubbleradius[bubbledistcount])-(bubble1y[bubblecount]+bubbleradius[bubblecount]);


bubble1dx[bubbledistcount] = bubble1dx[bubbledistcount] + 2.5 * (bubblefraction * bubblexdist * 0.5);
  bubble1dy[bubbledistcount] = bubble1dy[bubbledistcount] + 2.5 * (bubblefraction * bubbleydist * 0.5);
bubble1dx[bubblecount] = -bubble1dx[bubblecount] - (bubblefraction * bubblexdist * -0.5);
bubble1dy[bubblecount] = -bubble1dy[bubblecount] - (bubblefraction * bubbleydist * -0.5);
bubbledoubler[bubblecount]++;

if ((bubble1dy[bubblecount] >maxyspeed[bubblecount]))
{
bubble1dy[bubblecount] = maxyspeed[bubblecount];
}
if ((bubble1dy[bubblecount] <-maxyspeed[bubblecount]))
{
bubble1dy[bubblecount] = -maxyspeed[bubblecount];
}
if ((bubble1dy[bubbledistcount] >maxyspeed[bubblecount]))
{
bubble1dy[bubbledistcount] = maxyspeed[bubblecount];
}
if ((bubble1dy[bubbledistcount] <-maxyspeed[bubblecount]))
{
bubble1dy[bubbledistcount] = -maxyspeed[bubblecount];
}

if(bubbledoubler[bubbledistcount] == 10 & bubblestokill<6)
{

bubble1x[bubblestokill] = bubble1x[bubbledistcount] + 2*bubbleradius[bubbledistcount];
bubble1y[bubblestokill] = bubble1y[bubbledistcount] + 2*bubbleradius[bubbledistcount];
bubble1dx[bubblestokill] = - bubble1dx[bubbledistcount];
bubble1dy[bubblestokill] = bubble1dy[bubbledistcount];
bubble1ddy[bubblestokill] = bubble1ddy[bubbledistcount];
drawbubble[bubblestokill] = 2;
bubblestokill++;
bubbledoubler[bubbledistcount]=0;
}
if(bubble1dx[bubbledistcount]>maxxspeed[bubbledistcount])
{
bubble1dx[bubbledistcount] = maxxspeed[bubbledistcount];
}
if(bubble1dx[bubblecount]>maxxspeed[bubblecount])
{
bubble1dx[bubblecount] = maxxspeed[bubblecount];
}

if(bubble1dx[bubbledistcount]<-maxxspeed[bubbledistcount])
{
bubble1dx[bubbledistcount] = -maxxspeed[bubbledistcount];
}
if(bubble1dx[bubblecount]<-maxxspeed[bubblecount])
{
bubble1dx[bubblecount] = -maxxspeed[bubblecount];
}
}
}
bubbledistcount++;
}
bubbledistcount = 0;
bubblecount++;
}
bubblecount = 0;

// landTile[13][66]


playertilex1 = (xplayer-1)/20;
playertilex2 = (xplayer+20)/20;
playertiley1 = (yplayer/60);
playertiley2 = ((yplayer + 20)/60);
if ((
landTile[playertiley1 ][playertilex1] == 6 || 
landTile[playertiley1 ][playertilex1] == 3) & 
(landTile[playertiley2 ][playertilex1] == 6 || 
landTile[playertiley2 ][playertilex1] == 3)
)
{
left = false;
}
else
{
left = true;
}
if ((
landTile[playertiley1 ][playertilex2] == 6 || 
landTile[playertiley1 ][playertilex2] == 4 )& 
(landTile[playertiley2 ][playertilex2] == 6 || 
landTile[playertiley2 ][playertilex2] == 4)
)
{
right = false;
}
else
{
right = true;
}

if ((
landTile[playertiley2 ][playertilex1] == 5 || 
landTile[playertiley2 ][playertilex1] == 4 ||
landTile[playertiley2 ][playertilex1] == 3) & 
(landTile[playertiley2 ][playertilex2] == 5 || 
landTile[playertiley2 ][playertilex2] == 4 ||
landTile[playertiley2 ][playertilex2] == 3)
)
{
down = false;
}
else
{
down = true;
}





if(GetAsyncKeyState( 0x44 )) // D
{
if (right == true)
{
xplayer=xplayer + xspeed;
}
}
if(GetAsyncKeyState( 0x41 ))  // A
{
if (left == true)
{
xplayer = xplayer - xspeed; 
}
}
if((GetAsyncKeyState( VK_SPACE ))&(down == false))
{
dyplayer = 10;
}
if(dyplayer>0)
{
yplayer -= dyplayer;
dyplayer -= 0.1;
}
if (down == true)
{
yplayer += 5;
}

if(yplayer > (floory - playerheigth))
{
yplayer = (floory - playerheigth);
}



m_Screen->Line( xplayer, yplayer, mousex, mousey, 0xff0000 );
poppetje.Draw(xplayer,yplayer, m_Screen);

// bullet calculator

while(i<6)
{

  if((GetAsyncKeyState( MK_LBUTTON )||(GetAsyncKeyState(  WM_LBUTTONDOWN))) & (bullet1[i]==1) & (shotbreak > shoottime))
{
    bullet1[i] = 2;
x2bullet[i] = mousex;
y2bullet[i] = mousey;
x1bullet[i] = xplayer;
y1bullet[i] = yplayer;
steps[i] = ((sqrtf(((x2bullet[i]-x1bullet[i])*(x2bullet[i]-x1bullet[i]))+((y2bullet[i]-y1bullet[i])*(y2bullet[i]-y1bullet[i]))))/speed);
dxbullet[i]=(x2bullet[i]-x1bullet[i])/steps[i];
dybullet[i]=(y2bullet[i]-y1bullet[i])/steps[i];
xbullet[i] = x1bullet[i];
ybullet[i] = y1bullet[i];
shot = true;
shotbreak=0;
}
   if(bullet1[i] == 2)
{
  bullet.Draw(xbullet[i],ybullet[i], m_Screen);
xbullet[i] += dxbullet[i];
ybullet[i] += dybullet[i];

if (xbullet[i]<0||xbullet[i]>1300||ybullet[i]<0||ybullet[i]>900)
{
bullet1[i]=1;
xbullet[i]=0;
ybullet[i]=0;
}
}
if (shot == false)
{ 
i++;
}
else
{
i = 7;
}
}
a
i=0;
shot = false;
// making sure player wont shoot all bullets at once (+ giving possibilities to different kind of weapons)
shotbreak++;

// hitcalculator
while(i<6)
{
while (bubblecount < bubblestokill)
{
distance = sqrtf(((bubble1x[bubblecount]+bubbleradius[bubblecount])-(xbullet[i]+2))*((bubble1x[bubblecount]+bubbleradius[bubblecount])-(xbullet[i]+2))+((bubble1y[bubblecount]+bubbleradius[bubblecount])-(ybullet[i]+2))*((bubble1y[bubblecount]+bubbleradius[bubblecount])-(ybullet[i]+2)));

if(distance<27)
{


drawbubble[bubblecount] = 1;
xbullet[i] = 0;
ybullet[i] = 0;
bubble1x[bubblecount] = 0;
bubble1y[bubblecount] = 0;
}
bubblecount++;
}
i++;
bubblecount=0;
}


i=0;

deadbubblecount = (drawbubble[0]+drawbubble[1]+drawbubble[2]+drawbubble[3]+drawbubble[4]+drawbubble[5]);
if(deadbubblecount <= bubblestokill)
{

if(lvl == 1)
{

lvl2 ();
}
else if(lvl == 2)
{

lvl3 ();
}

}
if((deadbubblecount==bubblestokill) & (lvl == 3))
{
lvl3 ();
}






long long elapsed = milliseconds_now() - start;
// printf ("time: %f\n", elapsed );
if((elapsed>0)&(elapsed<1000/60))
{
// Sleep ((1000/60)-elapsed);
}


}
A638aa42130293f319eda7fa4ba121f4
0
fireside 141 Dec 31, 2012 at 12:34

I guess it’s up to you. Personally, I don’t like them. If nothing else, you’ll probably miss something more crucial in all that. If they don’t bother you, they are harmless as long as it works the way you want. The way I look at it is that, I haven’t written clear code if I get a warning.

E607ff029c51f19bc6b6b7002dec7023
0
fdmfdm 101 Dec 31, 2012 at 12:44

@fireside

I guess it’s up to you. Personally, I don’t like them. If nothing else, you’ll probably miss something more crucial in all that.

hehehe, gettign rid of them was never the question ;)
it was how :D by a call or by actually changing them.

but you are right, they can be annoying if you have something serious :)

B5262118b588a5a420230bfbef4a2cdf
0
Stainless 151 Dec 31, 2012 at 14:31

Well you should know that 2.5 is a double so if you do something like float x += 2.4; you will get a warning.

It’s good practice to add a ‘f’ to float variables. float x += 2.4f; will not generate a warning.

Then if you do something like int ix = x; that will generate a warning when int ix = (int)x; will not

Compilers are stupid, it’s up to you to prove you are more intelligent than they are by telling them “I wrote the code, I know what I’m doing!”

This is boring I know, but it is important. Some things that come up as warnings really are bugs.

For example

extern void dosomething(int x, int y, int* result);

void me()
{
     int x=10;
     int y=15;
     int z=0;
     dosomething(x,y,z);
}

Will generate a warning, something like “warning converting an int to a pointer without a cast”

Running the code will cause a crash.

E607ff029c51f19bc6b6b7002dec7023
0
fdmfdm 101 Dec 31, 2012 at 15:41

thanks stainless, that was quite a good explaination :)
ill check out all those warnings after i finished my tilecollisiondetector (which is bieing a pain as im trying to make to so that the bubbles bounce off corners realisticly…..)

46407cc1bdfbd2db4f6e8876d74f990a
0
Kenneth_Gorking 101 Dec 31, 2012 at 16:47

Keep in mind that casting a float to int, internally generates a call to ftol, which is quite slow. As for the VSync issue, I watched a Google I/O video yesterday that describes it pretty well, and why it helps: [media]http://www.youtube.com/watch?v=Q8m9sHdyXnE[/media]

E607ff029c51f19bc6b6b7002dec7023
0
fdmfdm 101 Jan 02, 2013 at 14:36

@Kenneth Gorking

Keep in mind that casting a float to int, internally generates a call to ftol, which is quite slow. As for the VSync issue, I watched a Google I/O video yesterday that describes it pretty well, and why it helps:

thanks for the video, ill watch that as soon as i can ( got work atm) but about the casting a float to int, which is slow.
in the tutorial i followed they had 1 part where they zoomed into a image by a float deltax:

[size=3]Surface* img = [/size][size=3]new [/size][size=3]Surface( "assets/aagun.tga" );[/size]
float dx = 2.0f;
void Game::Tick( float a_DT )
{
    Pixel* screen = m_Screen->GetBuffer(), *image = img->GetBuffer();
    for ( int x = 0; x < SCRWIDTH; x++ )
        for ( int y = 0; y < img->GetHeight(); y++ )
        {
            int readxpos = (int)(dx * x);
            Pixel sample = image[readxpos + y * img->GetPitch()];
            screen[x + y * m_Screen->GetPitch()] = sample;
        }

    dx *= 0.999f;
    Sleep( 10 );
}

they later changed that into

Surface* img = new Surface( "assets/aagun.tga" );
int dx = (int)(2.0f * 1024.0f);
void Game::Tick( float a_DT )
{
    Pixel* screen = m_Screen->GetBuffer(), *image = img->GetBuffer();
    for ( int x = 0; x < SCRWIDTH; x++ )
        for ( int y = 0; y < img->GetHeight(); y++ )
        {
            int readxpos = (dx * x) >> 10;
            Pixel sample = image[readxpos + y * img->GetPitch()];
           screen[x + y * m_Screen->GetPitch()] = sample;
        }

    dx = (dx * 999) >> 10;
    Sleep( 10 );
}

and this was indeed quit a bit faster
was this what you meant and would you advise this?
(just to prevent explenation, i understand the concept of this bitshift, and i understand why it is faster, im just asking if it is worth it to change the code to get this, as im making this as an assignment to get into the NHTV “game architecture and design” study (the programming part), and this is the first actual game im making, so i want it to be good, and the second good point is that it would be best to not learn things wrong at the start, to prevent bad habbits :) (like forgetting that damn ; )

B5262118b588a5a420230bfbef4a2cdf
0
Stainless 151 Jan 02, 2013 at 15:31

Well , if someone gave me that code to mark, it wouldn’t score very highly.

There are loads of changes you could make to improve the speed.

If it is worthwhile in a real world application is a completely different question.

For each pixel you are doing two multiplies and two method calls which you can remove easily

     int ipitch =img->GetPitch();
     int spitch=m_Screen->GetPitch();
     int maxs=ipitch*img->GetHeight();
     int rys = ryi = 0;
     while (ryi<maxs)
     {
           int readxpos = (dx*x)>>10;
           screen[rys+x]=image[ryi+readxpos];
           ryi+=ipitch;
           rys+=spitch;
     }

Replacing multiplies with additions is a standard practice from the old days when a multiply was a hell of a lot slower than an addition.
Also moving anything that can be pre-calculated out of an inner loop is good practice.

E607ff029c51f19bc6b6b7002dec7023
0
fdmfdm 101 Jan 02, 2013 at 16:00

stainless im not sure if i follow you here,
i can understand the part of not putting to much in the inner loop, i have actually started with replacing my current max x and maxy system with a tilecollision system(which is a pain because my hight of a tile is not the same as the height of the upper and lower tile (they both have a part black in them) but it is working as far as i am now)

but this part:

For each pixel you are doing two multiplies and two method calls which you can remove easily

are you talking about my background?

m_Screen->Clear( 0 );
   for (int indexX = 0; indexX <= 39; indexX++)
    {
        for (int indexY = 0; indexY <= 10; indexY++)
        {
            int tile = landTile[indexY][indexX];
            tileSet[tile]->CopyTo( m_Screen, indexX * 20, indexY * 60 );
        }
    }

should be something like

m_Screen->Clear( 0 );



while (x < 40)
{
int indexY=0;
while (y<11)
{
int tile = landTile[y][x];
        tileSet[tile]->CopyTo( m_Screen, indexX, indexY);
indexY+=60;
y++;
}
indexX+=20;
x++;
y=0;
}
x=0;
indexX=0;

is that what you mean?

(and i can understand that my coding wont get top grade yet XD)

A638aa42130293f319eda7fa4ba121f4
0
fireside 141 Jan 02, 2013 at 17:34

as im making this as an assignment to get into the NHTV “game architecture and design” study (the programming part)

It looks to me like you may be getting caught up a little too much in details, at least I consider architecture and design to be higher level. I’m just a hobbyist, but what I like to do is write a game so it works, then rewrite it so it’s designed well. Things like this would go last if there was a speed problem, but for me, that never happened. The games were too simple. IMO, if it’s designed well, it’s easy to add variations in game play.

E607ff029c51f19bc6b6b7002dec7023
0
fdmfdm 101 Jan 02, 2013 at 17:58

æwell, actually the name of the course is a bit misleading :)
there are 4 directions to go, and one is programming, which is what im going for, and the assignment is:

Write a small 2D single-player game based on the following theme: ‘Bubbles’. Observe the following requirements:

  • The maximum upload of your zipped (compressed) game is 10Mb (This should include your executable and files required to run your game. To test that you have all the files make sure you try your game on another computer. Also include the files left in your project after you have done a “clean all” to remove all compiled files).
  • The game should be real-time (as opposed to turn-based).
  • The game should be your own work. If you use source-code, tutorials and/or art from others then state this clearly.
  • The game must run on a PC with Windows 7.
  • If your game requires a tool to run it then make sure this tool is available in a free version and make sure the free edition actually runs your code.
  • Graphics are completely irrelevant, unless produced by your code (e.g. a particle effect). Feel free to use third-party art or use simple lines and boxes (again state where everything comes from). The presentation is still relevant.
  • Add a ‘readme.txt’ with instructions on how to start and control your game.

bubble.jpg

Submit your game, the source-code and the read-me in a single zip-file using the file upload system on this assessment website.

which reminds me, does anyone know how to do that clear all on microsoft visual studio 2010? :D
as said before, never done this before :)

and kenneth gorking, that video is amazing, it explains things so beautifully :)and one last thing fireside,
im actually changing my code so that i can change things quite easily, such as making new lvls with different bubblestartingplaces and different sizes bubbles, and a different levellayout :) (like my lvl 2 atm in the code that i have on my computer, not here, gives a small pillar in the enter on which the player can jump (and which prevents the player from just walking from left to right :)