Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[SFML 2.1][STL] Zapełnienie kontenera vector obiektami klasy.

Ostatnio zmodyfikowano 2014-05-08 11:44
Autor Wiadomość
chitler
Temat założony przez niniejszego użytkownika
[SFML 2.1][STL] Zapełnienie kontenera vector obiektami klasy.
» 2014-05-07 18:09:35
Witam. Mam problem tego typu że chcę w pętli for wykonywanej przez ustaloną liczbę razy, dodać nowy element do kontenera typu vector. Dodanym elementem ma być obiekt klasy "targets" z polami o typach: sf::Sprite, sf::Texture, sf::Image i innymi podstawowymi. W konstruktorze klasy "targets", nadaje każdemu elementowi własne właściwości, teksturę (akurat to każdy nowy element ma taki sam) oraz, skalę, rozmiar, położenie X i Y, które są wybierane losowo.

Chcę osiągnąć aby załóżmy pętla przeszła 3 razy, i wypełniła kontener trzema obiektami klasy "targets", a potem chcę te 3 Sprajty nanieść na ekran.

1.Tak nie działa
Zapełnanie vectora:
C/C++
int countTarget = 3;
vector < targets > test;

for( int i = 0; i < countTarget; i++ )
{
   
    test.push_back( targets() );
}
Lub tak:
C/C++
int countTarget = 3;
vector < targets > test;

for( int i = 0; i < countTarget; i++ )
{
    targets tmpTargets;
    test.push_back( tmpTargets );
}

I to się kompiluje, lecz wyświetlany obraz jest niepoprawny. Są to 3 prostokąty, o różnych skalach i położeniu, czyli tak jakby nie wczytała się tekstura do sprajta.

A gdy zrobię to tak, to działa:
C/C++
int countTarget = 3;
targets tmpTarget[ countTarget ];
vector < targets > test;

for( int i = 0; i < countTarget; i++ )
{
   
    test.push_back( tmpTarget[ i ] );
}

Nie można jakoś usprawnić tych pierwszych niedziałających sposobów, żeby działały? Jestem po prostu ciekaw, i chcę powiększyć wiedzę. Pozatym bardziej elegancko będzie bez tymczasowej tablicy statycznej.

wyświetlam to zawsze w ten sam sposób.

C/C++
for( int i = 0; i < test.size(); i++ )
{
    Window.draw( test[ i ].cel ); /*cel to pole typu sf::Sprite, któremu w konstruktorze została nadana tekstura, rozmiary i położenie*/
}

Mogę dodać jeszcze zdjęcia, tego jak to wygląda, a jak nie wygląda, oraz kody klasy. Będe bardzo wdzięczny za pomoc.
Pozdrawiam
P-109438
colorgreen19
» 2014-05-07 21:13:10
napisałes jakoś tak nie składnie. Napisz co ci nie działa, co działa, co chcesz osiągnąć a co brzydko wygląda;
P-109448
pekfos
» 2014-05-07 21:21:24
Najprawdopodobniej nie obsługujesz poprawnie kopiowania obiektu targets.

z polami o typach: sf::Sprite, sf::Texture, sf::Image i innymi podstawowymi.
Wow.. To na jakiś konkurs, na najgorszy projekt?
P-109451
chitler
Temat założony przez niniejszego użytkownika
» 2014-05-08 11:20:36
no dobra, post nie jest najlepszy, ale ja też jestem tylko początkującym programistą. pefkos, dlaczego chcesz mnie zniechęcić i zgnoić zamiast zmotyowować?
proszę o to cały projekt:
pytanie po prostu brzmi: jak najlepiej zainicjalizować objekty target i wpakować je do kontenera vector
C/C++
#include <stdio.h>
#include "SFML/Window.hpp"
#include "SFML/Graphics.hpp"
#include <string>
#include <vector>
#include <iostream>
#include <ctime>
#include <cstdlib>
#include "targets.h"
using namespace std;


