当前位置: 首页 > news >正文

【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=c2c1∣cosθ=(c2c1).x,纵向距离 d h = ∣ c 2 − c 1 ∣ sin ⁡ θ = ( c 2 − c 1 ) . y d_h = |c2-c1|\sin \theta = (c2-c1).y dh=c2c1∣sinθ=(c2c1).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+w2dw, o h = h 1 + h 2 2 − d h o_h = \frac{h_1+h_2}{2} - d_h oh=2h1+h2dh

代码实现

# 获取重叠部分的向量
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-c1var half_size = (rect1.size + rect2.size)/2.0var 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

测试代码

extends Node2Dvar 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.positionif 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()

效果:

推动按钮

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

测试代码:

extends Node2D@onready var button1: Button = $Button1
@onready var button2: Button = $Button2func _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.positionif 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)

测试效果:

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


http://www.mrgr.cn/news/41837.html

相关文章:

  • 「4.3」维护序列
  • android Activity生命周期
  • SpringBoot实现美容院管理自动化:技术与实践
  • 【PostgreSQL】实战篇——数据备份和恢复的最佳实践和工具
  • Go语言实现长连接并发框架 - 连接
  • #Swift :回调地狱 的解决 —— 通过 task/await 来替代 nested mutiple trailing closure 来进行 回调的解耦
  • 智能编码助手【通义灵码】实践指南
  • 容器适配器-stack、queue、priority_queue和仿函数
  • SpringBoot系列 启动流程
  • 登录功能开发 P167重点
  • 【Redis入门到精通九】Redis中的主从复制
  • Redis: 集群架构,优缺点和数据分区方式和算法
  • 软件修改工具----盘点那些免费的windows系统下的16进制编辑器 软件修改好帮手
  • Framebuffer学习
  • Python字符串string方法大全及使用方法[2]以及FastApi关闭接口文档、隐藏部分接口、关闭schemes的实现
  • CSS 实现楼梯与小球动画
  • (c#)unity中sqlite多线程同时开启事务会导致非常慢
  • python 棒棒糖图
  • python中的copy方法
  • Java - LeetCode面试经典150题 - 区间 (三)