Projekt mur, program graficzny.

0

Witam. Mam do zrobienie program graficzny, który będzie tworzyć mur o szerokości i wysokości takiej jakiej wpisze użytkownik. Algorytm już mam, potrzebuję tylko przeniesienia go do Lazarus'a. Mam do dyspozycji dwa rodzaje cegły, pierwsza o szerokości 2 np. XX a druga cegła o szerokości 3 np. XXX.
Przykład użytkownik wpisze szerokość 9 i wysokość 2(każda cegła ma wysokość 1) to będzie:

|XX|XX|XX|XXX|
|XXX|XX|XX|XX|

Można na kartce rozrysować, będzie lepiej widoczne.
Niestety nie mam doświadczenia w środowisku Lazarus.
Chciałbym żeby zamiast cegły XX będzie plik xx.png a za cegłę XXX, xxx.png i żeby to fajnie się doklejało do kolejnej cegły.
Chyba, że lepiej będzie rysować za pomocą polecenia ? Proszę o przykładowy kod albo odnośnik. Cokolwiek :)
Dziękuje.
Pozdrawiam
XYZ

dodanie znaczników <code> i `` - fp

0

Ja bym wstawiał dynamicznie TImage, ustawiał według współrzędnych(do tego jakaś procedurka) i już. Pamiętaj tylko o tym, że mur może wyjść poza obszar ekranu.

0

@serge - dziękuję za szybką odpowiedź. Pierwsza sprawa to wychwyciłeś już moje kolejne pytanie co gdy mur wyjdzie poza obszar ekranu ? Czy jakiś suwak ?
Czy mógłbyś mi pokazać przykładowy kod jak utworzyć obiekt obrazka o danej wielkości i współrzędnych ? Albo przynajmniej mnie nakieruj :)

1

To marsz do Google. Tam później musisz do bólu: szukać, czytać i kombinować. A w ostateczności pisać na forum. Umieszczasz wątek nie w Newbie, a nie ogarniasz podstaw? Oj, lenistwo. Masz tutaj jeden z wielu linków: http://pl.wikibooks.org/wiki/Delphi/Dynamiczne_tworzenie_komponentów i działaj.

0

@olesio - nie ogarniam grafiki, podstawy znam :)

0

@wolacinio, może przeczytasz najpierw przynajmniej tytuł linku leniu?

1
wolacinio napisał(a)

Algorytm już mam, potrzebuję tylko przeniesienia go do Lazarus'a.

To gdzie masz ten algorytm - na kartce?

wolacinio napisał(a)

Mam do dyspozycji dwa rodzaje cegły, pierwsza o szerokości 2 np. XX a druga cegła o szerokości 3 np. XXX.

Skoro masz dwie cegły, to masz dwa pliki; Skoro masz dwa pliki - potrzebne Ci dwie zmienne, do których załadujesz te dwie grafiki;

wolacinio napisał(a)

Przykład użytkownik wpisze szerokość 9 i wysokość 2(każda cegła ma wysokość 1)

Wystarczą proste obliczenia - nic szczególnego; A skoro masz już algorytm (zapewne także do obliczania ilości i typu cegieł) to pomijam;

wolacinio napisał(a)

Chyba, że lepiej będzie rysować za pomocą polecenia?

Obliczać pozycję kolejnych cegiełek i tak musisz, więc mniej roboty będziesz miał rysując na jednym komponencie cegiełki, niż tworząc dla każdej z nich osobny komponent;

serge napisał(a)

Ja bym wstawiał dynamicznie TImage, ustawiał według współrzędnych(do tego jakaś procedurka) i już.

Szkoda czasu i pamięci na tworzenie wielu takich samych komponentów, skoro jedne obliczenia można wykorzystać do rysowania wczytanych grafik w odpowiednim miejscu;


@wolacinio - dobierz odpowiedni typ do przechowywania grafik PNG i wykorzystaj obliczenia do malowania cegiełek na jednym komponencie; Chyba, że chcesz koniecznie tworzyć komponenty dynamicznie to zrób w ten sposób; Poczytaj najpierw jak się je tworzy, przechowuje i zwalnia z pamięci.

0

Dzięki @Furious Programming
Ehh jak ciężko wrócić do tego języka programowanie ... :D
Mam taki komponent

