Skip to content

Source: Analog Clock

Anıl Özbek edited this page Nov 6, 2013 · 2 revisions

Analog Clock

This example which use SFML's CircleShape and RectangleShape functions to draw an analog clock is aimed at beginner SFML users.

Analog Clock

////////////////////////////////////////////////////////////
// Headers:
// ctime for getting system time and
// cmath for sin and cos functions
////////////////////////////////////////////////////////////
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <ctime>
#include <cmath>


////////////////////////////////////////////////////////////
/// Entry point of application
///
/// \return Application exit code
///
////////////////////////////////////////////////////////////
int main()
{
    // Define some variables and constants
    const int screenWidth = 800;
    const int screenHeight = 600;
    const float PI = 3.1415927;
    const int clockCircleSize = 250;
    const int clockCircleThickness = 2;
    int x, y;
    float angle = 0.0;

    // Set multisampling level
    sf::ContextSettings settings;
    settings.antialiasingLevel = 8;

    // Create the window of the application
    sf::RenderWindow window(sf::VideoMode(screenWidth, screenHeight), "SFML Analog Clock", sf::Style::Close, settings);

    // Define windowCenter which gets the center of the window here, right after creating window
    sf::Vector2f windowCenter = sf::Vector2f(window.getSize().x / 2.0f, window.getSize().y / 2.0f);

    // Create a list for clock's dots
    sf::CircleShape dot[60];

    // Create dots and place them to very right positions
    for (int i=0; i<60; i++)
    {
        x = (clockCircleSize - 10) * cos(angle);
        y = (clockCircleSize - 10) * sin(angle);

        if (i%5 == 0)
            dot[i] = sf::CircleShape(3);
        else
            dot[i] = sf::CircleShape(1);
        dot[i].setFillColor(sf::Color::Black);
        dot[i].setOrigin(dot[i].getGlobalBounds().width / 2, dot[i].getGlobalBounds().height / 2);
        dot[i].setPosition(x + window.getSize().x / 2, y + window.getSize().y / 2);

        angle = angle + ((2 * PI)/60 );
    }

    // Create outline of the clock
    sf::CircleShape clockCircle(clockCircleSize);

    clockCircle.setPointCount(100);
    clockCircle.setOutlineThickness(clockCircleThickness);
    clockCircle.setOutlineColor(sf::Color::Black);
    clockCircle.setOrigin(clockCircle.getGlobalBounds().width / 2, clockCircle.getGlobalBounds().height / 2);
    clockCircle.setPosition(window.getSize().x / 2 + clockCircleThickness, window.getSize().y / 2 + clockCircleThickness);

    // Crate another circle for center
    sf::CircleShape centerCircle(10);

    centerCircle.setPointCount(100);
    centerCircle.setFillColor(sf::Color::Red);
    centerCircle.setOrigin(centerCircle.getGlobalBounds().width / 2, centerCircle.getGlobalBounds().height / 2);
    centerCircle.setPosition(windowCenter);

    // Create hour, minute, and seconds hands
    sf::RectangleShape hourHand(sf::Vector2f(5, 180));
    sf::RectangleShape minuteHand(sf::Vector2f(3, 240));
    sf::RectangleShape secondsHand(sf::Vector2f(2, 250));

    hourHand.setFillColor(sf::Color::Black);
    minuteHand.setFillColor(sf::Color::Black);
    secondsHand.setFillColor(sf::Color::Red);

    hourHand.setOrigin(hourHand.getGlobalBounds().width / 2, hourHand.getGlobalBounds().height - 25);
    minuteHand.setOrigin(minuteHand.getGlobalBounds().width / 2, minuteHand.getGlobalBounds().height - 25);
    secondsHand.setOrigin(secondsHand.getGlobalBounds().width / 2, secondsHand.getGlobalBounds().height - 25);

    hourHand.setPosition(windowCenter);
    minuteHand.setPosition(windowCenter);
    secondsHand.setPosition(windowCenter);

    // Create sound effect
    sf::Music clockTick;
    if (!clockTick.openFromFile("resources/clock-1.wav"))
        return EXIT_FAILURE;
    clockTick.setLoop(true);
    clockTick.play();

    // Use a part of SFML logo as clock brand
    sf::Texture clockBrand;
    if (!clockBrand.loadFromFile("resources/clock-brand.png"))
    {
        return EXIT_FAILURE;
    }

    sf::Sprite clockBrandSprite;
    clockBrandSprite.setTexture(clockBrand);
    clockBrandSprite.setOrigin(clockBrandSprite.getTextureRect().left + clockBrandSprite.getTextureRect().width/2.0f,
                             clockBrandSprite.getTextureRect().top + clockBrandSprite.getTextureRect().height/2.0f);

    clockBrandSprite.setPosition(window.getSize().x/2, window.getSize().y -100);


    // Create clock background
    sf::Texture clockImage;
    if (!clockImage.loadFromFile("resources/clock-image.png"))
    {
        return EXIT_FAILURE;
    }

    clockCircle.setTexture(&clockImage);
    clockCircle.setTextureRect(sf::IntRect(40, 0, 500, 500));

    while (window.isOpen())
    {
        // Handle events
        sf::Event event;
        while (window.pollEvent(event))
        {
            // Window closed: exit
            if (event.type == sf::Event::Closed)
                window.close();
        }

        // Get system time
        std::time_t currentTime = std::time(NULL);

        struct tm * ptm = localtime(&currentTime);

        hourHand.setRotation(ptm->tm_hour*30 + (ptm->tm_min/2) );
        minuteHand.setRotation(ptm->tm_min*6 + (ptm->tm_sec/12) );
        secondsHand.setRotation(ptm->tm_sec*6);

        // Clear the window
        window.clear(sf::Color::White);

        // Draw all parts of clock
        window.draw(clockCircle);

        for (int i=0; i<60; i++)
        {
            window.draw(dot[i]);
        }

        window.draw(clockBrandSprite);
        window.draw(hourHand);
        window.draw(minuteHand);
        window.draw(secondsHand);
        window.draw(centerCircle);

        // Display things on screen
        window.display();
    }

    return EXIT_SUCCESS;
}

// Used resources:
// SFML logo (Laurent Gomila)    : http://www.sfml-dev.org/download/goodies/
// Clock background (Melih Polat): http://mlhplt.deviantart.com/art/6090-188018260
// Ticking sound (AntumDeluge)   : http://opengameart.org/content/ticking-clock-0

// Some other cool analog clock examples:
// https://github.com/paulhoux/Cinder-Samples/tree/master/AnalogClock
// https://gist.github.com/madc/2984060
// http://qt-project.org/doc/qt-5.0/qtgui/analogclock.html
// http://rosettacode.org/wiki/Draw_a_clock
// http://bobo.vyrobce.cz/index.php?id=34&n=opengl-hodiny
// http://www.codeproject.com/Articles/10627/Yet-Another-Analog-Clock
// http://www.youtube.com/watch?v=gJSZwMCBlU8
Clone this wiki locally