橘子钟表 铜牌收录

程序简介

这个橘子钟表程序主要分成三个部分:画表盘、画表针、显示当前时间。画表盘部分运用到了三次贝塞尔曲线、HSL 颜色模型以及字符串格式化命令,其中三次贝塞尔曲线确定点的坐标比较复杂。画表针主要涉及到计算各表针运动的弧度。显示当前时间所用字体为等宽字体,其作用在于居中后效果更均匀。

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

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

程序截图

程序源码

/////////////////////////////////////////////////////////
// 程序名称:橘子钟表
// 编译环境:Visual C++ 2010,Unicode 字符集,EasyX_20220610
// 作  者:陈附议 <2968001745@qq.com>
// 发布日期:2021-7-25
// 最后修改:2021-7-25
//
#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;
}

评论 (5) -

  • polybezier(pts, 13);没有定义标识符啊,这个是什么函数,怎么程序找不到呢?
  • 这个用到的字体可以去哪里找呢
  • 为什么复制源码,他显示出来的表盘数字是整体向下的?
    • outtextxy(125 * cos(n * 2 * PI / 12 + PI / 2) - w / 2,
        -(125 * sin(n * 2 * PI / 12 + PI / 2)) - h / 2,
        s);
    • // 定义字符串长和宽,居中 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); 此处代码有误,括号的位置有误。应改成 outtextxy((int)(125 * cos(n * 2 * PI / 12 + PI / 2) - w / 2), -(int)(125 * sin(n * 2 * PI / 12 + PI / 2)) - h / 2, s);&nbsp;

添加评论