【Godot4.0】几何图形、网格、刻度线顶点求取函数库ShapePoints

本文主要是介绍【Godot4.0】几何图形、网格、刻度线顶点求取函数库ShapePoints,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

概述

用于生成常见二维几何图形顶点数据PackedVector2Array)的静态函数库。
生成的数据可用于_drawLine2DPolygon2D等进行绘制和显示。

枚举

enum{AXIS_X = 1,AXIS_Y = 2,
}
enum{SIDE_UP = 1,SIDE_RIGHT = 2,SIDE_BOTTOM = 3,SIDE_LEFT = 4
}

测试场景

创建一个Control为根节点的场景。我们将基于这个空的控件,来实现绘图函数的测试。
image.png
在你的Godot4.2测试工程中创建脚本文件ShapePoints.gd,将ShapePoints源码拷贝到这个脚本文件中。
为Control节点添加如下的基础脚本:

@tool
extends Controlfunc _draw():pass# 获取绘制函数能正确使用的控件Rect2
func get_draw_safety_rect() -> Rect2:var rect = get_rect()return Rect2(rect.position - position,rect.size/scale)

其中:

  • @tool开启工具脚本模式,这样脚本会在编辑器中实时运行
  • _draw()CanvasItem类型的虚函数,用于执行draw_*绘图函数的绘图任务
  • 隐含:_draw()会在控件进入场景树和改变大小等时机自动重绘。
  • get_draw_safety_rect()函数可以获取在任意平移、旋转和缩放下都保持显示正确的控件矩形区域

基础图形点求取函数

rect(size:Vector2,offset:Vector2 = Vector2.ZERO) -> PackedVector2Array

返回长宽为size的矩形的四个顶点的数据。offset可以理解为整体的偏移。

使用CanvasItem内置draw_rect绘制矩形

CanvasItem内置的draw_rect函数本身就可以进行矩形的绘制。

@tool
extends Controlfunc _draw():var rect =  get_draw_safety_rect()draw_rect(rect,Color.WHITE,false,2)# 获取绘制函数能正确使用的控件Rect2
func get_draw_safety_rect() -> Rect2:var rect = get_rect()return Rect2(rect.position - position,rect.size/scale)

绘制后的效果,无论是平移、旋转还是缩放,都可以看到矩形被正确绘制。
image.pngimage.png

使用ShapePoints的Rect函数

ShapePointsRect函数返回的是一个包含矩形的5个顶点PackedVector2Array,在Control_draw()中,我们使用draw_polyline绘制白色,宽度为2,和控件矩形一样大的空心矩形。

@tool
extends Controlfunc _draw():var ctl_rect = get_draw_safety_rect()var points = ShapePoints.rect(ctl_rect.size,ctl_rect.position)draw_polyline(points,Color.WHITE,2)# 获取绘制函数能正确使用的控件Rect2
func get_draw_safety_rect() -> Rect2:var rect = get_rect()return Rect2(rect.position - position,rect.size/scale)

image.png
draw_polyline(points,Color.WHITE,2)改为draw_polyline(points,[Color.WHITE])可以绘制实心矩形。

regular_polygon(start_angle:int,edges:int,r:float,offset:Vector2) -> PackedVector2Array

返回正多边形顶点。

@tool
extends Controlfunc _draw():var ctl_rect = get_draw_safety_rect()var points = ShapePoints.regular_polygon(0,3,ctl_rect.size.y/2.0,ctl_rect.get_center())draw_polyline(points,Color.WHITE,2)# 获取绘制函数能正确使用的控件Rect2
func get_draw_safety_rect() -> Rect2:var rect = get_rect()return Rect2(rect.position - position,rect.size/scale)

draw_polyline(points,Color.WHITE,2)改为draw_polygon(points,[Color.WHITE]),就可以绘制实心三角形。
image.pngimage.png
通过改变edges参数为4、5、6…可以创建正方形、正五边形、正六边形等等。
edges=4edges=5edges=6edges=12

circle(r:float,offset:Vector2) -> PackedVector2Array

返回圆顶点。

@tool
extends Controlfunc _draw():var ctl_rect = get_draw_safety_rect()var points = ShapePoints.circle(ctl_rect.size.y/2.0,ctl_rect.get_center())draw_polyline(points,Color.WHITE,1)# 获取绘制函数能正确使用的控件Rect2
func get_draw_safety_rect() -> Rect2:var rect = get_rect()return Rect2(rect.position - position,rect.size/scale)

image.png

sector(start_angle:int,end_angle:int,r:float) -> PackedVector2Array

返回扇形顶点。

@tool
extends Controlfunc _draw():var ctl_rect = get_draw_safety_rect()var points = ShapePoints.sector(0,90,ctl_rect.get_center().y,ctl_rect.size.y/2.0)draw_polyline(points,Color.WHITE,1)# 获取绘制函数能正确使用的控件Rect2
func get_draw_safety_rect() -> Rect2:var rect = get_rect()return Rect2(rect.position - position,rect.size/scale)

