EGE——罗盘时钟

罗盘时钟

完美复刻抖音上的罗盘时钟。~~~

#include <stdio.h>
#include <graphics.h>
#include <math.h>
#include <time.h>
#include <string.h>
#define windwidth 640				//窗口宽度
#define windhigh  480				//窗口高度
#define pai 3.1415926				//定义π的值	
#define MAXSIZE 10					//定义文字长度
#define MAXNUM 60					//定义分钟和秒的数组最大长度

/*此处用sin函数实现初始化时分秒表盘的变速展开,y=sin(0到180),
  y值的和为展开的速度;也可以用抛物线方程实现*/
#define Ch 1.909084					//每45度sin值的和与15度的比值,用于实现时针变速展开;360/24=15
#define Cm 3.180190					//每30度sin值的和与6度的比值,用于实现分针变速展开;360/60=6
#define Cs 2.117701					//每20度sin值的和与6度的比值,用于实现秒针的变速展开;
#define eps 1e-8					//定义浮点数比较精度,用于比较两个浮点数是否相等
#define Equ(a,b) fabs((a)-(b))<(eps)//定义判断浮点数是否相等的宏
typedef struct _node{				//声明表盘结构体
	char time[MAXSIZE];				//存放需要输出汉字时间的字符串
	double x;						//输出汉字时间的水平位置
	double y;						//输出汉字时间的垂直位置
	double angle;					//当下时间的角度,x轴正方向为0(或者为360),顺时针递增
	int c;							//输出位置距离原点的距离
}Node;

Node sec[MAXNUM];					//定义秒针数组
Node min[MAXNUM];					//定义分针数组
Node hou[MAXNUM];					//定义时针数组
/*该函数返回180度内sin值的和与S的比值,参数S为需要旋转的角度,用于实现变速旋转*/
double C_sin(double S){				
	double f=0,sum=0;
	for(int i=0;i<=20;i++){			//20控制旋转速度
		f=sin(pai/180*i*9);
		sum+=f;
	}
	return sum/S;
}
/*初始化表盘结构体*/
void init_time(){
	char num[][MAXSIZE]={"零","一","二","三","四","五","六","七","八","九","十","十一","十二",\
		"十三","十四","十五","十六","十七","十八","十九","二十","二十一","二十二","二十三",\
		"二十四","二十五","二十六","二十七","二十八","二十九","三十","三十一","三十二","三十三",\
		"三十四","三十五","三十六","三十七","三十八","三十九","四十","四十一","四十二","四十三","四十四",\
		"四十五","四十六","四十七","四十八","四十九","五十","五十一","五十二","五十三","五十四","五十五",\
		"五十六","五十七","五十八","五十九"};
	for(int i=0;i<MAXNUM;i++){
		strcpy(sec[i].time,num[i]);
		strcat(sec[i].time,"秒");
		sec[i].c=windhigh/2+40;
		sec[i].x=windhigh/2+40+windwidth/2;
		sec[i].y=windhigh/2;
		sec[i].angle=360;
		
		strcpy(min[i].time,num[i]);
		strcat(min[i].time,"分");
		min[i].c=windhigh/2-40;
		min[i].x=windhigh/2-40+windwidth/2;
		min[i].y=windhigh/2;
		min[i].angle=360;
		
		if(i<24){
			strcpy(hou[i].time,num[i]);
			strcat(hou[i].time,"时");
			hou[i].c=windhigh/2-120;
			hou[i].x=windhigh/2-120+windwidth/2;
			hou[i].y=windhigh/2;
			hou[i].angle=360;
		}
	}
}
/*初始化表盘位置,实现展开过程*/
void init_hand(int cnt){				//cnt为调用此函数的次数
	static double h=0,m=0,s=0;			//定义静态变量,h、m、s分别控制时分秒表盘展开速度
	if(cnt<=45){						//调用45次,时针展开完成,45次从0-180.每次变化4度
		h+=sin(pai/180*cnt*4);			//实现h值的变速增加,最终h/Ch=15,为两个相邻小时的间隔度数
		for(int i=0;i<MAXNUM-1;i++){	//从0时到23时,间隔逐渐增加至15.
			hou[i+1].angle=hou[i].angle-h/Ch;
		}
	}
	
	if(cnt>=30&&cnt<=60){				//调用30次,分针展开完成,30次从0-180,每次变化6度
		m+=sin(pai/180*(cnt-30)*6);		//实现m值的变速增加,最终m/Cm=6,为两个相邻分钟的间隔度数
		for(int i=1;i<MAXNUM;i++){		//从0分到59分,间隔逐渐增加至6。
			min[i].angle=min[i-1].angle-m/Cm;
		}
	}
	if(cnt>=50&&cnt<=70){				//调用20次,秒针展开完成,20次从0-180,每次变化9度
		s+=sin(pai/180*(cnt-50)*9);		//实现s值的变速增加,最终s/Cs=6,为两个相邻秒的间隔度数
		for(int i=1;i<MAXNUM;i++){		//从0秒到59秒,间隔逐渐增加至6.
			sec[i].angle=sec[i-1].angle-s/Cs;
		}
	}
}

/*实现表盘顺时针旋转*/
void spin_hand(struct tm *t){
	
	int s=t->tm_sec,m=t->tm_min,h=t->tm_hour;
	static int flag=0,n=0;
	if(flag==0){						//对表,cs、cm、ch为sin值的和与旋转角度的比值
		static double cs=C_sin(360-sec[s].angle);
		static double cm=C_sin(360-min[m].angle);
		static double ch=C_sin(360-hou[h].angle);
		double vs=sin(pai/180*n*9)/cs;	//秒针旋转速度
		double vm=sin(pai/180*n*9)/cm;	//分针旋转速度
		double vh=sin(pai/180*n*9)/ch;	//时针旋转速度
		if(n<=20){						//调用20次完成对时
			n++;
			for(int i=0;i<MAXNUM;i++){
				sec[i].angle+=vs;
				min[i].angle+=vm;
				hou[i].angle+=vh;
			}
		}else{
			flag=1;						//标记完成对时
		}
	}
	if(flag){							//进入正常时间宣传速度
		static int dx=windwidth/2,dy=windhigh/2+17;
		line(windwidth/2,windhigh/2+17,dx,dy);
		if(dx<windwidth){				//实现划线的动态效果
			dx+=80;
		}else{
			for(int i=0,k=360;i<MAXNUM;i++,k-=6,s++,m++){
				sec[s%60].angle=k;		//s为此时刻秒数,s%60保证了sec[s%60]不会越界,变化范围0-59。
				min[m%60].angle=k;		//同上
			}
			for(int i=0,k=360;i<24;i++,h++,k-=15){
				hou[h%24].angle=k;		//继续同上,不过k的变化幅度每次15度
			}
		}		
	}	
}
/*画表盘*/
void draw_hand(){
	setcolor(EGEARGB(0XFF,255,255,255));
	setbkmode(TRANSPARENT);
	LOGFONTW font;
	getfont(&font);
	font.lfHeight=16;
	
	for(int i=0;i<60;i++){
		if(i<24){
			font.lfEscapement=-hou[i].angle/0.1;	//字体的角度默认是前端翘起为正角度,单位0.1
			setfont(&font);
			hou[i].x=hou[i].c*cos(hou[i].angle*pai/180)+windwidth/2+0.5;//浮点数末位+0.5实现四舍五入
			hou[i].y=hou[i].c*sin(hou[i].angle*pai/180)+windhigh/2+0.5;
			settextjustify(RIGHT_TEXT,TOP_TEXT);
			xyprintf(hou[i].x,hou[i].y,hou[i].time);
		}
		
		font.lfEscapement=-min[i].angle/0.1;
		setfont(&font);
		min[i].x=min[i].c*cos(min[i].angle*pai/180)+windwidth/2+0.5;
		min[i].y=min[i].c*sin(min[i].angle*pai/180)+windhigh/2+0.5;
		xyprintf((int)min[i].x,(int)min[i].y,min[i].time);
		
		font.lfEscapement=-sec[i].angle/0.1;
		setfont(&font);
		sec[i].x=sec[i].c*cos(1.0*sec[i].angle*pai/180)+windwidth/2+0.5;
		sec[i].y=sec[i].c*sin(1.0*sec[i].angle*pai/180)+windhigh/2+0.5;
		xyprintf((int)sec[i].x,(int)sec[i].y,sec[i].time);
	}
}

void draw_bk(PIMAGE bkimg,struct tm *now){
	putimage(0,0,bkimg);
	setcolor(EGEARGB(0XFF,255,255,255));
	setbkmode(TRANSPARENT);
	setfont(16,0,"仿宋");
	settextjustify(CENTER_TEXT,TOP_TEXT);
	xyprintf(windwidth/2,windhigh/2,"%d年%d月%d日",now->tm_year+1900,now->tm_mon+1,now->tm_mday);
}
int main(int argc,char const *argv[]){
	//初始化窗口
	setinitmode(INIT_ANIMATION,200,200);
	setcaption("时钟");
	initgraph(windwidth,windhigh);
	//设置背景图
	PIMAGE bkimg=newimage(640,480);		
	getimage(bkimg,"2.jpg",0,0);
	init_time();
	
	//EGE高级画图,抗锯齿
	ege_enable_aa(true);
	
	//主要消息循环
	for(int cnt=0;is_run();delay_fps(60)){
		time_t t;		//定义一个time_t类型的变量t,其实也就是long int类型
		time(&t);		//time函数给t赋值,为1970年1月1日至此刻的秒数。
		struct tm *now=localtime(&t); 	//定义一个struct tm 类型的结构体指针,指向localtime函数返回的此刻时间
//		char *timeNow=ctime(&t);		//ctime函数将t转换为表达此刻时间的字符串

		cleardevice();					//清屏
		draw_bk(bkimg,now);
		if(cnt<=90){
			init_hand(cnt);
			cnt++;
		}
		else{
			spin_hand(now);
		}
		
		draw_hand();
	}
	delimage(bkimg);					//删除背景图片内存,防止内存泄露
	closegraph();
	return 0;
}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CLion是一款由JetBrains开发的集成开发环境(IDE),专门用于C和C++语言的开发。EGE(Easy Graphics Engine)是一个简单易用的图形库,可以在Windows平台上进行图形编程。 要配置CLion来使用EGE进行图形编程,可以按照以下步骤进行操作: 1. 下载EGE库文件:在EGE的官方网站(https://xege.org/)上下载最新版本的EGE库文件。 2. 创建CLion项目:打开CLion,选择"Create New Project"创建一个新的项目。 3. 配置项目:选择"C++ Executable"作为项目类型,并选择合适的项目名称和路径。 4. 配置CMakeLists.txt文件:在项目的根目录下找到CMakeLists.txt文件,并将以下代码添加到文件中: ``` cmake_minimum_required(VERSION 3.17) project(Your_Project_Name) set(CMAKE_CXX_STANDARD 14) add_executable(Your_Project_Name main.cpp) target_link_libraries(Your_Project_Name graphics) ``` 5. 将EGE库文件复制到项目目录下:将下载的EGE库文件中的graphics.h和libgraphics.a文件复制到项目的根目录下。 6. 配置编译器选项:在CLion的菜单栏中选择"File" -> "Settings" -> "Build, Execution, Deployment" -> "CMake",在"CMake options"中添加以下代码: ``` -DGRAPHICSLIB="path/to/libgraphics.a" ``` 将"path/to/libgraphics.a"替换为你实际存放libgraphics.a文件的路径。 7. 编写代码:在项目中创建一个main.cpp文件,并编写你的图形程序代码。 8. 构建和运行:点击CLion界面上的"Build"按钮进行构建,然后点击"Run"按钮来运行你的程序。 希望以上步骤能够帮助你成功配置CLion来使用EGE进行图形编程!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值