旋转
如果直接用setRotation旋转,得到的不是围绕中心的,而是围绕左上角旋转的结果
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const{
if(m_attribute.RotateWithVelocity){
// 计算角度(弧度)
float angleRadians = std::atan2(m_gameWorldObject->speedv, m_gameWorldObject->speedh);
// 转换为度数
float angleDegrees = angleRadians * 180.0f / 3.14159265f;
// 设置旋转 默认纹理图片都是0度向x轴正右方向
m_rectangleShape->setRotation(angleDegrees);
}
//画
target.draw(*m_rectangleShape, states);
//画物理体积边界
sf::RectangleShape bound;
bound.setPosition((float)m_gameWorldObject->rect.left,(float)m_gameWorldObject->rect.top);//位置
bound.setSize(sf::Vector2f((float)m_attribute.Width,(float)m_attribute.Height));//大小
bound.setOutlineColor(sf::Color(255,1,221));//边界线颜色
bound.setOutlineThickness(1.0);//边界线粗细
bound.setFillColor(sf::Color(255,255,255,0));//透明填充
target.draw(bound);
//画图形边界
sf::RectangleShape abound;
abound.setPosition(m_rectangleShape->getPosition());//位置
abound.setSize(m_rectangleShape->getSize());//大小
abound.setOutlineColor(sf::Color(55,221,221));//边界线颜色
abound.setOutlineThickness(1.0);//边界线粗细
abound.setFillColor(sf::Color(255,255,255,0));//透明填充
target.draw(abound);
}其中的白底图片是绘制的箭头纹理,粉色框代表的是箭头的物理体积,蓝色框代表的是箭头纹理图片的位置和大小。旋转之后是围绕左上角旋转的结果。
所以需要使用setOrigin设置中心
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const{
if(m_attribute.RotateWithVelocity){
m_rectangleShape->setOrigin(m_rectangleShape->getSize().x/2,m_rectangleShape->getSize().y/2);
// 计算角度(弧度)
float angleRadians = std::atan2(m_gameWorldObject->speedv, m_gameWorldObject->speedh);
// 转换为度数
float angleDegrees = angleRadians * 180.0f / 3.14159265f;
// 设置旋转 默认纹理图片都是0度向x轴正右方向
m_rectangleShape->setRotation(angleDegrees);
}
//画
target.draw(*m_rectangleShape, states);
//画物理体积边界
sf::RectangleShape bound;
bound.setPosition((float)m_gameWorldObject->rect.left,(float)m_gameWorldObject->rect.top);//位置
bound.setSize(sf::Vector2f((float)m_attribute.Width,(float)m_attribute.Height));//大小
bound.setOutlineColor(sf::Color(255,1,221));//边界线颜色
bound.setOutlineThickness(1.0);//边界线粗细
bound.setFillColor(sf::Color(255,255,255,0));//透明填充
target.draw(bound);
//画图形边界
sf::RectangleShape abound;
abound.setPosition(m_rectangleShape->getPosition());//位置
abound.setSize(m_rectangleShape->getSize());//大小
abound.setOutlineColor(sf::Color(55,221,221));//边界线颜色
abound.setOutlineThickness(1.0);//边界线粗细
abound.setFillColor(sf::Color(255,255,255,0));//透明填充
target.draw(abound);
}但是因为中心被改变,不仅仅旋转围绕中心,连位置这些变换也是根据中心设定的,所以得到的是这种效果。蓝框代表的是绘制图片的位置,箭头图片需要与粉框代表的物理体积重合,但是实际上图片绘制在了左上偏离的地方。因为它不再以图片左上角作为位置根据,而是用中心作为位置根据
所以最后需要进行位置修正,让绘制偏离右下角与设置中心一样的距离,就能够重合了
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const{
if(m_attribute.RotateWithVelocity){
m_rectangleShape->setOrigin(m_rectangleShape->getSize().x/2,m_rectangleShape->getSize().y/2);
// 计算角度(弧度)
float angleRadians = std::atan2(m_gameWorldObject->speedv, m_gameWorldObject->speedh);
// 转换为度数
float angleDegrees = angleRadians * 180.0f / 3.14159265f;
// 设置旋转 默认纹理图片都是0度向x轴正右方向
m_rectangleShape->setRotation(angleDegrees);
sf::Vector2f pos = m_rectangleShape->getPosition();
pos.x += m_rectangleShape->getSize().x/2;
pos.y += m_rectangleShape->getSize().y/2;
m_rectangleShape->setPosition(pos);
}
//画
target.draw(*m_rectangleShape, states);
//画物理体积边界
sf::RectangleShape bound;
bound.setPosition((float)m_gameWorldObject->rect.left,(float)m_gameWorldObject->rect.top);//位置
bound.setSize(sf::Vector2f((float)m_attribute.Width,(float)m_attribute.Height));//大小
bound.setOutlineColor(sf::Color(255,1,221));//边界线颜色
bound.setOutlineThickness(1.0);//边界线粗细
bound.setFillColor(sf::Color(255,255,255,0));//透明填充
target.draw(bound);
//画图形边界
sf::RectangleShape abound;
abound.setPosition(m_rectangleShape->getPosition());//位置
abound.setSize(m_rectangleShape->getSize());//大小
abound.setOutlineColor(sf::Color(55,221,221));//边界线颜色
abound.setOutlineThickness(1.0);//边界线粗细
abound.setFillColor(sf::Color(255,255,255,0));//透明填充
target.draw(abound);
}一开始我觉得,如果我旋转之前setOrigin设置了中心,之后恢复中心,是不是不影响位置。结果是错的。等于一开始的没有设置中心。依旧按照左上角旋转。
if(m_attribute.RotateWithVelocity){
m_rectangleShape->setOrigin(m_rectangleShape->getSize().x/2,m_rectangleShape->getSize().y/2);
// 计算角度(弧度)
float angleRadians = std::atan2(m_gameWorldObject->speedv, m_gameWorldObject->speedh);
// 转换为度数
float angleDegrees = angleRadians * 180.0f / 3.14159265f;
// 设置旋转 默认纹理图片都是0度向x轴正右方向
m_rectangleShape->setRotation(angleDegrees);
//尝试恢复原点
m_rectangleShape->setOrigin(0,0);
}左右翻转
上面的旋转代码能够处理左右朝向的问题都转换成了角度。对于不需要根据运动方向旋转的投掷物,只需要简单的根据左右朝向翻转一下
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const{
if(m_attribute.RotateWithVelocity){
m_rectangleShape->setOrigin(m_rectangleShape->getSize().x/2,m_rectangleShape->getSize().y/2);
// 计算角度(弧度)
float angleRadians = std::atan2(m_gameWorldObject->speedv, m_gameWorldObject->speedh);
// 转换为度数
float angleDegrees = angleRadians * 180.0f / 3.14159265f;
// 设置旋转 默认纹理图片都是0度向x轴正右方向
m_rectangleShape->setRotation(angleDegrees);
sf::Vector2f pos = m_rectangleShape->getPosition();
pos.x += m_rectangleShape->getSize().x/2;
pos.y += m_rectangleShape->getSize().y/2;
m_rectangleShape->setPosition(pos);
}else if(m_gameWorldObject->speedh<0){//如果是向左速度,反转图像
//设置原点
m_rectangleShape->setOrigin(sf::Vector2f(m_rectangleShape->getLocalBounds().width, 0));
//设置缩放
m_rectangleShape->scale(-1.f, 1.f);
}
//画
target.draw(*m_rectangleShape, states);
//画物理体积边界
sf::RectangleShape bound;
bound.setPosition((float)m_gameWorldObject->rect.left,(float)m_gameWorldObject->rect.top);//位置
bound.setSize(sf::Vector2f((float)m_attribute.Width,(float)m_attribute.Height));//大小
bound.setOutlineColor(sf::Color(255,1,221));//边界线颜色
bound.setOutlineThickness(1.0);//边界线粗细
bound.setFillColor(sf::Color(255,255,255,0));//透明填充
target.draw(bound);
//画图形边界
sf::RectangleShape abound;
abound.setPosition(m_rectangleShape->getPosition());//位置
abound.setSize(m_rectangleShape->getSize());//大小
abound.setOutlineColor(sf::Color(55,221,221));//边界线颜色
abound.setOutlineThickness(1.0);//边界线粗细
abound.setFillColor(sf::Color(255,255,255,0));//透明填充
target.draw(abound);
if(m_attribute.RotateWithVelocity){
;
}else if(m_gameWorldObject->speedh<0){
//恢复缩放
m_rectangleShape->scale(-1.f, 1.f);
//恢复原点
m_rectangleShape->setOrigin(sf::Vector2f(0, 0));
}
}总结
现在就是能够处理旋转和翻转两个场景。用的代码可能不是最优雅、正确的、官方的解决办法。但是能用。