Tablica obiektów typu TImage

0

Witam,
na wstępie proszę o wyrozumiałość, przeniosłem się z konsoli na aplikacje okienkowe i czuję się jak w nowym świecie.
Do sedna. Tworzę pierwszą aplikację okienkową, którą jest gra Arkanoid-zbijamy piłeczką klocki.
Problem pojawia się gdy tworzę dużą ilość klocków do zbicia, na każdy utworzony klocek piszę tą samą instrukcje, co jest bez sensu. Czy można utworzyć tablicę obiektów TImage i sprawdzać warunki w pętli dla każdego obiektu tablicy?
Dziękuję za odpowiedz.
Pozdrawiam!

// Bricks 2
    else if (kolizja(b, Image2) && Image2->Visible == true)
    {
        x = -x;
        y = -y;
        Image2->Visible = false;
        gate=true;
    }
// Bricks 3
    else if (kolizja(b, Image3) && Image3->Visible == true)
    {
        x = -x;
        y = -y;
        Image3->Visible = false;
        gate=true;
    } 
1

Tak oczywiście, w klasie:

TImage *bricks[100];

W konstruktorze jeżeli klocki są bezpośrednio na formatce to:

for(int i=0,k=0;i<ControlCount;++i) if(typeid(TImage*)==typeid(Controls[i])) bricks[k++]=(TImage*)Controls[i];

Z tym że radzę jednak bezpośrednie stworzenie tych klocków przy starcie poziomu.

0

Dziękuję za szybką i profesjonalną odpowiedz, chciałbym jeszcze potwierdzić moje przemyślenia.

  1. ComponentCount, przechowuje informację o ilości wszystkich komponentów( TButton, TLabel, TImage, itd)
  2. for(int i=0,k=0;i<ControlCount;++i) - Przeszukaj Wszystkie komponenty na formatce
  3. if(typeid(TImage*)==typeid(Controls[i])) - Jeżeli komponentem jest typ TImage, zwróć true
  4. Tablica Controls[i] Zawiera typ danego komponentu ?
  5. bricks[k++]=(TImage*)Controls[i]; - do kolejnych elementów tablicy przypisz wskaźnik na typ TImage. Controls[i] ?
    Stworzyłem prosty program:
    Umieściłem na formatce 5 obiektów: 3xTImage, TLabel, Tbutton.
    for wykonuje się 5 razy, ale warunek if nie został spełniony ani razu, chyba jednak nie do końca wiem jak działa Control[i] :D
    Poproszę o wytłumaczenie :)
 
#include <vcl.h>
#include <typeinfo>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
TImage *bricks[10];
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)
{
int d=0; /// Ile razy wykona sie petla
    for(int i=0,k=0;i<ControlCount;++i)
    {
        if(typeid(TImage*)==typeid(Controls[i]))
        {
         bricks[k++]=(TImage*)Controls[i];
         bricks[k]->Visible = true;
         d++;
        }
    }
     Label1->Caption = IntToStr(d);
}
//---------------------------------------------------------------------------
1

Ad 1. Nie myl ComponentCount/Components z ContolCount/Controls czym jest jedno i drugie dobrze opisane w dokumentacji - bardziej skrótowo nie dam rady opisać, bardziej rozlegle nie mam czasu opisywać.
Ad 2. Nie, Kontrolki
Ad 3. Jeżeli kontrolka jest typu - ale nic nie zwracaj tylko wykonaj to co pod if
Ad 4. Zawiera wskaźniki na kontrolki.
Ad 5. Chrzani waść ten kod wypierniczy się na tym wierszu bricks[k]->Visible = true;

  1. TImage *bricks[10]; miało być w klasie a nie jako zmienna globalna.
  2. Pętla wykona się ControlCount razy
  3. Klocków będzie znaleziono k sztuk
  4. Jeżeli warunek nie działa to ten : if(dynamic_cast<TImage*>(Controls[i])) będzie działać na 100%
0

Widzę, że będę musiał zaopatrzyć się w nowe książki, sama symfonia C++ niewiele mi tu pomoże. Pokuszę się o zaopatrzenie w C++ Builder 6 dla każdego.

  1. Szanuję Twój czas i nie chcę abyś mi wyjaśniał dokładnie czym są ComponentCount/Components, ale chciałbym wiedzieć gdzie konkretnie mogę o tym poczytać, zanim zaopatrzę się w literaturę. Szukałem w internecie ale musiałem wpisywać mało konkretne hasła.
  2. A co w przypadku gdy na formatce znajdują się inne obiekty TImage(np piłka ktora zbijam klocki)?
    -Myślałem nad dodatkowym warunkiem sprawdzającym Name obiektu. Powiedz, mi czy to dobry pomysł, jeżeli tak to spróbuję coś pokombinować.
1

http://bit.ly/14m30N2
Twórz klocki dynamicznie, przy starcie poziomu.
Twój pomysł jest zły, jeżeli już to użyj właściwość Tag.

0

Świetnie właściwość Tag, to jest to czego potrzebowałem.

Chciałbym jeszcze zapytać, co zamiast "Controls[i]" powinienem napisać gdybym chciał utworzył tablicę obiektów TTimer?
Myślałem nad tym aby z każdej cegiełki po jej zbiciu, wylatywał dolar i tutaj chce zastosować Tablice obiektów TTimer- każdy dolar miałby osobny Timer.

if(Controls[i]->Tag==3) 
1
darthachill napisał(a):

... gdybym chciał utworzył tablicę obiektów TTimer?

Twórz klocki dynamicznie, przy starcie poziomu.

0

Na początku nie zrozumiałem co miałeś na myśli, teraz wiem, że chodziło o tworzenie obiektów od strony kodu. Poszukałem, znalazłem, działa. Testowo ustawiłem dla 1 elementu, potem pomyślę jak porozstawiać resztę.

        const int max = 1;
        TImage *img[1];
        for (int i = 0; i < max; ++i)
        {
         img[i] = new TImage(this);
         img[i]->Parent = Form1;
         img[i]->Picture->LoadFromFile("img/ball.bmp");
         img[i]->Left = 100;
         img[i]->Top = 100;
         img[i]->Visible = true;
         }

Zastanawia mnie jedna rzecz. Za co w tej linijce odpowiada "this", Poszukałem na własną rękę informacji w symfonii i w internecie ale nie znalazłem odpowiedzi akurat dla takiego przypadku.

img[i] = new TImage(this);

Utworzyłem klasę z funkcją tworzącą klocki. Lecz przy kompilacji otrzymuję poniższy błąd:
f[C++ Error] Unit1.cpp(25): E2285 Could not find a match for 'TImage::TImage(Brick * const)'
kompilator wskazał linijkę o którą nadmieniłem wyżej.

 class Brick
{
  TImage *img[1];

  public:
  void load_image();
};

void Brick::load_image()
{
        const int max = 1;
        for (int i = 0; i < max; ++i)
        {
         img[i] = new TImage(this);
         img[i]->Parent = Form1;

         img[i]->Picture->LoadFromFile("img/ball");
         img[i]->Left = 100;
         img[i]->Top = 100;
         img[i]->Visible = true;
        }
}

Dziękuję i pozdrawiam!

1

this - wskaźnik na obiekt klasy na rzecz którego wywołana dana metoda.
Wewnątrz Brick zamień this na Form1

0

Opłacało się zainwestować w książkę wraz z Twoimi radami udało mi się zrozumieć to z czym wcześniej miałem problem. Teraz stanąłem na innym problemie, Mianowicie utworzyłem klasę Brick, tworzę w niej obiekt TTimer timer, i chciałbym teraz wejść w zdarzenie OnTimer. Tworząc obiekt typu TTimer na formatce mogłem skorzystać z:

void __fastcall TForm1::Timer1Timer(TObject *Sender)
{

} 

Jak dostać się do tej funkcji gdy tworzę obiekt dynamicznie ?

0

Te Brick'i masz wstawić do jakieś dynamicznej tablicy, np vector

0

To może inaczej. Zacząłem tworzyć od nowa program - był bez ładu i składu. Tworzę więc po kolei klasy: Ball, Paddle, Bricks.
Nie wiem jednak jak odnieść się do zdarzenia OnTimer(które będzię się wykonywać co określony Interval zegara) dla składnika klasy TTimer *timer.
Teraz zaczynam mieć wątpliwości czy umieszczanie zegara w klasie Ball to dobry pomysł.

#include "mmsystem.h"
class Ball
{
    int x, y;
    TForm  *form;
    TTimer *timer;
    TImage *img;

public:

    Ball(TForm *f=Form1, int x=8, int y=8)
    {
        form = f;
        this->x=x;
        this->y=y;
        img_creator();
        timer_creator();
    }
    void timer_creator();
    void img_creator();
    void snd_creator();
};
///****************************************************************
void Ball::img_creator()
{
    img = new TImage(form);
    img-> Parent = form;
    img-> Left = x;
    img-> Top = y;
    img-> Picture->LoadFromFile("img/ball.bmp");
    img-> AutoSize = true;
    img-> Visible = true;
}
///****************************************************************
void Ball:: snd_creator()
{
    sndPlaySound("snd/ball.wav",SND_ASYNC);
}
///****************************************************************
void Ball::timer_creator()
{
 timer = new TTimer(form);
 timer-> Enabled = true;
 timer-> Interval = 30;
}
1

Beznadziejny. W tej klasie musisz mieć wektor prędkości. Natomiast timer ma być jeden na wszystko.

1 użytkowników online, w tym zalogowanych: 0, gości: 1