procedure TForm1.cegla(i : integer);
var brickxxx : TFileName;
Image1: TImage;
begin
  Image1:=Timage.Create(self);
  brickxxx := '1.png';
  Image1.Top:=i;
  Image1.Picture.LoadFromFile(brickxxx);
  Image1.Parent:=self;
  Image1.Visible:=True;
  Image1.free;
end; 

I wywołanie cegla(100), cegla(110), cegla(120) itd.
Niestety nie działa :( Czy dobrą drogę obrałem ?
Jednak zdecydowałem się żeby cegły były obrazkiem bo w tedy lepiej to będzie wyglądać.
Czyli zrobić komponent z parametrami które będą ustawiać obrazek w prawidłowej pozycji tak ?
W załączniku wysyłam plik wykładu, czy mogę w taki sposób zrobić ?
Przepraszam ale mam straszne przyzwyczajenie do C/C++/C# (metody) :D

0

Komponent tworzysz dobrze, ale nigdzie nie nadajesz mu rozmiarów - właściwości Width i Height;

No i nigdzie nie przechowujesz referencji do tych dynamicznie tworzonych TImage, więc później nie będziesz się mógł do nich odwołać; Przydałaby się jakaś tablica takich komponentów, bo choć formularz sam będzie potrafił usunąć wszystkie dynamicznie utworzone komponenty, to jednak dobrą praktyką jest sprzątać po sobie;

Niestety nie działa :(

Jeśli tak będziesz opisywał to co się dzieje z Twoim programem, to nie zdziw się, jeśli długo będziesz musiał czekać na odpowiedź...

0

Hehe ok już wiem w czym był błąd ;) Miałem wywołanie w pętli metodę cegla, która nie wykonywała się ani razu :)
Ale po co mi adresy tych komponentów ? Przecież wyświetlam obrazek, po czym zwalniam pamięć dla kolejnego komponentu.
Jutro się tym zajmę, na dziś to wystarczy :D Dam znać gdybym miał problem.
Dzięki.

0

Nie, Tworzysz komponent z obrazkiem, on zajmuje pamięć i dopóki nie zrobisz Image1.Free; dopóty nie zostanie zwolniona pamięć. Jakby tak było jak mówisz, to po wyświetleniu obrazka on by zniknął (bo niby pamiec jest zwalniana). A poniewaz nie przechowujesz adesów tych komponentów, to nie zrobisz Free.

0

Witam ponownie. Zrobiłem ... prawie :)
Oto kod:
http://pastebin.com/C435wq6K
Mam problem jedynie z tym, żeby po wygenerowaniu nowego muru, usunąć poprzedni mur. Teraz tak działa, że część muru nakłada się na poprzedni.
Jakaś podpowiedź ?

0

Trzymać Imagesy w dynamicznej tablicy of TImage i na jej elementach operować w pętli zwalniając poprzednie elemety. Ewentualnie również pętla i Timage(FindComponent(... + IntToStr(IteratorPetli)) nadając oczywiście cegłom sensowne nazwy z dodatkową liczbą przy tworzeniu. A przy niszczeniu oczywiście sprawdzając czy to do czego się odnosisz <> nil.

0

@olesio - ale masz na myśli zwalnianie metodą free ? Bo jak zwolnię to i tak zostanie na ekranie chyba. Tutaj trzeba skasować z ekranu :)
Jutro poprawię kod.

0

@wolacinio, jakim cudem zostanie na ekranie po free?

0

No patrz. To masz jakiegoś "magicznego" Lazarusa. Bo u mnie pod nim (w wersji 64 bit) oraz pod Delphi 7 Personal, taki kod jak poniżej powoduje, że po kliknięciu na przycisk Image "znika". Najprawdopodobniej zwalniasz nie ten Image, co chcesz albo już ich tyle natworzyłeś, że się tam motasz. Najlepiej napisać jakieś herezje. A komuś kto Ci doradza konkretnie, wymyśleć w odpowiedzi, że jego sposób nie działa :/ Ok, to kombinuj po swojemu, tylko jaki sens ma wtedy pytanie o wszystko na forum, skoro wiesz lepiej :/

//...

