【Godot4.2】Rect2拓展——mRect2类

概述

Rect2存在一些问题,比如难以获取除positionendcenter之外的其他点。虽然计算并不复杂,就是简单的向量加减。但每次手动计算则比较麻烦。
其实在ShapePoints静态函数库中,已经尝试返回矩形的四个顶点,用于绘制矩形。

# 返回矩形的顶点
# 注意:以(0,0)为几何中心
static func rect(size:Vector2) -> PackedVector2Array:var points:PackedVector2Array = [-size/2,-size/2 + Vector2.RIGHT * size.x,size/2,-size/2 + Vector2.DOWN * size.y,-size/2]return points

mRect2要做的是基于一个Rect2,快速返回九个位置点。

源代码

基于简单的思想,简单的实现了mRect2

# ========================================================
# 名称:mRect2
# 类型:自定义类
# 作者:巽星石
# Godot版本:4.1-stable (official) --> v4.2.1.stable.official [b09f793f5]
# 基于Rect2获取更多的边角点信息。
# 创建时间:2023-07-09 17:46:49
# 最后修改时间:202432121:09:52
# ========================================================class_name mRect2var _rect:Rect2# =================================== 构造 ===================================
func _init(rect:Rect2):_rect = rect# =================================== 静态方法 ===================================
# 根据position和size构造
static func by_size(position:Vector2,size:Vector2) -> mRect2:var rect = Rect2(position,size)return mRect2.new(rect)# 根据x,y,width,height 构造
static func by_xywh(x:float,y:float,width:float,height:float) -> mRect2:var rect = Rect2(x,y,width,height)return mRect2.new(rect)# =================================== 方法 ===================================
## 矩形 - 左上角 - 坐标
func top_left() -> Vector2:return _rect.position## 矩形 - 顶边中心 - 坐标
func top_center() -> Vector2:return _rect.position + Vector2.RIGHT * (_rect.size.x/2)## 矩形 - 顶边中心 - 坐标
func top_right() -> Vector2:return _rect.position + Vector2.RIGHT * _rect.size.x## 矩形 - 左边中心 - 坐标
func left_center() -> Vector2:return _rect.position + Vector2.DOWN * (_rect.size.y/2)## 矩形 - 矩形中心 - 坐标
func center() -> Vector2:return _rect.get_center()## 矩形 - 右边中心 - 坐标
func right_center() -> Vector2:return  _rect.get_center() + Vector2.RIGHT * (_rect.size.x/2)## 矩形 - 左下角 - 坐标
func left_bottom() -> Vector2:return _rect.position + Vector2.DOWN * _rect.size.y## 矩形 - 底边中心 - 坐标
func bottom_center() -> Vector2:return _rect.get_center()  + Vector2.DOWN * (_rect.size.y/2)## 矩形 - 右下角 - 坐标
func right_bottom() -> Vector2:return  _rect.end## 矩形 - 四个角坐标点 - 数组
## 可同于绘制矩形
func corners() -> PackedVector2Array:return [top_left(),top_right(),right_bottom(),left_bottom()]# 返回向外扩展一定距离的四个角顶点
func expend_corners(length:float) -> PackedVector2Array:var arr:PackedVector2Arrayvar v1 = - Vector2.ONE * lengtharr.append(top_left() + v1)arr.append(top_right() + v1.rotated(deg_to_rad(90)))arr.append(right_bottom() + v1.rotated(deg_to_rad(180)))arr.append(left_bottom() + v1.rotated(deg_to_rad(270)))return arr# 返回向外扩展一定距离的四个角顶点水平和垂直延伸出一定距离的点坐标
func expend_corners_lines(length:float,a:float = 10.0,b:float =10.0) -> PackedVector2Array:var arr:PackedVector2Arrayvar v1 = - Vector2.ONE * lengthvar p1 = top_left() + v1  # 第一个扩展点var v_a1 = Vector2.RIGHT * a  # 水平向量var v_b1 = Vector2.DOWN * b   # 垂直向量arr.append_array([p1,p1+v_a1]) # 添加水平线arr.append_array([p1,p1+v_b1]) # 添加垂直线# 右上角点var rad2 = deg_to_rad(90)var p2 = top_right() + v1.rotated(rad2)arr.append_array([p2,p2 - v_a1]) # 添加水平线arr.append_array([p2,p2 + v_b1]) # 添加垂直线# 右上角点var rad3 = deg_to_rad(180)var p3 = right_bottom() + v1.rotated(rad3)arr.append_array([p3,p3 - v_a1]) # 添加水平线arr.append_array([p3,p3 - v_b1]) # 添加垂直线# 右上角点var rad4 = deg_to_rad(270)var p4 = left_bottom() + v1.rotated(rad4)arr.append_array([p4,p4 + v_a1]) # 添加水平线arr.append_array([p4,p4 - v_b1]) # 添加垂直线return arr## 返回矩形对应的9个点 - 数组
func points() -> PackedVector2Array:return [top_left(),top_center(),top_right(),right_center(),right_bottom(),bottom_center(),left_bottom(),left_center(), center()]

