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

SFML losowo dzialajacy program

Object Storage Arubacloud
0 głosów
187 wizyt
pytanie zadane 23 grudnia 2016 w C i C++ przez 10kw10 Pasjonat (22,880 p.)
edycja 23 grudnia 2016 przez 10kw10

Otoz mam taki dziwny problem, program losowo sie uruchamia, raz nie, a raz tak. Nie raz u mnie jest wszystko ok, dziala tryb Debug i Release, lecz na innych komputerach juz nie.

Wydaje mi sie ze problem lezy tu po stronie wskaznika i klas wirtualnych.

kod:

Balwan.cpp

#include <SFML/Graphics.hpp>
#include <cmath>
#include <vector>
#include "Przyciski.h"
#include "Kategorie.h"

int main()
{
    sf::Font czcionka;
    sf::Texture t;sf::Sprite tlo;
    button przycisk;
    sniezka s[8];
    kostka kosc;
    kursor k; // mysz
    kategorie *wsk;
    cialo c;
    //na_glowe ng;oczy o;nos n;usta u;na_szyje ns;do_reki dr;
    //std::vector <int> adresy;
    //adresy.push_back((int)&c);
    sf::Sprite balwan[7];
    ladowanie(czcionka,t,tlo);
    przycisk.zaladuj(); // ladowanie zmiennych

    wsk=&c;

    sf::Clock zegar;
    sf::Time czas;

    sf::RenderWindow okno( sf::VideoMode( 860, 640 ), "Rysuj balwana" );
    okno.setMouseCursorVisible(false);
    while( okno.isOpen() )
    {
        przycisk.zmien(przycisk.najechany);
        sf::Vector2f mysz = okno.mapPixelToCoords(sf::Mouse::getPosition(okno));
        sf::Event zdarzenie;
        while( okno.pollEvent( zdarzenie ) )
        {
            if( zdarzenie.type == sf::Event::Closed )okno.close();
            if( zdarzenie.type == sf::Event::Resized )okno.setSize( sf::Vector2u( 860, 640 ) );
            if( zdarzenie.type == sf::Event::MouseButtonPressed && zdarzenie.mouseButton.button == sf::Mouse::Left ) // klikniecie lewym przyciskiem myszy
            {
                przycisk.klik(mysz);
                kosc.klik(mysz);
             // wsk=(kategorie*)adresy[przycisk.aktywny];
                kosc.los=10;
            }
        } //while
       wsk->ustaw(kosc.los);
       // if(kosc.rysowanie==true)balwan[0]=wsk->rysuj();

        kosc.na_kosci(mysz);
        //animacja kostki
        if(czas.asMilliseconds()>=90 && kosc.anime==true && kosc.wylosowano==false){kosc.animacja();zegar.restart();}
        if(kosc.wylosowano==true)kosc.losowanie();

        for(int i=0;i<8;i++)s[i].przejechano(mysz,przycisk.najechany,przycisk.image);
        // najechanie na image
        przycisk.najechanie(mysz);

        for(int i=0;i<8;i++){if(s[i].pierwszy==true || s[i].poza==true){s[i].losuj(przycisk.najechany,przycisk.image);}}
        okno.clear();
        okno.draw(tlo);
        przycisk.rysuj(okno);
        kosc.rysuj(okno);
        if(przycisk.anime==true){for(int i=0;i<8;i++){s[i].ruch(przycisk.najechany,przycisk.image);s[i].rysuj(okno);}}
        else {for (int i=0;i<8;i++)s[i].pierwszy=true;}
        k.rysuj(okno,mysz);
        wsk->rysuj(okno);
        //okno.draw(balwan[0]);
        okno.display();

        czas=zegar.getElapsedTime();
    } //while
    return 0;
}

Kategorie.h

#ifndef KATEGORIE_H_INCLUDED
#define KATEGORIE_H_INCLUDED

#include <SFML/Graphics.hpp>

class kategorie
{
public:
    sf::Sprite o; //obraz
    sf::Texture *t; // textura
    int posx,posy;
    virtual void ustaw(int &los)=0;
    virtual void rysuj(sf::RenderWindow &okno)=0;

};

class cialo:public kategorie
{
public:
    cialo();
    ~cialo();
    virtual void ustaw(int &los);
    virtual void rysuj(sf::RenderWindow &okno);
};

#endif // KATEGORIE_H_INCLUDED

Kategorie.cpp

#include <SFML/Graphics.hpp>
#include <iostream>
#include <windows.h>
#include <time.h>

#include "Kategorie.h"

cialo::cialo()
{
    t=new sf::Texture [6];

    t[0].loadFromFile("img/cialo/balwan1.png");
    t[1].loadFromFile("img/cialo/balwan2.png");
    t[2].loadFromFile("img/cialo/balwan3.png");
    t[3].loadFromFile("img/cialo/balwan4.png");
    t[4].loadFromFile("img/cialo/balwan5.png");
    t[5].loadFromFile("img/cialo/balwan6.png");
}

cialo::~cialo()
{
    delete t;
}

