Пятница, 16 Апреля 2021, 19:17

Приветствую Вас Гость

[ Новые сообщения · Игроделы · Правила · Поиск ]
  • Страница 1 из 1
  • 1
Форум игроделов » Программирование » Delphi/Pascal/Object Pascal » Массив из картинок В Delphi 7
Массив из картинок В 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
постоянный участник
Сейчас нет на сайте
приснится ж такое
facepalm
FerasetДата: Суббота, 22 Сентября 2012, 20:41 | Сообщение # 3
Издание игр
Сейчас нет на сайте
Quote (daun)
приснится ж такое

angry
Чт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;

Это как бы случайная генерация карты, чтобы посмотреть, как она в принципе будет выглядеть. smile

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...
Если я неправильно понял, покажи в картинках, чего ты хочешь добиться... wacko
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
Издание игр
Сейчас нет на сайте
happy Спасиб конечн. Хотя я и так нашёл как обойти проблему. Единственное что не пойду как обратится к определённой картинке в канвасе кликом мыши.

Спасибо пользователю 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.

cry

Добавлено (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
постоянный участник
Сейчас нет на сайте
Про реализацию уже молчу, в нанотехнологиях не шарю.
Есть такая штука, алгоритм всей игры, ее каркас.
Игрок вносит изменения в базу, прога показывает базу, база хранит инфу.
Три отдельные части. Игра идет в базе, а не на мониторе у игрока.
И где место для кубов, пихаем все слои в один, эта докторская диссертация (колбаса). wacko
FerasetДата: Воскресенье, 30 Сентября 2012, 13:34 | Сообщение # 15
Издание игр
Сейчас нет на сайте
Где хранится такая база и как она реализуется?
хотя-бы примерную ориентацию подскажи, а я уже попробую в том направении двигаться и посмотрим что выйдет. dry


Спасибо пользователю 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)
Все к тому, что продумывать лучше заранее

А он и продумал "всё". У него даже "наброски обьектно ориентированной системы" есть... wacko По-моему, он просто не знает, что продумывать тут нужно, и не сможет пока описать чёткой структуры будущего проекта...


daunДата: Воскресенье, 30 Сентября 2012, 17:19 | Сообщение # 18
постоянный участник
Сейчас нет на сайте
Quote (TimKruz)
А он и продумал "всё". У него даже "наброски обьектно ориентированной системы" есть... По-моему, он просто не знает, что продумывать тут нужно, и не сможет пока описать чёткой структуры будущего проекта...

На ошибках, блин учимся.
Мая первая игра была крутая бродилка. По мере добавления сюжета (пихал в код), зависала все больше, и больше, пока колом не встала.
Жуть. Жаль не сохранилась. biggrin
Форум игроделов » Программирование » Delphi/Pascal/Object Pascal » Массив из картинок В Delphi 7
  • Страница 1 из 1
  • 1
Поиск:

Все права сохранены. GcUp.ru © 2008-2021 Рейтинг