C语言实现绘制可爱的橘子钟表

 更新时间:2022年12月28日 15:29:06   作者:C语言小火车  
这篇文章主要为大家详细介绍了如何利用C语言实现绘制可爱的橘子钟表,文中的示例代码讲解详细,具有一定的学习价值,感兴趣的可以了解一下

简介

这个橘子钟表程序主要分成三个部分:画表盘、画表针、显示当前时间。画表盘部分运用到了三次贝塞尔曲线、HSL 颜色模型以及字符串格式化命令,其中三次贝塞尔曲线确定点的坐标比较复杂。

画表针主要涉及到计算各表针运动的弧度。

显示当前时间所用字体为等宽字体,其作用在于居中后效果更均匀。

程序当中计算三次贝塞尔曲线坐标部分,我定义了 13 个点,其中 0 点和 11 点 12 点重合,3 点和 4 点重合,5 点和 6 点重合,10 点和 9 点重合。这样做的目的是便于确定起始点、控制点和终点。

程序中用到了 Broadway 字体,好像是装 Office 的时候带的字体。如果看不到文字效果,请先安装这个字体。

程序截图

源码

#include <stdio.h>
#include <conio.h>
#include <graphics.h>
#include <math.h>
 
const double PI = 3.141592654;	// 定义圆周率
 
 
// 画表盘
void dial()
{
	// 画蓝色背景
	setbkcolor(0xe6cdb4);		// 设置背景色
	cleardevice();				// 清屏
 
	// 画黄色外圆
	setlinestyle(PS_SOLID, 10);	// 设置线宽为十个像素
	setlinecolor(YELLOW);		// 设置画线颜色为黄色
	setfillcolor(WHITE);		// 设置填充颜色为白色
	fillcircle(0, 0, 170);		// 画圆
 
	// 填充扇形颜色
	int r = 150;				// 定义半径为 150
	setlinestyle(PS_SOLID, 2);	// 设置线宽为两像素
	for (int n = 0; n < 10; n++)
	{
		// 画橘子瓣的三次贝塞尔曲线
		POINT pts[13];				// 定义数组,起始点、控制点 1、控制点 2、终点(起点)、控制点 1、控制点 2、终点(起点)……
		double a = 2 * PI * n / 10;	// 橘子瓣弧度
		pts[0].x = int(r / 8 * cos(a + 2 * PI / 22));
		pts[0].y = int(r / 8 * sin(a + 2 * PI / 22));	pts[12] = pts[11] = pts[0];
		pts[1].x = int(r / 12 * cos(a + 2 * PI / 22));	pts[2].x = int(r / 12 * cos(a - 2 * PI / 22));
		pts[1].y = int(r / 12 * sin(a + 2 * PI / 22));	pts[2].y = int(r / 12 * sin(a - 2 * PI / 22));
		pts[3].x = int(r / 8 * cos(a - 2 * PI / 22));
		pts[3].y = int(r / 8 * sin(a - 2 * PI / 22));	pts[4] = pts[3];
		pts[5].x = int(r * cos(a - 2 * PI / 22));
		pts[5].y = int(r * sin(a - 2 * PI / 22));		pts[6] = pts[5];
		pts[9].x = int(r * cos(a + 2 * PI / 22));
		pts[9].y = int(r * sin(a + 2 * PI / 22));		pts[10] = pts[9];
		pts[7].x = int(r * 1.1 * cos(a - 2 * PI / 30));	pts[8].x = int(r * 1.1 * cos(a + 2 * PI / 30));
		pts[7].y = int(r * 1.1 * sin(a - 2 * PI / 30));	pts[8].y = int(r * 1.1 * sin(a + 2 * PI / 30));
 
		int c = HSLtoRGB(36.0f * n, 0.8f, 0.8f);				// 设置彩虹色
		setlinecolor(c);										// 设置画线颜色为彩虹色
		polybezier(pts, 13);									// 画三次贝塞尔曲线	
 
		setfillcolor(c);										// 设置填充色为彩虹色
		floodfill(int(r / 2 * cos(a)), int(r / 2 * sin(a)), c);	// 填充橘子瓣
	}
 
	// 显示表盘细节
	settextcolor(BLACK);				// 设置字体颜色
	setbkmode(TRANSPARENT);				// 设置背景色为透明
	for (int n = 0; n < 12; n++)
	{
		// 整点刻度
		setfillcolor(BLACK);
		solidcircle(int(145 * cos(n * 2 * PI / 12)), -int(145 * sin(n * 2 * PI / 12)), 2);
		solidcircle(int(145 * cos(n * 2 * PI / 4)),  -int(145 * sin(n * 2 * PI / 4)),  4);
 
		// 显示数字
		wchar_t s[10];
		swprintf_s(s, 10, L"%d", 12 - n);		// int 类型转换成 char 类型
 
		// 设置字体、大小及输出
		if ((12 - n) % 3 == 0)	settextstyle(48, 0, L"Broadway");
		else					settextstyle(24, 0, L"Broadway");
 
		// 定义字符串长和宽,居中
		int w, h;
		w = textwidth(s);
		h = textheight(s);
		outtextxy(int(125 * cos(n * 2 * PI / 12 + PI / 2) - w / 2),
				 -int(125 * sin(n * 2 * PI / 12 + PI / 2) - h / 2),
				  s);
	}
}
 
 
// 显示数字时钟
void digital(int h, int m, int s)
{
	// 画显示当前时间的三个小矩形
	setlinecolor(LIGHTGRAY);	// 设置边框颜色为浅灰色
	setfillcolor(WHITE);		// 设置填充颜色为白色
	fillrectangle(-40 - 13, 50, -40 + 13, 50 + 26);
	fillrectangle(     -13, 50,       13, 50 + 26);
	fillrectangle( 40 - 13, 50,  40 + 13, 50 + 26);
 
	// 显示当前时间
	settextstyle(24, 0, L"Consolas");
	wchar_t a[10];
	int w;
	swprintf_s(a, 10, L"%d", h);	w = textwidth(a);	outtextxy(-40 - w / 2, 50, a);
	swprintf_s(a, 10, L"%d", m);	w = textwidth(a);	outtextxy(     -w / 2, 50, a);
	swprintf_s(a, 10, L"%d", s);	w = textwidth(a);	outtextxy( 40 - w / 2, 50, a);
}
 
 
// 画表针
void needles(int h, int m, int s)
{
	double a = PI / 2 - (2 * PI * h / 12 + 2 * PI * 1 / 12 * m / 60);	// 时针所走弧度
	double b = PI / 2 - (2 * PI * m / 60 + 2 * PI * 1 / 60 * s / 60);	// 分针所走弧度
	double c = PI / 2 - 2 * PI * s / 60;								// 秒针所走弧度
 
	setlinecolor(BLACK);												// 设置画线颜色为黑色
	setlinestyle(PS_SOLID, 9);											// 设置线宽为九像素
	line(0, 0, int(50 * cos(a)), int(-50 * sin(a)));					// 画时针
 
	setlinestyle(PS_SOLID, 6);											// 设置线宽为六像素
	line(0, 0, int(100 * cos(b)), int(-100 * sin(b)));					// 画分针
 
	setlinecolor(RED);													// 设置画线颜色为红色
	setlinestyle(PS_SOLID, 3);											// 设置线宽为三像素
	line(int(20 * cos(c + PI)), -int(20 * sin(c + PI)), int(130 * cos(c)), -int(130 * sin(c)));	// 画秒针
}
 
 
// 主函数
int main()
{
	// 创建绘图窗口
	initgraph(640, 480);
	BeginBatchDraw();		// 开启批量绘图
	setorigin(320, 240);	// 设置原点
 
	while (true)
	{
		// 计算
		SYSTEMTIME ti;		// 定义变量保存当前时间
		GetLocalTime(&ti);	// 获取当前时间
 
		// 绘画
		cleardevice();
		dial();										// 画表盘
		digital(ti.wHour, ti.wMinute, ti.wSecond);	// 画数字时钟
		needles(ti.wHour, ti.wMinute, ti.wSecond);	// 画表针
 
		// 延时
		FlushBatchDraw();
		Sleep(1000);
	}
 
	_getch();
	EndBatchDraw();
	closegraph();
	return 0;
}