bool isSpriteClicked( sf::Sprite & av_Sprite, sf::RenderWindow & av_Window )
{
   
    int mouseX = sf::Mouse::getPosition().x;
    int mouseY = sf::Mouse::getPosition().y;
   
    sf::Vector2i windowPosition = av_Window.getPosition();
   
    if( mouseX > av_Sprite.getPosition().x + windowPosition.x && mouseX <( av_Sprite.getPosition().x + av_Sprite.getGlobalBounds().width + windowPosition.x )
    && mouseY > av_Sprite.getPosition().y + windowPosition.y + 30 && mouseY <( av_Sprite.getPosition().y + av_Sprite.getGlobalBounds().height + windowPosition.y + 30 ) )
    {
        if( sf::Mouse::isButtonPressed( sf::Mouse::Left ) )
        {
            return true;
        }
        return false;
    }
   
    return false;
   
}

bool isMaskNotAlpha( sf::Image & maska, sf::RenderWindow & Window, sf::Sprite & sprajt )
{
    int mouseX = sf::Mouse::getPosition( Window ).x;
    int mouseY = sf::Mouse::getPosition( Window ).y;
    float skalaX = sprajt.getScale().x;
    float skalaY = sprajt.getScale().y;
    int sprX = sprajt.getPosition().x;
    int sprY = sprajt.getPosition().y;
    int maskaX = maska.getSize().x * skalaX;
    int maskaY = maska.getSize().y * skalaY;
   
    /*cout<<mouseX<<"x"<<mouseY<<" rozmiar X maski to:"<<maskaX<<" skala x maski:"<<skalaX<<" pozycja x origin sprajta:"<<sprX<<endl;
        cout<<mouseX<<"y"<<mouseY<<" rozmiar Y maski to:"<<maskaY<<" skala y maski:"<<skalaY<<" pozycja y origin sprajta:"<<sprY<<endl;
        cout<<"rownanie X: "<<mouseX<<" - "<<maskaX<<" - "<<sprX<<" = "<< mouseX - maskaX - sprX<<endl;
        cout<<"rownanie Y: "<<mouseY<<" - "<<maskaY<<" - "<<sprY<<" = "<< mouseY - maskaY - sprY<<endl;*/
    if( mouseX - maskaX - sprX < 0 && mouseY - maskaY - sprY < 0 )
    {
        sf::Color check = maska.getPixel(( mouseX - sprX ) *( 1 / skalaX ),( mouseY - sprY ) *( 1 / skalaX ) );
        //cout<<"sprawdzam piksela na obrazku o coordach"<< (mouseX - sprX)*(1/skalaX)  << " x "<< (mouseY - sprY)*(1/skalaX) <<endl;
        if( check.a == 255 )
             return true;
        else
             return false;
       
    }
    return false;
   
}

