因为贴图不一定是一个规则图形,所以抽象出边框、然后用图形边框检测的思路有点困难。
对于不规则的贴图,我的主要思路是$spriteA$和$spriteB$先判断矩形边框是否重叠,如果重叠,取相交矩形进入像素检测。
初步判断重叠:
用sfml的函数 spriteA.intersects(spriteB) 即可,返回一个bool值表示是否重叠。
计算相交矩形:
从边出发,很显然交矩形$A\cap B$的边是$A$、$B$八条边中的其中四条。$A\cap B$的顶边是$A$、$B$顶边中的最低一条,$A\cap B$的左边是$A$、$B$左边中的最右一条,剩下两条边同理,因此可以假设存在相交矩形然后计算,之后再计算矩形是否合法(因为已经判断重叠了,所以不需要这一步)。
sf::IntRect getIntersectionInt(sf::FloatRect A, sf::FloatRect B) { int top = max((int)A.top, (int)B.top); int left = max((int)A.left, (int)B.left); int down = min((int)(A.top + A.height), (int)(B.top + B.height)); int right = min((int)(A.left + A.width), (int)(B.left + B.width)); sf::IntRect(sf::Vector2i(left, top), sf::Vector2i(right - left, down - top)); }
像素点检测
遍历一遍所有像素点,提取出像素点的颜色,可以用 color.Transparent 判断(返回bool值,表示是否透明),也可以用 color.a 判断(返回透明度,颜色的alpha值)。这里我选择用后者:
bool Weapon::isHit(Monster& monster) { sf::FloatRect weaponBounds = GetBoundingRect(); sf::FloatRect monsterBounds = monster.GetBoundingRect(); if (weaponBounds.intersects(monsterBounds) == false) // 如果矩形不重叠 return false; sf::Image weaponImage = GetSprite().getTexture()->copyToImage(); sf::Image monsterImage = monster.GetTexture()->copyToImage(); sf::IntRect intersection = getIntersectionInt(weaponBounds, monsterBounds); // 计算两个矩形的交叠矩形 for (int x = intersection.left; x <= intersection.left + intersection.width; x++) // 遍历交叠矩形的像素点 for (int y = intersection.top; y <= intersection.top + intersection.height; y++) { // 注意:Image本身没有position,因此要用相对位置 sf::Color colorA = weaponImage.getPixel(x - GetSprite().getPosition().x, y - GetSprite().getPosition().y); sf::Color colorB = monsterImage.getPixel(x - monster.GetPosition().x, y - monster.GetPosition().y); if (colorA.a > 0 && colorB.a > 0) // 如果该点两个sprite都不透明,即为重叠,碰撞成立 return true; } return false; }
标签:int,top,sf,碰撞检测,sfml,矩形,像素点,left From: https://www.cnblogs.com/wegret/p/17562802.html