SFML и C++ Уроки \ Разработка игр › Форумы › SFML Graphics › Перед отображением спрайта показывает всю картинку
В этой теме 2 ответа, 2 участника, последнее обновление PSImozg 7 года/лет назад.
-
АвторСообщения
-
Вопрос в общем в заголовке темы. После уничтожения объекта создаю его по новой, в этот момент при нагрузке на ПК видно как сначала подгружается вся картинка и затем показывает нужный спрайт.
C++1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374#include "animationmanager.h"#include <QDebug>AnimationManager::AnimationManager() {}AnimationManager::~AnimationManager() {animList.clear();}/* name -* texture -* x -* y -* w -* h -* count -* speed -* step -* loop*/void AnimationManager::create(String name, Texture &texture, int x, int y, int w, int h, int count, float speed, int step, bool Loop) {Animation a;a.speed = speed;a.loop = Loop;a.sprite.setTexture(texture);//a.sprite.setOrigin(0, h);for (int i = 0; i < count; i++) {a.frames.push_back(IntRect(x + i * step, y, w, h));a.frames_flip.push_back(IntRect(x + i * step + w, y, -w, h));}animList[name] = a;currentAnim = name;}void AnimationManager::draw(RenderWindow &window, int x, int y) {animList[currentAnim].sprite.setPosition(x, y);window.draw(animList[currentAnim].sprite);}void AnimationManager::tick(float time) {animList[currentAnim].tick(time);}void AnimationManager::set(String name) {currentAnim = name;animList[currentAnim].flip = 0;}void AnimationManager::flip(bool b) {animList[currentAnim].flip = b;}float AnimationManager::getH() {return animList[currentAnim].frames[0].height;}float AnimationManager::getW() {return animList[currentAnim].frames[0].width;}bool AnimationManager::isPlaying() {return animList[currentAnim].isPlaying;}void AnimationManager::pause() {animList[currentAnim].isPlaying = false;}void AnimationManager::play() {animList[currentAnim].isPlaying = true;}C++123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134#include "enemy.h"#include <QDebug>Enemy::Enemy(AnimationManager &a, int x, int y, std::vector<Object> objects): Entity(a, x, y) {obj = objects;anim.set("resp1");life = true;posX = x;posY = y;dx = 0;dy = 0;timer = 0;moveRandom();option("Enemy", 10);collision();}void Enemy::update(float time) {timer += time;collision();if (dx == 0 && dy == 0) {//anim.pause();}x += dx * time * 0.3;y += dy * time * 0.3;if (timer > 5000) {moveRandom();timer = 0;}anim.tick(time);}void Enemy::drive() {}void Enemy::collision() {for (unsigned int i = 0; i < obj.size(); i++) {if (getRect().intersects(obj[i].rect)) {if (obj[i].name == "solid" || obj[i].name == "water") {switch (direction_) {case 'D':y = obj[i].rect.top - h;moveRandom();break;case 'U':y = obj[i].rect.top + obj[i].rect.height;moveRandom();break;case 'R':x = obj[i].rect.left - w;moveRandom();break;case 'L':x = obj[i].rect.left + obj[i].rect.width;moveRandom();break;default:break;}}}}if (Health <= 0) {anim.set("driveUp1");anim.set("TankBoom");dx = 0;dy = 0;if (anim.isPlaying() == false) {life = false;}}}void Enemy::moveUp() {dy = -0.1;dx = 0;anim.set("driveUp1");direction_ = 'U';}void Enemy::moveDown() {dy = 0.1;dx =0;anim.set("driveDown1");direction_ = 'D';}void Enemy::moveLeft() {dx = -0.1;dy =0;anim.set("driveH1");anim.flip(true);direction_ = 'L';}void Enemy::moveRight() {dx = 0.1;dy = 0;anim.set("driveH1");direction_ = 'R';}void Enemy::moveRandom() {int num;num = rand() % 4 ;switch (num) {case 0:moveUp();break;case 1:moveDown();break;case 2:moveLeft();break;case 3:moveRight();break;default:break;}}//void Enemy::shot() {//}C++123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198#include "gametanks.h"#include <QtTest/qtest.h>GameTanks::GameTanks() {m_numberEnemy = 1;srand(QDateTime::currentMSecsSinceEpoch());}void GameTanks::startGame() {// Создаем главное окно приложенияsf::RenderWindow window(sf::VideoMode(825, 627), "Tanks");//Загружаем шрифтFont font;font.loadFromFile("sansation.ttf");//Загрузка текстурm_texturesMap.insert("Tank", getTexture("tank.png")); //TODO: Оптимизировать для нескольких текстур.Menu menu;menu.startMenu2(window);Levels lvl;lvl.LoadFromFile();AnimationManager animTank;animTank.create("resp", m_texturesMap["Tank"], 331, 1, 30, 30, 1, 0.005);animTank.create("driveH", m_texturesMap["Tank"], 331, 67, 30, 30, 8, 0.005, 33);animTank.create("driveDown", m_texturesMap["Tank"], 331, 34, 30, 30, 8, 0.005 , 33);animTank.create("driveUp", m_texturesMap["Tank"], 331, 1, 30, 30, 8, 0.005 , 33);AnimationManager animBullet; //TODO: Переделать отображение полета пуль во все стороныanimBullet.create("shootH", m_texturesMap["Tank"], 145, 1, 5, 30, 1, 0.01);animBullet.create("shootW", m_texturesMap["Tank"], 100, 13, 30, 5, 1, 0.01);animBullet.create("shootBoom", m_texturesMap["Tank"], 1, 1, 30, 30, 3, 0.005, 33, false);AnimationManager animEnemy;animEnemy.create("resp1", m_texturesMap["Tank"], 331, 133, 30, 30, 1, 0.005);animEnemy.create("driveH1", m_texturesMap["Tank"], 331, 199, 30, 30, 8, 0.005, 33);animEnemy.create("driveDown1", m_texturesMap["Tank"], 331, 166, 30, 30, 8, 0.005 , 33);animEnemy.create("driveUp1", m_texturesMap["Tank"], 331, 133, 30, 30, 8, 0.005 , 33);animEnemy.create("TankBoom", m_texturesMap["Tank"], 1, 1, 30, 30, 3, 0.005, 33, false);//std::list<Entity *> entities;std::list<Entity *>::iterator it;Player Tank(animTank, 364, 563, lvl.GetAllObjects());Text score("", font, 28);score.setColor(Color::Red);score.setPosition(35, 1);Text healText("", font, 28);healText.setColor(Color::Red);healText.setPosition(635, 590);Enemy *enemy = new Enemy(animEnemy, 364, 400, lvl.GetAllObjects());entities.push_back(enemy);SoundBuffer buffer;buffer.loadFromFile("tank_fire_bullet.ogg");Sound musicFire;musicFire.setBuffer(buffer);SoundBuffer buffer2;buffer2.loadFromFile("tank_explode.ogg");Sound musicBoom;musicBoom.setBuffer(buffer2);musicBoom.setVolume(50);// Создаем переменную таймера (нужен для плавной анимации)sf::Clock clock;// Главный цикл приложенияwhile (window.isOpen()) {QTest::qSleep(10);ostringstream scoreStream;scoreStream << Tank.getScore();score.setString("Score: " + scoreStream.str());ostringstream healStream;healStream << Tank.getHealth();healText.setString("Health: " + healStream.str());// Обрабатываем события в циклеsf::Event event;while (window.pollEvent(event)) {// Кроме обычного способа наше окно будет закрываться по нажатию на Escapeif (event.type == sf::Event::Closed ||(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape)) {window.close();}if (event.type == Event::KeyPressed) {if (event.key.code == Keyboard::Space) {entities.push_back(new Bullet(animBullet, Tank.x, Tank.y, Tank.getLastKey(), lvl.GetAllObjects()));musicFire.play();}}}if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) {Tank.key["L"] = true;}if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) {Tank.key["R"] = true;}if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) {Tank.key["Up"] = true;}if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) {Tank.key["Down"] = true;}if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space)) {Tank.key["Space"] = true;}// Очисткаwindow.clear();// Здесь мы сохраняем прошедшее время в миллисекундах и перезапускаем таймерfloat time = clock.getElapsedTime().asMicroseconds();clock.restart();time = time / 700; // здесь регулируем скорость игрыif (time > 20) {time = 20;}lvl.Draw(window);Tank.update(time);Tank.draw(window);//Проверяем столкновение пули с врагомfor (it = entities.begin(); it != entities.end(); it++) {if ((*it)->Name == "Bullet") {Entity *bullet = *it;for (std::list<Entity *>::iterator it2 = entities.begin(); it2 != entities.end(); it2++) {Entity *enemy = *it2;if ((*it2)->Name == "Enemy") {if (bullet->Health > 0) {if (bullet->getRect().intersects(enemy->getRect())) {bullet->Health = 0;enemy->Health -= 5;}}}}}}//Проверяем жив ли объект, если нет то удаляем егоfor (it = entities.begin(); it != entities.end();) {Entity *b = *it;b->update(time);if (b->life == false) {if (b->Name == "Bullet") {musicFire.stop();musicBoom.play();}if (b->Name == "Enemy") {m_numberEnemy--;Tank.setScore(100);}it = entities.erase(it);delete b;} else {it++;}}if (m_numberEnemy == 0) {int x = 32 + rand() % 728;int y = 32 + rand() % 531;qDebug () << "x" << x << "y" << y ;entities.push_back(new Enemy(animEnemy, x, y, lvl.GetAllObjects()));m_numberEnemy++;}//Отрисовываем динамические объектыfor (it = entities.begin(); it != entities.end(); it++) {(*it)->draw(window);}window.draw(score);window.draw(healText);// Тут будут вызываться функции обновления и отрисовки объектовwindow.display();}}При таком же создании пули, этой проблемы не возникает.
Вложения:
You must be logged in to view attached files.Если при создании объекта вы вызываете texture.loadFromFile(“name.png”), то переместите загрузку текстур в отдельное место, и при создании нового объекта указывайте ссылку на уже загруженную текстуру в качестве аргумента. Тоже самое касается остальных файлов ресурсов, звуки, музыка.
Вот наглядный пример.
C++1234567891011121314151617#pragma once#include<SFMLGraphics.hpp>typedef sf::Texture JPG, PNG;class Texture{public:PNG arnold_Platformer;JPG wall;private:inline void Load(sf::Texture& t, sf::String file);inline void LoadSmoth(sf::Texture& t, sf::String file);public: Texture(void);};C++1234567891011121314151617#pragma once#include<SFMLGraphics.hpp>typedef sf::Texture JPG, PNG;class Texture{public:PNG arnold_Platformer;JPG wall;private:inline void Load(sf::Texture& t, sf::String file);inline void LoadSmoth(sf::Texture& t, sf::String file);public: Texture(void);};C++1234567891011121314151617Texture::Texture(void){Load(arnold_Platformer, "arnold_platformer.png");Load(wall, "crate.png");}#include "Texture.h"inline void Texture::LoadSmoth(sf::Texture& t, sf::String file){t.loadFromFile("Textures/"+file);t.setSmooth(true);}inline void Texture::Load(sf::Texture& t, sf::String file){t.loadFromFile("Textures/"+file);}C++12wall[0] = new Wall(vec2f(-37.5f,-37.5f), vec2f(10.f,75.f), texture.wall, world, 0, "Wall");wall[1] = new Wall(vec2f(5.f,0.f), vec2f(75.f,10.f), texture.wall, world, 0, "Wall");Если я вас правильно понял, то для текстуры у меня именно так и сделано. Или примерно так.
C++1m_texturesMap.insert("Tank", getTexture("tank.png"));Но дело не в этом. Код еще сырой и экспериментальный. Поэтому требует многих изменений.
По поводу моей проблемы. Я ее таки решил. Была она в том, что при создании динамического объекта в который я передавал анимацию. Не успевал срабатывать метод setTextureRect у объекта <b>Sprite.</b>
-
АвторСообщения
Для ответа в этой теме необходимо авторизоваться.