【Godot4.2】实现简单时钟组件

news2025/2/24 10:29:18

概述

Godot的CanvasItem类型提供的绘图函数,以及向量旋转,玩起来很有意思。

基于_draw的实现

用向量旋转的方法,可以实现时钟的分针、时针、秒针的旋转。再通过每帧调用_draw更新绘图就可以让时钟动起来了。

当然我们还需要从Time单例那里获取当前的时分秒信息。

extends Control
# 基础参数
var center = Vector2(100,100) # 表盘中心
var r = 80 # 表盘半径
var h_r = 60 # 时针长度
var m_r = 50 # 分针长度
var s_r = 40 # 秒针长度

func _process(delta):
	queue_redraw()

func _draw():
	# 获取当前时间信息
	var dict = Time.get_datetime_dict_from_system()
	# 绘制
	draw_circle(center,80,Color("#ccc"))
	draw_line(center,(Vector2.UP * h_r).rotated((2* PI /12) * dict["hour"])+ center,Color("#444"),4)
	draw_line(center,(Vector2.UP * m_r).rotated((2* PI /60) * dict["minute"])+ center,Color("#444"),2)
	draw_line(center,(Vector2.UP * s_r).rotated((2* PI /60) * dict["second"])+ center,Color("#444"),1)

在这里插入图片描述

绘制表盘数字

上面的表盘光秃秃的,根本没有一个钟表的样子,所以我们draw_string方法绘制表盘数字。

# 绘制表盘数字
extends Control
# 基础参数
var center = Vector2(100,100) # 表盘中心
var r = 80 # 表盘半径
var h_r = 60 # 时针长度
var m_r = 50 # 分针长度
var s_r = 40 # 秒针长度

var default_font = ThemeDB.fallback_font
var default_font_size = ThemeDB.fallback_font_size


func _process(delta):
	queue_redraw()

func _draw():
	# 获取当前时间信息
	var dict = Time.get_datetime_dict_from_system()
	# 绘制
	draw_circle(center,80,Color("#ccc"))
	draw_line(center,(Vector2.UP * h_r).rotated((2* PI /12) * dict["hour"])+ center,Color("#444"),4)
	draw_line(center,(Vector2.UP * m_r).rotated((2* PI /60) * dict["minute"])+ center,Color("#444"),2)
	draw_line(center,(Vector2.UP * s_r).rotated((2* PI /60) * dict["second"])+ center,Color("#444"),1)

	# 绘制表盘数字
	for i in range(1,13):
		draw_string(default_font, 
		(Vector2.UP * 70).rotated((2* PI /12) * i) + center - Vector2(5,-5),
		str(i),HORIZONTAL_ALIGNMENT_CENTER,-1, default_font_size,Color("#444"))

一个由纯绘图函数实现的钟表控件就搞定了。
在这里插入图片描述

基于图片实现

当然,我们也可以用图片来实现一个更好看的钟表。

我在PS中设计了一个简单的钟表:
在这里插入图片描述

分别导出元件:
在这里插入图片描述
在这里插入图片描述

导入Godot中后,进行元件组装:
在这里插入图片描述

修改根节点代码如下:

extends Control

@onready var h_pointer = $pan/HPointer
@onready var m_pointer = $pan/MPointer
@onready var s_pointer = $pan/SPointer

func _process(delta):
	# 获取当前时间信息
	var dict = Time.get_datetime_dict_from_system()
	h_pointer.rotation = dict["hour"] * (2 * PI / 12)
	m_pointer.rotation = dict["minute"] * (2 * PI / 60)
	s_pointer.rotation = dict["second"] * (2 * PI / 60)

效果如下:
在这里插入图片描述
可以看到,代码一下子变少了。

抛砖引玉啊,期望各位可以受到启发。

EasyClock

这是本人纯粹基于_draw制作的简易参数化时钟组件。

可以自由缩放,支持各种颜色、字体、字号修改以及开启或关闭绘制数字、刻度等功能。

目前基于_process刷新有点浪费,后期可能基于Timer进行修改。
在这里插入图片描述