起始角度0,结束角度90,半径为Control高度一半的扇形:
image.png
sector(-120,45,ctl_rect.get_center().y,ctl_rect.get_center())则表示起始角度-120,结束角度45,半径为Control高度一半的扇形:
image.png

arc(start_angle:int,end_angle:int,r:float,offset:Vector2) -> void

返回圆弧顶点。

@tool
extends Controlfunc _draw():var ctl_rect = get_draw_safety_rect()var points = ShapePoints.arc(-120,45,ctl_rect.get_center().y,ctl_rect.get_center())draw_polyline(points,Color.WHITE,1)# 获取绘制函数能正确使用的控件Rect2
func get_draw_safety_rect() -> Rect2:var rect = get_rect()return Rect2(rect.position - position,rect.size/scale)

起始角度-120,结束角度45,半径为Control高度一半的弧形:
image.png

star(start_angle:int,edges:int,r:float,r2:float = 0,offset:Vector2 = Vector2.ZERO) -> void

返回星形顶点。

@tool
extends Controlfunc _draw():var ctl_rect = get_draw_safety_rect()var r1 = ctl_rect.size.y/2.0var points = ShapePoints.star(0,5,r1,r1/2.0,ctl_rect.get_center())draw_polyline(points,Color.WHITE,1)# 获取绘制函数能正确使用的控件Rect2
func get_draw_safety_rect() -> Rect2:var rect = get_rect()return Rect2(rect.position - position,rect.size/scale)

起始角度0,5个角,外径为Control高度一半,内径为外径一半的五角星:
image.png
其他edges参数下生成的星形:
edges=4edges=6edges=12

round_rect(size:Vector2,r1:float,r2:float,r3:float,r4:float) -> PackedVector2Array

这是是描述。

@tool
extends Controlfunc _draw():var ctl_rect = get_draw_safety_rect()var r1 = ctl_rect.size.y/2.0var points = ShapePoints.round_rect(ctl_rect.size,10,10,10,10,ctl_rect.position)draw_polyline(points,Color.WHITE,1)# 获取绘制函数能正确使用的控件Rect2
func get_draw_safety_rect() -> Rect2:var rect = get_rect()return Rect2(rect.position - position,rect.size/scale)

Control大小始终一致,四个圆角半径都固定是10px的空心圆角矩形(下图左),改为draw_polygon(points,[Color.WHITE])后就是实心矩形:
image.pngimage.png
或者通过先draw_polygondraw_polyline,绘制实心带描边的圆角矩形:

@tool
extends Controlfunc _draw():var ctl_rect = get_draw_safety_rect()var r1 = ctl_rect.size.y/2.0var points = ShapePoints.round_rect(ctl_rect.size,10,10,10,10,ctl_rect.position)draw_polygon(points,[Color.WHITE])draw_polyline(points,Color.ORANGE,2)# 获取绘制函数能正确使用的控件Rect2
func get_draw_safety_rect() -> Rect2:var rect = get_rect()return Rect2(rect.position - position,rect.size/scale)

image.png
可以设定四个圆角半径的数值不同:

round_rect(ctl_rect.size,10,20,40,100,ctl_rect.position)

image.png
也可以将圆角半径设为一个动态变化的比例值。

var r = ctl_rect.size.x/20.0 
var points = ShapePoints.round_rect(ctl_rect.size,r,r,r,r,ctl_rect.position)

chamfer_rect(size:Vector2,a:float,b:float,c:float,d:float) -> PackedVector2Array

返回倒角矩形顶点。

@tool
extends Controlfunc _draw():var ctl_rect = get_draw_safety_rect()var r1 = ctl_rect.size.y/2.0var points = ShapePoints.chamfer_rect(ctl_rect.size,10,20,30,40,ctl_rect.position)draw_polyline(points,Color.WHITE,2)# 获取绘制函数能正确使用的控件Rect2
func get_draw_safety_rect() -> Rect2:var rect = get_rect()return Rect2(rect.position - position,rect.size/scale)

image.png

capsule(size:Vector2) -> PackedVector2Array

返回胶囊形顶点。

@tool
extends Controlfunc _draw():var ctl_rect = get_draw_safety_rect()var r1 = ctl_rect.size.y/2.0var points = ShapePoints.capsule(ctl_rect.size,ctl_rect.position)draw_polyline(points,Color.WHITE,2)# 获取绘制函数能正确使用的控件Rect2
func get_draw_safety_rect() -> Rect2:var rect = get_rect()return Rect2(rect.position - position,rect.size/scale)

image.pngimage.png

spindle(size:Vector2) -> PackedVector2Array

返回梭形顶点。目前版本还有瑕疵

