Среда, 14 Апреля 2021, 08:07

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

[ Новые сообщения · Игроделы · Правила · Поиск ]
  • Страница 1 из 1
  • 1
Форум игроделов » Программирование » Delphi/Pascal/Object Pascal » Дума над канвасом
Дума над канвасом
FerasetДата: Суббота, 29 Сентября 2012, 21:59 | Сообщение # 1
Издание игр
Сейчас нет на сайте
Вопрос стоит такой:
Как изходя из этого кода:
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.

... при нажатии клавищи на определённую координату, поверх поля выводить куб.
Примерно так должно выглядеть:

dry

Вот сам Файл с exeшником.


Спасибо пользователю TimCruz, за то что научил меня спокойствию, терпимости и вере в цели.



Сообщение отредактировал Feraset - Суббота, 29 Сентября 2012, 22:00
TimKruzДата: Суббота, 29 Сентября 2012, 22:19 | Сообщение # 2
старожил
Сейчас нет на сайте
Всё туманно. Всё зависит от того, для чего тебе нужно выводить этот куб.
Если тебе нужно выводить только один куб, сохрани его координаты в каких-нибудь глобальных переменных.
Типа var cx, cy:integer в модуле, а при выводе на экран (в событии таймера) проверять cx и cy и соответственно рисовать куб.

Quote (Feraset)
map1:array[0..30,0..30,0..30]of byte;

Ты что, рассчитываешь сделать изометрическую карту высотой в 31 блок? Если игра 2D, делать больше 3-4 ячеек в высоту бессмысленно, но даже эти будут друг друга перекрывать.

Quote (Feraset)
Code
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;

Что-то я не понял смысла этого куска кода. Ты каждые N миллисекунд создаёшь 2 битмапа, копируешь в них картинку из каких-то image на форме, задаёшь картинку из битмапа в качестве картинки кнопки, и удаляешь битмапы. Что это за бред? wacko

Quote (Feraset)
Timer5.Enabled:=True;

У тебя 5 таймеров на форме? shock Учись справляться со всеми задачами с помощью только одного таймера...

P.S. Тебе уже в предыдущей теме правильно сказали - с таким подходом у тебя вряд ли получится что-то хорошее. Прежде, чем бросаться что-то делать, стоит всё подробно изучить, поработать с мелкими проектами, подробно продумать техническую сторону основного проекта и только после этого приниматься за его разработку...




Сообщение отредактировал TimKruz - Суббота, 29 Сентября 2012, 22:20
FerasetДата: Суббота, 29 Сентября 2012, 22:34 | Сообщение # 3
Издание игр
Сейчас нет на сайте
Quote (TimKruz)
Ты что, рассчитываешь сделать изометрическую карту высотой в 31 блок? Если игра 2D, делать больше 3-4 ячеек в высоту бессмысленно, но даже эти будут друг друга перекрывать.

Проблему перекрывания собираюсь решить прозрачностью рядом находящихся блоков. Не в этом сейчас беда.
Quote (TimKruz)
У тебя 5 таймеров на форме?

Да эт всего лишь для кнопок движения персонажа. Так сказать для теста(проба пера.)
Quote (TimKruz)
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;

А что здесь не так? Я всеголишь леплю на кнопки image. Есть какие то другие более рациональные варианты? Да и вообще это так для красоты, делал без особой надобности smile

Что же касается поставленной задачи, у меня получалось её решить с двумя изьянами:
1 - перерисовывалось всё поле canvas.
2 - куб ставился не по координатам а в точке клика мыши

Насчёт №2 думаю впринципе можно применить метод базовой точки, а вот насчёт канваса - даже и не знаю.


Спасибо пользователю TimCruz, за то что научил меня спокойствию, терпимости и вере в цели.



Сообщение отредактировал Feraset - Воскресенье, 30 Сентября 2012, 01:45
TimKruzДата: Воскресенье, 30 Сентября 2012, 15:39 | Сообщение # 4
старожил
Сейчас нет на сайте
Quote (Feraset)
Проблему перекрывания собираюсь решить прозрачностью рядом находящихся блоков.

Всё равно, тридцать полупрозрачных блоков, накладывающихся друг на друга, создадут такую кашу, что игроку ничего не будет понятно. Хочешь трёхмерности карты - делай 3D-игру. Но 3D ты сейчас точно не осилишь...
Quote (Feraset)
Да эт всего лишь для кнопок движения персонажа. Так сказать для теста(проба пера.)

Глупости делаешь... Ты в этой куче таймеров-кнопок сам запутаешься потом...
Quote (Feraset)
А что здесь не так? Я всеголишь леплю на кнопки image.

