使用最小数量的位来从碰撞对列表中创建碰撞位
using minimum amount of bits to create collision bitmask from Collision Pair List
确定一对对象- a
和 b
-可以相互碰撞,大多数物理引擎(例如参考1,2(使用以下公式: -
((a.m1 & b.m2) !=0) && ((a.m2 & b.m1) !=0)
上面公式中的&
是"answers" bit mask operation。
如果我有各种类型的实体,则为他们创建位掩码的一种简单方法是定义碰撞对列表。
碰撞对列表的示例: -
-
player
可以与另一个player
碰撞 -
tree
可以与bullet
碰撞 -
tree
可以与另一个tree
碰撞 -
bullet
可以与另一个bullet
碰撞
要计算m1
和m2
,我将m1
分配为1,2,4,8,...
。最后,我对每对进行"或" "操作(请参见下面的makeItCollide()
(。
这是代码(coliru demo(: -
#include <iostream>
#include <string>
class Mask{
public: int m1=0;
public: int m2=0;
};
void makeItCollide(Mask& mask1,Mask& mask2){
mask1.m2=mask1.m2|mask2.m1;
mask2.m2=mask2.m2|mask1.m1;
}
int main(){
Mask player;
Mask tree ;
Mask bullet;
Mask air ;
int run=1;
player.m1=run;run*=2; //1
tree .m1=run;run*=2; //2
bullet.m1=run;run*=2; //4
air .m1=run;run*=2; //8
makeItCollide(player,player);
makeItCollide(tree ,bullet);
makeItCollide(tree ,tree);
makeItCollide(bullet,bullet);
//test :
//(tree.m1 & bullet.m2 != 0) && (tree.m2 & bullet.m1 != 0) --> true
//(player.m1 & air.m2 != 0) && (player.m2 & air.m1 != 0) --> false
}
它有效。但是,我非常浪费地使用钻头。(1型1位(
如果我有64 类型,那将是有问题的。
问题:
如何计算m1
&amp;m2
来自任何一般碰撞对列表以达到最小量的位?
解决方案不需要完整的代码。
换句话说,只有粗略的指南可能非常有用。
编辑:(根据Dempzorz的评论澄清(
上面示例中更好的解决方案之一可能是: -
-
air.m1
= 0,air.m2
= 0 -
player.m1
= 1,player.m2
= 1 -
tree.m1
= 2,tree.m2
= 3 -
bullet.m1
= 2,bullet.m2
= 3
此解决方案仅对m1
使用2位用于m2
。
这也是我的算法有多差的证据(4 4位(。
碰撞的(对称(矩阵:
让使用代码中的std::vector<std::bitset>
来简化,而不是比特菲尔德:
template <std::size_t N>
void Simplify(const std::vector<std::bitset<N>>& m)
{
int index = 1;
for (const auto& b : m) {
std::bitset<4> res;
for (std::size_t i = 0; i != b.size(); ++i) {
if (b[b.size() - 1 - i]) {
res |= m[i];
}
}
if (res == b && b.count() != 1) {
std::cout << index << "th type can be removedn";
return;
}
++index;
}
std::cout << "No more simplicationsn";
}
让我们用样本进行测试:
const std::vector<std::bitset<4>> m4 = {
std::bitset<4>{"1000"}, // player
std::bitset<4>{"0110"}, // tree
std::bitset<4>{"0110"}, // bullet
std::bitset<4>{"0000"}, // air
};
Simplify(m4); // 2th type can be removed
const std::vector<std::bitset<4>> m3 = {
std::bitset<4>{"100"}, // player
std::bitset<4>{"010"}, // tree/bullet
std::bitset<4>{"000"}, // air
};
Simplify(m3); // 3th type can be removed
const std::vector<std::bitset<4>> m2 = {
std::bitset<4>{"10"}, // player
std::bitset<4>{"01"}, // tree/bullet
};
Simplify(m2); // No more simplifications
demo
相关文章:
- Pybind11:将元组列表从Python传递到C++
- 从链接列表c++中删除一个项目
- 如何(从固定列表中)选择一个数字序列,该序列将与目标数字相加
- C++如何通过用户输入删除列表元素
- 读取文件的最后一行并输入到链接列表时出错
- 复制列表初始化的隐式转换的等级是多少
- LNK2038、MSVS2017 MAGMA的原因列表
- 不能在初始值设定项列表中将非常量表达式从类型 'int' 缩小到'unsigned long long'
- 没有为自己的结构调用列表推回方法
- 使用简单类型列表实现的指数编译时间.为什么
- 一对向量构造函数:初始值设定项列表与显式构造
- 标准是否使用多余的大括号(例如 T{{{10}}})定义列表初始化?
- 通过for循环使用用户输入填充列表
- C++:如何使函数只返回作为列表一部分的字符串
- 概念中的cv限定符需要表达式参数列表
- 下面是我为检测链接列表中的循环而制作的代码
- 建议在运行时将带有类实例的列表从c++导入qml
- 如何维护资源管理器项目视图中当前可见的项目列表
- 使用最小数量的位来从碰撞对列表中创建碰撞位
- 在单独列表中的两个精灵的碰撞