Классы Image, Tileset и Tilemovi являются надстройками над классом sf::Sprite для упрощения создания последующих сложных конструкций.
1. Image – тоже самое что и sf::Sprite. Содержит основные методы управления и плавное изменение прозрачности за счёт float alpha.
2. Tileset – унаследован от Image. Имеет часть необходимые параметры и методы для описания и управления Tileset-ом.
3. Tilemovi – унаследован от Tileset. Добавлена запрограммированная смена кадров.
Исходный код классов предоставлен в конце статьи.
Как пользоваться:
IMAGE
1. Подключаем
1 |
#include "image.h" |
2. создаём экземпляр класса и загружаем картинку
1 2 3 |
Image image; image.load("DSL.png"); image.setPosition(256, 64); |
3. рисуем в окне
1 |
image.draw(&window); |
Результат:
4. Важные особенности:
а) Загрузка производится из каталога images
б) Привязка к точке по номеру.
1 |
void setOriginNum(int number); |
Стандартно привязка по центру (5)
5. Основной функционал:
5.1. Изменение координат
1 2 3 |
image.setPosition(x,y); image.move(x,y); image.move2(distance, angle); |
Пример:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
#include "stdafx.h" //DSL Test #include "image.h" //DSL Test using namespace std; int main() { sf::RenderWindow window(sf::VideoMode(700, 700), "kychka-pc.ru/legozaur"); //////////////////////////////////////////////// //////////////////////////////////////////////// Image image01; image01.load("image01.png"); image01.setPosition(16, 16); Image image02; image02.load("image01.png"); image02.setPosition(16+32, 16); float i = 0; //////////////////////////////////////////////// //////////////////////////////////////////////// float time = 0; sf::Clock clock; while (window.isOpen()) { time = clock.getElapsedTime().asSeconds(); clock.restart(); sf::Event event; while (window.pollEvent(event)) { if (event.type == sf::Event::Closed) window.close(); } window.clear(sf::Color(100, 100, 100)); ////////////////////////////////////// ////////////////////////////////////// if(i < 3) { image01.move(50*time, 50*time); image02.move2(50*time*sqrt(2), 135); i+= time; } else { i = 0; image01.setPosition(16,16); image02.setPosition(16+32,16); } image01.draw(&window); image02.draw(&window); ////////////////////////////////////// ////////////////////////////////////// window.display(); } return 0; } |
Результат запуска:
5.2. Вращение
1 2 |
image.setRotation(angle); image.rotate(angle); |
Пример:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
#include "stdafx.h" //DSL Test #include "image.h" //DSL Test using namespace std; int main() { sf::RenderWindow window(sf::VideoMode(700, 700), "kychka-pc.ru/legozaur"); //////////////////////////////////////////////// //////////////////////////////////////////////// Image image01; Image image02; image01.load("image01.png"); image02.load("image01.png"); image01.setPosition(16, 16); image02.setPosition(16 + 32, 16); cout << "image02.getRotation() = " << image02.getRotation() << endl; image02.setRotation(90); cout << "image02.getRotation() = " << image02.getRotation() << endl; Image image1; Image image2; Image image3; image1.load("magicCircle/1/circle1.png"); image2.load("magicCircle/1/circle2.png"); image3.load("magicCircle/1/circle3.png"); image1.setPosition(350, 350); image2.setPosition(350, 350); image3.setPosition(350, 350); //////////////////////////////////////////////// //////////////////////////////////////////////// float time = 0; sf::Clock clock; while (window.isOpen()) { time = clock.getElapsedTime().asSeconds(); clock.restart(); sf::Event event; while (window.pollEvent(event)) { if (event.type == sf::Event::Closed) window.close(); } window.clear(sf::Color(100, 100, 100)); ////////////////////////////////////// ////////////////////////////////////// image2.rotate(-5*time); image3.rotate(5*time); image01.draw(&window); image02.draw(&window); image1.draw(&window); image2.draw(&window); image3.draw(&window); ////////////////////////////////////// ////////////////////////////////////// window.display(); } return 0; } |
Результат запуска
5.3 Уменьшение / увеличение размеров
1 2 3 |
image.setScale(factorX, factorY); image.scale(factor); image.scale(factorX, factorY); |
5.4 Разворот по вертикали / горизонтали
1 2 |
image.flipHorizontally(); image.flipVertically(); |
Исходный код классов:
IMAGE
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
//Image.h // v03.05.2016 // Created by Kildushov Oleg // Создатель - Кильдюшов Олег // vk.com/legozaur // kychka-pc.ru - nikname: legozaur #include "stdafx.h" #ifndef DSL_IMAGE_H #define DSL_IMAGE_H class Image { protected: float _alpha; // прозрачность sf::String file; // Файл с расширением sf::Image image; // SFML изображение sf::Texture texture; // SFML текстура sf::Sprite sprite; // SFML спрайт void update_alpha(); public: float alpha; float x; float y; int w; int h; Image(); Image(sf::String filename); void data(); void load(sf::String filename); void draw(sf::RenderWindow *window); float getPositionX(void); float getPositionY(void); void setPositionX(float x); void setPositionY(float y); void setPosition(float x, float y); void move(float dx, float dy); void move2(float distance, float angle); void setAlpha(float value_alpha); void setDAlpha(float value_alpha); float getAlpha(); void setRotation(float angle); void setRotation(sf::String str, float angle); void rotate(float angle); float getRotation(); void setScale(float factorX, float factorY); void scale(float factor); void scale(float factorX, float factorY); float getScale(); float getScaleX(); float getScaleY(); float getSizeX(void); float getSizeY(void); float getSizeXcurr(); float getSizeYcurr(); void setOriginNum(int number); sf::Sprite getSprite(); void coutPosition(void); // === NEW === void flipHorizontally(); void flipVertically(); sf::Image getImage(); void setImage(sf::Image image); void setPixel(unsigned int x, unsigned int y, const sf::Color color); sf::Color getPixel(unsigned int x, unsigned int y) const; int getAlphaPixel(unsigned int x, unsigned int y) const; // === === === }; #endif DSL_IMAGE_H // |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 |
//Image.cpp // v03.05.2016 // Created by Kildushov Oleg // Создатель - Кильдюшов Олег // vk.com/legozaur // kychka-pc.ru - nikname: legozaur #include "image.h" #include "myMath.h" void Image::update_alpha() { if(alpha < 0) _alpha = alpha = 0; if(alpha > 255) _alpha = alpha = 255; sprite.setColor(sf::Color(255,255,255,alpha)); } Image::Image() { data(); } Image::Image(sf::String filename) { data(); load(filename); w = image.getSize().x; h = image.getSize().y; } void Image::data() { x = 0; y = 0; w = 0; h = 0; setAlpha(255); } void Image::load(sf::String filename) { image.loadFromFile("images/" + filename); texture.loadFromImage(image); sprite.setTexture(texture); sprite.setTextureRect(sf::IntRect(0, 0, getSizeX(), getSizeY())); // задаём спрайту один прямоугольник для вывода setOriginNum(5); // привязка по середине w = image.getSize().x; h = image.getSize().y; } void Image::draw(sf::RenderWindow *window) { window->draw(sprite); } float Image::getPositionX(void) { return sprite.getPosition().x; } float Image::getPositionY(void) { return sprite.getPosition().y; } void Image::setPositionX(float x) { float y = sprite.getPosition().y; sprite.setPosition(x, y); } void Image::setPositionY(float y) { float x = sprite.getPosition().x; sprite.setPosition(x, y); } void Image::setPosition(float x, float y) { //sprite.setPosition(x, y); this->x = x; this->y = y; sprite.setPosition(this->x, this->y); } void Image::move(float dx, float dy) { //sprite.move(dx, dy); x+=dx; y+=dy; sprite.setPosition(x,y); } void Image::move2(float distance, float angle) { float dx = distance * mySin(angle); float dy = -1 * distance * myCos(angle); move(dx, dy); } void Image::setAlpha(float value_alpha) { alpha = value_alpha; update_alpha(); } void Image::setDAlpha(float value_alpha) { alpha += value_alpha; update_alpha(); } float Image::getAlpha() { return alpha; } void Image::setRotation(float angle) { sprite.setRotation(angle); } void Image::setRotation(sf::String str, float angle) { /* int number; if(str == "x") number = 1; else if(str == "y") number = 2; else if(str == "z") number = 3; else number = 0; switch(number) { case 1: angleX += angle; break; case 2: angleY += angle; break; case 3: angleZ += angle; break; } update_rotation(); */ } void Image::rotate(float angle) { sprite.rotate(angle); } float Image::getRotation() { return sprite.getRotation(); } void Image::setScale(float factorX, float factorY) { sprite.setScale(factorX, factorY); } void Image::scale(float factor) { sprite.scale(factor, factor); } void Image::scale(float factorX, float factorY) { sprite.scale(factorX, factorY); } float Image::getScale() { float scaleX = sprite.getScale().x; float scaleY = sprite.getScale().y; if(scaleX == scaleY) return scaleX; // or scaleY else return 0; } float Image::getScaleX() { return sprite.getScale().x; } float Image::getScaleY() { return sprite.getScale().y; } float Image::getSizeX(void) { return image.getSize().x; } float Image::getSizeY(void) { return image.getSize().y; } float Image::getSizeXcurr() { float width = image.getSize().x; float scaleX = sprite.getScale().x; return width * scaleX; } float Image::getSizeYcurr() { float height = image.getSize().y; float scaleY = sprite.getScale().y; return height * scaleY; } void Image::setOriginNum(int number) { int width = image.getSize().x; int height = image.getSize().y; switch(number) { case 1: sprite.setOrigin( 0, 0); break; case 2: sprite.setOrigin(float(width)/2, 0); break; case 3: sprite.setOrigin( width, 0); break; case 4: sprite.setOrigin( 0, float(height)/2); break; case 5: sprite.setOrigin(float(width)/2, float(height)/2); break; case 6: sprite.setOrigin( width, float(height)/2); break; case 7: sprite.setOrigin( 0, height); break; case 8: sprite.setOrigin(float(width)/2, height); break; case 9: sprite.setOrigin( width, height); break; default: cout << "Image::setOriginNum(1~9);" << endl; } } sf::Sprite Image::getSprite() { return sprite; } void Image::coutPosition(void) { cout << getPositionX() << ":" << getPositionY() << endl; } // === NEW === void Image::flipHorizontally() { image.flipHorizontally(); texture.loadFromImage(image); sprite.setTexture(texture); } void Image::flipVertically() { image.flipVertically(); texture.loadFromImage(image); sprite.setTexture(texture); } sf::Image Image::getImage() { return image; } void Image::setImage(sf::Image image) { this->image = image; w = image.getSize().x; h = image.getSize().y; texture.loadFromImage(image); sprite.setTexture(texture); sprite.setTextureRect(sf::IntRect(0, 0, getSizeX(), getSizeY())); // задаём спрайту один прямоугольник для вывода } void Image::setPixel(unsigned int x, unsigned int y, const sf::Color color) { image.setPixel(x, y, color); } sf::Color Image::getPixel(unsigned int x, unsigned int y) const { if(x<0 || y<0 || x>=w || y>=h) return sf::Color(0,0,0,0); else return image.getPixel(x, y); } int Image::getAlphaPixel(unsigned int x, unsigned int y) const { return image.getPixel(x, y).a; } // === === === // |
TILESET
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
//Tileset.h // v03.05.2016 // Created by Kildushov Oleg // Создатель - Кильдюшов Олег // vk.com/legozaur // kychka-pc.ru - nikname: legozaur #include "stdafx.h" #include "Image.h" #ifndef DSL_TILESET_H #define DSL_TILESET_H class Tileset : public Image { protected: bool flag1; // Дошёл до конца, идти обратно? (true - разворот) bool flag2; // Уже конец? bool flag3; // Нужно ли переходить на новую строку (для нелинейных тайлстов) int numFrameWcur; // текущей номер кадра по ширине int numFrameHcur; // высоте int numFrameWmax; // максимальное количество кадров на ширину int numFrameHmax; // высоту int numFrameWmax2; // максимальное текущее количество кадров на ширину int numFrameHmax2; // высоту int frameW; // ??? int frameH; // ??? int numFrame; public: Tileset(); //Tileset(sf::String filename, int number_frame_width, int number_frame_height); Tileset(sf::String filename); // void data_frames(int number_frame_width, int number_frame_height); void data_frames_blackboard(int number_frame_width, int number_frame_height); void draw(sf::RenderWindow *window); // void data(); void update_frame(); void setNumFrameWcur(int number); // void setNumFrameHcur(int number); // int getNumFrameWcur(); // int getNumFrameHcur(); // void setFlag1(bool flag); // void setFlag3(bool flag); // //bool getFlag1(); //bool getFlag3(); }; #endif DSL_TILESET_H // |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
//Tileset.cpp // v03.05.2016 // Created by Kildushov Oleg // Создатель - Кильдюшов Олег // vk.com/legozaur // kychka-pc.ru - nikname: legozaur #include "Tileset.h" Tileset::Tileset() { data(); } Tileset::Tileset(sf::String filename) { data(); load("tileset/" + filename); } void Tileset::data_frames(int number_frame_width, int number_frame_height) { numFrame = number_frame_width*number_frame_height; numFrameWmax = number_frame_width; numFrameHmax = number_frame_height; data_frames_blackboard(numFrameWmax, numFrameHmax); numFrameWcur = 1; numFrameHcur = 1; int width = getSizeX(); int height = getSizeY(); // Если ширина и высота тайлсета не 1 картинка, высчитываем ширину и высоту кадра if(number_frame_width > 1) frameW = int(width/number_frame_width); else frameW = width; if(number_frame_height > 1) frameH = int(height/number_frame_height); else frameH = height; // Устанавливаем середину в кадр sprite.setOrigin(width/numFrameWmax - frameW/2, height/numFrameHmax - frameH/2); sprite.setTextureRect(sf::IntRect((numFrameWcur-1)*frameW, (numFrameHcur-1)*frameH, frameW, frameH)); } void Tileset::data_frames_blackboard(int number_frame_width, int number_frame_height) { // Функция задаёт рабочую область Tileset-а // Используется для тайсетов, в которых есть лишние оласти numFrameWmax2 = number_frame_width; numFrameHmax2 = number_frame_height; } void Tileset::draw(sf::RenderWindow *window) { window->draw(sprite); } void Tileset::data() { flag1 = false; flag2 = false; flag3 = false; numFrame = 1; // Общее количество кадров numFrameWcur = 1; // текущее количество кадров на ширину numFrameHcur = 1; // высоту numFrameWmax = 1; // максимальное количество кадров на ширину numFrameHmax = 1; // высоту frameW = getSizeX(); // frameH = getSizeY(); // } void Tileset::update_frame() { // Обновление кадра if(flag1 == true) {// Надо ли поворачивать тайлсет? if(flag2 == true) {// Если идём назад... numFrameWcur--; if(numFrameWcur < 1) {// Если текущий кадр меньше 1 flag2 = false; numFrameWcur = 2; } } else {// Если идём вперёд numFrameWcur++; if(numFrameWcur > numFrameWmax2) { flag2 = true; numFrameWcur = numFrameWmax2-1; } } } else {// Если не надо разворачиваться в конце numFrameWcur++; if(numFrameWcur > numFrameWmax2) numFrameWcur = 1; // Если ушли за тайлсет, переходим на кадр1 } // меняем тайл визуально sprite.setTextureRect(sf::IntRect((numFrameWcur-1)*frameW, (numFrameHcur-1)*frameH, frameW, frameH)); } // Установка кадра по ширине void Tileset::setNumFrameWcur(int number) { if(number > numFrameWmax) numFrameWcur = numFrameWmax; else if(number < 1) numFrameWcur = 1; else numFrameWcur = number; sprite.setTextureRect(sf::IntRect((numFrameWcur-1)*frameW, (numFrameHcur-1)*frameH, frameW, frameH)); } // Установка кадра по высоте void Tileset::setNumFrameHcur(int number) { if(number > numFrameHmax) numFrameHcur = numFrameHmax; else if(number < 1) numFrameHcur = 1; else numFrameHcur = number; sprite.setTextureRect(sf::IntRect((numFrameWcur-1)*frameW, (numFrameHcur-1)*frameH, frameW, frameH)); } // Возвращает текущий номер кадра по ширине int Tileset::getNumFrameWcur() { return numFrameWcur; } // Возвращает текущий номер кадра по высоте int Tileset::getNumFrameHcur() { return numFrameHcur; } void Tileset::setFlag1(bool flag) { flag1 = flag; } void Tileset::setFlag3(bool flag) { flag3 = flag; } // |
TILEMOVI
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
//Tilemove.h // v03.05.2016 // Created by Kildushov Oleg // Создатель - Кильдюшов Олег // vk.com/legozaur // kychka-pc.ru - nikname: legozaur #pragma once #include "stdafx.h" #include "tileset.h" #ifndef DSL_TILEMOVI_H #define DSL_TILEMOVI_H class Tilemovi : public Tileset { private: float timeFrameCur; // время для накопления float timeFrameMax; // время для смены кадра public: Tilemovi(void); Tilemovi(sf::String filename); ~Tilemovi(void); void data(); void shift_frame(float time); void data_time_frame(float time_shift_frame); }; #endif DSL_TILEMOVI_H |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
//Tilemovi.cpp // v03.05.2016 // Created by Kildushov Oleg // Создатель - Кильдюшов Олег // vk.com/legozaur // kychka-pc.ru - nikname: legozaur #include "Tilemovi.h" Tilemovi::Tilemovi(void) { data(); } Tilemovi::Tilemovi(sf::String filename) { data(); load("tileset/" + filename); } Tilemovi::~Tilemovi(void) { // } void Tilemovi::data(void) { data_time_frame(0.25); // стандартная частота смены кадров } void Tilemovi::shift_frame(float time) { /////////////////////////////////////////////////////////// // if(numFrame <= 1) - Если(количество кадров меньше или равно 1) то менять кадр не надо /////////////////////////////////////////////////////////// if(numFrame > 1) { timeFrameCur += time; if(timeFrameCur >= timeFrameMax) { update_frame(); timeFrameCur -= timeFrameMax; } } } void Tilemovi::data_time_frame(float time_shift_frame) { // Задаёт время, при котором будет сменяться кадр timeFrameCur = 0; // timeFrameMax = time_shift_frame; // } |