Wszystkie pliki, screeny z debuggera, film z problemem na dysku gogle
Witam
Tworzę w builderze arkanoida, na początku tworzy obiekt figure i tworzy za pomocą jego metod taką odwróconą piramidkę z bloczków które mamy trafić.
W timerze mam pętlę która sprawdza po kolei wszystkie bloki (wskaźniki do TImage zawarte w vectorze utworzonym wraz z obiektem figure) czy ich Visible==true, potem czy piłka się od któregoś odbije, a następnie jeśli piłka dotknęła którejś ściany bloku to ustawia jego Visible na false (funkcja collReflex używa funkcji wallcheck, więc jeśli jedna się "uaktywni" to druga na pewno też, sprawdzałem to).
Gdy uruchamiam grę (żadnych warningów ani errorów od kompilatora) wszystko jest dobrze, piłka spada, przegrywam, uruchamia się funkcja reset() i gram od nowa.
Za drugim razem czasami (na oko w 70% przypadków) trafiam jakiś blok, piłka się odbija,** jego Visible ustawiane jest na false a blok nie znika.**
Następnie gdy piłka "wleci" w ten blok to przeleci pod nim bez odbicia i trafi następne bloki które zachowają się tak samo.
Blok nie znika pomimo, że na pewno ma ustawione Visible na false, po linijce która to ustawiała wstawiłem ifa który to potwierdził
if(figure->blocks[i]->Visible==false) { Label2->Caption=i;}
oraz sprawdziłem w debuggerze (screeny załączę, w okienku do poglądania zmiennych widać że block[9] visible=false) oraz, żeby było ciekawiej, dla tego bloku wykonuje się później warunek
if(figure->blocks[i]->Visible==true
jednak mimo to piłka od tego bloku widmo się nie odbija choć jest wystarczająco blisko.
Nie mam pojęcia o co chodzi, poniżej fragmenty kodu z paroma objaśnieniami
Fragment z timera w głównym pliku, timer porusza obiektem ball i sprawdza kolizje z blokami
void __fastcall TForm1::ruchTimer(TObject *Sender)
{
// [CODE]
for(unsigned int i=0;i<figure->num_blocks();i++)
{
if(figure->blocks[i]->Visible==true) //ten warunek czasami potrafi się wykonać nawet na bloku którego visible==false
{
collReflex(figure->blocks[i],ball,x,y,0,wallcheck::out); // "sprawdź czy blocks[i] jest blisko, sprawdź z której strony bloku i w odpowiedni sposób go odbij"
if(wallCheck(figure->blocks[i],ball,0,wallcheck::out)!=wallcheck::none) //jeśli ball nie nie dotyka żadnej ściany blocks[i] (ściana != none) to:
{
figure->blocks[i]->Visible=false; //za każdym razem gdy powinien, warunek przepuszcza tutaj kompilator, visible jest zmieniane na false
got_hit++; //ilość trafionych bloków
if(figure->blocks[i]->Visible==false) //ten warunek zawsze się spełnia wtedy kiedy powinien (bo blok faktycznie został trafiony), jednak ja nadal widzę ten blok
{Label1->Caption="true"; Label2->Caption=i;} //drugi caption widać na filmie który też wrzucę tu gdzieś, aby mieć pewność że o ten blok chodzi
break;
}
}
}
if(got_hit==figure->num_blocks())
win();
}
Funkcja restart()( która może mieć znaczenie bo przed jej drugim wywołaniem działa poprawnie, pierwsze wywołanie w konstruktorze TForm1, drugie po pierwszej przegranej )
void restart()
{ delete figure; //ustawione na wszelki wypadek, bo naprawdę już nie wiem co robię źle
figure=new Figure(Form1,BRICKBMP); // w pliku nagłówkowym głównego pliku znajduje się deklaracja Figure * figure; oraz #include "SetFigure.h" który załączę poniżej
figure->set_figure(Form1,Figure::pyramid,3); //utwórz odwróconą piramidę która ma 3 piętra w Form1
//[CODE] bez znaczenia, ustawianie pozycji ball i paddle
got_hit=0;
}
SetFigure.h - plik nagłówkowy klasy Figure, załączę kod w całości
class Figure
{
private:
String BLOCKBMP; //set_bmp_file(String)
TForm* parent_form;
unsigned int numBlocks; //num_blocks()
unsigned int levels; //get_lvls()
unsigned int bmp_width; //get_bmp_width()
unsigned int bmp_height; //get_bmp_height()
bool defPosChanged; //control
bool bmp_changed; //control
int startTop; //
int startLeft; //
int between_hor; //get_between_hor()
int between_ver; //get_between_ver()
public:
std::vector <TImage*> blocks; //vector contains all the blocks in figure
enum choose {pyramid=0 };
//constructor:
Figure(TForm*,String);
//public methods:
unsigned int num_blocks(); //returning number of blocks in figure
unsigned int get_lvls();
unsigned int get_between_hor();
unsigned int get_between_ver();
unsigned int get_bmp_width();
unsigned int get_bmp_height();
void set_bmp_file(String);
void set_block(TImage *,TForm*);
void create_inv_pyr(TForm*);
void set_figure(TForm*,enum choose=pyramid,unsigned int=3);
};
Plik źródłowy klasy Figure (cały oprócz prostych metod, typu get_jakaśwartość)
//contructor:
Figure::Figure(TForm* parent,String bmpfile)
{
this->parent_form=parent;
set_bmp_file(bmpfile);
defPosChanged=false;
bmp_changed=true;
}
void Figure::set_bmp_file(String path)
{
BLOCKBMP=path;
bmp_changed=true;
}
void Figure::set_block(TImage * block,TForm* parent_form) //funkcja pomocnicza, ustawia podstawowe parametry każdego bloku z osobna, pozycja jest ustalana później
{
block->Parent=parent_form;
block->Picture->LoadFromFile(BLOCKBMP);
block->Visible=true;
block->AutoSize=true;
block->Transparent=true;
block->Enabled=true;
}
void Figure::create_inv_pyr(TForm* parent_form) // lvls- levels of pyramid
{
numBlocks=(levels*(levels+1));
blocks.reserve(num_blocks());
for(unsigned int i=0;i<num_blocks();i++)
{
blocks.insert(blocks.begin()+i,new TImage(parent_form));
set_block(blocks[i],parent_form);
}
unsigned int num=0;
for(unsigned int i=get_lvls();i>0;i--) //ustawianie pozycji bloków, funkcja notmin() to zwraca po prostu wartość bezwględną, static cast ze względu na unsigned int
{ // tak, wiem że wystarczyłoby notmin<int>() ale to chyba rzutowanie niejawne a to podobno nieładnie
for(unsigned int j=(i*2);j>0;j--)
{
blocks[num]->Top=startTop+(get_between_ver()+get_bmp_height())*somth::notmin<int>(static_cast<unsigned int>(i)-static_cast<unsigned int>(get_lvls()));
blocks[num]->Left=startLeft+(get_between_hor()+get_bmp_width())*somth::notmin<int>(static_cast<unsigned int>(j)-static_cast<unsigned int>(i)*2)+get_bmp_width()*somth::notmin<int>(static_cast<unsigned int>(i)-static_cast<unsigned int>(get_lvls()));
num++;
}
}
}
void Figure::set_figure(TForm* parent_form, enum choose choice,unsigned int lvls) //w tej funkcji wybierasz jedną z figur, na razie jest tylko piramida
{
levels=lvls;
if(bmp_changed==true) //jeśli wywołasz funkcję set_bmp_file() (czyli zmienisz podaną w konstruktorze ścieżke do grafiki) to zmierz jej wielkość na nowo
{
TImage * block=new TImage(parent_form);
block->Parent=parent_form;
block->Picture->LoadFromFile(BLOCKBMP);
block->AutoSize=true;
bmp_width=block->Width;
bmp_height=block->Height;
bmp_changed=false;
delete block;
}
switch(choice)
{
case 0: //pyramid
if(defPosChanged==false)
{ //setting defaults jeśli ustawisz jakieś swoje wartości to raczej nie chcesz aby funkcja ponownie ustawiła ci defaultowe, po to jest ten if
between_hor=5;
between_ver=5;
startTop=parent_form->Height/16;
startLeft=parent_form->Width/2-get_lvls()*get_bmp_width()-get_between_hor()*get_lvls()+get_between_hor()/2;
defPosChanged=true;
}
create_inv_pyr(parent_form);
break;
default:
ShowMessage("Error in choosing right figure");
break;
}
}
```cpp <Enter> twój kod <Enter>```