设置对象相对于其他对象的位置
Set object position relative to other object
所以我尝试学习游戏开发,我想让我的角色可以移动它的肘部。 the elbow looks like this,它由2个精灵组成,arm1和arm2。 Arm1 可以以其原点为基础旋转,arm2 应位于 arm1 的尖端(距 arm1 原点约 60 px)。但我不知道如何将 arm2 放在正确的位置,就像在 img 中一样。我尝试使用极坐标,因为我知道角度和臂距
lines[0].position=Vector2f(arm1.getPosition().x,arm1.getPosition().y);
lines[0].color=Color::Blue;
armPos.x=arm1.getPosition().x+(d*cos(AngleToRad(arm1.getRotation()-toleransi) ));
armPos.y=arm1.getPosition().y+(d*sin(AngleToRad(arm1.getRotation()-toleransi)));
lines[1].position=armPos;
lines[1].color=Color::Blue;
cir.setPosition(armPos);
arm1.setPosition(mc.getPosition().x+10,mc.getPosition().y-50);
arm2.setPosition(arm1.getPosition().x,mc.getPosition().y-10);
,但这不起作用。我使用圆和线只是为了调试。
完整代码如下所示:
#include <SFML/Graphics.hpp>
#include <math.h>
#include <iostream>
#include <vector>
#include "Player.h"
#include "Particle.h"
using namespace sf;
float AngleToRad(float a)
{
return (a/360.0f)*3.14159265359;
}
int main()
{
RenderWindow window(VideoMode(1000,640), "Small Life");
//////////////Setup////////////
//mc//
Texture idle_texture;
idle_texture.loadFromFile("image/idle.png");
IntRect player_rect(264,0,264,264);
Sprite mc(idle_texture,player_rect);
mc.setOrigin(132,264);
Player player(&idle_texture, Vector2u(4,1),0.3f);
mc.setPosition(0,300);
mc.setScale(0.7,0.7);
//arm//
Texture arm1_texture;
arm1_texture.loadFromFile("image/arm1.png");
Sprite arm1(arm1_texture);
Texture arm2_texture;
arm2_texture.loadFromFile("image/arm2.png");
Sprite arm2(arm2_texture);
arm1.setOrigin(70,158);
arm2.setOrigin(79,158);
arm1.setScale(0.5,0.5);
arm2.setScale(0.7,0.7);
//blood//
Texture blood_texture;
blood_texture.loadFromFile("image/blood.png");
CircleShape cir(10);
cir.setOrigin(5,5);
VertexArray lines(LinesStrip,2);
cir.setFillColor(Color::Red);
float deltaTime=0.0f;
Clock clock;
Clock particle_time;
float speed=0.2f;
std::vector<Sprite>bloodVec;
std::cout<<sin(1.5708)<<" "<<cos(AngleToRad(180))<<" "<< AngleToRad(180)<<" "<<" "<<asin(1)<<" "<<acos(1)<<std::endl;
while (window.isOpen())
{
Event event;
deltaTime=clock.restart().asSeconds();
while (window.pollEvent(event))
{
if (event.type == Event::Closed)
window.close();
}
if(Keyboard::isKeyPressed(Keyboard::W)) mc.move(0,-speed);
if(Keyboard::isKeyPressed(Keyboard::S)) mc.move(0,speed);
if(Keyboard::isKeyPressed(Keyboard::A)) mc.move(-speed,0);
if(Keyboard::isKeyPressed(Keyboard::D)) mc.move(speed,0);
//blood particle//
if(particle_time.getElapsedTime().asSeconds()>1.5f)
{
IntRect blRect(0,0,200,200);
Sprite b_blood(blood_texture,blRect);
ParticleConstDrop(b_blood,mc.getPosition());
bloodVec.push_back(b_blood);
particle_time.restart();
}
int bloodCount=bloodVec.size();
for(int i=0;i<bloodCount;i++)
{
window.draw(bloodVec[i]);
}
Vector2f armPos(arm1.getPosition());
float d=30.0f;
float toleransi=90;
lines[0].position=Vector2f(arm1.getPosition().x,arm1.getPosition().y);
lines[0].color=Color::Blue;
armPos.x=arm1.getPosition().x+(d*cos(AngleToRad(arm1.getRotation()-toleransi) ));
armPos.y=arm1.getPosition().y+(d*sin(AngleToRad(arm1.getRotation()-toleransi)));
lines[1].position=armPos;
lines[1].color=Color::Blue;
cir.setPosition(armPos);
arm1.setPosition(mc.getPosition().x+10,mc.getPosition().y-50);
arm2.setPosition(arm1.getPosition().x,mc.getPosition().y-10);
arm1.setRotation(110);//arm1.getRotation()+0.1
player.Update(0,deltaTime);
mc.setTextureRect(player.plRect);
window.draw(arm1);
//window.draw(arm2);
window.draw(mc);
window.draw(cir);
window.draw(lines);
window.display();
window.clear(Color(255,255,255));
}
return 0;
}
任何人都可以告诉我我的代码有什么问题,或者有其他实现方法吗?
相对位置是通过变换合成(矩阵乘法)实现的。您可以尝试手动执行,但 SFML 已经实现了它,甚至更好:它在 sf::Sprite::draw
.
后面使用它
那么让我们看看:arm2
必须有一个相对于 arm1
的位置,那么我们该怎么做呢?
- 在
arm2
本地坐标arm2
中设置arm2
的原点,其中肘关节。
- 在
arm1
局部坐标中设置arm2
的位置,其中肘关节。
- 每次绘制
arm2
时,将 arm1
转换传递给 sf::RenderStates
。下面会进行变换乘法
// Do this once
arm2.setOrigin(elbow_x_in_arm2, elbow_y_in_arm2);
arm2.setPosition(elbow_x_in_arm1, elbow_y_in_arm1);
// But this, each time you draw them
window.draw(arm1);
window.draw(arm2, sf::RenderStates(arm1.getTransform()));
结果:
每当您移动、旋转或缩放 arm1
时,arm2
将保持附加状态。另外,如果你旋转arm2
,它会绕着肘部旋转。
重要!
arm2
的变换将表示 局部变换 ,因此即使它绘制在正确的位置,数据也不包含全局 position/rotation/scale。例如,如果你想检查 arm2
中的碰撞,你应该考虑到这一点:
// don't use this to get the bounding box
sf::FloatRect boundingBoxBad = arm2.getGlobalBounds(); // WRONG: now they are not global
// use this:
sf::Transform tr1 = arm1.getTransform();
sf::Transform tr2 = arm2.getTransform();
sf::FloatRect boundingbBoxGood = tr2.transformRect(tr1.transformRect(arm2.getLocalBounds()));
所以我尝试学习游戏开发,我想让我的角色可以移动它的肘部。 the elbow looks like this,它由2个精灵组成,arm1和arm2。 Arm1 可以以其原点为基础旋转,arm2 应位于 arm1 的尖端(距 arm1 原点约 60 px)。但我不知道如何将 arm2 放在正确的位置,就像在 img 中一样。我尝试使用极坐标,因为我知道角度和臂距
lines[0].position=Vector2f(arm1.getPosition().x,arm1.getPosition().y);
lines[0].color=Color::Blue;
armPos.x=arm1.getPosition().x+(d*cos(AngleToRad(arm1.getRotation()-toleransi) ));
armPos.y=arm1.getPosition().y+(d*sin(AngleToRad(arm1.getRotation()-toleransi)));
lines[1].position=armPos;
lines[1].color=Color::Blue;
cir.setPosition(armPos);
arm1.setPosition(mc.getPosition().x+10,mc.getPosition().y-50);
arm2.setPosition(arm1.getPosition().x,mc.getPosition().y-10);
,但这不起作用。我使用圆和线只是为了调试。 完整代码如下所示:
#include <SFML/Graphics.hpp>
#include <math.h>
#include <iostream>
#include <vector>
#include "Player.h"
#include "Particle.h"
using namespace sf;
float AngleToRad(float a)
{
return (a/360.0f)*3.14159265359;
}
int main()
{
RenderWindow window(VideoMode(1000,640), "Small Life");
//////////////Setup////////////
//mc//
Texture idle_texture;
idle_texture.loadFromFile("image/idle.png");
IntRect player_rect(264,0,264,264);
Sprite mc(idle_texture,player_rect);
mc.setOrigin(132,264);
Player player(&idle_texture, Vector2u(4,1),0.3f);
mc.setPosition(0,300);
mc.setScale(0.7,0.7);
//arm//
Texture arm1_texture;
arm1_texture.loadFromFile("image/arm1.png");
Sprite arm1(arm1_texture);
Texture arm2_texture;
arm2_texture.loadFromFile("image/arm2.png");
Sprite arm2(arm2_texture);
arm1.setOrigin(70,158);
arm2.setOrigin(79,158);
arm1.setScale(0.5,0.5);
arm2.setScale(0.7,0.7);
//blood//
Texture blood_texture;
blood_texture.loadFromFile("image/blood.png");
CircleShape cir(10);
cir.setOrigin(5,5);
VertexArray lines(LinesStrip,2);
cir.setFillColor(Color::Red);
float deltaTime=0.0f;
Clock clock;
Clock particle_time;
float speed=0.2f;
std::vector<Sprite>bloodVec;
std::cout<<sin(1.5708)<<" "<<cos(AngleToRad(180))<<" "<< AngleToRad(180)<<" "<<" "<<asin(1)<<" "<<acos(1)<<std::endl;
while (window.isOpen())
{
Event event;
deltaTime=clock.restart().asSeconds();
while (window.pollEvent(event))
{
if (event.type == Event::Closed)
window.close();
}
if(Keyboard::isKeyPressed(Keyboard::W)) mc.move(0,-speed);
if(Keyboard::isKeyPressed(Keyboard::S)) mc.move(0,speed);
if(Keyboard::isKeyPressed(Keyboard::A)) mc.move(-speed,0);
if(Keyboard::isKeyPressed(Keyboard::D)) mc.move(speed,0);
//blood particle//
if(particle_time.getElapsedTime().asSeconds()>1.5f)
{
IntRect blRect(0,0,200,200);
Sprite b_blood(blood_texture,blRect);
ParticleConstDrop(b_blood,mc.getPosition());
bloodVec.push_back(b_blood);
particle_time.restart();
}
int bloodCount=bloodVec.size();
for(int i=0;i<bloodCount;i++)
{
window.draw(bloodVec[i]);
}
Vector2f armPos(arm1.getPosition());
float d=30.0f;
float toleransi=90;
lines[0].position=Vector2f(arm1.getPosition().x,arm1.getPosition().y);
lines[0].color=Color::Blue;
armPos.x=arm1.getPosition().x+(d*cos(AngleToRad(arm1.getRotation()-toleransi) ));
armPos.y=arm1.getPosition().y+(d*sin(AngleToRad(arm1.getRotation()-toleransi)));
lines[1].position=armPos;
lines[1].color=Color::Blue;
cir.setPosition(armPos);
arm1.setPosition(mc.getPosition().x+10,mc.getPosition().y-50);
arm2.setPosition(arm1.getPosition().x,mc.getPosition().y-10);
arm1.setRotation(110);//arm1.getRotation()+0.1
player.Update(0,deltaTime);
mc.setTextureRect(player.plRect);
window.draw(arm1);
//window.draw(arm2);
window.draw(mc);
window.draw(cir);
window.draw(lines);
window.display();
window.clear(Color(255,255,255));
}
return 0;
}
任何人都可以告诉我我的代码有什么问题,或者有其他实现方法吗?
相对位置是通过变换合成(矩阵乘法)实现的。您可以尝试手动执行,但 SFML 已经实现了它,甚至更好:它在 sf::Sprite::draw
.
那么让我们看看:arm2
必须有一个相对于 arm1
的位置,那么我们该怎么做呢?
- 在
arm2
本地坐标arm2
中设置arm2
的原点,其中肘关节。 - 在
arm1
局部坐标中设置arm2
的位置,其中肘关节。 - 每次绘制
arm2
时,将arm1
转换传递给sf::RenderStates
。下面会进行变换乘法
// Do this once
arm2.setOrigin(elbow_x_in_arm2, elbow_y_in_arm2);
arm2.setPosition(elbow_x_in_arm1, elbow_y_in_arm1);
// But this, each time you draw them
window.draw(arm1);
window.draw(arm2, sf::RenderStates(arm1.getTransform()));
结果:
每当您移动、旋转或缩放 arm1
时,arm2
将保持附加状态。另外,如果你旋转arm2
,它会绕着肘部旋转。
重要!
arm2
的变换将表示 局部变换 ,因此即使它绘制在正确的位置,数据也不包含全局 position/rotation/scale。例如,如果你想检查 arm2
中的碰撞,你应该考虑到这一点:
// don't use this to get the bounding box
sf::FloatRect boundingBoxBad = arm2.getGlobalBounds(); // WRONG: now they are not global
// use this:
sf::Transform tr1 = arm1.getTransform();
sf::Transform tr2 = arm2.getTransform();
sf::FloatRect boundingbBoxGood = tr2.transformRect(tr1.transformRect(arm2.getLocalBounds()));