# ========================================================
# 名称:EasyClock
# 类型:Control扩展节点
# 简介:利用_draw实现的参数化的指针型钟表组件
# 作者:巽星石
# Godot版本:4.0.3-stable (official)
# 创建时间:2023-07-02 14:36:14
# 最后修改时间:20237216:22:40
# ========================================================
@tool
extends Control
class_name EasyClock
# =================================== 参数 ===================================
# 功能开关
@export_group("switch")
## 是否绘制中心
@export var draw_center:bool = false:
	set(val):
		draw_center = val
		queue_redraw()
## 是否绘制数字
@export var draw_nums:bool = false:
	set(val):
		draw_nums = val
		queue_redraw()
## 是否绘制刻度
@export var draw_scales:bool = false:
	set(val):
		draw_scales = val
		queue_redraw()
# 颜色
@export_group("Color")
## 表盘 - 颜色
@export var bk_color:Color = Color("#ccc"):
	set(val):
		bk_color = val
		queue_redraw()
## 时针 - 颜色
@export var h_color:Color = Color("#444"):
	set(val):
		h_color = val
		queue_redraw()
## 分针 - 颜色
@export var m_color:Color = Color("#444"):
	set(val):
		m_color = val
		queue_redraw()
## 秒针 - 颜色
@export var s_color:Color = Color("#444"):
	set(val):
		s_color = val
		queue_redraw()
## 中心点 - 颜色
@export var center_color:Color = Color("#ccc"):
	set(val):
		center_color = val
		queue_redraw()
# 宽度
@export_group("Width")
## 时针 - 宽度
@export var h_width:int = 10:
	set(val):
		h_width = val
		queue_redraw()
## 分针 - 宽度
@export var m_width:int = 5:
	set(val):
		m_width = val
		queue_redraw()
## 秒针 - 宽度
@export var s_width:int = 3:
	set(val):
		s_width = val
		queue_redraw()
@export_group("nums")
## 表盘数字 - 颜色
@export var nums_color:Color = Color("#ccc"):
	set(val):
		nums_color = val
		queue_redraw()
## 默认字体大小
@export var font_size = 14:
	set(val):
		font_size = val
		queue_redraw()
## 默认字体	
@export var font:SystemFont:
	set(val):
		font = val
		queue_redraw()


# =================================== 动态计算参数 ===================================
var center = Vector2(100,100) # 表盘中心
var r = 80 # 表盘半径
var h_r = 60 # 时针长度
var m_r = 50 # 分针长度
var s_r = 40 # 秒针长度

func _ready():
	resized.connect(func():
		calc()
	)
	calc()
	queue_redraw()

# 重新计算
func calc():
	center = get_global_rect().get_center()
	r = get_global_rect().size.y/2
	h_r = r * 0.82
	m_r = r * 0.85
	s_r = r * 0.9

func _process(delta):
	queue_redraw()

func _draw():
	# 获取当前时间信息
	var dict = Time.get_datetime_dict_from_system()
	# 绘制表盘
	draw_circle(center,r,bk_color)
	draw_circle(center,r * 0.8,bk_color.darkened(0.2))
	draw_circle(center,r * 0.8 - 10,bk_color.darkened(0.15))
	# 绘制日期
	var date := "%d.%d.%d" % [dict["year"],dict["month"],dict["day"]]
	draw_string(font, 
	Vector2.DOWN * r * 0.4 + center - Vector2(font_size * 2,-font_size/2),
	date,HORIZONTAL_ALIGNMENT_CENTER,-1,font_size * 1.5,nums_color)
	# 绘制时间
	# 绘制数字
	if draw_nums:
		for i in range(1,13):
			var f_size = font_size if i % 3 != 0 else font_size * 2
			draw_string(font, 
			(Vector2.UP * (r - f_size/1.25)).rotated((2* PI /12) * i) + center - Vector2(f_size/3,-f_size/2),
			str(i),HORIZONTAL_ALIGNMENT_CENTER,-1,f_size,nums_color)
	# 绘制
	draw_line(center,(Vector2.UP * h_r).rotated((2* PI /12) * dict["hour"]) + center,h_color,h_width)
	draw_line(center,(Vector2.UP * m_r).rotated((2* PI /60) * dict["minute"]) + center,m_color,m_width)
	draw_line(center,(Vector2.UP * s_r).rotated((2* PI /60) * dict["second"]) + center,s_color,s_width)
	# 绘制中心
	if draw_center:
		draw_circle(center,r * 0.1,center_color)
		draw_circle(center,r * 0.1 - 8,center_color.darkened(0.2))
		draw_circle(center,5,center_color.darkened(0.3))
	# 绘制刻度线
	if draw_scales:
		for i in range(60):
			draw_line((Vector2.UP * r * 0.9).rotated((2* PI /60) * i) + center ,(Vector2.UP * r * 0.95).rotated((2* PI /60) * i) + center,s_color,1)
	

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1532397.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Amuse .NET application for stable diffusion

Amuse github地址:https://github.com/tianleiwu/Amuse .NET application for stable diffusion, Leveraging OnnxStack, Amuse seamlessly integrates many StableDiffusion capabilities all within the .NET eco-system Welcome to Amuse! Amuse is a profes…

【Maven】使用maven-jar、maven-assembly、maven-shade优雅的实现第三方依赖一同打Jar包

文章目录 一.前言二.常规Jar 打包:maven-jar-plugin三.Shade 打包:maven-shade-plugin1.如何使用2.将部分jar包添加或排除3.将依赖jar包内部资源添加或排除4.自动将所有不使用的类排除5.将依赖的类重命名并打包进来 (隔离方案)6.修…

使用ansible批量修改操作系统管理员账号密码

一、ansible server端配置 1、对于Linux主机配置免密登录ssh-copy-id -i ~/.ssh/id_rsa.pub rootremote_ip 2、在/etc/ansible/hosts文件中添加相应主机IP 3、对于Windows主机需要在/etc/ansible/hosts文件中进行以下配置 192.168.83.132 ansible_ssh_useradministrator an…

147 Linux 网络编程3 ,高并发服务器 --多路I/O转接服务器 - select

从前面的知识学习了如何通过socket ,多进程,多线程创建一个高并发服务器,但是在实际工作中,我们并不会用到前面的方法 去弄一个高并发服务器,有更加好用的方法,就是多路I/O转接器 零 多路I/O转接服务器 多…

电脑硬盘误删怎么恢复,误删硬盘的文件能不能再恢复

误删硬盘的文件能不能再恢复?很多朋友都很关心这个问题,不用担心,误删硬盘文件是可以恢复的!使用电脑不可避免会遇到一些糊涂的时刻,比如误删了重要的文件。当我们发现自己不小心将硬盘上的文件删除时,心里…

【STM32】读写BKP备份寄存器RTC实时时钟

目录 BKP BKP简介 BKP基本结构 BKP测试代码 RTC RTC简介 RTC框图 RTC基本结构 硬件电路 RTC操作注意事项 接线图 初始化 使用BKP解决只初始化一次时间 初始化参考代码 RTC设置时间 RTC读取时间 完整代码 MyRTC.c MyRTC.h main.c BKP BKP简介 BKP&#xff0…

Centos7部署单节点MongoDB(V4.2.25)

🎈 作者:互联网-小啊宇 🎈 简介: CSDN 运维领域创作者、阿里云专家博主。目前从事 Kubernetes运维相关工作,擅长Linux系统运维、开源监控软件维护、Kubernetes容器技术、CI/CD持续集成、自动化运维、开源软件部署维护…

Apipost数据模型上线,解决相似数据结构复用问题

在API设计和开发过程中,存在许多瓶颈,其中一个主要问题是在遇到相似数据结构的API时会产生重复性较多的工作:在每个API中都编写相同的数据,这不仅浪费时间和精力,还容易出错并降低API的可维护性。 为了解决这个问题&a…

乐优商城(九)数据同步RabbitMQ

1. 项目问题分析 现在项目中有三个独立的微服务: 商品微服务:原始数据保存在 MySQL 中,从 MySQL 中增删改查商品数据。搜索微服务:原始数据保存在 ES 的索引库中,从 ES 中查询商品数据。商品详情微服务:做…

【phoenix】flink程序执行phoenix,phoenix和flink-sql-connector-hbase包类不兼容

问题报错 Caused by: java.lang.RuntimeException: java.lang.RuntimeException: class org.apache.flink.hbase.shaded.org.apache.hadoop.hbase.client.ClusterStatusListener$MulticastListener not org.apache.hadoop.hbase.client.ClusterStatusListener$Listener如下图&…

语音识别教程:Whisper

语音识别教程:Whisper 一、前言 最近看国外教学视频的需求,有些不是很适应,找了找AI字幕效果也不是很好,遂打算基于Whisper和GPT做一个AI字幕给自己。 二、具体步骤 1、安装FFmpeg Windows: 进入 https://github.com/BtbN/FF…

使用光标精灵更换电脑鼠标光标样式,一键安装使用

想要让自己在使用电脑时更具个性化,让工作和娱乐更加愉快,改变你的电脑指针光标皮肤可能是一个简单而有效的方法。很多人或许并不清楚如何轻松地调整电脑光标样式,下面我就来分享一种简单的方法。 电脑光标在系统里通常只有几种默认图案&…

支付宝手机网站支付,微信扫描二维码支付

支付宝手机网站支付 支付宝文档 响应示例 <form name"punchout_form" method"post" action"https://openapi.alipay.com/gateway.do?charsetUTF-8&methodalipay.trade.wap.pay&formatjson&signERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE…

软件的安装与卸载(YUM)

YUM&#xff1a;yum 是一个方便的"应用商店"&#xff0c;你可以通过它轻松地安装、更新和删除软件包&#xff0c;就像从应用商店中下载和安装应用程序一样。&#xff08;这个得用root身份&#xff0c;普通用户权限不够&#xff09; 常用命令&#xff1a; 1.安装软件…

提供数字免疫力:采取整体方法来优化您的网络

采用数字技术已成为许多美国企业的关键竞争优势&#xff0c;导致其在与新部署的云解决方案的安全连接方面的投资不断增加。然而&#xff0c;随着越来越多的关键应用程序迁移到云端&#xff0c;公司保护其敏感数据和资源变得更具挑战性&#xff0c;因为这些资产现在超出了内部防…

计算机网络相关

OSI七层模型 各层功能&#xff1a; TCP/IP四层模型 应用层 传输层 网络层 网络接口层 访问一个URL的全过程 在浏览器中输入指定网页的 URL。 浏览器通过 DNS 协议&#xff0c;获取域名对应的 IP 地址。 浏览器根据 IP 地址和端口号&#xff0c;向目标服务器发起一个 TCP…

c++ 指针大小

C的一个指针占内存几个字节&#xff1f; 结论&#xff1a; 取决于是64位编译模式还是32位编译模式&#xff08;注意&#xff0c;和机器位数没有直接关系&#xff09; 在64位编译模式下&#xff0c;指针的占用内存大小是8字节在32位编译模式下&#xff0c;指针占用内存大小是4字…

11种创造型设计模式(下)

观察者模式 我们可以比喻观察者模式是一种类似广播的设计模式 介绍 观察者模式&#xff1a;对象之间多对一依赖的一种设计方案&#xff0c;被依赖的对象是Subject&#xff0c;依赖的对象是Observer&#xff0c;Subject通知Observer变化。 代码 说明&#xff1a; WeatherStat…

sdsl库编译安装和使用

1. 下载和编译 git clone https://github.com/simongog/sdsl-lite.git cd sdsl-lite# 建一个conda环境 激活环境&#xff0c;安装cmake。 ./install.sh /usr/local/ 2. 示例代码 #include <sdsl/suffix_arrays.hpp> #include <fstream>using namespace sdsl;int…

SpringCloud Gateway工作流程

Spring Cloud Gateway的工作流程 具体的流程&#xff1a; 用户发送请求到网关 请求断言&#xff0c;用户请求到达网关后&#xff0c;由Gateway Handler Mapping&#xff08;网关处理器映射&#xff09;进行Predicates&#xff08;断言&#xff09;&#xff0c;看一下哪一个符合…