int main( int argc, char * argv[] )
{
    srand( time( NULL ) );
   
    sf::Texture texture2;
    if( !texture2.loadFromFile( "celownik.png" ) )
    {
        cout << "nie mozna otworzyc celownika" << endl;
    }
    sf::Sprite celownik;
    celownik.setTexture( texture2 );
    celownik.setPosition( 200, 200 );
    celownik.setOrigin( 33, 34 );
   
   
    int countTarget = 3;
    targets tmpTarget[ countTarget ];
    vector < targets > test;
   
    for( int i = 0; i < countTarget; i++ )
    {
       
        test.push_back( tmpTarget[ i ] );
    }
   
    cout << test.size();
   
   
   
   
   
    sf::RenderWindow Window( sf::VideoMode( 640, 480 ), "Shoot da Bastard" );
   
    while( Window.isOpen() )
    {
        celownik.setPosition( sf::Mouse::getPosition( Window ).x, sf::Mouse::getPosition( Window ).y );
       
       
        sf::Event Event;
        while( Window.pollEvent( Event ) )
        {
            switch( Event.type )
            {
            case sf::Event::Closed:
                Window.close();
                break;
            case sf::Event::MouseButtonPressed:
                for( int i = 0; i < test.size(); i++ )
                {
                    if( isSpriteClicked( test[ i ].cel, Window ) )
                    {
                        if( isMaskNotAlpha( test[ i ].maska, Window, test[ i ].cel ) )
                        {
                            cout << "TRAFILO W NIEPRZEZROCZYSTY" << endl;
                            //targets tmpTarget2;
                            //test.insert  /[i].insert(tmpTarget2);
                        }
                       
                    }
                    else
                         cout << "nietrafiony" << endl;
                   
                }
               
                break;
               
                default:
                break;
            }
        }
       
       
        Window.clear( sf::Color::Black );
        for( int i = 0; i < test.size(); i++ )
        {
            Window.draw( test[ i ].cel );
        }
        Window.draw( celownik );
        Window.display();
    }
    return 0;
}
plik z metodami
C/C++
#include "targets.h"
using namespace std;
targets::targets()
{
    scale = RandFloatDced( 2, 10 );
    coordX = RandInt( 0, 640 -( 350 * scale ) );
    coordY = RandInt( 0, 480 -( 350 * scale ) );
   
    if( !texture.loadFromFile( "hitlerAlfa.png" ) )
    {
        cout << "nie mozna otworzyc celu" << endl;
    }
    cel.setTexture( texture );
    cel.setPosition( coordX, coordY );
    cel.scale( scale, scale );
    if( !maska.loadFromFile( "hitlerAlfa.png" ) )
    {
        cout << "nie mozna otworzyc maski" << endl;
    }
    cout << "wylosowane coordy x:" << coordX << " y:" << coordY << endl;
    cout << "wylosowana skala: " << scale << endl;
}

int targets::RandInt( int a, int b )
{
    int result =( rand() % b - a ) + a;
    return result;
}

float targets::RandFloatDced( int a, int b )
{
    //float result = LO + static_cast <float> (rand()) /( static_cast <float> (RAND_MAX/(HI-LO)));
    float result =( rand() % b - a ) + a;
    result = result / 10;
    cout << result << endl;
    return result;
   
}
targets::~targets() { }
klasa targets
C/C++
#ifndef TARGETS_H
#define TARGETS_H
#include <cstdlib>
#include <iostream>
#include "SFML/Window.hpp"
#include "SFML/Graphics.hpp"


class targets
{
public:
    int coordX;
    int coordY;
    float scale;
    sf::Texture texture;
    sf::Sprite cel;
    sf::Image maska;
   
    targets();
    ~targets();
    int RandInt( int a, int b );
    float RandFloatDced( int a, int b );
   
   
};

#endif // TARGETS_H
P-109485
pekfos
» 2014-05-08 11:44:19
pefkos, dlaczego chcesz mnie zniechęcić i zgnoić zamiast zmotyowować?
'pekfos', a takiego zamiaru nie mam. To po prostu prawdopodobnie najgorsze możliwe rozwiązanie do przypisywania tekstur obiektom - początkujący czy nie, wiedzieć nie zaszkodzi.. I to jest też przyczyna problemu. targets nie ma konstruktora kopiującego i operatora przypisania, który zapewniłby poprawne kopiowanie sprajta. sf::Sprite trzyma tylko wskaźnika na teksturę, ustawiany w setTexture(). Obecnie, po skopiowaniu obiektu i zniszczeniu oryginału, wskaźnik nie jest poprawny. Wracając do początku - tekstury powinny być trzymane oddzielnie. Utwórz do tego klasę, lub twórz tekstury jako luźne zmienne i przypisuj je obiektom za pomocą metody podobnej to setTexture() ze sprajta. Wraz z kopiowaniem obiektu, tekstury nie zmienią swojego położenia, więc nie będziesz musiał programować kopiowania. No i tekstury będziesz ładować wtedy raz, a nie osobno do każdego obiektu, co jest wolne i pamięciożerne.
P-109486
« 1 »
  Strona 1 z 1