【Godot4.3】基于中心点连线的矩形重叠检测

概述

这个方法是我自己想到的,经典的矩形重叠(碰撞)检测,是一段很复杂的逻辑判断,而根据两个矩形中点连线,与两个矩形宽度和高度之和一半的比较,就可以判断两个矩形是否重叠,并且能够计算出重叠向量。

  • 通过给两个矩形施加反向的一半重叠向量,可以将两个矩形"推开"。
  • 通过用鼠标自由移动的矩形,可以使用给原本静止的矩形施加重叠向量,从而推动它

真实的物理碰撞是要考虑两个物体的质量和速度的,本文和ShapeTest所研究的只是几何上的重叠和重叠部分的向量求取。

基本原理

将两矩形中心进行连线:

  • 则横向距离 d w = ∣ c 2 − c 1 ∣ cos ⁡ θ = ( c 2 − c 1 ) . x d_w = |c2-c1|\cos \theta = (c2-c1).x dw=∣c2−c1∣cosθ=(c2−c1).x,纵向距离 d h = ∣ c 2 − c 1 ∣ sin ⁡ θ = ( c 2 − c 1 ) . y d_h = |c2-c1|\sin \theta = (c2-c1).y dh=∣c2−c1∣sinθ=(c2−c1).y
  • 如果 d w < w 1 + w 2 2 d_w<\frac{w_1+w_2}{2} dw<2w1+w2且 d h < h 1 + h 2 2 d_h<\frac{h_1+h_2}{2} dh<2h1+h2说明两个矩形发生了重叠。
  • 重叠的距离: o w = w 1 + w 2 2 − d w o_w=\frac{w_1+w_2}{2} - d_w ow=2w1+w2−dw, o h = h 1 + h 2 2 − d h o_h = \frac{h_1+h_2}{2} - d_h oh=2h1+h2−dh

代码实现

swift 复制代码
# 获取重叠部分的向量
func get_overlap(rect1:Rect2,rect2:Rect2) -> Vector2:
	var overlap:= Vector2()
	
	var c1:Vector2 = rect1.get_center()
	var c2:Vector2 = rect2.get_center()
	var vec12:Vector2 = c2-c1
	
	var half_size = (rect1.size + rect2.size)/2.0
	
	var dw = abs(vec12.x)
	var dh = abs(vec12.y)
	
	if dw < half_size.x and dh < half_size.y:
		overlap.x = (half_size.x - dw)
		overlap.y = (half_size.y - dh)
	return overlap

测试代码

swift 复制代码
extends Node2D

var rect1 = Rect2(300,300,100,60)
var rect2 = Rect2(400,400,100,60)


func _process(delta: float) -> void:
	rect2.position = get_global_mouse_position()
	var ove = get_overlap(rect1,rect2)
	var d_pos = rect2.position - rect1.position
	if ove.x >= ove.y:
		rect1.position -= Vector2(0,ove.y) * sign(d_pos.y)
	else:
		rect1.position -= Vector2(ove.x,0) * sign(d_pos.x)
	queue_redraw()

func _draw() -> void:
	draw_rect(rect1,Color.AQUAMARINE,false,1)
	draw_rect(rect2,Color.AQUAMARINE,false,1)
	
	var c1 = rect1.get_center()
	var c2 = rect2.get_center()

效果:

推动按钮

将矩形换为两个按钮控件:

测试代码:

swift 复制代码
extends Node2D

@onready var button1: Button = $Button1
@onready var button2: Button = $Button2


func _process(delta: float) -> void:
	button2.position = get_global_mouse_position()
	
	var ove = get_overlap(button1.get_rect(),button2.get_rect())
	var d_pos = button2.position - button1.position
	if ove.x >= ove.y:
		button1.position -= Vector2(0,ove.y) * sign(d_pos.y)
	else:
		button1.position -= Vector2(ove.x,0) * sign(d_pos.x)

测试效果:

其实,你可以将按钮替换为任意的控件或容器。

相关推荐
巽星石4 天前
【Godot4.3】自定义数列类NumList
godot·gdscript·斐波那契·数列
Android技术栈21 天前
鸿蒙(API 12 Beta6版)图形加速【OpenGL ES平台内插模式】超帧功能开发
elasticsearch·harmonyos·鸿蒙·鸿蒙系统·openharmony·图形·超帧
Android技术栈23 天前
鸿蒙(API 12 Beta6版)图形【NativeWindow开发指导 (C/C++)】方舟2D图形服务
c语言·c++·harmonyos·鸿蒙·鸿蒙系统·openharmony·图形
Android技术栈24 天前
鸿蒙(API 12 Beta6版)【ArkGraphics 3D场景搭建以及管理】方舟3D图形
3d·华为·harmonyos·鸿蒙·鸿蒙系统·openharmony·图形
Android技术栈24 天前
鸿蒙(API 12 Beta6版)【ArkGraphics 3D资源创建以及使用】方舟3D图形
3d·华为·harmonyos·鸿蒙·鸿蒙系统·openharmony·图形
Android技术栈1 个月前
鸿蒙(API 12 Beta6版)图形加速【Vulkan平台】超帧功能开发
华为·harmonyos·鸿蒙·鸿蒙系统·openharmony·图形·超帧
Colinnian1 个月前
godot开发初体验
游戏引擎·godot
巽星石1 个月前
【Godot4.3】基于纯绘图函数自定义的线框图控件
godot·gdscript·绘图·自定义控件·线框图
Android技术栈1 个月前
鸿蒙(API 12 Beta3版)图形【AR Engine简介】 AR引擎服务
音视频·harmonyos·鸿蒙·鸿蒙系统·openharmony·图形·引擎