tBane Temat założony przez niniejszego użytkownika |
» 2025-10-26 21:46:09 Już mam ręczne ustawianie rozmiaru i obliczanie animacji/klatek. Teraz chcę zrobić automat który niekoniecznie musi zawsze dobrze obliczać szerokośćKlatki/wysokośćKlatki/liczbęAnimacji/liczbęKlatek ale zazwyczaj żeby działał dla poprawnie narysowanych spritesheetów
// edit mam pomysł na wyznaczanie nr animacji i nr klatki animacjaID = rectPosY / maxFrameHeight; klatkaID = rectPosX / maxFrameWidth;
Co o tym myślisz pekfos ? |
|
pekfos |
» 2025-10-26 22:16:50 Twoja koncepcja nie rozwiązuje problemu jak tą animację wyświetlić w grze. Masz animację z klatkami 32x32 dla jednego aktora, z klatkami 68x68 dla drugiego, itp. Jak te animacje wyświetlisz? Musisz ręcznie podać przesunięcie dla tych animacji, zależnie od tego co w nich jest. Nie wiedziałem co masz, więc opisałem rozwiązanie które rozwiązuje wszystko. Jak masz edytor do animacji, to nie chcesz mieć jeszcze kroku ręcznego dopasowywania przez wpisanie stałych do kodu, prawda? W animowanych modelach 3d, wszystko jest względem punktu 0,0,0, bo nie ma problemu tam że model idzie w ujemne współrzędne. Tu są tylko dodatnie współrzędne, więc musisz mieć offset. Z takiego edytora powinien wychodzić plik graficzny i plik z opisem animacji. W ogólnym przypadku, nie ma żadnej reguły jak klatki są zorganizowane w pliku graficznym. |
|
tBane Temat założony przez niniejszego użytkownika |
» 2025-10-26 22:30:32 Eh. Nic nie rozumiem. Jutro spróbuję napisać kod moją metodą i wrzucę na forum. Ok? |
|
skovv |
» 2025-10-27 00:08:39 Najlepiej bez zabawy ręcznie wpisać ale jak już musisz to: - ustal kolor tła jakie ma animacja(jakiś kolor albo przezroczyste) - sprawdzaj cały obrazek w poziomych liniach od góry do momentu aż znajdziesz inne Pixel. Jeśli znajdziesz to bool coswykryto = true, int start = aktualney - dalej sprawdzasz te poziome linie w za każdym razem z y += 1 do momentu aż znajdziesz linie gdzie cała linia ma kolor tła, wtedy int przewidywanawysokosc=y - teraz lecisz piony od x=0 na wysokościach od 0 do przewidywanawysokosc. Jak coś znajdzie to coswykryto = true - lecisz dalej aż znów cała linia będzie pusta i masz int przewidywanaszerokosc=x
Da Ci to (najpewniej) klatkę, mozesz teraz napisać prowizoryczny system liczenia klatek(najlepiej w prawo):
Bool git = false Int maybex = przewidywanaszerokosc While(!git){ If(przewidywanaszerokosc podzielona przez maybex daje wynik z resztą) maybex += 1; Else { Bool byłobrazek = false; Ilośćklatek = przewidywanaszerokosc / maybex; For(i = 0; i<ilość klatek; i++){ Tu sprawdzaj czy w pionowej lini na pozycji x = i*maybex - czy było na tej linii coś poza tłem. Jeśli tak to byłobrazek= true; } If byłobrazek to maybex += 1 Else git = true } Jak wyjdzie ci te maybex to sprawdzaj czy pasuje taki wymiar dla klatkay. Myślę że cos w tym stylu
Sorry ale pisze z telefonu, musiałem pilnie wyjechać na 2 dni i bez pc :D |
|
tBane Temat założony przez niniejszego użytkownika |
» 2025-10-27 13:59:27 Ok. Mam taki kod. Co o nim sądzicie? No i dla pierwszego sprajta działa. Wypisuje 4 klatki.  Dla drugiego sprajta generuje 12 klatek (4x troll + 4x outline czarny + 4x ogień). Przydałoby się jakoś scalić te recty. Chyba nawet mam pomysł jak to zrobić. Po prostu przeiteruję wszystkie recty i zrobię sf::IntRect contains Dla trzeciego sprajta ładuje 55 klatek. Nie wiem skąd te dodatkowe ale pewnie to pojedyncze piksele. Warto by wyznaczyć tylko te największe klatki. Jako, że w moim programie najmniejsza dopuszczalna klatka ma 16x16 to odrzucę te mniejsze. Kod:#include <iostream> #include <string> #include <functional> #define NOMINMAX #include <windows.h> #include <fcntl.h> #include <io.h>
#include "SFML/Window.hpp" #include "SFML/Graphics.hpp"
std::vector < sf::IntRect > framesRects;
void loadFrame( sf::Image & image, int x, int y, sf::IntRect & frameRect, sf::Color backgroundColor ) { if( x < 0 || y < 0 || x >= image.getSize().x || y >= image.getSize().y ) return; if( image.getPixel( sf::Vector2u( x, y ) ) != backgroundColor ) { if( x < frameRect.position.x ) frameRect.position.x = x; if( y < frameRect.position.y ) frameRect.position.y = y; if( x >= frameRect.position.x + frameRect.size.x ) frameRect.size.x = x - frameRect.position.x + 1; if( y >= frameRect.position.y + frameRect.size.y ) frameRect.size.y = y - frameRect.position.y + 1; image.setPixel( sf::Vector2u( x, y ), backgroundColor ); loadFrame( image, x + 1, y, frameRect, backgroundColor ); loadFrame( image, x - 1, y, frameRect, backgroundColor ); loadFrame( image, x, y + 1, frameRect, backgroundColor ); loadFrame( image, x, y - 1, frameRect, backgroundColor ); loadFrame( image, x + 1, y + 1, frameRect, backgroundColor ); loadFrame( image, x - 1, y - 1, frameRect, backgroundColor ); loadFrame( image, x + 1, y - 1, frameRect, backgroundColor ); loadFrame( image, x - 1, y + 1, frameRect, backgroundColor ); } }
void loadAnimations( sf::Image image ) { sf::Color backgroundColor = image.getPixel( sf::Vector2u( 0, 0 ) ); for( int y = 0; y < image.getSize().y; y++ ) { for( int x = 0; x < image.getSize().x; x++ ) { if( image.getPixel( sf::Vector2u( x, y ) ) != backgroundColor ) { sf::IntRect frameRect; frameRect.position.x = x; frameRect.position.y = y; frameRect.size.x = 1; frameRect.size.y = 1; framesRects.push_back( frameRect ); loadFrame( image, x, y, frameRect, backgroundColor ); } } } }
int main() { _setmode( _fileno( stdout ), _O_U16TEXT ); sf::RenderWindow * window = new sf::RenderWindow( sf::VideoMode( { 800, 600 } ), "Anim Loader", sf::Style::Titlebar | sf::Style::Resize | sf::Style::Close ); window->setFramerateLimit( 60 ); sf::Clock fpsClock; float fps = 0.0f; int frameCount = 0; sf::Image spriteSheet; spriteSheet.loadFromFile( "spr.png" ); loadAnimations( spriteSheet ); std::wcout << "Loaded " << framesRects.size() << " frames.\n"; while( window->isOpen() ) { frameCount++; if( fpsClock.getElapsedTime().asSeconds() >= 1.0f ) { fps = frameCount / fpsClock.restart().asSeconds(); frameCount = 0; window->setTitle( L"Anim Paint - FPS: " + std::to_wstring( int( fps ) ) ); } while( const std::optional event = window->pollEvent() ) { if( event->is < sf::Event::Closed >() ) window->close(); } window->clear( sf::Color( 56, 56, 56 ) ); window->display(); } }
|
|
skovv |
» 2025-10-27 14:08:43 Czyli ogółem działa? Czyta 55 klatek bo 9x6. Możesz sprawdzac po obliczeniu klatki x y czy któres klatki nie są puste. |
|
tBane Temat założony przez niniejszego użytkownika |
» 2025-10-27 14:11:23 no właśnie sprawdzam... if( image.getPixel( sf::Vector2u( x, y ) ) != backgroundColor ) i usuwam cały kształt ... Więc nie wiem skąd te dodatkowe klatki, może jakieś piksele tam są. Tak usunąłem w dwóch miejscach piksele w spritesheet'cie i teraz pokazuje 53 klatki, wiec gdzieś jakieś piksele jeszcze są. Ale chyba wszystko dobrze działa. |
|
tBane Temat założony przez niniejszego użytkownika |
» 2025-10-27 14:39:47 Dodałem scalanie klatek i usuwanie tych z rozmiarem poniżej 16x16. Teraz poprawnie ładuje 50 klatek :-) #include <iostream> #include <string> #include <functional> #define NOMINMAX #include <windows.h> #include <fcntl.h> #include <io.h>
#include "SFML/Window.hpp" #include "SFML/Graphics.hpp"
void loadFrame( sf::Image & image, int x, int y, std::vector < sf::IntRect > & framesRectsList, sf::IntRect & frameRect, sf::Color backgroundColor ) { if( x < 0 || y < 0 || x >= image.getSize().x || y >= image.getSize().y ) return; if( image.getPixel( sf::Vector2u( x, y ) ) != backgroundColor ) { if( x < frameRect.position.x ) frameRect.position.x = x; if( y < frameRect.position.y ) frameRect.position.y = y; if( x >= frameRect.position.x + frameRect.size.x ) frameRect.size.x = x - frameRect.position.x + 1; if( y >= frameRect.position.y + frameRect.size.y ) frameRect.size.y = y - frameRect.position.y + 1; image.setPixel( sf::Vector2u( x, y ), backgroundColor ); loadFrame( image, x + 1, y, framesRectsList, frameRect, backgroundColor ); loadFrame( image, x - 1, y, framesRectsList, frameRect, backgroundColor ); loadFrame( image, x, y + 1, framesRectsList, frameRect, backgroundColor ); loadFrame( image, x, y - 1, framesRectsList, frameRect, backgroundColor ); loadFrame( image, x + 1, y + 1, framesRectsList, frameRect, backgroundColor ); loadFrame( image, x - 1, y - 1, framesRectsList, frameRect, backgroundColor ); loadFrame( image, x + 1, y - 1, framesRectsList, frameRect, backgroundColor ); loadFrame( image, x - 1, y + 1, framesRectsList, frameRect, backgroundColor ); } }
void mergeFrames( std::vector < sf::IntRect > & framesRectsList ) { int i = 0; while( i < framesRectsList.size() ) { for( int j = 0; j < framesRectsList.size(); j++ ) { if( i == j ) continue; sf::IntRect & rectA = framesRectsList[ i ]; sf::IntRect & rectB = framesRectsList[ j ]; if( rectA.findIntersection( rectB ) ) { int left = std::min( rectA.position.x, rectB.position.x ); int top = std::min( rectA.position.y, rectB.position.y ); int right = std::max( rectA.position.x + rectA.size.x, rectB.position.x + rectB.size.x ); int bottom = std::max( rectA.position.y + rectA.size.y, rectB.position.y + rectB.size.y ); rectA.position.x = left; rectA.position.y = top; rectA.size.x = right - left + 1; rectA.size.y = bottom - top + 1; framesRectsList.erase( framesRectsList.begin() + j ); if( j < i ) i--; j--; } } i += 1; } }
void deleteSmallFrames( std::vector < sf::IntRect > & framesRectsList ) { for( int i = 0; i < framesRectsList.size(); i++ ) { sf::IntRect & rect = framesRectsList[ i ]; if( rect.size.x < 16 || rect.size.y < 16 ) { framesRectsList.erase( framesRectsList.begin() + i ); i--; } } }
void loadAnimations( sf::Image image, std::vector < sf::IntRect > & framesRectsList ) { sf::Color backgroundColor = image.getPixel( sf::Vector2u( 0, 0 ) ); for( int y = 0; y < image.getSize().y; y++ ) { for( int x = 0; x < image.getSize().x; x++ ) { if( image.getPixel( sf::Vector2u( x, y ) ) != backgroundColor ) { sf::IntRect frameRect; frameRect.position.x = x; frameRect.position.y = y; frameRect.size.x = 1; frameRect.size.y = 1; loadFrame( image, x, y, framesRectsList, frameRect, backgroundColor ); framesRectsList.push_back( frameRect ); } } } mergeFrames( framesRectsList ); deleteSmallFrames( framesRectsList ); }
int main() { _setmode( _fileno( stdout ), _O_U16TEXT ); sf::RenderWindow * window = new sf::RenderWindow( sf::VideoMode( { 800, 600 } ), "Anim Loader", sf::Style::Titlebar | sf::Style::Resize | sf::Style::Close ); window->setFramerateLimit( 60 ); sf::Clock fpsClock; float fps = 0.0f; int frameCount = 0; sf::Image spriteSheet; spriteSheet.loadFromFile( "sprite sheet — kopia.png" ); std::vector < sf::IntRect > framesRectsList; loadAnimations( spriteSheet, framesRectsList ); std::wcout << "Loaded " << framesRectsList.size() << " frames.\n"; while( window->isOpen() ) { frameCount++; if( fpsClock.getElapsedTime().asSeconds() >= 1.0f ) { fps = frameCount / fpsClock.restart().asSeconds(); frameCount = 0; window->setTitle( L"Anim Paint - FPS: " + std::to_wstring( int( fps ) ) ); } while( const std::optional event = window->pollEvent() ) { if( event->is < sf::Event::Closed >() ) window->close(); } window->clear( sf::Color( 56, 56, 56 ) ); window->display(); } }
|
|
| 1 « 2 » 3 4 |