Skip to content

Instantly share code, notes, and snippets.

@Przemekkkth
Last active July 15, 2023 17:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Przemekkkth/3a0c9acae9d8824780a7b9b7bb07fbe2 to your computer and use it in GitHub Desktop.
Save Przemekkkth/3a0c9acae9d8824780a7b9b7bb07fbe2 to your computer and use it in GitHub Desktop.
A SFML app which shows an analog clock.
#include <SFML/Graphics.hpp>
#include <algorithm>
#include <cmath>
#include <iostream>
#include <chrono>
#include <ctime>
static float DEG_TO_RAD(float degrees)
{
return degrees * (M_PI / 180);
}
class AnalogClock
{
public:
AnalogClock(int w, int h) : WIDTH(w), HEIGHT(h), H_WIDTH(WIDTH/2), H_HEIGHT(HEIGHT/2), RADIUS(H_HEIGHT - 50)
{
m_radiusMap["sec"] = RADIUS - 10;
m_radiusMap["min"] = RADIUS - 55;
m_radiusMap["hour"] = RADIUS - 100;
m_radiusMap["digit"] = RADIUS - 30;
for(int i = 0; i < 60; ++i)
{
m_clock60[i] = i*6;
}
}
const int width() const { return WIDTH; }
const int height() const { return HEIGHT; }
const int h_width() const { return H_WIDTH; }
const int h_height() const { return H_HEIGHT;}
sf::Vector2f getClockPos(int clock_hand, std::string key) {
if(m_radiusMap.find(key) == m_radiusMap.end())
{
std::cout << "Key " << key << " not found." << std::endl;
exit(EXIT_FAILURE);
}
float x = H_WIDTH + m_radiusMap[key] * std::cos(DEG_TO_RAD(m_clock60[clock_hand]) - M_PI_2);
float y = H_HEIGHT + m_radiusMap[key] * std::sin(DEG_TO_RAD(m_clock60[clock_hand]) - M_PI_2);
return sf::Vector2f(x,y);
}
void drawFace(sf::RenderWindow& window)
{
for (const auto& pair : m_clock60) {
int digit = pair.first;
int radius = 0;
if (digit % 3 == 0 && digit % 5 == 0) {
radius = 20;
} else if (digit % 5 == 0) {
radius = 8;
} else {
radius = 2;
}
sf::CircleShape circle(radius);
circle.setFillColor(sf::Color::Transparent);
if(radius == 2)
{
circle.setFillColor(sf::Color::White);
}
circle.setOrigin(circle.getGlobalBounds().width/2.0f, circle.getGlobalBounds().height/2.0f);
circle.setOutlineColor(sf::Color::White);
circle.setOutlineThickness(10.0f);
float x = getClockPos(digit, "digit").x;
float y = getClockPos(digit, "digit").y;
circle.setPosition(x, y);
window.draw(circle);
}
}
void drawClock(sf::RenderWindow& window)
{
sf::Vertex hourLine[] =
{
sf::Vertex(sf::Vector2f(H_WIDTH, H_HEIGHT), sf::Color::Red),
sf::Vertex(sf::Vector2f(getClockPos(m_hour, "hour").x, getClockPos(m_hour, "hour").y) , sf::Color::Red)
};
window.draw(hourLine, 2, sf::Lines);
sf::Vertex minuteLine[] =
{
sf::Vertex(sf::Vector2f(H_WIDTH, H_HEIGHT), sf::Color::Green),
sf::Vertex(sf::Vector2f(getClockPos(m_minute, "min").x, getClockPos(m_minute, "min").y) , sf::Color::Green)
};
window.draw(minuteLine, 2, sf::Lines);
sf::Vertex secondLine[] =
{
sf::Vertex(sf::Vector2f(H_WIDTH, H_HEIGHT), sf::Color::Blue),
sf::Vertex(sf::Vector2f(getClockPos(m_second, "sec").x, getClockPos(m_second, "sec").y) , sf::Color::Blue)
};
window.draw(secondLine, 2, sf::Lines);
sf::CircleShape circle(8.0f);
circle.setOrigin(4.0f, 4.0f);
circle.setFillColor(sf::Color::White);
circle.setPosition(H_WIDTH, H_HEIGHT);
window.draw(circle);
}
void drawText(sf::RenderWindow& window)
{
sf::Text text;
sf::Font font;
//You should set valid font to see actual time.
font.loadFromFile("sansation.ttf");
text.setFont(font); // font is a sf::Font
text.setString(getActualTime());
//You can downsize text size
text.setCharacterSize(150); // in pixels, not points!
text.setFillColor(sf::Color::Red);
text.setStyle(sf::Text::Bold);
text.setPosition(0, 0);
window.draw(text);
}
std::string getActualTime(){
std::time_t currentTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
std::tm* timeInfo = std::localtime(&currentTime);
int hours = timeInfo->tm_hour;
std::string hourStr = hours < 10 ? "0"+std::to_string(hours) : std::to_string(hours);
int minutes = timeInfo->tm_min;
std::string minuteStr = minutes < 10 ? "0"+std::to_string(minutes) : std::to_string(minutes);
int seconds = timeInfo->tm_sec;
std::string secundStr = seconds < 10 ? "0"+std::to_string(seconds) : std::to_string(seconds);
std::string retVal = hourStr + ":" + minuteStr + ":" + secundStr;
m_hour = ( (hours%12) * 5+ int(minutes/12) ) % 60;
m_minute = minutes;
m_second = seconds;
return retVal;
}
private:
const int WIDTH;
const int HEIGHT;
const int H_WIDTH;
const int H_HEIGHT;
const int RADIUS;
std::map<std::string, int> m_radiusMap;
std::map<int, int> m_clock60;
int m_hour, m_minute, m_second;
};
int main()
{
//You can downsize resolution. It is quite big 2400x1600.
AnalogClock analogClock(2400, 1600);
const unsigned int FPS = 10; //The desired FPS. (The number of updates each second).
sf::RenderWindow window(sf::VideoMode(analogClock.width(), analogClock.height()), "Analog Clock SFML C++");
window.setFramerateLimit(FPS);
sf::Event ev;
while (window.isOpen())
{
//Handle events
while (window.pollEvent(ev))
{
if (ev.type == sf::Event::Closed)
window.close();
}
// Draw stuff
window.clear();
analogClock.drawFace(window);
analogClock.drawClock(window);
analogClock.drawText(window);
window.display();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment