• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Cpp ,SFML, Własna Klasa Kształtów.

VPS Starter Arubacloud
0 głosów
752 wizyt
pytanie zadane 10 kwietnia 2018 w C i C++ przez Damian.W Początkujący (320 p.)

Witam.

Od kilku dni próbuję zrobić własny kształt, którego moim zdaniem brakuje w bibliotece SFML ( w sumie brakuje tam dużo kształtów).

Taki prostokąt z zaokrąglonymi bokami  (taki prawie owal który fajnie pasuje na guziki).

Ogólnie na początku próbowałem zrobić funkcje która narysuje kształt używając klasy sf::ConvexShape.

I udało się funkcja działa ok. Następnie przyszła Myśl żeby zrobić własną klasę kształtu co by było idealne.

I tutaj mnie wyłożyło.

Próbowałem zrobić klasę kształtu który (w środku rysuje obiekt klasy sf::ConvexShape ) i też się udało.

Ale nie mogę zmieniać pozycji ani koloru obiektu w tamtej klasie bezpośrednio tylko poprzez odwołanie się w taki sposób:
 

Mojaklasa krowa; 

krowa.setFillColor(sf::Color::Red);  // Niedziała

krowa.shape.setFillColor(sf::Color::Red); //Działa.

Więc pomyślałem żeby zamiast korzystać z sf::ConvexShape zrobić własną klasę kształtu.

Próbowałem skopiować klasę sf::ConvexShape i ją przerobić niestety kompilacja się sypie.

Próbowałem również odpalić przykładową klasę kształtu podaną przez twórców SFML niestety  nawet jej nie udało mi się zastosować  kompilacja się sypie. i nie wiem już co jest grane być może ja źle ją implementuje.

Ogólnie klas dopiero się uczę więc na pewno gdzieś robię masę błędów.

To program z klasą podaną przez SFML nie kompiluje się i wywala

||=== Build: Debug in rerer (compiler: GNU GCC Compiler) ===|
/home/damian/Desktop/rerer/main.cpp||In function ‘int main()’:|
/home/damian/Desktop/rerer/main.cpp|28|error: conflicting return type specified for ‘virtual unsigned int main()::EllipseShape::getPointCount() const’|
/usr/include/SFML/Graphics/Shape.hpp|196|error:   overriding ‘virtual std::size_t sf::Shape::getPointCount() const’|
/home/damian/Desktop/rerer/main.cpp|50|error: cannot declare variable ‘test’ to be of abstract type ‘main()::EllipseShape’|
/home/damian/Desktop/rerer/main.cpp|7|note:   because the following virtual functions are pure within ‘main()::EllipseShape’:|
/usr/include/SFML/Graphics/Shape.hpp|213|note:     virtual sf::Vector2f sf::Shape::getPoint(std::size_t) const|
||=== Build failed: 3 error(s), 0 warning(s) (0 minute(s), 2 second(s)) ===|

 

#include <SFML/Graphics.hpp>
#include "krowa.h"

int main()
{
    class EllipseShape : public sf::Shape
{
public :

    explicit EllipseShape(const sf::Vector2f& radius = sf::Vector2f(0, 0)) :
    m_radius(radius)
    {
        update();
    }

    void setRadius(const sf::Vector2f& radius)
    {
        m_radius = radius;
        update();
    }

    const sf::Vector2f& getRadius() const
    {
        return m_radius;
    }

    virtual unsigned int getPointCount() const
    {
        return 30; // fixed, but could be an attribute of the class if needed
    }

    virtual sf::Vector2f getPoint(unsigned int index) const
    {
        static const float pi = 3.141592654f;

        float angle = index * 2 * pi / getPointCount() - pi / 2;
        float x = std::cos(angle) * m_radius.x;
        float y = std::sin(angle) * m_radius.y;

        return sf::Vector2f(m_radius.x + x, m_radius.y + y);
    }

private :

    sf::Vector2f m_radius;
};
    
    sf::RenderWindow app(sf::VideoMode(800, 600), "SFML window");
    EllipseShape test;

	// Start the game loop
    while (app.isOpen())
    {
        // Process events
        sf::Event event;
        while (app.pollEvent(event))
        {
            // Close window : exit
            if (event.type == sf::Event::Closed)
                app.close();
        }

        // Clear screen
        app.clear();

        // Draw the sprite
        app.draw(test);

        // Update the window
        app.display();
    }

    return EXIT_SUCCESS;
}

Proszę o nakierowanie mnie co robię źle. Lub o jakieś przykłady.

Ogólnie chciałbym aby moja klasa robiła element konstruktorem w którym podaje parametry lub ewentualnie metoda która go  zbuduje po podaniu wymiarów i parametrów. (nie chodzi mi o algorytm bo to mam ale o ciało)