使用

可以通过以下3种方式构建mRect2实例:

  • 可以通过给mRect2new()传入一个Rect2类型来创建mRect2实例
  • 可以通过by_size静态方法,基于positionsize2个参数创建mRect2实例
  • 可以通过by_xywh静态方法,基于xywidthheight4个参数创建mRect2实例
var rect = mRect2.new(Rect2.new())
var rect = mRect2.by_size(Vector2(100,100),Vector2(300,400))
var rect = mRect2.by_xywh(100,100,300,400)

快速获取矩形的某个特殊点坐标

mRect2中,将一个矩形的4个顶点、4个边的中点以及矩形中心点,共9个特殊点,从左上角开始,顺时针存入points方法所返回的数组中,你可以通过points()[下标]形式获取相应的点。
或者也可以通过对应名称的方法获取。

# 获取安全矩形
var rect = mRect2.new(get_draw_safety_rect())
print(rect.top_left())       # 左上角 -- 等价于rect.points()[0]
print(rect.top_center())     # 上边中点 -- 等价于rect.points()[1]
print(rect.top_right())      # 右上角	 -- 等价于rect.points()[2]
print(rect.right_center())   # 右边中点 -- 等价于rect.points()[3]
print(rect.right_bottom())   # 右下角	 -- 等价于rect.points()[4]
print(rect.bottom_center())  # 下边中点 -- 等价于rect.points()[5]
print(rect.left_bottom())    # 左下角	 -- 等价于rect.points()[6]
print(rect.left_center())    # 左边中点 -- 等价于rect.points()[7]
print(rect.center())         # 中点 -- 等价于rect.points()[8]

绘制矩形的9个特殊点

我们创建如下场景:
image.png
为根节点添加代码如下:

@tool
extends Controlfunc _draw():# 获取安全矩形var rect = mRect2.new(get_draw_safety_rect())# 绘制边框矩形draw_rect(get_draw_safety_rect(),Color.GREEN_YELLOW,false,1)# 绘制9个特殊点for point in rect.points():draw_circle(point,5,Color.GOLDENROD)# 获取绘制函数能正确使用的控件Rect2
func get_draw_safety_rect() -> Rect2:var rect = get_rect()return Rect2(rect.position - position,rect.size/scale)

可以看到绘制出的效果:
image.png
之所以大费周章的编写方法获取这9个点的位置,是因为,基于它们我们可以对矩形进行一定的修饰。比如在矩形外四个角上绘制选择框等。

在矩形的四个角外绘制特殊纹理

获取四个角向外扩展一定距离后的坐标

@tool
extends Controlfunc _draw():# 获取安全矩形var rect = mRect2.new(get_draw_safety_rect())draw_rect(get_draw_safety_rect(),Color.YELLOW_GREEN,false,2)# 获取和绘制向外扩展的四个角顶点var points = rect.expend_corners(20) # 获取向外扩展20像素后的四个角顶点坐标for point in points:draw_circle(point,5,Color.YELLOW)# 获取绘制函数能正确使用的控件Rect2
func get_draw_safety_rect() -> Rect2:var rect = get_rect()return Rect2(rect.position - position,rect.size/scale)

通过expend_corners可以获取四个角向外扩展一定距离的坐标,从而可以在矩形的4个角之外,绘制特殊的形状。这里简单的绘制了4个圆点:
image.png

获取四个角向外扩展一定距离后水平和垂直延伸的线段

expend_corners_lines更近一步,获取从扩展点水平和垂直延伸出给定长度的线段的坐标。
使用draw_multiline就可以直接绘制。

@tool
extends Controlfunc _draw():# 获取安全矩形var rect = mRect2.new(get_draw_safety_rect())draw_rect(get_draw_safety_rect(),Color.YELLOW_GREEN,false,2)# 获取和绘制向外扩展的四个角顶点var points = rect.expend_corners_lines(20,50,60) # 获取向外扩展20像素后的四个角顶点坐标draw_multiline(points,Color.YELLOW,2)# 获取绘制函数能正确使用的控件Rect2
func get_draw_safety_rect() -> Rect2:var rect = get_rect()return Rect2(rect.position - position,rect.size/scale)

绘制后的效果:
image.png
应用之一就是为Sprite2D等绘制选中框。