void cialo::ustaw(int &los)
{
    if(los<7)
    {
    o.setTexture(t[los-1]);
    if(los==1)o.setPosition(200,-100);
    else if(los==2)o.setPosition(200,0);
    else o.setPosition(200,-50);
    }
}

void cialo::rysuj(sf::RenderWindow &okno)
{
    okno.draw(o);
}

Zauwazylem tez ze gdy dam:

//std::vector <int> adresy;
//adresy.push_back((int)&c);

//---bez komentarzy--------

std::vector <int> adresy;
adresy.push_back((int)&c);

To juz nie dziala lub nie zawsze ;/

O co tu wgl chodzi ?! Mam wzywac egzorcyste czy jak ? :D

Pozdrawiam

komentarz 23 grudnia 2016 przez niezalogowany
Nie lepiej przechowywać adresy tak: std::vector <void*> adresy;?
komentarz 23 grudnia 2016 przez JAKUBW Nałogowiec (33,470 p.)
Jeżeli raz działa a raz nie to upewnij się, że wszystkie zmienne są inicjalizowane(zawsze mają przypisaną wartość), tak samo że wskaźnikami. W razie potrzeby użyj debugera, bo crash całej aplikacji to zazwyczaj odwołanie się do nulla.

BTW. Zamiast metody rysuj to po prostu odziedzicz klasę po klasie sf::Drawable.
komentarz 23 grudnia 2016 przez 10kw10 Pasjonat (22,880 p.)
std::vector <void*> adresy;

tzn w tej sytuacji to tak by wygladalo ? std::vector <kategoria*>adresy; a potem adresy.push_back(&c) bez zadnego rzutowania ?

 

Klasa moze dziedziczyc po 2 innych ? Jak by to wygladalo i jak mialbym wtedy uzyc okno.draw(); ?
komentarz 23 grudnia 2016 przez JAKUBW Nałogowiec (33,470 p.)

Program wywala się tu:

void sniezka::przejechano(sf::Vector2f &mysz,int &n,sf::Sprite image[])
{
    if(!(mysz.x>=image[n].getPosition().x &&    // lewa
                    mysz.x<=image[n].getPosition().x+90 && // prawa
                    mysz.y-0.0000000000001>=image[n].getPosition().y-0.0000000000001 &&    // gora
                    mysz.y+0.0000000000001<=image[n].getPosition().y+90.01))   // dol
                pierwszy=true;
}

Oraz tu:

void kursor::rysuj(sf::RenderWindow &okno,sf::Vector2f &mysz)
{
    kur.setPosition(mysz);
    okno.draw(kur);
}

I tu:

void sniezka::rysuj(sf::RenderWindow &okno)
{
    okno.draw(snieg);
}

Naruszenie ochrony pamięci... Może próbujesz rysować na nie otworzonym oknie? 

A co do pytania to tak, klasy mogą dziedziczyć po wielu klasach, ale nie w każdym języku. W c++ tak, ale w java czy C# już nie. Tam są "interfejsy". A tak będzie to wyglądać po przebudowaniu: 

//h

#ifndef KATEGORIE_H_INCLUDED
#define KATEGORIE_H_INCLUDED

#include <SFML/Graphics.hpp>

class kategorie : public sf::Drawable {
 public:
   sf::Sprite o; //obraz
   sf::Texture *t; // textura
   int posx,posy;
   virtual void ustaw(int &los)=0;
 private:
   virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const = 0;
};

class cialo:public kategorie {
 public:
   cialo();
   ~cialo();
   virtual void ustaw(int &los);
private:
   virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const;
};

#endif // KATEGORIE_H_INCLUDED

//cpp

#include <SFML/Graphics.hpp>
#include <iostream>
#include <windows.h>
#include <time.h>

#include "Kategorie.h"

cialo::cialo()
{
    t=new sf::Texture [6];

    t[0].loadFromFile("img/cialo/balwan1.png");
    t[1].loadFromFile("img/cialo/balwan2.png");
    t[2].loadFromFile("img/cialo/balwan3.png");
    t[3].loadFromFile("img/cialo/balwan4.png");
    t[4].loadFromFile("img/cialo/balwan5.png");
    t[5].loadFromFile("img/cialo/balwan6.png");
}

cialo::~cialo()
{
    delete t;
}

void cialo::ustaw(int &los)
{
    if(los<7)
    {
    o.setTexture(t[los-1]);
    if(los==1)o.setPosition(200,-100);
    else if(los==2)o.setPosition(200,0);
    else o.setPosition(200,-50);
    }
}
void cialo::draw(sf::RenderTarget& target, sf::RenderStates states) const
{
      target.draw(o);
}

A tak to możesz narysować:

okno.draw(*wsk);

Aha, no i podstawowa zasada: Nazwy klas piszemy WIELKIMI literami.

komentarz 23 grudnia 2016 przez JAKUBW Nałogowiec (33,470 p.)

A to:

k_tex[0].loadFromFile("img/kostka/kostka1.png");
    k_tex[1].loadFromFile("img/kostka/kostka2.png");
    k_tex[2].loadFromFile("img/kostka/kostka3.png");
    k_tex[3].loadFromFile("img/kostka/kostka4.png");
    k_tex[4].loadFromFile("img/kostka/kostka5.png");
    k_tex[5].loadFromFile("img/kostka/kostka6.png");
    k_tex[6].loadFromFile("img/kostka/kostka7.png");
    k_tex[7].loadFromFile("img/kostka/kostka8.png");
    k_tex[8].loadFromFile("img/kostka/kostka9.png");
    k_tex[9].loadFromFile("img/kostka/kostka10.png");
    k_tex[10].loadFromFile("img/kostka/kostka11.png");
    k_tex[11].loadFromFile("img/kostka/kostka12.png");
    k_tex[12].loadFromFile("img/kostka/kostka13.png");
    k_tex[13].loadFromFile("img/kostka/kostka14.png");

Możesz zastąpić pętlą:

for(std::size_t i = 0;i<14;i++)
      k_tex[i].loadFromFile(std::string("img/kostka/kostka" + intToStr(i+ 1) + ".png"));

Tylko dodaj najpierw funkcję:

std::string intToStr(int n)
{
     std::string tmp;
     if(n < 0) {
      tmp = "-";
      n = -n;
     }
     if(n > 9)
      tmp += intToStr(n / 10);
     tmp += n % 10 + 48;
     return tmp;
}

 

komentarz 23 grudnia 2016 przez 10kw10 Pasjonat (22,880 p.)
Tak juz sobie poradzilem i naprawilem ;)

Czym to sie rozni: dziedziczenie klasy sf::Drawable a normalne przekazanie okna i narysowanie ? Ktore lepsze ?

Bede pamietal o tej zasadzie

A tak poza tym, troche to dziwne ze na jednym komputerze normalnie dziala a na drugim juz nie :D
komentarz 23 grudnia 2016 przez JAKUBW Nałogowiec (33,470 p.)
Dziedziczenie po klasie sf Drawable jest lepsze, bo daje więcej możliwości oraz jest bardziej profesjonalnie. Wiadomo, że wszystko co jest po sf Drawable można narysować, więc to ułatwia poznanie kodu. Poza tym wtedy możesz rysować po wszystkim po czym da się rysować (dziedziczy po sf RenderTarget) a nie tylko po oknie, które z resztą dziedziczy po sf RenderTarget i po sf Window. Dodatkowo możesz wtedy rysować ze specjalnymi zmianami (sf::RenderStates) czyli na przykład z shaderami itd.
komentarz 23 grudnia 2016 przez 10kw10 Pasjonat (22,880 p.)

troche nie rozumiem tego zmieniania na str :D

moze byc tak po mojemu ?

string inttostr(int n)
{
    string tmp;
    ostringstream ss;
    ss<<n;
    tmp=ss.str();
    return tmp;
}

 

komentarz 23 grudnia 2016 przez JAKUBW Nałogowiec (33,470 p.)
Może, dowolną funkcja, byle zamieniła na string. Powinna być ta ze standardu C++ (to_string()), ale CodeBlocks ma z nią jakiś problem.
komentarz 5 stycznia 2017 przez SimiVoid Pasjonat (19,790 p.)
Przenosząc aplikację trzeba pamiętać aby także skopiować DO TEGO SAMEGO KATALOGU pliki *.dll
komentarz 5 stycznia 2017 przez 10kw10 Pasjonat (22,880 p.)
Wtedy nawet by sie nie kompilowal
komentarz 6 stycznia 2017 przez Danthee Początkujący (260 p.)

Żeby w CodeBlocksie zadziałało to_string trzeba zrobić taki myk: 

#include <iostream>
#include <string>
#include <sstream>
using namespace std;
 
template <class T>
string to_string(T obj)
{
    stringstream ss;
    ss << obj;
    return ss.str();
}

 

1 odpowiedź

0 głosów
odpowiedź 23 grudnia 2016 przez niezalogowany

Najprawdopodobniej błąd może być tutaj:

cialo::~cialo()
{
    delete t;
}

Powinno być

cialo::~cialo()
{
    delete[] t;
}

 

komentarz 23 grudnia 2016 przez 10kw10 Pasjonat (22,880 p.)
czyli w sumie wszedzie tam gdzie mam wskaznik a potem tworze tablice ? bo nie tylko tam jest tak.
komentarz 23 grudnia 2016 przez niezalogowany
Jeżeli tworzysz tablicę dynamicznie, to usuwasz ją używając delete[] wskaznik;

Podobne pytania

0 głosów
2 odpowiedzi 223 wizyt
pytanie zadane 24 sierpnia 2016 w C i C++ przez Maciek123233 Gaduła (3,400 p.)
0 głosów
0 odpowiedzi 625 wizyt
pytanie zadane 26 lipca 2019 w C i C++ przez Jakub 0 Pasjonat (23,120 p.)
0 głosów
1 odpowiedź 621 wizyt
pytanie zadane 26 marca 2017 w C i C++ przez szym3ns Użytkownik (860 p.)

92,619 zapytań

141,468 odpowiedzi

319,786 komentarzy

62,001 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

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy 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!

...