Pozdrawiam Damian.

2 odpowiedzi

+1 głos
odpowiedź 10 kwietnia 2018 przez j23 Mędrzec (194,920 p.)
edycja 10 kwietnia 2018 przez j23
int main()
{
    class EllipseShape : public sf::Shape
    {
         ...
    }

    ...
}

 

W C++ nie możesz definiować klas wewnątrz ciała funkcji.

komentarz 10 kwietnia 2018 przez Damian.W Początkujący (320 p.)

Tak wiem ale skopiowałem cały program który aktualnie miałem w C::B na forum.

A klas przeniosłem do main w akcie desperacji bo już zgłupiałem. błędy wywala takie same czy klasa jest przed main czy w main błędy są opisane w moim zapytaniu.

Nie wiem czy o takie kody chodzi.

/home/damian/Desktop/rerer/main.cpp|28|error: conflicting return type specified for ‘virtual unsigned int main()::EllipseShape::getPointCount() const’|
/usr/include/SFML/Graphics/Shape.hpp|196|error:   overriding ‘virtual std::size_t sf::Shape::getPointCount() const’|
/home/damian/Desktop/rerer/main.cpp|50|error: cannot declare variable ‘test’ to be of abstract type ‘main()::EllipseShape’|

 

komentarz 10 kwietnia 2018 przez j23 Mędrzec (194,920 p.)

Metoda getPointCount powinna zwracać wartość typu std::size_t, a nie unsigned int. Popraw to.

 

PS. czytaj aktualną dokumentację SFML-a (2.4.2).

komentarz 10 kwietnia 2018 przez Damian.W Początkujący (320 p.)

Zmieniłem i zadziałało.

Jednak zrobienie własnej klasy dziedziczącej po sf::Shape mnie przerosło.  O ile przykład działa to sam nie jestem w stanie stworzyć własnej klasy.

Zrobiłem klasę która dziedziczy po sf::ConvexShape dodałem jedną funkcję i uzyskłem efekt który chciałem.

Jednak chciałbym kiedyś zrobić to od podstaw dziedzicząc z sf::Shape

Jeżeli miałbyś jakieś ciekawe przykłady z SFML jak robić własne klasy to chętnie poczytam.

 

Moja obecna Klasa wygląda tak.

using namespace sf;
class Krowa : public ConvexShape
{
public:
    void setShape(float p_X, float p_Y,int size_x,float radius,int number_points)
    {

        if (radius>size_x/2) radius=size_x/2;
        this->setPointCount(number_points+2);
        this->setPosition(p_X,p_Y);
        this->setFillColor(Color::Red);
        //setOrigin(p_X,p_Y);
        float start=p_X+size_x-radius;
        this->setPoint(0, Vector2f(start, p_Y));
        //shape.setRotation(20);
        int loop=1;

        number_points/=4;
        for(int k=0; k<4; k++)
        {

            for(int i=1; i<=number_points; i++)
            {
                float stopnie=(90-i*(90/number_points))*0.017453293;
                float sinusA= sin(stopnie);
                float cosinusA= cos(stopnie);

                switch (loop)
                {
                case 1:
                    this->setPoint(i, Vector2f(start+cosinusA*radius, (p_Y+radius)-sinusA*radius));
                    break;
                case 2:
                    this->setPoint(i+number_points, Vector2f(start+sinusA*radius, (p_Y+radius)+cosinusA*radius));
                    break;
                case 3:
                    this->setPoint(i+(number_points*2)+1, Vector2f((p_X+radius)-cosinusA*radius, (p_Y+radius)+sinusA*radius));
                    break;
                case 4:
                    this->setPoint(i+(number_points*3)+1, Vector2f((p_X+radius)-sinusA*radius, (p_Y+radius)-cosinusA*radius));
                    break;
                }
            }

            if (loop==3) loop++;
            if (loop==2)
            {
                loop++;
                this->setPoint((number_points*2)+1, Vector2f(p_X+radius, p_Y+radius*2));
            }
            if (loop==1) loop++;
        }


    }

};

 

komentarz 10 kwietnia 2018 przez mokrowski Mędrzec (155,460 p.)
edycja 10 kwietnia 2018 przez mokrowski

@j23, abstrahując od problemu, można definiować klasy w funkcji. Często się tak robi przy metodach fabrykujących.

#include <iostream>
#include <memory>

struct CalcInt {
    virtual int calculate(int) const = 0;
    virtual ~CalcInt() {};
};

std::unique_ptr<CalcInt> calcMaker(int a) {
    class CalcImpl1: public CalcInt {
        int calculate(int a) const override {
            return a * 3;
        }
    };

    class CalcImpl2: public CalcInt {
        int calculate(int a) const override {
            return a * 10;
        }
    };
    if(a % 2) {
        return std::make_unique<CalcImpl1>();
    }
    return std::make_unique<CalcImpl2>(); 
}

int main() {
    std::cout << calcMaker(1)->calculate(2) << '\n';
}

 

komentarz 10 kwietnia 2018 przez j23 Mędrzec (194,920 p.)

@mokrowski, faktycznie, można.

 

O ile przykład działa to sam nie jestem w stanie stworzyć własnej klasy.

A co jest problemem?

komentarz 10 kwietnia 2018 przez Damian.W Początkujący (320 p.)

Chyba zrozumienia jak działa klasa Shape.

Przydał by się jakiś poradnik który tłumaczy co i jak. Z czytania dokumentacji wiele się nie dowiedziałem. Wiem że muszę użyć dwóch wirtualnych metod aby to zadziałało i dawać metodę update(). natomiast nie potrafię narysować własnego obiektu.

W Przykładzie  nie wiem jak zmusić ta metodę do narysowania czegoś innego niż elipsa koło

porostu niewidem jak zaimplementować moją funkcję w tą klasę. Bo z tego co rozumiem ona rysuje punkty.

virtual sf::Vector2f getPoint(unsigned int index)

 

komentarz 10 kwietnia 2018 przez j23 Mędrzec (194,920 p.)

Klasa pochodna powinna zdefiniować dwie metody: getPointCount i getPoint:

class Square : public sf::Shape
{
private:
	sf::Vector2f m_points[4];
	
public:
	Square()
	{
		m_points[0] = sf::Vector2f(0, 0);
		m_points[1] = sf::Vector2f(100, 0);
		m_points[2] = sf::Vector2f(100, 100);
		m_points[3] = sf::Vector2f(0, 100);

		update();
	}

	std::size_t getPointCount () const { return 4; }
 
	sf::Vector2f getPoint (std::size_t index) const 
	{
		return m_points[index];
	}

};

I w zasadzie to cała filozofia użycia klasy Shape.

komentarz 11 kwietnia 2018 przez Damian.W Początkujący (320 p.)
edycja 13 kwietnia 2018 przez Damian.W

Witam.

No i tera zaczynam rozumieć tą klasę przykład działa :) elegancko.

To tak jak by dwie funkcje które robią pętlę .

Jedna zwraca ilość wykonywanych powtórzeń  druga  rysuje z tablicy numer wektora który jest zgodny z licznikiem czyli coś jak by pętla for:).

Dzięki za pomoc teraz własne kształty stoją przede-mną otworem :)

Jak ukończę pierwszą klasę wrzucę tutaj do przeglądnięcia bo jak ktoś kto dłużej siedzi w programowaniu ją przepatrzy to wyłapie od razu czy tak powinna wyglądać i tu mam na myśli dobre nawyki programowania i styl tworzenia klas.

Pozdrawiam i dziękuję za pomoc.

Klasa Nowego obiektu "owalu" wielokąt-u koła itp.

Proszę o sugestie poprawy kodu w celach edukacyjnych.

Plik.H

#ifndef OWAL_H
#define OWAL_H
#include <SFML/Graphics.hpp>
using namespace sf;

class Owal: public Shape
{
private:
    Vector2f *m_points;
    int  tablica_jakosci[25]={4,6,8,10,12,14,16,18,20,22,24,26,32,
                              34,38,42,46,52,60,62,72,74,88,90,92};/// zmiana tablicy skutkuje wadliwym dzialaniem.
    int qualityx=32;
    int licznik=12;
public:

    float promien,size_x;

    Owal(float prom,int szer,int jakosc ); 
    ///Twoży obiekt i wprowadza dane ale go nie rysuje.
    
    void setShape();  
    /// ustawia "rysuje" aktualizuje kształt.
    
    void ustaw_jakosc(int jakosc);
    /// Ustawia jkość podaj liczbę od 0 do 24.
    ///Jakość jest zdefiniowana przez tablicę 25 elementową.
    
    void jakosc_Minus_jeden(); 
    /// Zmniejsza jakość o jeden.
    
    void jakosc_Plus_jeden();
    /// Zmniejsza jakość o jeden

    void zmien_rozmiar_x(int ile);
    /// zwiększa/zmniejsza rozmiar x o podaną wartość.
    /// np: obiekt.zmien_rozmiar(-5);  przydatne do animacji najmniejsza wartość to promień razy 2.
    
    void zmien_promien(float ile);
    /// zwiększa/zmniejsza promień o podaną wartość.
     /// np: obiekt.zmien_promien(-5.0f);  przydatne do animacji najmniejsza wartość to promień razy 2.


    std::size_t getPointCount () const;
    Vector2f getPoint (std::size_t index) const;
};
#endif // OWAL_H