@tool
extends Controlfunc _draw():var ctl_rect = get_draw_safety_rect()var r1 = ctl_rect.size.y/2.0var points = ShapePoints.spindle(ctl_rect.size,ctl_rect.position)draw_polyline(points,Color.WHITE,2)# 获取绘制函数能正确使用的控件Rect2
func get_draw_safety_rect() -> Rect2:var rect = get_rect()return Rect2(rect.position - position,rect.size/scale)

image.pngimage.png

特殊图形

taiji(r:float,offset:Vector2) -> Dictionary

返回太极图案各部分的字典。

  • taiji["pan"]:底盘的圆形
  • taiji["yin"]:阴鱼
  • taiji["yang"]:阳鱼
  • taiji["yin_eye"]:阴鱼眼
  • taiji["yang_eye"]:阳鱼眼
@tool
extends Controlfunc _draw():var ctl_rect = get_draw_safety_rect()var r1 = ctl_rect.size.y/2.0var taiji = ShapePoints.taiji(ctl_rect.size.y/2.0,ctl_rect.get_center())draw_polyline(taiji["pan"],Color.WHITE,2)draw_polyline(taiji["yin"],Color.WHITE,2)draw_polyline(taiji["yang"],Color.WHITE,2)draw_polyline(taiji["yin_eye"],Color.WHITE,2)draw_polyline(taiji["yang_eye"],Color.WHITE,2)# 获取绘制函数能正确使用的控件Rect2
func get_draw_safety_rect() -> Rect2:var rect = get_rect()return Rect2(rect.position - position,rect.size/scale)

image.png
注意:目前版本有瑕疵,用draw_polygon绘制阳鱼部分时随着Control缩放,部分情况下无法绘制实心多边形。期待后续改进。

helix(start_angle:int,start_r:float,end_r:float,step:int,offset:Vector2) -> PackedVector2Array

返回螺旋线顶点。注意:目前版本有瑕疵,后续改进

@tool
extends Controlfunc _draw():var ctl_rect = get_draw_safety_rect()var r1 = ctl_rect.size.y/2.0var points = ShapePoints.helix(0,0,ctl_rect.size.x/2.0,10,ctl_rect.get_center())draw_polyline(points,Color.WHITE,2)# 获取绘制函数能正确使用的控件Rect2
func get_draw_safety_rect() -> Rect2:var rect = get_rect()return Rect2(rect.position - position,rect.size/scale)

image.png

边线重复半圆花纹

repeat_circle(length:float,r:float,space:float = 0,axis:int = AXIS_X,concave:bool = false,reverse:bool = false,offset:Vector2 = Vector2.ZERO) -> PackedVector2Array

返回重复半圆花纹的线。

@tool
extends Controlfunc _draw():var ctl_rect = get_draw_safety_rect()var r1 = ctl_rect.size.y/2.0var points = ShapePoints.repeat_circle(ctl_rect.size.x,10)draw_polyline(points,Color.WHITE,2)# 获取绘制函数能正确使用的控件Rect2
func get_draw_safety_rect() -> Rect2:var rect = get_rect()return Rect2(rect.position - position,rect.size/scale)

image.png
可以设定半圆之间的间隔:

repeat_circle(ctl_rect.size.x,10,10)

image.png
可以设定半圆是凸出还是凹进去:

repeat_circle(ctl_rect.size.x,10,10,true)

image.png
最后一个参数将点的位置全部逆序,可以用于拼接矩形。

repeat_circle(ctl_rect.size.x,10,10,true,true)

可以设定纵向:

repeat_circle(ctl_rect.size.y,10,0,ShapePoints.AXIS_Y)

image.png

repeat_circle_edge(size:Vector2,r:float,space:float,side:int,concave:bool) -> PackedVector2Array

返回指定size大小的矩形所能使用的重复半圆边线。其中side可以使用以下枚举的值:

enum{SIDE_UP = 1,SIDE_RIGHT = 2,SIDE_BOTTOM = 3,SIDE_LEFT = 4
}

分别代表矩形的上、右、底、左四边。根据side的不同,会返回适用于矩形不同边的半圆重复花纹。

@tool
extends Controlfunc _draw():var ctl_rect = get_draw_safety_rect()var r1 = ctl_rect.size.y/2.0var points = ShapePoints.repeat_circle_edge(ctl_rect.size,10,10,ShapePoints.SIDE_LEFT)draw_polyline(points,Color.WHITE,2)# 获取绘制函数能正确使用的控件Rect2
func get_draw_safety_rect() -> Rect2:var rect = get_rect()return Rect2(rect.position - position,rect.size/scale)

image.pngimage.png
image.pngimage.png

repeat_circle_edge_rect(size:Vector2,r:float,space:float,concave:bool) -> PackedVector2Array

返回带重复半圆花边的矩形。

