Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: sf::clock not working (or maybe I am being stupid)  (Read 5338 times)

0 Members and 1 Guest are viewing this topic.

TG HellHound

  • Newbie
  • *
  • Posts: 4
    • View Profile
    • Email
sf::clock not working (or maybe I am being stupid)
« on: August 16, 2012, 05:40:44 pm »
Ok so I am creating a Space Invaders clone and I need to have a sprite that changes between two images. To do this I am using the Clock.GetElapsedTime function to switch to the second image once it hits a certain time, this however is just not working. Could someone maybe point out where I am going wrong, as this code looks fine to me:
sf::Clock clock;
                float ElapsedTime = clock.GetElapsedTime();


                if (Window.IsOpened())  Invader1Sprite.Move(-50 * 0.0005,0 );
               
                if (ElapsedTime >= 3.0) Invader1Sprite.SetImage(Invader2);
       

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11032
    • View Profile
    • development blog
    • Email
Re: sf::clock not working (or maybe I am being stupid)
« Reply #1 on: August 16, 2012, 05:47:30 pm »
If this is your actual code then there's a lot of things wrong with it...
If you've stripped it down just to a few calls, then we can't really help you since the whole thing is not put into the context.

In which scenario should your game be running when the window is not open? The if(Window.IsOpened()) doesn't make any sense if you complete code follows the suggested way with the use of a while(Window.IsOpened()).
If you have the decleration of the clock next to the time request you'll create a new clock object each iteration and the elapsedtime between creation and request will be just a few milli or micro seconds.
The precision of floats isn't that high so multiplying with 0.0005 isn't really adviced the whole calculation should be more something like speed*detlaTime.
I very strongly advice you to use SFML 2, since it's in probably all direction better and less buggy than SFML 1.6.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

TG HellHound

  • Newbie
  • *
  • Posts: 4
    • View Profile
    • Email
Re: sf::clock not working (or maybe I am being stupid)
« Reply #2 on: August 16, 2012, 05:56:09 pm »
The if(Window.IsOpened()) is just there to start the sprite moving without requiring any input. Could you elaborate on what you mean by

If you have the decleration of the clock next to the time request you'll create a new clock object each iteration and the elapsedtime between creation and request will be just a few milli or micro seconds.

And here is all of my code to give you context:

#include <SFML\Graphics.hpp>
#include <iostream>

int main()

{

        sf::VideoMode Vmode(800, 600, 32);
        sf::RenderWindow Window(Vmode, "Invaders");


        sf::Image Invader1;
        if (!Invader1.LoadFromFile("Invader1.png"))
                return 1;

        sf::Sprite Invader1Sprite;
        Invader1Sprite.SetImage(Invader1);
        Invader1Sprite.Move(100,0);
        Invader1Sprite.SetPosition(600,0);

        sf::Image Invader2;
        if (!Invader2.LoadFromFile("Invader2.png"))
                return 1;

       
       
       
        while(Window.IsOpened())
        {
               
               
                sf::Event Event;
                while (Window.GetEvent(Event))
                {

                        switch (Event.Type)

                        {
                        case sf::Event::Closed: Window.Close(); break;
                        default: break;
                        }
                }
                Window.Clear(sf::Color(0, 0, 0));
                Window.Draw(Invader1Sprite);

       
                Window.Display();
                sf::Clock clock;
                float ElapsedTime = clock.GetElapsedTime();

// Move the sprite
                if (Window.IsOpened())  Invader1Sprite.Move(-50 * 0.0005,0 );
               
                if (ElapsedTime >= 3.0) Invader1Sprite.SetImage(Invader2);
       
               
        }

        return 0;
}

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11032
    • View Profile
    • development blog
    • Email
Re: sf::clock not working (or maybe I am being stupid)
« Reply #3 on: August 16, 2012, 06:09:06 pm »
The if(Window.IsOpened()) is just there to start the sprite moving without requiring any input.
The sprite will also move without the if statement... ::)

Could you elaborate on what you mean by
If you have the decleration of the clock next to the time request you'll create a new clock object each iteration and the elapsedtime between creation and request will be just a few milli or micro seconds.
Next to the following explenation it also means that you should go again back to a C++ book and learn a bit more about the language... ;)

A variable or class instance is kept alive only within a specific scope, this can either be the global scope or the local scope. A scope can be created easily with the { }-brackets and everything you declare inside or instanciate inside won't be accessable outside and will be destroyed at the end of the scope (= }).
{
    int a = 0;
}
std::cout << a std::endl;
That code will give you an error because a does not exist in the scope outside of the curlybrackets.

The same is true for a if, for loop or while loop:
while(window.isOpen())
{
    sf::Clock clock;
}
Every iteration you'll end up at the closing curlybracket and the clock instance will be deleted. Thus in the next itereation a new clock object will be created and initialized with 0.

As I already said before the time distance between one and the other call is mostly just a few microseconds, thus the following code will always print out a number smaller than one second.
while(window.isOpen())
{
    sf::Clock clock;
    float dt = clock.getElapsedTime().asSeconds();
    std::cout << dt << "s" << std::endl;
}

