Mam swój wizerunek z przezroczystym tłem. Chcę znaleźć krawędzie obrazu i uformować wielokąt z obrysu. Istnieje wiele metod/sposobów, w jakie mógłbym to zrobić. Chcę to zrobić w Javie (do mojej gry, która używa JBox2d Polygons do wykrywania kolizji).

Myślałem o tym i zastanawiam się, jak to będzie działać. Mógłbym spróbować wykryć wszystkie przezroczyste piksele, a następnie odwrócić zaznaczenie i wybrać tylko piksele, które mają 1 sąsiadujący przezroczysty piksel. To wszystko jest bardzo skomplikowane i chciałbym uzyskać wskazówki.

5
liamzebedee 15 sierpień 2011, 10:05
1
Mogę sobie wyobrazić, że jeśli zrobisz to w ten sposób, otrzymasz bardzo skomplikowane wielokąty. Sugerowałbym użycie prostych kształtów, które również pomogą w problemach z wydajnością i rozgrywką.
 – 
Tom
15 sierpień 2011, 10:07
Przepraszam, jeśli to trochę noobiczne. Czym są proste kształty?
 – 
liamzebedee
15 sierpień 2011, 10:10
Koła i prostokąty to prymitywne kształty, ale trójkąty, a nawet wielokąty z kilkoma bokami są wystarczająco proste. W swoich aplikacjach/grach używam głównie pudełek i kręgów. Mógłbym ci więcej powiedzieć, ale jestem w pracy.
 – 
Tom
15 sierpień 2011, 10:17
Np. implementacje Shape, którego związek tworzą Area.
 – 
trashgod
15 sierpień 2011, 10:18

2 odpowiedzi

Najlepsza odpowiedź

Istnieją dwa aspekty do twojego pytania.

  1. Wykrywanie krawędzi. Jeśli twój obraz ma kanał alfa, powinieneś być w stanie wybrać odpowiedni próg i przeprowadzić wykrywanie krawędzi, aby znaleźć „krawędzie” przezroczystych/nieprzezroczystych pikseli. Jeśli jest to tylko GIF z „przezroczystym” kolorem, powinno to być nieco łatwiejsze, ponieważ efektywnie pracujesz z czarno-białym obrazem.

  2. Wektoryzacja. Tutaj staje się (naprawdę) trudne. Pole konwersji rastra na wektor to żyzny grunt. Przyjrzałbym się, w jaki sposób wdrażane są rozwiązania takie jak Potrace (GPL), a następnie mógłbym spróbować zbudować z tego własne.

Jednak w przypadku gry osobiście nie próbowałbym w ten sposób nawet próbować wykrywania krawędzi/kolizji w czasie rzeczywistym. Ponieważ pracuję z duszkami, używałbym obramowań i innych rastrowych techniki.

Jeśli naprawdę chcę oparte na wielokątach wykrywanie krawędzi/kolizji, prawdopodobnie zdecydowałbym się wcześniej ręcznie śledzić krawędzie i po prostu przechowywać je razem z każdym obrazem rastrowym, a następnie wykonywać na nich obliczenia (przestrzeń wymiany na czas). Zakładam, że obrazy, z którymi pracujesz, nie są generowane dynamicznie w czasie wykonywania, co umożliwia wstępne obliczenia.

3
Community 23 maj 2017, 15:06
Odnosząc się do ostatniego akapitu- zamierzam wcześniej ręcznie prześledzić krawędzie. Zastanawiam się, czy byłoby to mniej lub bardziej wydajne niż posiadanie „podstawowych” kształtów, czy naprawdę nie miałoby to żadnego wpływu na wydajność?
 – 
liamzebedee
15 sierpień 2011, 12:37
Zależałoby to w dużej mierze od implementacji i algorytmu, którego używasz (lub którego używa JBox2D). Ogólnie jednak spodziewałbym się, że prostsze kształty oznaczają szybsze wykrywanie kolizji (mniej krawędzi do sprawdzenia).
 – 
Alistair A. Israel
15 sierpień 2011, 12:58

To nie jest tak naprawdę odpowiedź na twoje pytanie, aby uzyskać idealną kolizję pikseli, ale chcę powiedzieć, że złym pomysłem jest uzależnianie urządzeń od obrazów.

  • Box2D nie obsługuje wklęsłych urządzeń.
  • Box2D (oryginalna wersja w C++, nie wiem jak to działa w JBox2D) ma limit do 8 wierzchołków na wielokąt.

Z tych dwóch powodów możesz pomyśleć o stworzeniu jednego kwadratowego urządzenia na piksel, ale będzie to bardzo kosztowne w czasie przetwarzania.

W mojej prawie ukończonej grze definiuję swoje urządzenia za pomocą edytora poziomów.
Oto fragment jednego z moich poziomów (xml):

<body id="STONE" depth="13" angle="0.000000" type="static" x="7.939437" y="0.750494" tags=""  >
    <image id="stone_img" img="IMG_STONE" depth="0" x="-0.362081" y="0.526663" w="1.400000" h="1.600000" angle="0.000000" colorize="ffffffff"/>
    <fixture id="" density="1.000000" friction="0.300000" restitution="0.300000" sensor="false" shape="rect" x="-0.188671" y="0.806253" w="1.000000" h="2.200000" angle="0.545597" tags="" />
    <fixture id="" density="1.000000" friction="0.300000" restitution="0.300000" sensor="false" shape="rect" x="0.412080" y="-0.097607" w="1.000000" h="2.200000" angle="0.000000" tags="" />
</body>

Myślę, że to najlepszy sposób pracy z Box2D.
Mam nadzieję, że to Cię zainspiruje :D

1
Martijn Courteaux 15 sierpień 2011, 14:21