Дума над канвасом
| |
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. ... при нажатии клавищи на определённую координату, поверх поля выводить куб. Примерно так должно выглядеть:
Вот сам Файл с 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 на форме, задаёшь картинку из битмапа в качестве картинки кнопки, и удаляешь битмапы. Что это за бред?
Quote (Feraset) Timer5.Enabled:=True; У тебя 5 таймеров на форме? Учись справляться со всеми задачами с помощью только одного таймера...
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. Есть какие то другие более рациональные варианты? Да и вообще это так для красоты, делал без особой надобности
Что же касается поставленной задачи, у меня получалось её решить с двумя изьянами: 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) Да и вообще это так для красоты, делал без особой надобности Вот-вот, налепишь десяток ненужных вещей для красоты, а потом то что нужно работать перестанет... Quote (Feraset) 2 - куб ставился не по координатам а в точке клика мыши Ну при клике по форме ты получаешь координаты поля в массиве карты, и, следовательно, для вывода картинки на это поле нужно умножить координаты на высоту и ширину одного поля карты.
Из другой темы (не надо было туда-сюда копировать вопросы, отвечу только здесь): Quote (Feraset) Где хранится такая база и как она реализуется? Под базой понимаются определённые данные в оперативной памяти компьютера или в виде файлов на жёстком диске. В твоём случае пока что подойдёт простой массив или набор переменных.
Ты так и не ответил, зачем тебе нужен этот куб. Предположим, он является выделением клетки. Тогда можно сделать такую глобальную переменную: 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 |
|
| |
|