@tool
extends Sprite2Dfunc _draw():var rect = mRect2.new(get_rect())# 获取和绘制向外扩展的四个角顶点var points = rect.expend_corners_lines(20,50,60) # 获取向外扩展20像素后的四个角顶点坐标draw_multiline(points,Color.YELLOW,2)

image.png

总结

  • 这个类初始创建于2023年7月9日,于2024年3月21日进行了一定的改进和扩充。当然在我眼里这个类还有很大的拓展和改进空间,但是对于基础的选择框问题,也就是创造它的初衷,已经基本达到了。
  • 我不知道这个类是不是对你们有用,但是对于我自己是有一定的用途的

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c++的学习之路:2、入门(1)

一、 C关键字 c的关键字要比c语言要多31个足足有63个,这里我只是了解了下每个有啥作用,具体使用方法以及更多的知识将在后续学习中,慢慢扩展使用,下方表格就是c的63个关键字 asmdoifreturntryautodoubleinlinetypedefdynamic_ca…

归并算法详细解析

归并排序 1945年,约翰冯诺依曼(John von Neumann)发明了归并排序,这是典型的分治算法的应用。归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Di…

公司系统中了.rmallox勒索病毒如何恢复数据?

早晨上班时刻: 当阳光逐渐洒满大地,城市的喧嚣开始涌动,某公司的员工们纷纷踏入办公大楼,准备开始新的一天的工作。他们像往常一样打开电脑,准备接收邮件、查看日程、浏览项目进展。 病毒悄然发作: 就在员…

Python学习:元组

Python 元组概念 Python 中的元组(tuple)是不可变的有序集合。它是一种数据类型,类似于列表(list),但在创建后不能被修改。元组使用圆括号 () 来表示,其中的元素可以是任意类型,并且…

“洞见·智领未来——2024行业开局暨成渝(内江)服务外包产业发展大会”共商服务外包新未来新业态

3月19日-20日,由中国信息协会、中共内江市委、内江市人民政府指导,中国信息协会数字经济专委会、中共内江市东兴区委、内江市东兴区人民政府共同主办,鸿联九五集团、首席客户官百人会(CCO100)承办的“洞见 智领未来—…

Spring学习记录之注解开发

前面我们已经了解了Spring是如何创建Bean以及完成依赖注入的,但我们会发现,其似乎并没有达到简化开发的目的,这是因为 我们还没有接触到注解开发。 注解开发之组件 我们在要使用Bean的地方使用Comonpent(组件)注解&a…

Linux 文件系统:重定向、缓冲区

目录 一、重定向 1、输出重定向 2、输入重定向 3、追加重定向 4、dup2 系统调用 二、理性理解Linux系统下“一切皆文件” 了解硬件接口 三、缓冲区 1、为什么要有缓冲区? 2、刷新策略 3、缓冲模式改变导致发生写时拷贝 未创建子进程时 创建子进程时 使用fflush…

某招聘系统0day挖掘(获取4站点报告证书)

前言: 21年的挖的漏洞了 漏洞均已提交且均已修复,这里文章只做技术交流 挖掘过程 对我来说,毕竟喜欢直接黑盒挖0day,一个0day挖到后就可以刷上百分。 如该系统正常找了一个招聘系统用的比较多的 如该通用系统,该通用系统存在一个注册功能 正常的进行注册一个账户进去…

算法打卡day11

今日任务: 1)239. 滑动窗口最大值 2)347.前 K 个高频元素 239. 滑动窗口最大值 题目链接:239. 滑动窗口最大值 - 力扣(LeetCode) 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移…

Windows 11 鼠标右键可选择 cmd 命令行选项

** Windows 11 鼠标右键可选择 cmd 命令行选项 ** 在文件夹内打开命令行,只能使用 Windows 自带的 PowerShell , 作为一个 cmd 重度使用用户来说很是折磨,需要打开 cmd 然后切换盘符再 cd 。。。 现在咱们自己创建一个可以打开 cmd 的方法…

【Leetcode每日一题】 递归 - Pow(x, n)(难度⭐⭐)(40)

1. 题目解析 题目链接:50. Pow(x, n) 这个问题的理解其实相当简单,只需看一下示例,基本就能明白其含义了。 2.算法原理 在这个算法中,递归函数的任务是求出 x 的 n 次方。那么,这个函数是怎么工作的呢?它…

关于Devin,它只是人类历史的一个正常延续而已

近期,关于Devin的讨论无疑成为了科技界的热点话题。作为一款由初创公司Cognition AI研发的AI程序员,Devin凭借其惊人的“端到端解决成功率”和高效完成需求的能力,在各大社交媒体和科技论坛上引发了广泛的讨论。然而,在这场看似前…