procedure TForm1.FormCreate(Sender: TObject);
begin
  Image1.Picture.Icon := Application.Icon;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Image1.Free;
end;
0

Czyli nie zostanie mam rozumieć ? :D
Ok. Czyli robię tak, że zapisuje do tablicy TImage adresy każdej cegły. A gdy wcisnę przycisk Generuj, w procedurze mam usuwać wszystkie cegły tak ?

0

Masz nie używać TImage do tego celu, wystarczy szereg Canvas.Draw w OnPaint
Skoro poszedłeś długą i bezsensowną drogą to przynajmniej sprawdzaj to o czym tobie mówią.

0

@_13th_Dragon - zawszę jakoś wybieram tą trudniejszą drogę :D może dlatego, że więcej się nauczę ... to taka dygresja :)
@olesio - nie zauważyłem, twojego postu

Pierwsza sprawa, nie znam LCL ani VCL więc się pytam, nie wymądrzam.
Druga sprawa, nie chce rysować za pomocą Canvas tylko chcę pliki .png
Zrobię to na tablicy, po czym zwolnię pamieć przed generowaniem nowego muru.

procedure TForm1.FormCreate(Sender: TObject);
begin
  Image1.Picture.Icon := Application.Icon;
end;
 
procedure TForm1.Button1Click(Sender: TObject);
begin
  Image1.Free;
end;

Co to ?

0
wolacinio napisał(a):

@olesio - nie zauważyłem, twojego postu
(...)
Co to ?

Przykładowy kod jaki miałeś sprawdzić. Bo twierdziłeś, że po Free Image Ci nie "znika".

0

Sprawdziłem. Dalej obrazki się nakładają tzn. nie skasowało poprzedniego tylko nałożyło nowe na stare obrazki.
Zerknie ktoś na kod ? Proszę się nie śmiać :)
Dzięki.

0
wolacinio napisał(a):

@_13th_Dragon - zawszę jakoś wybieram tą trudniejszą drogę :D może dlatego, że więcej się nauczę ... to taka dygresja :)
Czyli uważasz że więcej się nauczysz jeżeli będziesz kopać rów trzymając łopatę za stylisko zaś kopiąc trzonem?

wolacinio napisał(a):

Druga sprawa, nie chce rysować za pomocą Canvas tylko chcę pliki .png
A co ma jedno do drugiego?

2

Masz. I tak się nic nie nauczysz. Wybrałeś sobie chyba za trudny kierunek nauki. Skoro wymaga się od Ciebie samodzielności. A Ty nie umiesz pogoolować za kursami omawiającymi podstawy. I googlować oraz kombinować do bólu. I nieważne, dział Newbie, czy nie. Kombinujemy zawsze najpierw sami. Pisanie na jakie kolwiek forum to ostateczność.

EDIT: w kodzie poprawiłem chyba wszystkie błędy jakie zauważyłem. Przerobienie tego na rysowanie na przykład po Canvasie tylko jednego TImage, pozostawiam już Tobie. W końcu to jak rozumiem, projekt na zaliczenie, które Ty masz ogarnąć, a nie ktoś za Ciebie.

0

Dzięki wielkie @olesio :)
Działa pięknie, błędy graficzne i sposób rysowania już poprawiłem.
Czyli zasada jest taka jaką mi pisaliście w poprzednich postach tzn. przy dodawaniu nowego komponentu zapisuje do tablicy TImage, a gdy wcisnę przycisk uruchamia się pętla, która kasuje mi wszystkie (<>nil) komponenty i na sam koniec ustawie wielkość tablicy na 0 tak ?

Kocham programowanie, pisałem już większe i bardziej złożone aplikacje, więc programowanie nie jest mi obce. Pisanie projektów nauczyło mnie to, że tak naprawdę przy pisaniu skomplikowanych aplikacji człowiek najwięcej się uczy bo musi szukać bo forach, wortalach, blogach, skryptach itp., takie jest moje zdanie :)

Można też przerobić program w taki sposób

Timage(FindComponent('Image'+inttostr(i))); 

?

0

Zrób sobie kopię projektu i pokombinuj tak, jak chcesz żeby sobie odpowiedzieć na swoje pytania. Bo FindComponent zadziala dla komponentów z nadaną własnością Name.

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