По-моему, картинка кнопки типа BitBtn устанавливаешься ещё на этапе разработки формы в Delphi. А если нужно сменить картинку, при этом эта картинка хранится в компоненте Image, можно сделать так:
Code
BitBtn1.Glyph:=Image1.Picture.Bitmap;

Quote (Feraset)
Да и вообще это так для красоты, делал без особой надобности

Вот-вот, налепишь десяток ненужных вещей для красоты, а потом то что нужно работать перестанет... smile
Quote (Feraset)
2 - куб ставился не по координатам а в точке клика мыши

Ну при клике по форме ты получаешь координаты поля в массиве карты, и, следовательно, для вывода картинки на это поле нужно умножить координаты на высоту и ширину одного поля карты.

Из другой темы (не надо было туда-сюда копировать вопросы, отвечу только здесь):
Quote (Feraset)
Где хранится такая база и как она реализуется?

Под базой понимаются определённые данные в оперативной памяти компьютера или в виде файлов на жёстком диске. В твоём случае пока что подойдёт простой массив или набор переменных.

Ты так и не ответил, зачем тебе нужен этот куб. Предположим, он является выделением клетки. Тогда можно сделать такую глобальную переменную:
Code
Selected:TPoint;

TPoint - запись с полями X и Y типа integer. В ней будем хранить текущие координаты выделения. Если пользователь кликнул по клетке (2;3) - в Selected будут значения x=2 и y=3, а если пользователь снял выделение (скажем, нажал "отмена") сохраняются значения x=-1 и y=-1. Тогда в обработчике тика основного таймера сделаем следующее:
Code
//...блаблабла... - здесь циклы прорисовки карты
if (selected.x>-1) and (selected.y>-1) then buf.canvas.draw(selected.x*высотаблока, selected.y*ширинаблока, selcube);
form1.Canvas.Draw(0,0,buf);

При этом selcube - заранее (например, в FormOnCreate) заготовленный TBitmap с картинкой куба. Можно использовать картинку из ImageList'а, как тебе удобнее.

Но если ты собираешься сделать так, чтобы при клике по клетке появлялся куб, являющийся частью ландшафта (короче, как в Minecraft), то тебе нужно работать с массивом карты. То есть, например, у тебя весь ландшафт на уровне 0 (map[x,y,0]), а кубы ставятся на уровень 1 (map[x,y,1]); тогда можно просто в событии клика устанавливать значение ячейки массива map[item.x,item.y,1] равным индексу куба в базе картинок (imagelist'е). Допустим, 0 - пустая клетка, 1 - куб. При клике на форме в ячейку map[item.x,item.y,1] (где item - координаты кликнутой ячейки в массиве) заносится цифра 1. Ну а таймер рисует картинку с индексом 1 (куб) в соответствующей ячейке (потому что нужный код уже в нём есть).


FerasetДата: Воскресенье, 30 Сентября 2012, 23:18 | Сообщение # 5
Издание игр
Сейчас нет на сайте
Добавленный код:
Code
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: integer);
var item, item1:tpoint;
     z:integer;
begin
        if Cursor=crMultidrag then
           if (selected.x>-1) and (selected.y>-1) then
           buf.canvas.draw(selected.x*50, selected.y*50, cellcube);
           cellcube.LoadFromFile('1.bmp');
           form1.Canvas.Draw(0,0,buf);
      end;

Code
procedure TForm1.FormCreate(Sender: TObject);
var x,y,z:byte;
  begin
     cellcube:=TBitmap.Create;
     cellcube.Width:=40;
     cellcube.Height:=40;
     cellcube.Transparent:=True;
   end;
end;


При нажатии на координату выскакивает ошибка:


Спасибо пользователю TimCruz, за то что научил меня спокойствию, терпимости и вере в цели.

TimKruzДата: Понедельник, 01 Октября 2012, 19:39 | Сообщение # 6
старожил
Сейчас нет на сайте
Quote (Feraset)
При нажатии на координату выскакивает ошибка:

Ты на скриншоте, блин, сообщением об ошибке закрыл весь код (а там ведь ошибочная строчка выделяется).
В чём конкретно ошибка - не знаю, но это какая-то ошибка доступа к оперативной памяти...
Quote (Feraset)
cellcube.LoadFromFile('1.bmp');

Почему ты делаешь загрузку картинки в событии нажатия кнопки?! Ты должен сделать ещё в OnCreate.

P.S. Если ты всё-таки хочешь сделать функцию установки кубов на карту (как в майнкрафт/террарии), то тебе нужно работать по-другому - через массив карты...




Сообщение отредактировал TimKruz - Понедельник, 01 Октября 2012, 19:39
Форум игроделов » Программирование » Delphi/Pascal/Object Pascal » Дума над канвасом
  • Страница 1 из 1
  • 1
Поиск:

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