Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >圆-矩形碰撞分辨率

圆-矩形碰撞分辨率
EN

Game Development用户
提问于 2012-08-03 13:25:04
回答 3查看 8K关注 0票数 3

在我的游戏中,我有一个非轴对齐矩形,就像一辆汽车。我必须检查并解决矩形和圆形之间的碰撞,这是静止的。

我已经找到了很多确定碰撞的方法,但是在解决这个问题上找不到任何东西。很明显,如果发生碰撞,我必须把矩形往后推,但我找不到合适的方法。

有办法处理和解决矩形和圆圈之间的碰撞吗?像算法一样?

我正在c++开发。

EN

回答 3

Game Development用户

回答已采纳

发布于 2012-08-10 20:53:28

@ErikEsTT: OP特别要求的不仅仅是布尔值“是相交的”,它们需要最近的点或穿透深度,或者其他有意义的碰撞度量,而不仅仅是是/否。

要回答OP的问题,可以使用rect和圆形之间的带符号距离查询来实现圆形-vs-矩形。可能最简单的方法是将圆圈转换成rect的局部空间(其中它是一个轴对齐框),然后执行点-vs有符号距离查询。

这里有一个非常出色(但相当混乱)的签名框距离函数:http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm或任何好书(例如RTCD或GeomTools)都应该有类似的查询解释。

票数 0
EN

Game Development用户

发布于 2012-08-04 06:41:20

我取了这个回答,它是AABB -圆交点,并将它转换为OBB -圆交点,并增加了交点的计算。

代码语言:javascript
运行
AI代码解释
复制
struct Vec2
{
    Vec2(): x( 0.0f ), y( 0.0f ) { }
    Vec2( float _x, float _y ): x( _x ), y( _y ) { }

    float x, y;
};

struct Box
{
    Vec2 Position, Size;
    float rotation;
};

struct Circle
{
    Vec2 Position;
    float radius;
};

Vec2 TranslatePointOnBox( const Vec2& BoxPosition, const Vec2& BoxRotation, const Vec2& Point, const Vec2& Sign )
{
    Vec2 LocalPoint( Point.x * Sign.x, Point.y * Sign.y );

    Vec2 WorldPoint;

    // rotate
    WorldPoint.x = LocalPoint.x * BoxRotation.x - LocalPoint.y * BoxRotation.y + BoxPosition.x;
    WorldPoint.y = LocalPoint.y * BoxRotation.x + LocalPoint.x * BoxRotation.y + BoxPosition.y;

    // translate
    WorldPoint.x += BoxPosition.x;
    WorldPoint.y += BoxPosition.y;

    return WorldPoint;
}

bool Itersects( const Circle& circle, const Box& box, Vec2& OutputPoint )
{
    Vec2 Diff1; // difference in world coord.
    Vec2 Diff2; // difference in local coord.
    Vec2 Rotation;
    Vec2 HalfSize;
    Vec2 Sign;  // for restoring intersection quadrant

    Diff1.x = circle.Position.x - box.Position.x;
    Diff1.y = circle.Position.y - box.Position.y;

    Rotation.x = cos( box.rotation );
    Rotation.y = sin( box.rotation );

    Diff2.x = Diff1.x * Rotation.x - Diff1.y * Rotation.y;
    Diff2.y = Diff1.y * Rotation.x + Diff1.x * Rotation.y;

    Sign.x = Diff2.x < 0.0f ? -1.0f : 1.0f;
    Sign.y = Diff2.y < 0.0f ? -1.0f : 1.0f;

    Diff2.x = abs( Diff2.x );
    Diff2.y = abs( Diff2.y );

    HalfSize.x = box.Size.x / 2.0f;
    HalfSize.y = box.Size.y / 2.0f;

    // intersection AABB - circle
    if( Diff2.x > HalfSize.x + circle.radius ||
        Diff2.y > HalfSize.y + circle.radius )
    {
        OutputPoint = Vec2( 0.0f, 0.0f );
        return false;
    }

    if( Diff2.x <= HalfSize.x )
    {
        OutputPoint = TranslatePointOnBox( box.Position, Rotation, Vec2( HalfSize.x, Diff2.y ), Sign );
        return true;
    }
    if( Diff2.y <= HalfSize.y )
    {
        OutputPoint = TranslatePointOnBox( box.Position, Rotation, Vec2( Diff2.x, HalfSize.y ), Sign );
        return true;
    }

    float CornerDistSquared =
        pow( Diff2.x - HalfSize.x, 2.0f ) +
        pow( Diff2.y - HalfSize.y, 2.0f );

    if( CornerDistSquared <= circle.radius * circle.radius )
    {
        OutputPoint = TranslatePointOnBox( box.Position, Rotation, HalfSize, Sign );
        return true;
    }
    else
    {
        OutputPoint = Vec2( 0.0f, 0.0f );
        return false;
    }
}

注意:

相交点位于箱体表面,最接近圆心。

最好是在Vec2 rotation;中保持Box旋转,而不是在float rotation;中,这样就不需要计算sin/cos每个交叉口(只有当旋转发生变化时才计算)。

你可以省略OutputPoint = Vec2( 0.0f, 0.0f );,它在没有交集的情况下返回零向量。

票数 0
EN

Game Development用户

发布于 2013-09-13 09:06:54

我在这里回答了这个问题,但代码是用Java编写的(数学很容易翻译)。

