Explorar el Código

REDESIGNED: example: `shapes_digital_clock`

pull/5179/head
Ray hace 1 mes
padre
commit
a42eb2f79b
Se han modificado 2 ficheros con 174 adiciones y 43 borrados
  1. +174
    -43
      examples/shapes/shapes_digital_clock.c
  2. BIN
      examples/shapes/shapes_digital_clock.png

+ 174
- 43
examples/shapes/shapes_digital_clock.c Ver fichero

@ -11,7 +11,7 @@
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
* Copyright (c) 2025 Hamza RAHAL (@hmz-rhl)
* Copyright (c) 2025 Hamza RAHAL (@hmz-rhl) and Ramon Santamaria (@raysan5)
*
********************************************************************************************/
@ -20,37 +20,40 @@
#include <math.h> // Required for: cosf(), sinf()
#include <time.h> // Required for: time(), localtime()
#define DIGIT_SIZE 30
#define CLOCK_ANALOG 0
#define CLOCK_DIGITAL 1
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
typedef enum {
MODE_NORMAL = 0,
MODE_HANDS_FREE,
} ClockMode;
// Clock hand type
typedef struct {
int value;
Vector2 origin;
float angle;
int length;
int thickness;
Color color;
int value; // Time value
// Visual elements
float angle; // Hand angle
int length; // Hand length
int thickness; // Hand thickness
Color color; // Hand color
} ClockHand;
// Clock hands
typedef struct {
ClockMode mode;
ClockHand second;
ClockHand minute;
ClockHand hour;
ClockHand second; // Clock hand for seconds
ClockHand minute; // Clock hand for minutes
ClockHand hour; // Clock hand for hours
} Clock;
//----------------------------------------------------------------------------------
// Module Functions Declaration
//----------------------------------------------------------------------------------
static void UpdateClock(Clock *clock); // Update clock time
static void DrawClock(Clock clock, Vector2 centerPos); // Draw clock at desired position
static void DrawClockAnalog(Clock clock, Vector2 position); // Draw analog clock at desired center position
static void DrawClockDigital(Clock clock, Vector2 position); // Draw digital clock at desired position
static void DrawDisplayValue(Vector2 position, int value, Color colorOn, Color colorOff);
static void Draw7SDisplay(Vector2 position, char segments, Color colorOn, Color colorOff);
static void DrawDisplaySegment(Vector2 center, int length, int thick, bool vertical, Color color);
//------------------------------------------------------------------------------------
// Program main entry point
@ -62,16 +65,18 @@ int main(void)
const int screenWidth = 800;
const int screenHeight = 450;
SetConfigFlags(FLAG_MSAA_4X_HINT);
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - digital clock");
// Initialize clock
Clock myClock = {
.mode = MODE_NORMAL,
int clockMode = CLOCK_DIGITAL;
// Initialize clock
// NOTE: Includes visual info for anlaog clock
Clock clock = {
.second.angle = 45,
.second.length = 140,
.second.thickness = 3,
.second.color = BEIGE,
.second.color = MAROON,
.minute.angle = 10,
.minute.length = 130,
@ -94,11 +99,12 @@ int main(void)
//----------------------------------------------------------------------------------
if (IsKeyPressed(KEY_SPACE))
{
if (myClock.mode == MODE_HANDS_FREE) myClock.mode = MODE_NORMAL;
else if (myClock.mode == MODE_NORMAL) myClock.mode = MODE_HANDS_FREE;
// Toggle clock mode
if (clockMode == CLOCK_DIGITAL) clockMode = CLOCK_ANALOG;
else if (clockMode == CLOCK_ANALOG) clockMode = CLOCK_DIGITAL;
}
UpdateClock(&myClock);
UpdateClock(&clock); // Update clock required data: value and angle
//----------------------------------------------------------------------------------
// Draw
@ -107,11 +113,21 @@ int main(void)
ClearBackground(RAYWHITE);
DrawCircle(400, 225, 5, BLACK); // Clock center dot
// Draw clock in selected mode
if (clockMode == CLOCK_ANALOG) DrawClockAnalog(clock, (Vector2){ 400, 240 });
else if (clockMode == CLOCK_DIGITAL)
{
DrawClockDigital(clock, (Vector2){ 30, 60 });
DrawClock(myClock, (Vector2){ 400, 225 }); // Clock in selected mode
// Draw clock using default raylib font
// Get pointer to formated clock time string
// WARNING: Pointing to an internal static string that is reused between TextFormat() calls
const char *clockTime = TextFormat("%02i:%02i:%02i", clock.hour.value, clock.minute.value, clock.second.value);
DrawText(clockTime, GetScreenWidth()/2 - MeasureText(clockTime, 150)/2, 300, 150, BLACK);
}
DrawText("Press [SPACE] to switch clock mode", 10, 10, 20, DARKGRAY);
DrawText(TextFormat("Press [SPACE] to switch clock mode: %s",
(clockMode == CLOCK_DIGITAL)? "DIGITAL CLOCK" : "ANALOGUE CLOCK"), 10, 10, 20, DARKGRAY);
EndDrawing();
//----------------------------------------------------------------------------------
@ -154,31 +170,146 @@ static void UpdateClock(Clock *clock)
clock->second.angle -= 90;
}
// Draw clock
static void DrawClock(Clock clock, Vector2 centerPosition)
// Draw analog clock
// Parameter: position, refers to center position
static void DrawClockAnalog(Clock clock, Vector2 position)
{
if (clock.mode == MODE_HANDS_FREE)
{
DrawCircleLinesV(centerPosition, clock.minute.length, LIGHTGRAY);
// Draw clock base
DrawCircleV(position, clock.second.length + 40, LIGHTGRAY);
DrawCircleV(position, 12, GRAY);
DrawText(TextFormat("%i", clock.second.value), centerPosition.x + (clock.second.length - 10)*cosf(clock.second.angle*(float)(PI/180)) - DIGIT_SIZE/2, centerPosition.y + clock.second.length*sinf(clock.second.angle*(float)(PI/180)) - DIGIT_SIZE/2, DIGIT_SIZE, GRAY);
DrawText(TextFormat("%i", clock.minute.value), centerPosition.x + clock.minute.length*cosf(clock.minute.angle*(float)(PI/180)) - DIGIT_SIZE/2, centerPosition.y + clock.minute.length*sinf(clock.minute.angle*(float)(PI/180)) - DIGIT_SIZE/2, DIGIT_SIZE, RED);
// Draw clock minutes/seconds lines
for (int i = 0; i < 60; i++)
{
DrawLineEx((Vector2){ position.x + (clock.second.length + ((i%5)? 10 : 6))*cosf((6.0f*i - 90.0f)*DEG2RAD),
position.y + (clock.second.length + ((i%5)? 10 : 6))*sinf((6.0f*i - 90.0f)*DEG2RAD) },
(Vector2){ position.x + (clock.second.length + 20)*cosf((6.0f*i - 90.0f)*DEG2RAD),
position.y + (clock.second.length + 20)*sinf((6.0f*i - 90.0f)*DEG2RAD) }, ((i%5)? 1.0f : 3.0f), DARKGRAY);
// Draw seconds numbers
//DrawText(TextFormat("%02i", i), centerPosition.x + (clock.second.length + 50)*cosf((6.0f*i - 90.0f)*DEG2RAD) - 10/2,
// centerPosition.y + (clock.second.length + 50)*sinf((6.0f*i - 90.0f)*DEG2RAD) - 10/2, 10, GRAY);
}
DrawText(TextFormat("%i", clock.hour.value), centerPosition.x + clock.hour.length*cosf(clock.hour.angle*(float)(PI/180)) - DIGIT_SIZE/2, centerPosition.y + clock.hour.length*sinf(clock.hour.angle*(float)(PI/180)) - DIGIT_SIZE/2, DIGIT_SIZE, GOLD);
}
else if (clock.mode == MODE_NORMAL)
{
// Draw hand seconds
DrawRectanglePro((Rectangle){ centerPosition.x, centerPosition.y, clock.second.length, clock.second.thickness },
DrawRectanglePro((Rectangle){ position.x, position.y, clock.second.length, clock.second.thickness },
(Vector2){ 0.0f, clock.second.thickness/2.0f }, clock.second.angle, clock.second.color);
// Draw hand minutes
DrawRectanglePro((Rectangle){ centerPosition.x, centerPosition.y, clock.minute.length, clock.minute.thickness },
DrawRectanglePro((Rectangle){ position.x, position.y, clock.minute.length, clock.minute.thickness },
(Vector2){ 0.0f, clock.minute.thickness/2.0f }, clock.minute.angle, clock.minute.color);
// Draw hand hours
DrawRectanglePro((Rectangle){ centerPosition.x, centerPosition.y, clock.hour.length, clock.hour.thickness },
DrawRectanglePro((Rectangle){ position.x, position.y, clock.hour.length, clock.hour.thickness },
(Vector2){ 0.0f, clock.hour.thickness/2.0f }, clock.hour.angle, clock.hour.color);
}
// Draw digital clock
// PARAM: position, refers to top-left corner
static void DrawClockDigital(Clock clock, Vector2 position)
{
// Draw clock using custom 7-segments display (made of shapes)
DrawDisplayValue((Vector2){ position.x, position.y }, clock.hour.value/10, RED, Fade(LIGHTGRAY, 0.3f));
DrawDisplayValue((Vector2){ position.x + 120, position.y }, clock.hour.value%10, RED, Fade(LIGHTGRAY, 0.3f));
DrawCircle(position.x + 240, position.y + 70, 12, (clock.second.value%2)? RED : Fade(LIGHTGRAY, 0.3f));
DrawCircle(position.x + 240, position.y + 150, 12, (clock.second.value%2)? RED : Fade(LIGHTGRAY, 0.3f));
DrawDisplayValue((Vector2){ position.x + 260, position.y }, clock.minute.value/10, RED, Fade(LIGHTGRAY, 0.3f));
DrawDisplayValue((Vector2){ position.x + 380, position.y }, clock.minute.value%10, RED, Fade(LIGHTGRAY, 0.3f));
DrawCircle(position.x + 500, position.y + 70, 12, (clock.second.value%2)? RED : Fade(LIGHTGRAY, 0.3f));
DrawCircle(position.x + 500, position.y + 150, 12, (clock.second.value%2)? RED : Fade(LIGHTGRAY, 0.3f));
DrawDisplayValue((Vector2){ position.x + 520, position.y }, clock.second.value/10, RED, Fade(LIGHTGRAY, 0.3f));
DrawDisplayValue((Vector2){ position.x + 640, position.y }, clock.second.value%10, RED, Fade(LIGHTGRAY, 0.3f));
}
// Draw 7-segment display with value
static void DrawDisplayValue(Vector2 position, int value, Color colorOn, Color colorOff)
{
switch (value)
{
case 0: Draw7SDisplay(position, 0b00111111, colorOn, colorOff); break;
case 1: Draw7SDisplay(position, 0b00000110, colorOn, colorOff); break;
case 2: Draw7SDisplay(position, 0b01011011, colorOn, colorOff); break;
case 3: Draw7SDisplay(position, 0b01001111, colorOn, colorOff); break;
case 4: Draw7SDisplay(position, 0b01100110, colorOn, colorOff); break;
case 5: Draw7SDisplay(position, 0b01101101, colorOn, colorOff); break;
case 6: Draw7SDisplay(position, 0b01111101, colorOn, colorOff); break;
case 7: Draw7SDisplay(position, 0b00000111, colorOn, colorOff); break;
case 8: Draw7SDisplay(position, 0b01111111, colorOn, colorOff); break;
case 9: Draw7SDisplay(position, 0b01101111, colorOn, colorOff); break;
default: break;
}
}
// Draw seven segments display
// Parameter: position, refers to top-left corner of display
// Parameter: segments, defines in binary the segments to be activated
static void Draw7SDisplay(Vector2 position, char segments, Color colorOn, Color colorOff)
{
int segmentLen = 60;
int segmentThick = 20;
float offsetYAdjust = segmentThick*0.3f; // HACK: Adjust gap space between segment limits
// Segment A
DrawDisplaySegment((Vector2){ position.x + segmentThick + segmentLen/2.0f, position.y + segmentThick },
segmentLen, segmentThick, false, (segments & 0b00000001)? colorOn : colorOff);
// Segment B
DrawDisplaySegment((Vector2){ position.x + segmentThick + segmentLen + segmentThick/2.0f, position.y + 2*segmentThick + segmentLen/2.0f - offsetYAdjust },
segmentLen, segmentThick, true, (segments & 0b00000010)? colorOn : colorOff);
// Segment C
DrawDisplaySegment((Vector2){ position.x + segmentThick + segmentLen + segmentThick/2.0f, position.y + 4*segmentThick + segmentLen + segmentLen/2.0f - 3*offsetYAdjust },
segmentLen, segmentThick, true, (segments & 0b00000100)? colorOn : colorOff);
// Segment D
DrawDisplaySegment((Vector2){ position.x + segmentThick + segmentLen/2.0f, position.y + 5*segmentThick + 2*segmentLen - 4*offsetYAdjust },
segmentLen, segmentThick, false, (segments & 0b00001000)? colorOn : colorOff);
// Segment E
DrawDisplaySegment((Vector2){ position.x + segmentThick/2.0f, position.y + 4*segmentThick + segmentLen + segmentLen/2.0f - 3*offsetYAdjust },
segmentLen, segmentThick, true, (segments & 0b00010000)? colorOn : colorOff);
// Segment F
DrawDisplaySegment((Vector2){ position.x + segmentThick/2.0f, position.y + 2*segmentThick + segmentLen/2.0f - offsetYAdjust },
segmentLen, segmentThick, true, (segments & 0b00100000)? colorOn : colorOff);
// Segment G
DrawDisplaySegment((Vector2){ position.x + segmentThick + segmentLen/2.0f, position.y + 3*segmentThick + segmentLen - 2*offsetYAdjust },
segmentLen, segmentThick, false, (segments & 0b01000000)? colorOn : colorOff);
}
// Draw one 7-segment display segment, horizontal or vertical
static void DrawDisplaySegment(Vector2 center, int length, int thick, bool vertical, Color color)
{
if (!vertical)
{
// Horizontal segment points
// 3___________________________5
// / \
// /1 x 6\
// \ /
// \2___________________________4/
Vector2 segmentPointsH[6] = {
(Vector2){ center.x - length/2.0f - thick/2.0f, center.y }, // Point 1
(Vector2){ center.x - length/2.0f, center.y + thick/2.0f }, // Point 2
(Vector2){ center.x - length/2.0f, center.y - thick/2.0f }, // Point 3
(Vector2){ center.x + length/2.0f, center.y + thick/2.0f }, // Point 4
(Vector2){ center.x + length/2.0f, center.y - thick/2.0f }, // Point 5
(Vector2){ center.x + length/2.0f + thick/2.0f, center.y }, // Point 6
};
DrawTriangleStrip(segmentPointsH, 6, color);
}
else
{
// Vertical segment points
Vector2 segmentPointsV[6] = {
(Vector2){ center.x, center.y - length/2.0f - thick/2.0f }, // Point 1
(Vector2){ center.x - thick/2.0f, center.y - length/2.0f }, // Point 2
(Vector2){ center.x + thick/2.0f, center.y - length/2.0f }, // Point 3
(Vector2){ center.x - thick/2.0f, center.y + length/2.0f }, // Point 4
(Vector2){ center.x + thick/2.0f, center.y + length/2.0f }, // Point 5
(Vector2){ center.x, center.y + length/2 + thick/2.0f }, // Point 6
};
DrawTriangleStrip(segmentPointsV, 6, color);
}
}

BIN
examples/shapes/shapes_digital_clock.png Ver fichero

Antes Después
Anchura: 794  |  Altura: 445  |  Tamaño: 3.6 KiB Anchura: 800  |  Altura: 450  |  Tamaño: 18 KiB

Cargando…
Cancelar
Guardar