Plik.cpp

#include "Owal.h"

Owal::Owal(float prom,int szer,int jakosc)
{
    if(jakosc>24) jakosc=24;
    if(jakosc<0) jakosc=0;
    this->promien=prom;
    this->size_x=szer;
    this->qualityx=this->tablica_jakosci[jakosc];
}



void Owal::setShape()
{
    this->m_points=new Vector2f[this->qualityx];
    int kat_startu;
    float angle,x,y;

    for (int polowa=1; polowa<=2; polowa++)
    {
        if (polowa==1)  kat_startu=90;
        if (polowa==2)  kat_startu=270;

        for(int i=0; i<this->qualityx/2; i++)
        {
            angle = (kat_startu+i*(180/ (qualityx/2-1)))*0.017453293 ;///kąt startu plus (kąt kroku * numer punktu polowy) zamiana na radiany
            x = std::cos(angle) * this->promien;
            y = std::sin(angle) * this->promien;
            if (polowa==1)
            {
                this->m_points[i].x=x+this->promien;
                this->m_points[i].y=y+this->promien;
            }
            if (polowa==2)
            {
                this->m_points[i+this->qualityx/2].x=x+this->size_x-this->promien;
                this->m_points[i+this->qualityx/2].y=y+this->promien;
            }
        }
    }
    update();
}
void Owal::ustaw_jakosc(int jakosc)
{

    if(jakosc>24) jakosc=24;
    if(jakosc<0) jakosc=0;
    this->qualityx=this->tablica_jakosci[jakosc];
}

void Owal::jakosc_Plus_jeden()
{
    if (this->licznik<24 && this->licznik>=0)
    {
        this->licznik++;
        this->qualityx=this->tablica_jakosci[this->licznik];
    }

}
void Owal::jakosc_Minus_jeden()
{
    if (this->licznik<=24 && this->licznik>0)
    {
        this->licznik--;
        this->qualityx=this->tablica_jakosci[this->licznik];
    }

}
void Owal::zmien_rozmiar_x(int ile)
{

    this->size_x+=ile;
    if (this->size_x<=this->promien*2) this->size_x=this->promien*2;
}
void Owal::zmien_promien(float ile)
{

    this->promien+=ile;
    if (this->promien<=1) this->promien=1;
}


std::size_t Owal::getPointCount () const
{
    return this->qualityx;
}

Vector2f Owal::getPoint (std::size_t index) const
{
    return this->m_points[index];
}

 

0 głosów
odpowiedź 27 kwietnia 2018 przez Damian.W Początkujący (320 p.)

Witam

Odpowiadam na własne pytanie dlatego że nie chcę robić nowego posta bo tema tyczy się tej samej klasy.

Otóż natrafiłem na pewne ograniczenie związane z robieniem własnych kształtów przy tej klasie i nie wiem jak to rozwiązać a może porostu się nie da i muszę pokombinować aby jeden obiekt złożyć z kilku.

Otóż klasa świetnie robi kształty wypukłe. Natomiast przy wklęsłych lub nawet wypukłych ale o dziwnych kątach zaczyna rysować inaczej niż powinna.

To znaczy i to jest dziwne punkty są niby w tym miejscu gdzie je umieściliśmy (przynajmniej ich współrzędne) ale ich nie widać są przykryte.

Ciężko to wytłumaczyć bez przykładu.

        this->punkty[0] = sf::Vector2f(0, 0);
        this->punkty[1] = sf::Vector2f(250, 0);
        this->punkty[2] = sf::Vector2f(350, 55);
        this->punkty[3] = sf::Vector2f(1160,55);
        this->punkty[4] = sf::Vector2f(1113, 0);
        this->punkty[5] = sf::Vector2f(1360, 0);
        this->punkty[6] = sf::Vector2f(1360,250);
        this->punkty[7] = sf::Vector2f(0, 250);

np punkt[2] widać na współrzędnych około 450x mimo ze leży na 350x.

I tutaj pytanie czy jest w ogóle możliwe rysowanie za pomocą tej biblioteki takich kształtów. Czy zrobić obiekt złożony z kilku mniejszych kształtów.. (to troszkę komplikuje)

Pozdrawiam Damian

Podobne pytania

0 głosów
1 odpowiedź 523 wizyt
pytanie zadane 11 marca 2018 w C i C++ przez zpawlo00 Początkujący (310 p.)
+1 głos
2 odpowiedzi 461 wizyt
pytanie zadane 6 marca 2018 w C i C++ przez zpawlo00 Początkujący (310 p.)
+3 głosów
1 odpowiedź 1,342 wizyt

92,453 zapytań

141,262 odpowiedzi

319,088 komentarzy

61,854 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...