![]() |
|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
#1
|
||||
|
||||
![]() Я написал примитивный 3Д движок(незнаю как это ещё назвать). Вот код юнита:
Код:
unit Engine; interface uses EngineDraw,Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, ComCtrls; const ConstRad=57.295779513082320876798154814105; //1 радиан = ConstRad type ZoomRange = 1..20; MyCamera = class hAngle:integer; vAngle:integer; Zoom:ZoomRange; procedure TL; procedure TR; Procedure TUP; Procedure TD; {FOV:???} end; MyDisplay = class handle:HWND; Canvas:TCanvas; Camera:MyCamera; public procedure AssignTo(wnd:TWinControl); end; coords = class x:integer; y:integer; z:integer; p:integer; t:integer; public procedure Draw(display:MyDisplay); procedure SetDefault; end; line = class stp:coords; enp:coords; public procedure Draw(display:MyDisplay); procedure SetDefault; end; obj = class name:integer; dot:coords; lin:line; end; WorldObjects = class list:array of Obj; count:integer; procedure AddDot(x,y,z:integer); procedure AddLine(stp,enp:coords); end; implementation function ATR(Angle:integer):real;//Перевод из градусов в радианы.Стандартную begin //функцию не нашёл. Надо писать свою. ATR:=(Angle/ConstRad); end; {function ITF(input:integer):real; begin ITF:=strtofloat(IntToStr(input)); end; } procedure MyDisplay.AssignTo(wnd:TWinControl);//На что мы будем выводить изобр. var buffer:MyDisplay; begin buffer:=MyDisplay.Create; buffer.Canvas:=TCanvas.create; buffer.Canvas.Handle:=GetDC(wnd.Handle); self:=buffer; self.Camera:=(Self.Camera); Buffer.Canvas.Destroy; end; procedure MyCamera.TL; begin if hAngle=0 then hAngle:=359 else dec(hAngle); end; procedure MyCamera.TR; begin if hAngle=359 then hAngle:=0 else inc(hAngle); end; procedure MyCamera.TUP; begin if vAngle=0 then vAngle:=359 else dec(vAngle); end; procedure MyCamera.TD; begin if vAngle=359 then vAngle:=0 else inc(vAngle); end; procedure coords.SetDefault; //Обнуление параметров begin x:=0; y:=0; z:=0; p:=0; t:=0; end; procedure line.SetDefault; //Обнуление begin with stp do begin x:=0; y:=0; z:=0; p:=0; t:=0; end; with enp do begin x:=0; y:=0; z:=0; p:=0; t:=0; end; end; Procedure CalculateDotPos(Dot:coords;Display:MyDisplay); begin //Координата p(горизонталь) плоскости экрана dot.p:=round(cos(ATR(Display.Camera.hangle))*dot.x+Sin(ATR(Display.Camera.hangle))*dot.y); //Координата t(вертикаль) плоскости экрана dot.t:=0; end; Procedure CalculateLinePos(Line:line;display:MyDisplay); begin CalculateDotPos(Line.stp,display); //Вычисление координат начала линии CalculateDotPos(Line.enp,display); //Вычисление координат конца линии end; Procedure CalculateObjPos(s:obj;Display:MyDisplay); begin case s.name of 1:CalculateDotPos(s.dot,Display); //Вычисление позиции точки на экране 2:CalculateLinePos(s.lin,Display); //Вычисление позиции линии на экране end; end; Procedure coords.Draw(Display:MyDisplay); begin Display.Canvas.Pixels[self.p,self.t]; end; Procedure line.Draw(Display:MyDisplay); begin Display.Canvas.MoveTo(self.stp.p,self.stp.t); Display.Canvas.LineTo(enp.p,enp.t); end; procedure WorldObjects.AddDot(x,y,z:integer); begin list[count+1].name:=1; list[count+1].dot.x:=x; list[count+1].dot.y:=y; list[count+1].dot.z:=z; inc(count); end; procedure WorldObjects.AddLine(stp,enp:coords); var buf:WorldObjects; begin list[count+1].name:=2; list[count+1].lin.stp:=stp; list[count+1].lin.enp:=enp; inc(count); end; end. Код:
var Form1: TForm1; Display:MyDisplay; World:WorldObjects; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); begin Display:=MyDisplay.Create; Display.AssignTo(Panel1); World:=WorldObjects.Create; World.count:=0; end; procedure TForm1.Button1Click(Sender: TObject); var bufstp,bufenp:coords; begin bufstp:=coords.Create; bufenp:=coords.Create; Bufstp.x:=strtoint(edit1.Text); Bufstp.y:=strtoint(edit2.Text); Bufstp.z:=strtoint(edit3.Text); Bufenp.x:=strtoint(edit4.Text); Bufenp.y:=strtoint(edit5.Text); Bufenp.z:=strtoint(edit6.Text); World.AddLine(bufstp,bufenp); end; |
#2
|
||||
|
||||
![]() Вам надо свой конструктор для класса WorldObjects написать, где вы будете инициализировать свои переменные, а то вы описываете динамический массив, а создать его забываете.
Код:
WorldObjects = class list:array of Obj; count:integer; constructor Create; procedure AddDot(x,y,z:integer); procedure AddLine(stp,enp:coords); end; constructor WorldObjects.Create; begin SetLength(List, 0); Count := 0; end; И потом по логике Count надо бы свойством объявить, т.к. возвращает по сути длину List. ЗЫ: И еще, имейте ввиду, что динамический массив ведет отсчет от 0-элемента, поэтому list[count+1].name будет вызывать ошибку выхода за границы диапазона массива. Жизнь такова какова она есть и больше никакова. Помогаю за спасибо. Последний раз редактировалось Страдалецъ, 17.12.2009 в 11:20. |
#3
|
||||
|
||||
![]() Обьясните пожалуйста смысл вот этих действий, что оно делает:
SetLength(List, 0); Count := 0; Таким же образом мне надо было бы написать конструкторы для всех классов? Получается конструктор - это процедура, запрашивающая память для всех переменных класса, а без него эти переменные при обращении к ним ссылаются "вникуда"? Извиняюсь если вопросы слишком заезжаные. Я в работе с памятью не имею никаких навыков, только всё интуитивно теоретически понимаю. 2. Что значит "обьявить свойством" Как может выйти за границы массива, если массив динамический, то есть не имеет чётких границ, что я не понимаю? Спасибо. Последний раз редактировалось Енот, 18.12.2009 в 06:56. |
#4
|
||||
|
||||
![]() 1.Делать свой конструктор класса необязательно, т.к. по умолчанию все классы наследуются от базового класса у которого есть конструктор Create, но этот конструктор ничего не знает о наследнике и его переменных. И если для статических переменных вызов собственного конструктора можно упустить, то вот для динамических это уже обязательно.
2. Работа с динамическим массивом тоже требует определенных правил. Процедура SetLength инициализирует и устанавливает размерность для динамического масива. Без вызова хотя-бы раз этой процедуры, с таким массивом работать нельзя. В вашем случае, размерность изначально неизвестна, поэтому создаем пустой массив. При добавлении элеменета к массиву надо делать так: Код:
SetLength(List, Length(List)+1); Но вот, если вам потребуется вставить или удалить элемент из массива, то уже придется потрудится, т.к. готовых процедур для этого нет. Как альтернатива динамическому массиву, рекомендуется использовать базовый класс TList. Там уже предусмотрены все основные методы работы с таким массивом. 3. Объявить свойством в данном случае, это воспользоваться специальной конструкцией для классов - property. В вашем случае для чтения Count надо вызвать Length(List) и для записи в него SetLength(List, Length(List)+1). Код:
WorldObjects = class private procedure SetCount(Value: Integer); function GetCount: Integer; public list:array of Obj; count:integer; property Count: Integer read GetCount write SetCount; ... end; ... implementation procedure WorldObjects.SetCount(Value: Integer); begin SetLength(List, Value); end; function WorldObjects.GetCount: Integer; begin Result := Length(List); end; Жизнь такова какова она есть и больше никакова. Помогаю за спасибо. |
#5
|
||||
|
||||
![]() Схема действий:
1. Обьявляю что существует такой массив WorldObjects: Код:
constructor WorldObjects.Create; begin SetLength(List,0); Count := 0; end; 2. Указываю что в нём есть 1 элемент: Код:
procedure WorldObjects.SetCount(Value: Integer); begin SetLength(List, Value); end; ... WorldObjects.Setcount(1); 3. Пытаюсь сказать что это линия: Код:
list[count].name:=2; И на 3 этапе выбивает ошибку access violation! |
#6
|
|||
|
|||
![]() Скорее всего, т.к. list - это динамический массив, то первый его элемент имеет индекс 0, а вот последний - Length(list) - 1. Кстати, то же самое относится и к стандарным классам списков - TList, TStringList, TObjectList. Т.е. ты, видимо, пытаешься обратиться к несуществующему элементу, при том - к объекту. Ну и получаешь соответсвенно ошибку.
|