到此这篇关于C语言实现绘制可爱的橘子钟表的文章就介绍到这了,更多相关C语言钟表内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 减少C++代码编译时间的简单方法(必看篇)

    减少C++代码编译时间的简单方法(必看篇)

    下面小编就为大家带来一篇减少C++代码编译时间的简单方法(必看篇)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-01-01
  • C++  系统IO流介绍

    C++  系统IO流介绍

    这篇文章主要介绍了C++系统IO流,大部分人都是从输出"Hello World"开始的,本文会介绍C++中的IO细节,需要的朋友可以参考一下,希望对大家有所帮助
    2021-12-12
  • C++类中的static和const用法实例教程

    C++类中的static和const用法实例教程

    这篇文章主要介绍了C++类中的static和const用法,是C++面向对象程序设计中非常重要的概念,需要的朋友可以参考下
    2014-08-08
  • C++ decltype类型说明符

    C++ decltype类型说明符

    在C++中,decltype作为操作符,用于查询表达式的数据类型。decltype在C++11标准制定时引入,主要是为泛型编程而设计,以解决泛型编程中,由于有些类型由模板参数决定,而难以(甚至不可能)表示之的问题。
    2016-03-03
  • C/C++函数调用栈的实现方法

    C/C++函数调用栈的实现方法

    这篇文章主要介绍了C/C++函数调用栈的实现方法,可实现一个简单的脚本解释器,具有一定的参考借鉴价值,需要的朋友可以参考下
    2014-10-10
  • 一文带你了解C++中deque的使用

    一文带你了解C++中deque的使用

    C++中的deque是一种双端队列,可以在队列的前端和后端进行插入元素和删除操作,同时可以视作一个长度不定的数组,支持高效的插入和删除操作。本篇文章将深入探讨C++中的deque的使用,感兴趣的可以了解一下
    2023-05-05
  • C语言进阶栈帧示例详解教程

    C语言进阶栈帧示例详解教程

    这篇文章主要为大家介绍了C语言进阶栈帧的示例详解教程,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-02-02
  • C++使用grpc实现回射服务器

    C++使用grpc实现回射服务器

    gRPC是由Google开发的一个开源的高性能远程过程调用(RPC)框架,用于在分布式系统中实现跨语言的服务通信,本文我们就来看看C++如何使用grpc实现回射服务器
    2024-10-10
  • C语言取模取整的深入理解

    C语言取模取整的深入理解

    本文主要介绍了 C语言取模取整的深入理解,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • C++示例讲解friend static const关键字的用法

    C++示例讲解friend static const关键字的用法

    静态成员static是解决同一个类的不同对象之间数据和函数共享问题。区分全局变量,全局变量也能实现数据共享,但安全性和封装性被破坏了,友元提供了不同类或对象的成员函数之间、类的成员函数与一般函数之间进行数据共享的机制,const常引用-被引用的对象不能被更新
    2022-06-06

最新评论