Массив из картинок В Delphi 7
| |
Feraset | Дата: Суббота, 22 Сентября 2012, 19:39 | Сообщение # 1 |
Издание игр
Сейчас нет на сайте
| Задача такая как вывести массив из картинок без применения STRING/DRAWGrida на поле Form1.
С помощью драв грида получилось вот так:
Code TForm1 = class(TForm) DrawGrid1: TDrawGrid; ImageList1: TImageList; procedure DrawGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); private { Private declarations } public { Public declarations } end;
var Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.DrawGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); var X, Y, ImageIndex: Integer; begin ImageIndex := 0; X := Rect.Left + ((Rect.Right - Rect.Left - ImageList1.Width) div 2); Y := Rect.Top + ((Rect.Bottom - Rect.Top - ImageList1.Height) div 2); ImageList1.Draw(DrawGrid1.Canvas, X, Y, ImageIndex, True); end; Получившаяся картинка Здесь.
Не будет видна остальная часть картинки, так как она находится только в рамках поля. То бишь изометрия получается неполная.(Смысл ясен делаем поле(землю) из квадратов). Значит "выкопать" нужный участок не получится. Ну и естественно поверх GRIDа нелзя поставить какой либо объект. Если кто знает как этого избежать подскажите пожалуйста, желательно на примере. Заранее благодарю.
Спасибо пользователю TimCruz, за то что научил меня спокойствию, терпимости и вере в цели.
Сообщение отредактировал Feraset - Суббота, 22 Сентября 2012, 19:44 |
|
| |
daun | Дата: Суббота, 22 Сентября 2012, 20:04 | Сообщение # 2 |
постоянный участник
Сейчас нет на сайте
| приснится ж такое
|
|
| |
Feraset | Дата: Суббота, 22 Сентября 2012, 20:41 | Сообщение # 3 |
Издание игр
Сейчас нет на сайте
| Quote (daun) приснится ж такое Чт0 то неясно? П0моему я доходчиво изложил мысль.
Спасибо пользователю TimCruz, за то что научил меня спокойствию, терпимости и вере в цели.
Сообщение отредактировал Feraset - Суббота, 22 Сентября 2012, 20:42 |
|
| |
TimKruz | Дата: Суббота, 22 Сентября 2012, 20:50 | Сообщение # 4 |
старожил
Сейчас нет на сайте
| Делай примерно так: Code var Form1: TForm1; map:array[0..15,0..15]of byte; //Этот массив - карта. В каждой ячейке содержится тип блока. buf:tbitmap; //Буфер для вывода картинки, чтобы не мерцала. <...> //Событие таймера: procedure TForm1.Timer1Timer(Sender: TObject); var x,y:byte; //Переменные-счётчики begin buf.Canvas.Rectangle(0,0,buf.Width,buf.Height); //Очищаем буфер for x:=0 to 15 do for y:=0 to 15 do ImageList1.Draw(buf.canvas, //Рисуем на канве буфера... x*16, y*16, //Задаём позицию; здесь множитель 16 - высота/ширина одного блока в пикселях. map[x,y] //Блок какого типа нужно рисовать? ); //Копируем буфер на форму: form1.Canvas.Draw(0,0,buf); { Копировать картинку из одного места в другое можно быстрее, как-то так: bitblt(form1.Canvas.Handle,0,0,buf.Width,buf.Height, buf.Canvas.Handle,0,0,SRCCOPY); } end; Code procedure TForm1.FormCreate(Sender: TObject); var x,y:byte; begin //Инициализируем буфер buf:=tbitmap.create; buf.Width:=256; //Размеры буфера: ширина карты умножить на ширину одного блока, buf.Height:=256; //точно так же с высотой. buf.Canvas.Pen.Color:=clWhite; buf.Canvas.Brush.Color:=clWhite; randomize; for x:=0 to 15 do for y:=0 to 15 do map[x,y]:=random(3); //В качестве аргумента random - число картинок+1 end; Это как бы случайная генерация карты, чтобы посмотреть, как она в принципе будет выглядеть.
Quote (Feraset) Значит "выкопать" нужный участок не получится. Мне вот интересно, как ты планируешь реализовать "копание участка"? У тебя же, фактически, всё плоско, вид сверху... Если уж хочешь сделать игру, где можно копать землю - делай вид сбоку, как в платформерах. Quote (Feraset) Ну и естественно поверх GRIDа нелзя поставить какой либо объект. Во-первых, поверх таблицы можно что хочешь поставить. Во-вторых, в игре установка одного объекта на другой реализуется простейшим рисованием верхнего объекта после рисования нижнего, на том же месте (для частичного перекрывания, для полного нижний можно вообще не рисовать).
|
|
| |
Feraset | Дата: Суббота, 22 Сентября 2012, 21:39 | Сообщение # 5 |
Издание игр
Сейчас нет на сайте
| У нас получился вот такого вида код. Однако этот код Code unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, ImgList;
type TForm1 = class(TForm) Timer1: TTimer; ImageList1: TImageList; procedure Timer1Timer(Sender: TObject); procedure FormCreate(Sender: TObject); private { Private declarations } public { Public declarations } end;
var Form1: TForm1; map:array[0..15,0..15]of byte; buf:tbitmap; implementation
{$R *.dfm}
procedure TForm1.Timer1Timer(Sender: TObject); var x,y:byte; begin buf.Canvas.Rectangle(0,0,buf.Width,buf.Height); for x:=0 to 15 do for y:=0 to 15 do ImageList1.Draw(buf.canvas,x*64,y*64,map[x,y]); form1.Canvas.Draw(0,0,buf); end;
procedure TForm1.FormCreate(Sender: TObject); var x,y:byte; begin buf:=tbitmap.create; buf.Width:=256; buf.Height:=256; buf.Canvas.Pen.Color:=clWhite; buf.Canvas.Brush.Color:=clWhite; randomize; for x:=0 to 15 do for y:=0 to 15 do map[x,y]:=random(2); end;
end. Однако замысел такой что блок должен лежать слитно с другим блоком , а они лежат друг от друга на расстоянии. Особенно это видно если использовать x*64,y*64 imagelista.
Спасибо пользователю TimCruz, за то что научил меня спокойствию, терпимости и вере в цели.
Сообщение отредактировал Feraset - Суббота, 22 Сентября 2012, 21:40 |
|
| |
daun | Дата: Суббота, 22 Сентября 2012, 22:43 | Сообщение # 6 |
постоянный участник
Сейчас нет на сайте
| Тебе ImageList накой? Грузи изображение в переменную (TBitmap TPNGObject TJPEGImage) и выводи в цикле по координатам на Canvas, хоть в Image, хоть в Forme.
|
|
| |
Feraset | Дата: Суббота, 22 Сентября 2012, 23:07 | Сообщение # 7 |
Издание игр
Сейчас нет на сайте
| Сорри моя ошибка - можно просто уменьшить x*64,y*64 и кубы склеются. Единственное что нужно чтобы они не склеивались обрезанными а как бы накладывались друг на друга без обрезания.
Спасибо пользователю TimCruz, за то что научил меня спокойствию, терпимости и вере в цели.
|
|
| |
TimKruz | Дата: Воскресенье, 23 Сентября 2012, 19:08 | Сообщение # 8 |
старожил
Сейчас нет на сайте
| Quote (Feraset) Единственное что нужно чтобы они не склеивались обрезанными а как бы накладывались друг на друга без обрезания. Что-то я не понял, что тебе нужно. Например, у тебя куб размером 50x50 пикселей, картинка - 64x64, т.е. слева и внизу ещё полоски по 16 пикселей. Тогда тебе нужен буфер с шириной=50*ширина_карты+16 и высотой=50*высота_карты+16... Если я неправильно понял, покажи в картинках, чего ты хочешь добиться... Quote (daun) Тебе ImageList накой? Грузи изображение в переменную (TBitmap TPNGObject TJPEGImage) и выводи в цикле по координатам на Canvas, хоть в Image, хоть в Forme. Да, выгоднее делать банк изображений так: Code const images=4; var image:array[0..images]of TBitmap; или Code image:array of TBitmap; Но картинки нужно откуда-то загрузить, например, из ресурсов...
|
|
| |
Feraset | Дата: Понедельник, 24 Сентября 2012, 10:59 | Сообщение # 9 |
Издание игр
Сейчас нет на сайте
| Спасиб конечн. Хотя я и так нашёл как обойти проблему. Единственное что не пойду как обратится к определённой картинке в канвасе кликом мыши.
Спасибо пользователю TimCruz, за то что научил меня спокойствию, терпимости и вере в цели.
|
|
| |
TimKruz | Дата: Понедельник, 24 Сентября 2012, 20:12 | Сообщение # 10 |
старожил
Сейчас нет на сайте
| Quote (Feraset) как обратится к определённой картинке в канвасе кликом мыши У формы, как и большинства других объектов есть событие OnMouseDown (и соответствующий ему OnMouseUp). При этом передаются координаты курсора. С помощью этих координат ты можешь вычислить, на какую клетку был сделан клик, примерно так: Code procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var item:tpoint; //Здесь сохраним адрес клетки begin item.x:=x div 50; //50 - ширина item.y:=y div 50; //и длина клетки caption:='Выбрана клетка с координатами ('+inttostr(item.x)+'; '+inttostr(item.y)+')'; end; Если нумеруешь массив с нуля (например, [0..10,0..10]), то полученные числа будут адресом клетки - можно обратиться как map[item.x,item.y]. Естественно, если поле с картой занимает меньше общей площади окна, нужно ввести ограничение по ширине и высоте (например, if x<500 then...).
|
|
| |
Feraset | Дата: Четверг, 27 Сентября 2012, 16:45 | Сообщение # 11 |
Издание игр
Сейчас нет на сайте
| сделал вот такой вот редактор поля Code procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: integer); var item:tpoint; begin //в этом условии нужно чтобы картинка(куб) добавлялась поверх поля по тем же координатам куда кликнул, но не в поле. Пробовал использовать нижний код что ты мне дал но не нашёл в нём ни одной лазейки. Проблема в FormMouseDown(X, Y: integer) begin if Cursor=crDrag then begin "------------------------" // Может попробовать добавить image сверху(image.canvas...)? end; end;
item.x:=x div 42; item.y:=y div 42; caption:='Выбрана клетка с координатами ('+inttostr(item.x)+'; '+inttostr(item.y)+')'; begin if Cursor=crUpArrow then if map1[item.x,item.y]=(1) then begin buf.Canvas.Rectangle(0,0,buf.Width,buf.Height); ImageList1.Draw(buf.canvas,x*42,y*42,map1[item.x,item.y]); map1[item.x,item.y]:=4; end else begin buf.Canvas.Rectangle(0,0,buf.Width,buf.Height); ImageList1.Draw(buf.canvas,x*42,y*42,map1[item.x,item.y]); map1[item.x,item.y]:=1; end; end;
end;
procedure TForm1.BitBtn1Click(Sender: TObject); begin Cursor:=crUpArrow; end;
procedure TForm1.BitBtn2Click(Sender: TObject); begin Cursor:=crDrag; end;
end.
Добавлено (25.09.2012, 20:01) --------------------------------------------- Quote (TimKruz) Естественно, если поле с картой занимает меньше общей площади окна, нужно ввести ограничение по ширине и высоте (например, if x<500 then...). Впринципе оно и без ограничителя только по полю ставитДобавлено (27.09.2012, 16:45) --------------------------------------------- Я попробовал вот так. Но картинка поверх канваса появляется на считанные секунды: Code procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: integer); var item:tpoint; begin item.x:=x div 37; item.y:=y div 37; begin if Cursor=crDrag then //Åñëè êóðñîð êóáà òîãäà map1[x,y]:=3; form1.Canvas.Draw(0,0,buf); ImageList2.Draw(buf.canvas,x-50,y-100,map1[x,y]); end; <_<
Спасибо пользователю TimCruz, за то что научил меня спокойствию, терпимости и вере в цели.
Сообщение отредактировал Feraset - Четверг, 27 Сентября 2012, 16:44 |
|
| |
Akyltist | Дата: Четверг, 27 Сентября 2012, 17:04 | Сообщение # 12 |
заслуженный участник
Сейчас нет на сайте
| Feraset- ты на канву выводишь один раз, по событию мыши. А форма перерисоваваться можен n кол-во раз в секунду. Тебе надо перенести твою отрисовку как минимум в Form.OnPaint и включить DoubleBuffered.
PS: подход к созданию игр абсолютно не правильный, юзай движки с opengl или dx
|
|
| |
Feraset | Дата: Суббота, 29 Сентября 2012, 21:58 | Сообщение # 13 |
Издание игр
Сейчас нет на сайте
| Quote (Akyltist) перенести твою отрисовку как минимум в Form.OnPaint и включить DoubleBuffered Это как? И вообще куда запихивать DoubleBuffered? Я слышал с ним мороки много и багов?
Добавлено (29.09.2012, 21:58) --------------------------------------------- Вопрос стоит такой как изходя из этого кода: Code unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, ImgList, StdCtrls, Buttons;
type TForm1 = class(TForm) Timer1: TTimer; ImageList1: TImageList; BitBtn1: TBitBtn; BitBtn2: TBitBtn; Button1: TButton; Button2: TButton; Button3: TButton; Button4: TButton; Timer2: TTimer; Timer3: TTimer; Timer4: TTimer; Timer5: TTimer; ImageList2: TImageList; Image1: TImage; BitBtn3: TBitBtn; Image2: TImage; procedure Timer1Timer(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure BitBtn1Click(Sender: TObject); procedure BitBtn2Click(Sender: TObject); procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); procedure Button4Click(Sender: TObject); procedure BitBtn3Click(Sender: TObject); private { Private declarations } public { Public declarations } end; // îáúÿâëåíèå íîâîãî òèïà col_row const n=5; var Form1: TForm1; map1:array[0..30,0..30,0..30]of byte; buf:tbitmap; implementation
{$R *.dfm}
procedure TForm1.Timer1Timer(Sender: TObject); var x,y,z:byte; BMP, BMP1: TBitmap;
begin BMP:= TBitmap.Create; try bmp.Width:= Image1.Picture.Graphic.Width; bmp.Height:= Image1.Picture.Graphic.Height; bmp.Canvas.Draw (0, 0, Image1.Picture.Graphic); BitBtn2.Glyph:= BMP; finally; bmp.Free; end;
BMP1:= TBitmap.Create; try bmp1.Width:= Image2.Picture.Graphic.Width; bmp1.Height:= Image2.Picture.Graphic.Height; bmp1.Canvas.Draw (0, 0, Image2.Picture.Graphic); BitBtn3.Glyph:= BMP1; finally; bmp1.Free; end;
buf.Canvas.Rectangle(-2,-2,buf.Width,buf.Height); for x:=0 to 29 do for y:=0 to 29 do for z:=0 to 29 do ImageList1.Draw(buf.canvas,x*37,y*37,map1[x,y,z]); form1.Canvas.Draw(0,0,buf); end;
procedure TForm1.FormCreate(Sender: TObject); var x,y,z:byte; begin buf:=tbitmap.create; buf.Width:=261; buf.Height:=261; buf.Canvas.Pen.Color:=clBlack; buf.Canvas.Brush.Color:=clGray; randomize; for x:=0 to 29 do for y:=0 to 29 do for z:=0 to 29 do map1[x,y,z]:=random(2); end;
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: integer); var item, item1:tpoint; z:integer; begin item.x:=x div 37; item.y:=y div 37; begin if Cursor=crDrag then //Åñëè êóðñîð êóáà òîãäà for z:=29 downto 0 do if map1[item.x,item.Y,z]<>(3) then Break; if map1[item.x,item.y,z]=(1) then begin buf.Canvas.Rectangle(0,0,buf.Width,buf.Height); //äåëàåì çåìëþ 2 ImageList1.Draw(buf.canvas,x*37,y*37,map1[item.x,item.y,z]); map1[item.x,item.Y,z]:=3; end; end;
begin if Cursor=crUpArrow then for z:=29 downto 0 do if map1[item.x,item.Y,z]<>(3) then Break; if map1[item.x,item.y,z]=(0) then begin buf.Canvas.Rectangle(0,0,buf.Width,buf.Height); //äåëàåì çåìëþ 2 ImageList1.Draw(buf.canvas,x*37,y*37,map1[item.x,item.y,z]); map1[item.x,item.Y,z]:=3; end;
end;
caption:='Âûáðàíà êëåòêà ñ êîîðäèíàòàìè ('+inttostr(item.x)+'; '+inttostr(item.y)+'; '+inttostr(z)+'; '')'; end;
procedure TForm1.BitBtn1Click(Sender: TObject); begin Cursor:=crUpArrow; end;
procedure TForm1.BitBtn2Click(Sender: TObject); begin Cursor:=crDrag; end;
procedure TForm1.BitBtn3Click(Sender: TObject); begin Cursor:=crMultiDrag; end;
procedure TForm1.Button1Click(Sender: TObject); begin Timer2.Enabled:=True; end;
procedure TForm1.Button2Click(Sender: TObject); begin Timer3.Enabled:=True; end;
procedure TForm1.Button3Click(Sender: TObject); begin Timer4.Enabled:=True; end;
procedure TForm1.Button4Click(Sender: TObject); begin Timer5.Enabled:=True; end;
end. ... при нажатии клавищи на определённую координату, поверх поля выводить куб. Примерно так должно выглядеть:
Вот сам Файл с exeшником.
Спасибо пользователю TimCruz, за то что научил меня спокойствию, терпимости и вере в цели.
Сообщение отредактировал Feraset - Суббота, 29 Сентября 2012, 21:58 |
|
| |
daun | Дата: Воскресенье, 30 Сентября 2012, 09:44 | Сообщение # 14 |
постоянный участник
Сейчас нет на сайте
| Про реализацию уже молчу, в нанотехнологиях не шарю. Есть такая штука, алгоритм всей игры, ее каркас. Игрок вносит изменения в базу, прога показывает базу, база хранит инфу. Три отдельные части. Игра идет в базе, а не на мониторе у игрока. И где место для кубов, пихаем все слои в один, эта докторская диссертация (колбаса).
|
|
| |
Feraset | Дата: Воскресенье, 30 Сентября 2012, 13:34 | Сообщение # 15 |
Издание игр
Сейчас нет на сайте
| Где хранится такая база и как она реализуется? хотя-бы примерную ориентацию подскажи, а я уже попробую в том направении двигаться и посмотрим что выйдет.
Спасибо пользователю TimCruz, за то что научил меня спокойствию, терпимости и вере в цели.
|
|
| |
daun | Дата: Воскресенье, 30 Сентября 2012, 15:56 | Сообщение # 16 |
постоянный участник
Сейчас нет на сайте
| Теперь она есть: map1:array[0..30,0..30,0..30]of byte; пусть примитивная, но если устраивает требованиям игры, сойдет. В среднем случае используется запись record, - можно создать сложную структуру данных. В идеале классы: тот же record, только с методами (функциями) обработки данных. Все к тому, что продумывать лучше заранее, что бы не переписывать по сто раз, а просто добавлять, и отталкиваться при построении проги лучше от базы.
типа: 47,0 kb
|
|
| |
TimKruz | Дата: Воскресенье, 30 Сентября 2012, 16:43 | Сообщение # 17 |
старожил
Сейчас нет на сайте
| Quote (daun) map1:array[0..30,0..30,0..30]of byte; пусть примитивная, но если устраивает требованиям игры, сойдет. В среднем случае используется запись record, - можно создать сложную структуру данных. В идеале классы: тот же record, только с методами (функциями) обработки данных. Это верно, но главное - знать, где и что применять нужно. А то он сейчас сделает карту, в которой каждый блок - квадратик без каких-либо свойств - будет экземпляром класса tblock с собственным конструктором и кучей функций... Quote (daun) Все к тому, что продумывать лучше заранее А он и продумал "всё". У него даже "наброски обьектно ориентированной системы" есть... По-моему, он просто не знает, что продумывать тут нужно, и не сможет пока описать чёткой структуры будущего проекта...
|
|
| |
daun | Дата: Воскресенье, 30 Сентября 2012, 17:19 | Сообщение # 18 |
постоянный участник
Сейчас нет на сайте
| Quote (TimKruz) А он и продумал "всё". У него даже "наброски обьектно ориентированной системы" есть... По-моему, он просто не знает, что продумывать тут нужно, и не сможет пока описать чёткой структуры будущего проекта... На ошибках, блин учимся. Мая первая игра была крутая бродилка. По мере добавления сюжета (пихал в код), зависала все больше, и больше, пока колом не встала. Жуть. Жаль не сохранилась.
|
|
| |
|