The solution is the declare the clock outside of the loop and reset it every itereation.
sf::Clock clock;
while(window.isOpen())
{
    float dt = clock.restart().asSeconds();
    std::cout << dt << "s" << std::endl;
}
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

TG HellHound

  • Newbie
  • *
  • Posts: 4
    • View Profile
    • Email
Re: sf::clock not working (or maybe I am being stupid)
« Reply #4 on: August 16, 2012, 06:24:20 pm »
/facepalm Yep I just moved the sf::Clock clock out of the while(Window.IsOpened()) loop and it worked just as I wanted it to. Cheers for your help exploiter, many thanks :D

TG HellHound

  • Newbie
  • *
  • Posts: 4
    • View Profile
    • Email
Re: sf::clock not working (or maybe I am being stupid)
« Reply #5 on: August 16, 2012, 11:33:24 pm »
I have got stuck again, yes I am a total noob at this. So basically I want to have 2 loops going off one will be the loop for when my invader is moving left the other when it is moving right. Now my idea was that on the moving down part of each loop ie when the invader hits the side of the screen and moves down I would simply change a bool from being false to true and it would go onto the next loop, then that one at its down bit would change it back. Its not having it, the 2 errors I am getting while playing around with different things is either the sprite will go down and then continue moving the same way, ie not breaking out the loop when the bool changes, or if I force the loop to end with a break my program terminates.

Could you guys help me out again please:

while (movementloop = true){
                bool x ;
       
                if ( x = true)Invader1Sprite.Move(-2 * 0.05,0 );
                if ( x = false)Invader1Sprite.Move(-2 * 0.05, 0);
                float ElapsedTime = clock.GetElapsedTime();
                float ElapsedTime2 = clock2.GetElapsedTime();
             if (ElapsedTime >= 2.0){Invader1Sprite.SetImage(Invader2);}
                 if (ElapsedTime >= 4.0){Invader1Sprite.SetImage(Invader1); clock.Reset();}
                 if (ElapsedTime2 >= 10 ){Invader1Sprite.Move(0, 1 * 0.05); Invader1Sprite.Move(+2 * 0.05, 0);}
                 if (ElapsedTime2 >= 11){ clock2.Reset();movementloop = false; break;}
                 Window.Clear(sf::Color(0, 0, 0));
                Window.Draw(Invader1Sprite);
                Window.Display();}
               
                while (movementloop2=false){
                        bool x ;
                        if ( x = true)Invader1Sprite.Move(-2 * 0.05,0 );
                if ( x = false)Invader1Sprite.Move(2 * 0.05, 0);
                float ElapsedTime = clock.GetElapsedTime();
                float ElapsedTime2 = clock2.GetElapsedTime();
               
             if (ElapsedTime >= 2.0){Invader1Sprite.SetImage(Invader2);}
                 if (ElapsedTime >= 4.0){Invader1Sprite.SetImage(Invader1); clock.Reset();}
                 if (ElapsedTime2 >= 10 ){x=false;Invader1Sprite.Move(0, 1 * 0.05); Invader1Sprite.Move(+2 * 0.05, 0);}
                 if (ElapsedTime2 >= 11){ clock2.Reset();}
                 Window.Clear(sf::Color(0, 0, 0));
                Window.Draw(Invader1Sprite);
                Window.Display();
                movementloop = true;
                }
                }

Disregard all the random X's and things, I have been trying out a lot of different stuff.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11032
    • View Profile
    • development blog
    • Email
Re: sf::clock not working (or maybe I am being stupid)
« Reply #6 on: August 17, 2012, 12:19:46 am »
Next to the following explenation it also means that you should go again back to a C++ book and learn a bit more about the language... ;)

Having two drawing loops is completly wrong and won't work at all...
Your code should be structured like in this example.
Writing things in one line isn't a good practice because it breaks the reading flow and it will be harder to debug, since you can put breakpoints only on lines and not on statements/fuctions calls...
Additionally I don't see a sense in having two ElapsedTime, when both get caught at (nearly) the same time.
I suggest you take out a piece of paper and sketch out what you exactly want and what should happen when, then you could draw a flow-chart with the logic and then you can implement it. Implementation should mostly be the easy part, where as getting/understanding the logic behind it is the hard one.

Also I galdly point you again to the SFML 2.0rc release. ;)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

natchos

  • Jr. Member
  • **
  • Posts: 97
    • View Profile
    • Email
Re: sf::clock not working (or maybe I am being stupid)
« Reply #7 on: August 17, 2012, 12:22:46 am »
Shouldn't it be movementloop == true? movementloop = true would mean that you set movementloop to true, I believe, same with movementloop2 = true should be movemementloop2 == true.

Also why are you using movementloop and movementloop2?

Wouldn't it be easier to do it like this

while (movementloop == true
{
 //do somethingelse
}

while (movementloop == false)
{
 // do something else
}
 

Also I would recommend altering the calling of movementloop = true; to something like this

if (Invader1Sprite.GetPosition > SCREENEDGE) movementloop = true

this would make sure that movementloop would only be switched to true when the Invader reaches the screenborder (you would have to define SCREENEDGE first of course)
Do the same in both loops and it should work.

... Also, listen to eXpl0iter

 

anything