SFML и C++ Уроки \ Разработка игр › Форумы › SFML Graphics › непонятки в setOrigin
В этой теме 3 ответа, 2 участника, последнее обновление KindRedSand 5 года/лет, 11 мес. назад.
-
АвторСообщения
-
спасибо товарищи, что не бросили в пошлой проблеме, пришлось почти весь проект переписать столкнулся с проблемой
из ХМЛ файла подгружается анимация игрока пытаюсь установить кадр
C++1anim.sprite.setOrigin(0,anim.frames[0].height);но получается, что персонаж “висит” над объектами на расстоянии высоты спрайта. то есть спрайт отрисовывается из координат 0.0. в верх
если поменяю на
C++1anim.sprite.setPosition(0,anim.frames[0].height);то рисуется правильно, но при нажатии на клавишу вниз, когда персонаж должен присесть, спрайт поднимается вверх, то есть верхняя часть спрайта остаётся на месте, а нижняя уменьшается, получается что ноги поднимаются и он парит в воздухе.
как сделать, что бы было правильно?
если добавлять делитель к
C++1anim.sprite.setOrigin(0,anim.frames[0].height/ сюда);то расстояние уменьшается, если ставить число но это не выход. в данном методе у меня нет видимости высоты спрайта
C++1234567891011121314151617181920212223242526272829303132333435363738void loadFromXML(std::string fileName, Texture &t){TiXmlDocument animFile(fileName.c_str());animFile.LoadFile();TiXmlElement *head;head = animFile.FirstChildElement("sprites");TiXmlElement *animElement;animElement = head->FirstChildElement("animation");while (animElement){Animation anim;currentAnim = animElement->Attribute("title");int delay = atoi(animElement->Attribute("delay"));anim.speed = 1.0 / delay; anim.sprite.setTexture(t);TiXmlElement *cut;cut = animElement->FirstChildElement("cut");while (cut){int x = atoi(cut->Attribute("x"));int y = atoi(cut->Attribute("y"));int w = atoi(cut->Attribute("w"));int h = atoi(cut->Attribute("h"));anim.frames.push_back(IntRect(x, y, w, h));anim.frames_flip.push_back(IntRect(x, y, -w, h));cut = cut->NextSiblingElement("cut");}anim.sprite.setOrigin(0,anim.frames[0].height); // как прибить его к земле???? //set(0, ); PositionanimList[currentAnim] = anim;animElement = animElement->NextSiblingElement("animation");}}Origin это точка появления спрайта. Для анимации используется setTextureRect()
спасибо за подсказку, но все равно не понял как ей воспользоваться, поскольку в конструкторе анимации имею следующее:
C++1234567891011121314void tick(float time){if (!isPlaying) return;currentFrame += speed * time;if (currentFrame > frames.size()) {currentFrame -= frames.size();if (!loop) { isPlaying = false; return; }}int i = currentFrame;sprite.setTextureRect(frames[i]);if (flip) sprite.setTextureRect(frames_flip[i]);}а затем запускается
C++1void loadFromXML(std::string fileName, Texture &t)куда
C++1setTextureRect()запихнуть так и не придумал.
вышел из ситуации следующим образом. В классе игрока вставил костыль
C++1234void draw(RenderWindow &window){anim.draw(window, x, y + h);}вроде все хорошо, пока.
*Headbang* Sprite::setTextureRect принимает в качестве аргумента IntRect который указывает с какого места текстуры нужно брать картинку.
Ну и мы же используем язык по большей части ориентированый на ООП, дак почему же нам не использовать это?C++123456789101112131415161718192021222324252627282930313233343536//AnimatedSprite.h/// \brief A sprite that can be animated by Animation objects.class AnimatedSprite : public sf::Sprite{public:/// \brief Default Constructor.AnimatedSprite();~AnimatedSprite();/// \brief Add an animation to the sprite.void addAnimation(const std::string& name, Animation animation);/// \brief Remove an animation.void removeAnimation(const std::string& name);/// \brief Play an animation. Optional looping parameter.void playAnimation(const std::string& name, bool loop = false);/// \brief Stops the currently running animation.void stopAnimation();/// \brief Returns true if a animation is currently being playedbool isAnimationPlaying();/// \brief Returns the name of the playing animationstd::string getCurrentAnimationName();/// \brief Updates the sprite. Should be called every frame./// or by param 's' you can getvoid update(sf::Time frameTime, int Frames = -1);private:std::map<std::string, Animation> animations;std::string currentAnimation;bool looping;};C++1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859//AnimatedSprite.cpp#include "AnimatedSprite.h"AnimatedSprite::AnimatedSprite() : looping(false), currentAnimation(""){//ctor}AnimatedSprite::~AnimatedSprite(){//dtor}void AnimatedSprite::addAnimation(const std::string& name, Animation animation){animations[name] = animation;}void AnimatedSprite::removeAnimation(const std::string& name){auto pos = animations.find(name);if(pos != animations.end())animations.erase(pos);}void AnimatedSprite::playAnimation(const std::string& name, bool loop){if(animations.find(name) != animations.end()){currentAnimation = name;looping = loop;}}void AnimatedSprite::stopAnimation(){currentAnimation = "";}bool AnimatedSprite::isAnimationPlaying(){return (!currentAnimation.empty());}std::string AnimatedSprite::getCurrentAnimationName(){return currentAnimation;}void AnimatedSprite::update(sf::Time frameTime,int Frame){if(!currentAnimation.empty()) //Are we actually running an animation?{if(!animations[currentAnimation].update(frameTime, Frame) && !looping) //If the animation is finished and we are not looping, stop the animation.currentAnimation = "";else //Else we just update our subrectsetTextureRect(animations[currentAnimation].getCurrentFrame());}}C++123456789101112131415161718192021222324252627282930313233343536373839404142434445464748//Animation.h#ifndef ANIMATION_H#define ANIMATION_H#include <SFML/System/Time.hpp>#include <SFML/Graphics/Rect.hpp>#include <vector>/// \brief A class that stores animation data.class Animation{friend class AnimatedSprite;public:/// \brief Constructor.Animation(sf::Time duration = sf::Time::Zero, bool Manual = false);~Animation();/// \brief Sets the duration of the animation.void setDuration(sf::Time duration);/// \brief Add a frame to the animation.////// A frame is actually just an IntRect object which specifies the subrectangle of the texture.void addFrame(sf::IntRect rect);/// \brief Add a siquence of frames to the animation.void addComplexyUpToDown(int frameCount, int W, int H, int xStart = 0, int yStart = 0);/// \brief Add a siquence of frames to the animation.void addComplexyLeftToRight(int frameCount, int W, int H, int xStart = 0, int yStart = 0);/// \brief Add a siquence of frames to the animation.void addComplexyRightToLeft(int frameCount, int W, int H, int xStart, int yStart);private:sf::IntRect getCurrentFrame();bool update(sf::Time frametime, int Frames = -1);void reset();bool manual;sf::Time duration;sf::Time passedTime;std::vector<sf::IntRect> frames;unsigned currentFrame;};#endif // ANIMATION_HC++123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899//Animation.cpp#include "Animation.h"Animation::Animation(sf::Time dur, bool Manual) : passedTime(sf::Time::Zero), currentFrame(0){duration = dur;manual = Manual;}Animation::~Animation(){//dtor}void Animation::setDuration(sf::Time dur){duration = dur;}bool Animation::update(sf::Time frametime, int Frames){passedTime += frametime;if (!manual && Frames < 0)currentFrame = std::floor((passedTime.asSeconds()/duration.asSeconds()) * (frames.size()-1) + 0.5);else if (Frames == -2){currentFrame++;if (currentFrame > frames.size()-1){currentFrame = 0;return false;}}else if (Frames == -3){currentFrame--;if (currentFrame < 0){currentFrame = frames.size()-1;return false;}}else if (Frames > -1){currentFrame = Frames;if (currentFrame > frames.size() - 1){reset();return false;}}if(passedTime > duration && !manual){reset();return false;}return true;}sf::IntRect Animation::getCurrentFrame(){return frames[currentFrame];}void Animation::addFrame(sf::IntRect rect){frames.push_back(rect);}void Animation::addComplexyLeftToRight(int frameCount, int W, int H,int xStart, int yStart){for (int i = 1; i < frameCount; i++){addFrame(sf::IntRect(xStart+(W*i-W),yStart,W,H));}}void Animation::addComplexyRightToLeft(int frameCount, int W, int H, int xStart, int yStart){for (int i = frameCount; i > 0; i--){addFrame(sf::IntRect(xStart + (W*i - W), yStart, W, H));}}void Animation::addComplexyUpToDown(int frameCount, int W, int H, int xStart, int yStart){for (int i = 1; i < frameCount; i++){addFrame(sf::IntRect(xStart, yStart + (H*i - H), W, H));}}void Animation::reset(){passedTime = sf::Time::Zero;}C++1234567891011121314151617//ПримерAnimatedSprite sprite = AnimatedSprite();sprite.setTexture(texture);//Подгружаем текстуру как к обычному спрайтуAnimation anim1 = Animation(sf::milliseconds(1200));//В параметре указываем длительность анимации, сейчас 1,2 секундыanim1.addComplexyLeftToRight(7, 32, 64, 0, 65);//Можно добавлять и по кадрам, но этот метод позволяет добавлять кадры если они стоят в ряд куда проще//1 аргумент количество кадров, 2 - длинна каждого кадра, 3 - высота, 4 и 5 это оффсеты на текстуре по X и Y соответственноsprite.addAnimation("anim1", anim1);//Передаём анимацию спрайту с заданым именем.sprite.playAnimation("anim1");//Запускаем анимацю с заданым именемClock clock;Time time = clock.restart();sprite.update(time);//Ну и каждый тик спрайт автоматически подгонит нужный кадр если ему передавать время -
АвторСообщения
Для ответа в этой теме необходимо авторизоваться.