python矩形碰撞检测算法_四叉树与碰撞检测 !Cocos Creator !

四叉树与引擎内置碰撞检测的结合运用。

效果预览

绿色为参加检测的对象(当前四叉树节点),红色为碰撞对象。

197be3e1947d

image

如何使用

引入脚本 QuadtreeCollision.ts , 新建一个 QuadtreeCollision ,并初始化为世界坐标系下的对齐轴向的包围盒(AABB)。

// 这边是挂载在canvas下的脚本,用canvas的rect初始化创建。

this._quadCollision = new QuadtreeCollision(this.node.getBoundingBoxToWorld())

传入待检测的碰撞数组 cc.Collider[] 和测试对象的 cc.Collider。

返回准备测试的 cc.Collider[] 和发生碰撞的 cc.Collider[]。

// check(colliders: cc.Collider[], testCollider: cc.Collider)

const { retrieve, contacts } = this._quadCollision.check(this._all_collider, this.collider_role);

// retrieve 准备测试的对象(预览图中的绿色) cc.Collider[]

// contacts 碰撞对象(预览图中的红色) cc.Collider[]

实现原理

四叉树是什么?

白玉无冰是这样理解的,四叉树本身是树结构的一种,如果物体过多的话,先根据物体所处位置划分成四块,如果每个块的中的物体数量还是很多的话,继续划分成四块。如下图红线所示。

197be3e1947d

image

检测的时候,就是根据待测试对象的位置,去找属于哪个块,再把这个块中的物体告诉你。如下图中的绿色物体。

197be3e1947d

image

那么怎么实现四叉树呢?用好 github 就行了(误),搜了一下,找到一个库,直接拿来改改就行了。

//export default class QuadtreeCollision {

private _tree;

constructor(rect: { x: number, y: number, width: number, height: number }) {

this._tree = new Quadtree(rect);

}

197be3e1947d

image

那么怎么检测碰撞呢?

先看看引擎(v2.3.3)的 CollisionManager 是怎么处理的。

在 cc.Collider 这个组件 onEnable 时,会把这个组件加入 CollisionManager 中。

CollisionManager 添加 Collider 时,会遍历所有的 Collider ,根据分组创建一个碰撞连接。

197be3e1947d

image

所以,我们碰撞检测的思路,就在源码中搬过来改改。

197be3e1947d

image

将上面的代码整理出我们要用的检测代码如下。

function testContact(collider1, collider2) {

// 分组不通过

if (!cc.director.getCollisionManager()['shouldCollide'](collider1, collider2)) {

return false;

}

let world1 = collider1.world;

let world2 = collider2.world;

if (!world1.aabb.intersects(world2.aabb)) {

return false;

}

let isCollider1Polygon = (collider1 instanceof cc.BoxCollider) || (collider1 instanceof cc.PolygonCollider);

let isCollider2Polygon = (collider2 instanceof cc.BoxCollider) || (collider2 instanceof cc.PolygonCollider);

let isCollider1Circle = collider1 instanceof cc.CircleCollider;

let isCollider2Circle = collider2 instanceof cc.CircleCollider;

if (isCollider1Polygon && isCollider2Polygon) {

return cc.Intersection.polygonPolygon(world1.points, world2.points);

} else if (isCollider1Circle && isCollider2Circle) {

return cc.Intersection.circleCircle(world1, world2);

} else if (isCollider1Polygon && isCollider2Circle) {

return cc.Intersection.polygonCircle(world1.points, world2);

} else if (isCollider1Circle && isCollider2Polygon) {

return cc.Intersection.polygonCircle(world2.points, world1);

} else {

// cc.errorID(6601, cc.js.getClassName(collider1), cc.js.getClassName(collider2));

}

return false;

}

最后再结合四叉树碰撞,检测代码如下。

check(colliders: cc.Collider[], testCollider: cc.Collider) {

const ret: { retrieve: cc.Collider[], contacts: cc.Collider[] } = { retrieve: [], contacts: [] };

// 四叉树清理

this._tree.clear();

const collisionManager = cc.director.getCollisionManager();

collisionManager['updateCollider'](testCollider);

for (let i = 0, l = colliders.length; i < l; i++) {

const collider = colliders[i];

// 更新碰撞体世界aabb

collisionManager['updateCollider'](collider);

const aabb = collider['world'].aabb;

const rect = { x: aabb.x, y: aabb.y, height: aabb.height, width: aabb.width, collider: collider };

// 四叉树插入

this._tree.insert(rect)

}

// 四叉树抓出待检查的对象(属于那个块的所有节点)

const retrieveObjects = this._tree.retrieve(testCollider['world'].aabb);

retrieveObjects.forEach(element => {

ret.retrieve.push(element.collider);

// 抓出来后检查碰撞

if (testContact(element.collider, testCollider)) {

ret.contacts.push(element.collider);

}

});

return ret;

}

更多精彩

197be3e1947d

2D实现背景图3D滚动效果

197be3e1947d

物理挖洞系列

197be3e1947d

画线纹理之绳子

小结

分块!寻找对应的分块检测!

以上为白玉无冰使用 Cocos Creator v2.3.3 实现 "四叉树与碰撞检测" 的技术分享。如果对你有点帮助,欢迎分享给身边的朋友。

成就我们的恰恰就是那些不断重复做的事情。因此,优秀不是一种行为,而是一种习惯。

cocosCreator 3.x中,四叉树碰撞检测是一种高效的场景空间分割技术,用于处理大量游戏对象之间的碰撞检测四叉树(Quadtree)将游戏世界划分为多个区域,每个节点代表一个矩形区域,然后将这些区域递归地划分成四个更小的子区域,直到达到预定的条件,如区域内物体数量较少不再需要细分。 在ts (TypeScript)文件中,你可以通过以下步骤操作四叉树碰撞检测: 1. 首先,你需要导入cocos creator自带的碰撞库,例如`cc.PhysicsWorld`和`cc.QuadTree`。 ```typescript import { PhysicsWorld, QuadTree } from 'cocos creator'; ``` 2. 创建Physics World实例,并开启碰撞检测: ```typescript const physicsWorld = new PhysicsWorld(); world.addComponent(physicsWorld); physicsWorld.enable(); ``` 3. 初始化并创建QuadTree,通常你在游戏启动时执行: ```typescript const quadTree = new QuadTree(0, cc.size(500, 500), world); quadTree.update(); // 每次添加或删除游戏对象后更新四叉树 ``` 4. 添加游戏对象到Physics World,并注册到QuadTree上: ```typescript let sprite = ...; // 获取一个精灵 const bodyDef = new cc.PhysicsBodyDefinition({ type: cc.PhysicsBodyType.Dynamic }); bodyDef.shape = new cc.PolygonShape(sprite.getBoundingBox()); bodyDef.tag = sprite.id; sprite.addComponent(bodyDef); // 注册到碰撞系统和四叉树 physicsWorld.addBody(bodyDef, sprite.position); quadTree.insert(sprite.position, sprite); ``` 5. 当需要检查碰撞时,可以在四叉树上查找目标区域,比如查询是否与某个位置发生碰撞: ```typescript const collisionPoint = quadTree.queryPoint(position); if (collisionPoint && collisionPoint.length > 0) { // 发生碰撞,处理相应的逻辑 } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值