https://stackoverflow.com/questions/18704999/how-to-fix-circle-and-rectangle-overlap-in-collision-response/18790389#18790389

我的解决方案处理轴对齐框,但您可以轻松地将其转换为面向方向的框,方法是将圆圈、当前和未来位置围绕矩形中心旋转,直到矩形对齐为止。

上述代码代表高速移动圆,因此它们不能通过矩形,也不能跳过拐角。

票数 0
EN
页面原文内容由Game Development提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://gamedev.stackexchange.com/questions/33546

复制
相关文章
MySQL批量插入数据,一次插入多少行数据效率最高?
我们在操作大型数据表或者日志文件的时候经常会需要写入数据到数据库,那么最合适的方案就是数据库的批量插入。只是我们在执行批量操作的时候,一次插入多少数据才合适呢?假如需要插入的数据有百万条,那么一次批量插入多少条的时候,效率会高一些呢?这里博主和大家一起探讨下这个问题,应用环境为批量插入数据到临时表。
用户8949263
2022/04/08
8.7K0
iOS_只执行一次、timer内重复点击,只执行最后一次
[NSObject cancelPreviousPerformRequestsWithTarget:self];
mikimo
2022/07/20
1.4K0
OceanBase 数据库大赛:一次插入多条数据(草稿)
https://jgithub.com/hnwyllmm/miniob_test/issues/1
早起的鸟儿有虫吃
2021/11/18
1.5K0
OceanBase 数据库大赛:一次插入多条数据(草稿)
只出现一次的数字
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
_kyle
2020/11/25
8090
只出现一次的数字
只出现一次的元素
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
木瓜煲鸡脚
2020/09/24
8550
LeetCode,只出现一次的数字
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
微客鸟窝
2021/08/18
6040
LeetCode,只出现一次的数字
MySQL 批量操作,一次插入多少行数据效率最高?
我们在操作大型数据表或者日志文件的时候经常会需要写入数据到数据库,那么最合适的方案就是数据库的批量插入。只是我们在执行批量操作的时候,一次插入多少数据才合适呢?
Java技术栈
2023/02/27
2.4K0
MySQL 批量操作,一次插入多少行数据效率最高?
插入数据
 $db=DB::table('ad');         //多条记录         $id=$db->insert([             [                 'ad_merchant'=>0,                 'ad_img'=>'http://pic1.quanmingwang.com/shop/ZJcop8ludg_20171013_!!99959.png',                 'ad_w'=>'100',             
双面人
2020/02/13
9990
Android设置gif只播放一次
Android设置gif只播放一次 第一种写法: Glide.with(mContext).load(R.drawable.open_door_fail) .diskCacheStrategy(DiskCacheStrategy.SOURCE) .listener(new RequestListener<Integer, GlideDrawable>() { @Override
程序员飞飞
2020/02/27
2K0
LeetCode | 只出现一次的数字
题目 136. 只出现一次的数字 - 力扣(LeetCode) 给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。 你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。 示例 1 :
yiyun
2023/04/04
5740
LeetCode | 只出现一次的数字
找只出现一次的数字
  给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
Qt君
2020/08/05
6680
Swift 只出现一次的数字 - LeetCode
给定一个整数数组,除了某个元素外其余元素均出现两次。请找出这个只出现一次的元素。 备注: 你的算法应该是一个线性时间复杂度。 你可以不用额外空间来实现它吗?
韦弦zhy
2018/09/11
8150
136. 只出现一次的数字
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
Michel_Rolle
2021/03/07
2.6K0
136. 只出现一次的数字
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
张伦聪zhangluncong
2022/10/26
3780
[剑指offer] 数组中只出现一次的数字
一个整型数组里除了两个数字之外,其他的数字都出现了偶数次。请写程序找出这两个只出现一次的数字。
尾尾部落
2018/09/04
9260
136. 只出现一次的数字
程序员小航
2023/10/22
1410
136. 只出现一次的数字
找出只出现一次的数字---合集
/** * 数组中有两个出现一次的数字,其他数字都出现两次,找出这两个数字 * @param array * @param num1 * @param num2 */ public static void findNumsAppearOnce(int [] array,int num1[] , int num2[]) { if(array == null || array.length <= 1){ n
名字是乱打的
2022/05/13
3440
136. 只出现一次的数字
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
名字是乱打的
2021/12/23
3630
136. 只出现一次的数字
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。 示例 1: 输入: [2,2,1] 输出: 1 示例 2: 输入: [4,1,2,1,2] 输出: 4 你可以不使用额外空间来实现吗? 任何数和 00 做异或运算,结果仍然是原来的数 任何数和其自身做异或运算,结果是 00 class Solution { public int singleNumber(int[] nums) { /**
CaesarChang张旭
2021/06/22
5400
MariaDB 插入数据
存储在系统中的数据是数据库管理系统(DBMS)的核心,数据库被设计用来管理数据的存储、访问和维护数据的完整性,MariaDB中提供了功能丰富的数据库管理语句,包括有效地向数据库中插入数据的INSERT语句,更新数据的UPDATE语句以及当数据不再使用时删除数据的DELETE语句,本小结将依次来介绍这些命令的使用方法和技巧.
王瑞MVP
2022/12/28
2.3K0

相似问题

MySQL:每月只接收数据

34

从数据库中挑选每月只出现一次的数据

21

只插入一次

33

只插入一次

40

每月自动插入数据库

22
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档