@tool
extends Controlfunc _draw():var ctl_rect = get_draw_safety_rect()var r1 = ctl_rect.size.y/2.0var points = ShapePoints.repeat_circle_edge_rect(ctl_rect.size,10,10)draw_polyline(points,Color.WHITE,2)# 获取绘制函数能正确使用的控件Rect2
func get_draw_safety_rect() -> Rect2:var rect = get_rect()return Rect2(rect.position - position,rect.size/scale)

image.png

repeat_circle_edge_rect(ctl_rect.size,10,10,true)

image.png

网格点、网格十字和棋盘格

line_cross(position:Vector2,length:float,start_angle:int) -> Array

这是是描述。

@tool
extends Controlfunc _draw():var ctl_rect = get_draw_safety_rect()var r1 = ctl_rect.size.y/2.0var points = ShapePoints.line_cross(ctl_rect.get_center(),10,0)draw_polyline(points[0],Color.WHITE,2)  # 绘制水平线draw_polyline(points[1],Color.WHITE,2)  # 绘制垂直线# 获取绘制函数能正确使用的控件Rect2
func get_draw_safety_rect() -> Rect2:var rect = get_rect()return Rect2(rect.position - position,rect.size/scale)

在控件中心绘制一个白色十字:
image.png

checker_board_rects(size:Vector2,cell_size:Vector2) -> Array

返回棋盘格矩形集合。返回一个包含2个Array[Rect2]的数组。第1个数组存储所有空心矩形,第2个数组存储所有实心矩形。

@tool
extends Controlfunc _draw():var ctl_rect = get_draw_safety_rect()var r1 = ctl_rect.size.y/2.0var rects = ShapePoints.checker_board_rects(Vector2(10,10),ctl_rect.size/10.0)for rect in rects[0]:draw_rect(rect,Color.WHITE,false,1)for rect in rects[1]:draw_rect(rect,Color.WHITE,true,1)# 获取绘制函数能正确使用的控件Rect2
func get_draw_safety_rect() -> Rect2:var rect = get_rect()return Rect2(rect.position - position,rect.size/scale)

创建了一个始终随控件大小自适应的棋盘格,划分为10行10列:
image.pngimage.pngimage.png

rect_grid_points(size:Vector2,cell_size:Vector2) -> PackedVector2Array

返回矩形网格的所有顶点的位置。至于绘制什么,你可以自己说了算。

@tool
extends Controlfunc _draw():var ctl_rect = get_draw_safety_rect()var r1 = ctl_rect.size.y/2.0var points = ShapePoints.rect_grid_points(Vector2(10,10),ctl_rect.size/10.0)for point in points:draw_circle(point,5,Color.WHITE)# 获取绘制函数能正确使用的控件Rect2
func get_draw_safety_rect() -> Rect2:var rect = get_rect()return Rect2(rect.position - position,rect.size/scale)

依然是1010列网格,所有顶点绘制为半径5像素,填充白色的圆:
image.png

rect_grid_lines(size:Vector2,cell_size:Vector2) -> Dictionary

返回矩形网格的水平线和垂直线集合。

  • lines["h_lines"]:包含多个[p1,p2],也就是水平线段起止点信息的数组
  • lines["v_lines"]:包含多个[p1,p2],也就是垂直线段起止点信息的数组
@tool
extends Controlfunc _draw():var ctl_rect = get_draw_safety_rect()var r1 = ctl_rect.size.y/2.0var lines = ShapePoints.rect_grid_lines(Vector2(10,10),ctl_rect.size/10.0)for line in lines["h_lines"]:draw_line(line[0],line[1],Color.WHITE,1)# 获取绘制函数能正确使用的控件Rect2
func get_draw_safety_rect() -> Rect2:var rect = get_rect()return Rect2(rect.position - position,rect.size/scale)

只绘制横线:
image.png
绘制横线和竖线:

for line in lines["h_lines"]:draw_line(line[0],line[1],Color.WHITE,1)
for line in lines["v_lines"]:draw_line(line[0],line[1],Color.WHITE,1)

image.png

triangle_grid_points(size:Vector2,cell_size:Vector2) -> PackedVector2Array


这是是描述。2024年3月18日01:21:03,等待继续书写


hex_grid_points(size:Vector2,cell_size:Vector2) -> PackedVector2Array

这是是描述。

刻度线求取函数

arc_scale(start_angle:int,end_angle:int,steps:int,r:float,length:float) -> Array

这是是描述。

line_scale(ruler_width:float,steps:int,length:float) -> void

这是是描述。

连线和箭头求取函数

待扩展。

源代码

以下是完整源代码:

