Last active
July 15, 2023 17:28
-
-
Save Przemekkkth/3a0c9acae9d8824780a7b9b7bb07fbe2 to your computer and use it in GitHub Desktop.
A SFML app which shows an analog clock.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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(¤tTime); | |
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