# ========================================================
# 名称:ShapePoints
# 类型:静态函数库
# 简介:用于生成常见几何图形的顶点数据(PackedVector2Array)
#      可用于_draw和Line2DPolygon2D等进行绘制和显示
# 作者:巽星石
# Godot版本:4.1-stable (official) --> v4.2.1.stable.official [b09f793f5]
# 创建时间:2023-07-08 20:45:22
# 最后修改时间:202431801:20:17
# ========================================================
class_name ShapePoints# 返回矩形的顶点
static func rect(size:Vector2,offset:Vector2 = Vector2.ZERO) -> PackedVector2Array:var points:PackedVector2Array = [offset,offset + Vector2.RIGHT * size.x,offset + size,offset + Vector2.DOWN * size.y,offset]return points# 返回正多边形顶点
static func regular_polygon(start_angle:int,edges:int,r:float,offset:Vector2 = Vector2.ZERO):var points:PackedVector2Arrayvar vec  = Vector2.RIGHT.rotated(deg_to_rad(start_angle)) * rfor i in range(edges):points.append(vec.rotated(2* PI/edges * i) + offset)points.append(points[0])  # 返回第一个点return points# 返回圆顶点
static func circle(r:float,offset:Vector2 = Vector2.ZERO):var points = regular_polygon(0,2 * PI * r,r,offset)points.append(points[0])return points# 返回扇形顶点
# 注意start_angle和end_angle都是角度
static func sector(start_angle:int,end_angle:int,r:float,offset:Vector2 = Vector2.ZERO):var points:PackedVector2Arraypoints.append(Vector2.ZERO + offset)points.append_array(arc(start_angle,end_angle,r,offset))points.append(Vector2.ZERO + offset)return points# 弧形
# 注意start_angle和end_angle都是角度
static func arc(start_angle:int,end_angle:int,r:float,offset:Vector2 = Vector2.ZERO):var points:PackedVector2Arrayvar angle = deg_to_rad(end_angle - start_angle)var edges:float = ceilf(angle * r) # 要绘制的点的个数 = θ * rvar vec  = Vector2.RIGHT.rotated(deg_to_rad(start_angle)) * rfor i in range(edges+1):points.append(vec.rotated(angle/edges * i) + offset)return points# 星形
static func star(start_angle:int,edges:int,r1:float,r2:float = r1/2.0,offset:Vector2 = Vector2.ZERO):var points:PackedVector2Array# 外部半径var vec  = Vector2.RIGHT.rotated(deg_to_rad(start_angle)) * r1# 内部半径var vec2  = Vector2.RIGHT.rotated(deg_to_rad(start_angle + 180/edges)) * r2for i in range(edges):points.append(vec.rotated(2 * PI/edges * i) + offset)points.append(vec2.rotated(2 * PI/edges * i) + offset)points.append(points[0])  # 返回第一个点return points# 返回圆角矩形的顶点
# 注意:以(0,0)为几何中心
static func round_rect(size:Vector2,r1:float,r2:float,r3:float,r4:float,offset:Vector2 = Vector2.ZERO) -> PackedVector2Array:var points:PackedVector2Arraypoints.append_array(arc(180,270,r1,Vector2(r1,r1) + offset))points.append_array(arc(270,360,r2,Vector2(size.x - r2,r2) + offset))points.append_array(arc(0,90,r3,Vector2(size.x - r3,size.y -r3) + offset))points.append_array(arc(90,180,r4,Vector2(r4,size.y - r4) + offset))points.append(Vector2(0,r1)+offset)return points# 返回倒角矩形的顶点
# 注意:以(0,0)为几何中心
static func chamfer_rect(size:Vector2,a:float,b:float,c:float,d:float,offset:Vector2 = Vector2.ZERO) -> PackedVector2Array:var points:PackedVector2Array = [Vector2(0,a) + offset,Vector2(a,0) + offset,Vector2(size.x-b,0) + offset,Vector2(size.x,b) + offset,Vector2(size.x,size.y-c) + offset,Vector2(size.x-c,size.y) + offset,Vector2(d,size.y) + offset,Vector2(0,size.y-d) + offset]points.append(points[0]) # 闭合return points# 返回胶囊形的顶点
static func capsule(size:Vector2,offset:Vector2 = Vector2.ZERO) -> PackedVector2Array:var points:PackedVector2Array = []var r:float = min(size.x,size.y)/2.0if size.x>size.y: # 横向points.append_array(arc(90,270,r,Vector2(r,r) + offset))points.append_array(arc(-90,90,r,Vector2(size.x-r,r) + offset))else: # 纵向points.append_array(arc(180,360,r,Vector2(r,r) + offset))points.append_array(arc(0,180,r,Vector2(r,size.y-r) + offset))points.append(points[0]) # 闭合return points# 返回梭形的顶点
# 注意:以(0,0)为几何中心
static func spindle(size:Vector2,offset:Vector2 = Vector2.ZERO) -> PackedVector2Array:var points:PackedVector2Array = []var dx:float = size.x/2.0var dy:float = size.y/2.0var d_max = max(dx,dy)var d_min = min(dx,dy)var r = (pow(d_max,2.0) + pow(d_min,2.0))/(2.0 * d_min) # 圆弧半径var angle = rad_to_deg(asin(d_max/r))if dx<dy:points.append_array(arc(180-angle,180+angle,r,Vector2(r,dy)))points.append(Vector2(dx,0))points.append_array(arc(-angle,angle,r,Vector2(-r+2*dx+1,dy)))points.append(points[0]) # 闭合else:points.append_array(arc(270-angle,270+angle,r,Vector2(dx,r)))points.append(Vector2(size.x,dy))points.append_array(arc(90-angle,90+angle,r,Vector2(dx,-r+2*dy+1)))points.append(points[0]) # 闭合return points
# =================================== 特殊图形 ===================================
# 太极
static func taiji(r:float,offset:Vector2 = Vector2.ZERO) -> Dictionary:var dict = {pan = circle(r,offset), # 底部圆盘yin = [], # 阴鱼yang = [], # 阳鱼yin_eye = circle(r/10,Vector2(0,-r/2)+ offset), # 阴鱼眼yang_eye = circle(r/10,Vector2(0,r/2)+ offset), # 阳鱼眼}# 阴鱼dict["yin"].append_array(arc(90,270,r,offset))dict["yin"].append_array(arc(-90,90,r/2,Vector2(0,-r/2)+offset))var ac = arc(90,270,r/2,Vector2(0,r/2)+offset)ac.reverse()dict["yin"].append_array(ac)# 阳鱼dict["yang"].append_array(arc(-90,90,r,offset))dict["yang"].append_array(arc(90,270,r/2,Vector2(0,r/2)+offset))var ac2 = arc(-90,90,r/2,Vector2(0,-r/2)+offset)ac2.reverse()dict["yang"].append_array(ac2)return dict# 螺旋线
static func helix(start_angle:int,start_r:float,end_r:float,step:int =1,offset:Vector2 = Vector2.ZERO) -> PackedVector2Array:var points:PackedVector2Arrayvar steps = end_r - start_rfor i in range(steps):points.append(Vector2.RIGHT.rotated(deg_to_rad(start_angle + step * i)) * (start_r+i) + offset)return points# =================================== 花边图形 ===================================
enum{AXIS_X = 1,AXIS_Y = 2,
}# 返回与实际矩形不相关的重复半圆边数据
static func repeat_circle(length:float,r:float,space:float = 0,axis:int = AXIS_X,concave:bool = false,reverse:bool = false,offset:Vector2 = Vector2.ZERO) -> PackedVector2Array:var points:PackedVector2Arraymatch axis:AXIS_X:	# 水平方向var yu = fmod(length,(2.0 * r + space))  # 余数if !concave: # 凸出points.append(Vector2.ZERO + offset)for i in floorf(length/(2.0 * r + space)):points.append_array(arc(180,360,r,Vector2(2 * r + space,0) * i + Vector2(r + yu/2.0,0) + offset))points.append(Vector2(length,0) + offset)else: # 凹进去points.append(Vector2.ZERO + offset)for i in floorf(length/(2.0 * r + space)):var ac = arc(0,180,r,Vector2(2 * r + space,0) * i + Vector2(r + yu/2.0,0) + offset)ac.reverse()points.append_array(ac)points.append(Vector2(length,0) + offset)AXIS_Y: # 垂直方向var yu = fmod(length,(2.0 * r + space))  # 余数if !concave: # 凸出points.append(Vector2.ZERO + offset)for i in floorf(length/(2.0 * r + space)):points.append_array(arc(-90,90,r,Vector2(0,2 * r + space) * i + Vector2(0,r + yu/2.0) + offset))points.append(Vector2(0,length) + offset)else: # 凹进去points.append(Vector2.ZERO + offset)for i in floorf(length/(2.0 * r + space)):var ac = arc(90,270,r,Vector2(0,2 * r + space) * i + Vector2(0,r + yu/2.0) + offset)ac.reverse()points.append_array(ac)points.append(Vector2(0,length) + offset)# 是否逆序所有点if reverse:points.reverse()return points enum{SIDE_UP = 1,SIDE_RIGHT = 2,SIDE_BOTTOM = 3,SIDE_LEFT = 4
}# 返回边线重复半圆的矩形的边
static func repeat_circle_edge(size:Vector2,r:float,space:float = 0,side:int = SIDE_UP,concave:bool = false,offset:Vector2 = Vector2.ZERO) -> PackedVector2Array:var points:PackedVector2Arraymatch side:SIDE_UP:points.append_array(repeat_circle(size.x,r,space,AXIS_X,concave))SIDE_RIGHT:points.append_array(repeat_circle(size.y,r,space,AXIS_Y,concave,false,Vector2(size.x,0)))SIDE_LEFT:points.append_array(repeat_circle(size.y,r,space,AXIS_Y,!concave,true))SIDE_BOTTOM:points.append_array(repeat_circle(size.x,r,space,AXIS_X,!concave,true,Vector2(0,size.y)))return points# 返回边线重复半圆的矩形的边
static func repeat_circle_edge_rect(size:Vector2,r:float,space:float = 0,concave:bool = false,offset:Vector2 = Vector2.ZERO) -> PackedVector2Array:var points:PackedVector2Arraypoints.append_array(repeat_circle_edge(size,r,space,SIDE_UP,concave,offset))points.append_array(repeat_circle_edge(size,r,space,SIDE_RIGHT,concave,offset))points.append_array(repeat_circle_edge(size,r,space,SIDE_BOTTOM,concave,offset))points.append_array(repeat_circle_edge(size,r,space,SIDE_LEFT,concave,offset))return points# 返回指定点为中心,给定长度的两条互相垂直线段,可以用于绘制十字坐标线
static func line_cross(position:Vector2,length:float,start_angle:int = 0) -> Array:var start_rad = deg_to_rad(start_angle)# 水平线段俩端点var h_line = [Vector2.LEFT.rotated(start_rad) * length/2.0 + position,Vector2.RIGHT.rotated(start_rad) * length/2.0 + position,]# 水平线段俩端点var v_line = [Vector2.UP.rotated(start_rad) * length/2.0 + position,Vector2.DOWN.rotated(start_rad) * length/2.0 + position,]return [h_line,v_line]# =================================== 网格矩形求取函数 ===================================
# 矩形网格 - 棋盘格矩形求取函数
static func checker_board_rects(size:Vector2,cell_size:Vector2) -> Array:var rects_yang:Array[Rect2]var rects_yin:Array[Rect2]for x in range(size.x):for y in range(size.y):var pos = Vector2(x,y) * cell_sizeif (x % 2 == 0 and y % 2 == 0) or (x % 2 == 1 and y % 2 == 1):rects_yang.append(Rect2(pos,cell_size))else:rects_yin.append(Rect2(pos,cell_size))return [rects_yang,rects_yin]# =================================== 网格线和点求取函数 ===================================
# 方形 - 网格点求取函数
static func rect_grid_points(size:Vector2,cell_size:Vector2) ->PackedVector2Array:var points:PackedVector2Arrayfor x in range(size.x + 1):for y in range(size.y + 1):points.append(Vector2(x,y) * cell_size)return points# 三角 - 网格点求取函数
static func triangle_grid_points(size:Vector2,cell_size:Vector2) ->PackedVector2Array:var points:PackedVector2Arrayfor y in range(size.y + 1):if y % 2 == 0: # 偶数行for x in range(size.x + 1):points.append(Vector2(x,y) * cell_size)else: # 奇数行for x in range(size.x):points.append(Vector2(x,y) * cell_size + Vector2(cell_size.x/2,0))return points# 六边形 - 网格点求取函数
static func hex_grid_points(size:Vector2,cell_size:Vector2) ->PackedVector2Array:var points:PackedVector2Arrayfor y in range(size.y + 1):if y % 2 == 0: # 偶数行for x in range(size.x):if (x+1)% 3 != 0:points.append(Vector2(x,y) * cell_size + Vector2(cell_size.x/2,0))else: # 奇数行for x in range(size.x + 1):if x % 3 != 1:points.append(Vector2(x,y) * cell_size)return points# 方形 - 网格线求取函数
static func rect_grid_lines(size:Vector2,cell_size:Vector2) -> Dictionary:var lines = {v_lines = [], # 垂直的网格线h_lines = []  # 水平的网格线}var v_line1 = [Vector2.ZERO,Vector2.DOWN * cell_size.y * size.y]var h_line1 = [Vector2.ZERO,Vector2.RIGHT * cell_size.x * size.x]lines["v_lines"].append(v_line1)lines["h_lines"].append(h_line1)for x in range(1,size.x+1):var offset_x = Vector2(cell_size.x,0) * xlines["v_lines"].append([v_line1[0] + offset_x,v_line1[1] + offset_x])for y in range(1,size.y+1):var offset_y = Vector2(0,cell_size.y) * ylines["h_lines"].append([h_line1[0] + offset_y,h_line1[1] + offset_y])return lines# =================================== 刻度线生成 ===================================# 返回指定范围的弧形刻度线起始点坐标集合
# start_angle:起始角度
# end_angle:结束角度
# steps:切分次数
# r:半径
# length:刻度线长
static func arc_scale(start_angle:int,end_angle:int,steps:int,r:float,length:float) -> Array:var scales:Array = []var vec1 = (Vector2.RIGHT  * (r-length)).rotated(deg_to_rad(start_angle))var vec2 = (Vector2.RIGHT  * r).rotated(deg_to_rad(start_angle))var angle = deg_to_rad(end_angle - start_angle) # 夹角for i in range(steps+1):var line = [vec1.rotated((angle/steps) * i),vec2.rotated((angle/steps) * i)]scales.append(line)return scales# 返回指定范围的直线刻度线起始点坐标集合
static func line_scale(ruler_width:float,steps:int,length:float):var scales:Array = []var vec1 = Vector2.ZEROvar vec2 = Vector2.DOWN * lengthvar space = ruler_width/steps  # 单位间隔for i in range(steps+1):var line = [vec1 + Vector2(space,0) * i,vec2 + Vector2(space,0) * i]scales.append(line)return scales

这篇关于【Godot4.0】几何图形、网格、刻度线顶点求取函数库ShapePoints的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/821610

相关文章

POJ3041 最小顶点覆盖

N*N的矩阵,有些格子有物体,每次消除一行或一列,最少要几次消灭完。 行i - >列j 连边,表示(i,j)处有物体,即 边表示 物体。 import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;impo

OPENGL顶点数组, glDrawArrays,glDrawElements

顶点数组, glDrawArrays,glDrawElements  前两天接触OpenGL ES的时候发现里面没有了熟悉的glBegin(), glEnd(),glVertex3f()函数,取而代之的是glDrawArrays()。有问题问google,终于找到答案:因为OpenGL ES是针对嵌入式设备这些对性能要求比较高的平台,因此把很多影响性能的函数都去掉了,上述的几个函数都被移除了。接

”CSS 网格“二维布局系统(补充)——WEB开发系列32

CSS 网格布局是一种二维布局系统,用于网页设计。通过使用网格,你可以将内容以行和列的形式进行排列。此外,网格布局还能够简便地实现一些复杂的布局结构。 一、什么是网格布局? CSS网格布局是一种二维布局系统,它允许我们创建复杂的网页布局,既可以处理行也可以处理列。与传统的布局方法不同,网格布局将网页分成多个可控的区域,这些区域可以任意排列、对齐和调整大小。网格布局使得创建灵活且响应

鸿蒙(API 12 Beta6版)超帧功能开发【顶点标记】

超帧提供两种运动估计模式供开发者选择:分别为基础模式和增强模式。其中增强模式需要对绘制顶点的Draw Call命令进行额外的标记,在相机和物体快速运动的游戏场景超帧效果较基础模式更优,能够有效改善拖影问题。本章主要介绍增强模式的运动估计原理及顶点标记方法。 说明 Draw Call:指图形驱动库(OpenGL ES)中进行绘制的命令,例如glDrawElements、glDrawArrays、

Unity3D Shader详解:只画顶点或只画线框

在Unity3D开发中,Shader是控制渲染过程的关键组件,它允许开发者自定义物体的渲染方式。有时,为了特定的视觉效果,我们可能需要只渲染模型的顶点或者只显示其线框。下面,我们将详细探讨这两种效果的技术实现,并给出相应的代码示例。 对惹,这里有一个游戏开发交流小组,大家可以点击进来一起交流一下开发经验呀! 只画顶点 在Unity中直接“只画顶点”的概念可能不是非常直观,因为顶点本身只是模型

css——网格布局

名词解释 div{$}*9+tab键,快捷生成   记首字母gtc  网格布局:display: grid;        grid-template-columns: 100px 100px 100px;        grid-template-rows: 100px 100px 100px; (父元素) <!DOCTYPE html><html lang="en"

图形API学习工程(8):使用顶点索引缓冲

工程GIT地址:https://gitee.com/yaksue/yaksue-graphics 目标 在《图形API学习工程(5):图形管线&顶点缓冲》中,实现了渲染出一个三角形。 他有三个顶点。但是考虑图形变得复杂些的情况,就假如是一个四边形吧,那就需要分解为两个三角形来渲染了,而每个三角形需要三个顶点,也就是说,共需要6个顶点数据。 然而,如上图所示,实际上顶点是有重复的:0和3重复

Data Mesh,数据网格的道与术

周末的时候,看到有群友讨论关于 Data Mesh 的话题。这个名词我在2020年初的时候听到过一次,当时感觉就是一个概念,看的糊里糊涂,没有当回事。最近突然又被推上了话题风口,所以静下心来看了一下相关的论文和介绍。 在讨论 Data Mesh 之前,首先要给大家介绍一下 Service Mesh。 Service Mesh 公认的定义,是用以处理服务与服务之间通信的专用基础设施层。更本质的理

鸿蒙MPChart图表自定义(四)短刻度线

对于图表中的x轴效果,我们有时想要实现如图所示的特定刻度线。若需绘制x轴的短刻度线,我们可以利用现有资源,将原本的网格线稍作修改,只需绘制一条简洁的短线即可达到目的。 具体的方法就是写一个类MyXAxisRender继承自XAxisRenderer,重写父类的drawGridLine方法, 代码如下: import { Utils, XAxisRenderer } fro

Python下如何使用第三方函数库

Python下使用第三方函数库: 以httplib2 为例 以下代码为读取某网页信息: >>> import urllib    //该库可以访问web网页 >>>url="http://www.163.com"                   >>>content=urllib.urlopen(url).read()   //读取某网页信息 >>>open("163.com