Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.06.14;
Скачать: CL | DM;

Вниз

деление объекта   Найти похожие ветки 

 
Antol   (2005-05-28 22:39) [0]

У меня есть объект. Мне нужно, чтобы через определенное время он делился (из него создавался такой же). Как это можно сделать?


 
Yanis ©   (2005-05-28 22:41) [1]

Если нет ошибки в 17 строке, то магия поможет :)
А вообще вопрос не понятен. Поясни пожалуйста.


 
Просто Джо ©   (2005-05-28 23:25) [2]

Если я правильно понял.
Мой рецепт таков. Заводишь менеджер, он же "фабрика" объектов. То есть класс, который умеет создавать объекты определенных типов. Кроме того, он отвечает за сохранение в своих внутренних структурах ссылок на все порожденные объекты. Также, он несет ответственность за удаление своих объектов.
Когда реализуешь такой менеджер, считай -- самое главное сделал. После этого заводишь в менеджере таймер и в определенное время менежер создает объекты.
Если расписал непонятно, напиши что именно. Может быть вечерком набросая схематичный код.


 
Просто Джо ©   (2005-05-29 02:28) [3]

Привожу обещанный код.
-------------------------
Вот вариант 1, упрощенный. Код соответствует описанию, данному в [2].

Через определенные промежутки времени менеджер создает и добавляет в свой внутренний список новый объект TCustomObject. Доступ к существующим объектам предоставляется через индексное default-свойство Items менеджера. Количество созданных объектов можно узнать по значению свойства Count.
Менеджер создается и начинает отсчет автоматически при старте программы. При выходе из программы менеджер автоматически уничтожается. Доступ к нему можно получить через глобальную переменную ObjectManager.

------------------------

unit ObjMgr;

interface
uses Contnrs, ExtCtrls;

type
 // Объект, экземпляры которого будут "множится"
 TCustomObject = class
   //
 end;

 // Менеджер объектов
 TObjManager = class
 private
   FList: TObjectList;
   FTimer: TTimer;
   function GetItems(Index: Integer): TCustomObject;
   procedure OnTimer (Sender: TObject);
   procedure StartTimer (Interval: Integer);
   function GetObjectCount: Integer;
 public
   constructor Create; overload;
   constructor Create (Interval: Integer); overload;
   destructor Destroy; override;
   procedure CreateChild;
   property Items[Index: Integer]: TCustomObject read GetItems; default;
   property ObjectCount: Integer read GetObjectCount;
 end;

var
 ObjectManager: TObjManager;
 
implementation

{ TObjManager }

constructor TObjManager.Create;
begin
 inherited;
 FList := TObjectList.Create(True);
 StartTimer(1000);
end;

constructor TObjManager.Create(Interval: Integer);
begin
 inherited Create;
 FList := TObjectList.Create(True);
 StartTimer(Interval);
end;

procedure TObjManager.CreateChild;
begin
 FList.Add(TCustomObject.Create)
end;

destructor TObjManager.Destroy;
begin
 FTimer.Free;
 FList.Free;
 inherited;
end;

function TObjManager.GetItems(Index: Integer): TCustomObject;
begin
 Result := TCustomObject(FList[Index])
end;

function TObjManager.GetObjectCount: Integer;
begin
 Result := FList.Count
end;

procedure TObjManager.OnTimer(Sender: TObject);
begin
 CreateChild
end;

procedure TObjManager.StartTimer(Interval: Integer);
begin
 FTimer := TTimer.Create(nil);
 FTimer.OnTimer := OnTimer;
 FTimer.Interval := Interval;
 FTimer.Enabled := True;
end;

initialization
 ObjectManager := TObjManager.Create(2000);

finalization
 ObjectManager.Free;
 
end.


 
Просто Джо ©   (2005-05-29 02:33) [4]

Вот вариант 2, усложненный.
-----------------------------

Через определенные промежутки времени менеджер создает копию КАЖДОГО объекта, находящегося в его списке и сохраняет ее во внутреннем списке. Доступ к объектам в списке аналогичен предыдущему примеру. Класс, описывающий объект поддерживает метод Assign, в котором мы указываем какие именно свойства объекта необходимо передавать его копии. Все остальное -- по аналогии с предыдущим примером.
Обрати внимание на комментарии в коде.
-------------

unit ObjMgr2;

interface
uses SysUtils, Classes, Contnrs, ExtCtrls;

type
 // Объект, экземпляры которого будут "множится"
 TClonableObject = class (TPersistent)
 private
   FProperty1: Integer;
   FProperty2: string;
   // создает и возвращает копию текущего объекта
   function Clone: TClonableObject;
 public
   // присваивает объекту свойства объекта Source
   procedure Assign(Source: TPersistent); override;
   // это два тестовых свойства
   property Property1: Integer read FProperty1;
   property Property2: string read FProperty2;
 end;

 // Менеджер объектов
 TClonableObjManager = class
 private
   FList: TObjectList;
   FTimer: TTimer;
   function GetItems(Index: Integer): TClonableObject;
   procedure OnTimer (Sender: TObject);
   procedure StartTimer (Interval: Integer);
   function GetObjectCount: Integer;
   procedure DoCloneChildren;
 public
   procedure CreateChild;
   constructor Create; overload;
   constructor Create (Interval: Integer); overload;
   destructor Destroy; override;
   property Items[Index: Integer]: TClonableObject read GetItems; default;
   property ObjectCount: Integer read GetObjectCount;
 end;

var
 ClonableObjectManager: TClonableObjManager;

implementation

{ TObjManager }

constructor TClonableObjManager.Create;
begin
 inherited;
 FList := TObjectList.Create(True);
 StartTimer(1000);
end;

constructor TClonableObjManager.Create(Interval: Integer);
begin
 inherited Create;
 FList := TObjectList.Create(True);
 StartTimer(Interval);
end;

procedure TClonableObjManager.CreateChild;
begin
 FList.Add(TClonableObject.Create)
end;

destructor TClonableObjManager.Destroy;
begin
 FTimer.Free;
 FList.Free;
 inherited;
end;

procedure TClonableObjManager.DoCloneChildren;
var
 I: Integer;
begin
 // если есть объекты в списке, клонируем каждый из них
 // если список пуст, то создаем один объект и добавляем его в список
 if FList.Count <> 0 then
   for I := 0 to FList.Count-1 do
     FList.Add(Items[I].Clone)
 else
   CreateChild
end;

function TClonableObjManager.GetItems(Index: Integer): TClonableObject;
begin
 Result := TClonableObject(FList[Index])
end;

function TClonableObjManager.GetObjectCount: Integer;
begin
 Result := FList.Count
end;

procedure TClonableObjManager.OnTimer(Sender: TObject);
begin
 DoCloneChildren
end;

procedure TClonableObjManager.StartTimer(Interval: Integer);
begin
 FTimer := TTimer.Create(nil);
 FTimer.OnTimer := OnTimer;
 FTimer.Interval := Interval;
 FTimer.Enabled := True;
end;

{ TCustomObject }

procedure TClonableObject.Assign(Source: TPersistent);
begin
 if Source is TClonableObject then
 begin
   // здесь копируешь значение всех свойств,
   // которые должны копироваться при клонировании
   FProperty1 := TClonableObject(Source).FProperty1;
   FProperty2 := TClonableObject(Source).FProperty2;
 end
 else
   raise Exception.Create("Source is not TCustomObject.");
end;

function TClonableObject.Clone: TClonableObject;
begin
 // создаем новый объект того же типа
 Result := TClonableObject.Create;
 // и передаем ему наши свойства
 Result.Assign(Self);
end;

initialization
 // создаем глобальный менеджер
 // который каждые 2 сек будет клонировать
 // содержащиеся в нем объекты
 ClonableObjectManager := TClonableObjManager.Create(2000);

finalization
 ClonableObjectManager.Free;

end.


 
Просто Джо ©   (2005-05-29 02:43) [5]

Демонстрация работы.
-------------------------------
Сохраняешь каждый из приведенных юнитов в отдельных файлах ObjMgr.pas и ObjMgr2.pas, соответственно. Включаешь их в проект.
В uses юнита главной формы включаешь юниты ObjMgr и ObjMgr2.
На главной форме помещаешь два компонента TLabel и один TTimer. В обработчике OnTimer таймера пишешь:
 
Label1.Caption :=
   Format ("Objects: %d",[ObjectManager.ObjectCount]);

 Label2.Caption :=
   Format ("Objects: %d",[ClonableObjectManager.ObjectCount]);

И поставь у таймера интервал в 1 сек.

Запускаешь проект на выполнение и радуешься :)
Каждые 2 сек количество объектов в первом менеджере будет увеличиваться на 1.
Каждые 2 сек количество объектов во втором менеджере будет удваиваться, таким образом, ты будешь иметь удовольствие наблюдать за степенями двойки, что есть весьма поучительно и наглядно демонстрирует тщету человеческого существования :)))


 
DrPass ©   (2005-05-29 03:25) [6]

А слабО сделать размножение объектов не делением, а путем спаривания? Так, чтобы потомок получил часть VMT от папы, и часть - от мамы :)


 
Defunct ©   (2005-05-29 03:30) [7]

Навеяно идеей Просто Джо:

unit fLifeSim;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, ExtCtrls;

type
 TForm2 = class(TForm)
   Button1: TButton;
   Timer1: TTimer;
   Button2: TButton;
   procedure Button1Click(Sender: TObject);
   procedure Button2Click(Sender: TObject);
   procedure Timer1Timer(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form2: TForm2;

implementation
{$R *.dfm}

uses Contnrs;

type

 TCell = class
 private
   fRect     : TRect;
   fCanvas   : TCanvas;

   function    Fission:TCell;
 protected
   procedure   Draw;
 public

   procedure   Simulate;
   constructor Create(const Canvas: TCanvas; const Rect: TRect);dynamic;
   destructor  Destroy;override;
 end;

 TCellManager = class(TObjectList)
    procedure Simulate;
    destructor Destroy;override;
 end;

var Cells : TCellManager;
{ TManager }

procedure TCellManager.Simulate;
var
 i : integer;
begin
 for i := 0 to Count - 1 do
     TCell(Items[i]).Simulate
end;

destructor TCellManager.Destroy;
var
 i : integer;
begin
 for i := Count-1 downto 0 do
     Items[i].Free
end;

{ TCell }
constructor TCell.Create(const Canvas: TCanvas; const Rect: TRect);
begin
 if Assigned(Canvas) then
    fCanvas := Canvas
 else
    raise Exception.Create("no canvas assigned");
 fRect := Rect;
 Cells.Add( Self )
end;

function TCell.Fission: TCell;

   function GetDivVector( const Rect:TRect):TPoint;
   var
      Px, Py : TPoint;
   begin
      Result := Point(0, 0);

      Px := Point( Rect.Left, Rect.Right );
      Py := Point( Rect.Top, Rect.Bottom );

      if (Px.Y - Px.X) > (Py.Y - Py.X) then // horisontal div
         Result.X := (Px.Y - Px.X) div 2
      else // Vert div
         Result.Y := (Py.Y - Py.X) div 2
   end;

   function GetRectPiece( const Rect: TRect; const DivVector:TPoint; Up:Boolean):TRect;
   begin
      Result := Rect;

      if Up then
         begin
            Result.Right := Result.Right - DivVector.X;
            Result.Bottom := Result.Bottom - DivVector.Y;
         end
      else
         begin
            Result.Left := Result.Left + DivVector.X;
            Result.Top := Result.Top + DivVector.Y;
         end;
   end;

var
 Dv : TPoint;

begin
 Dv := GetDivVector( fRect );

 if (Dv.X > 0) or (Dv.Y > 0) then // the cell still can be divided
    begin
      Result := TCell.Create( fCanvas, GetRectPiece( fRect, Dv, False ) );
      fRect := GetRectPiece( fRect, Dv, True );
      Application.ProcessMessages
    end
 else
    Result := nil;
end;

procedure TCell.Simulate;
var
  NewCell : TCell;
begin
  NewCell := Self.Fission;
  if NewCell <> nil then
     NewCell.Draw;
  Draw
end;

procedure TCell.Draw;
begin
  with fCanvas do
  begin
     Pen.Color := Random( $FFFFFF);
     Brush.Color := Random( $FFFFFF);
     FillRect( fRect )
  end
end;

destructor TCell.Destroy;
begin
 inherited;
end;

procedure TForm2.Button1Click(Sender: TObject);
begin
 TCell.Create( Canvas, Self.ClientRect );
end;

procedure TForm2.Timer1Timer(Sender: TObject);
begin
 Cells.Simulate;
end;

initialization
 Cells := TCellManager.Create;

finalization
 Cells.Free

end.


 
Просто Джо ©   (2005-05-29 04:04) [8]


> [7] Defunct ©   (29.05.05 03:30)

Это зверство - Оно только через TaskManager снимается :) Уж очень занимательно было на это смотреть, вот и досмотрелся :))


 
Defunct ©   (2005-05-29 04:19) [9]

Просто Джо ©   (29.05.05 04:04) [8]

хехе, деление прекращается, когда клетка занимает квадрат 1x1, так что можно было дождаться без снятия TaskManager"ом ;>

А вообще у таймера интервал больше бы поставить, или вместо таймера кнопку кликать ;>


 
Anatoly Podgoretsky ©   (2005-05-29 11:21) [10]

Вообще то это умножение.


 
Antol   (2005-05-29 11:52) [11]

Просто Джо ,Defunct огромное спасибо!!!

Просто Джо ,у меня наверное голова с утра плохо соображает, но как обратится к самому объекту?(где он должен находится, как его сохранить?)
сейчас у меня просто счетчики делений.


 
Просто Джо ©   (2005-05-29 15:15) [12]

ObjectManager[Номер_объекта]
ClonableObjectManager[Номер_объекта]


 
Antol   (2005-05-29 17:45) [13]

А можно вместо объекта использовать картинку нарисованную с использованием canvas?


 
Antol   (2005-05-29 17:47) [14]

Удалено модератором


 
ferr ©   (2005-05-29 18:14) [15]

Опиши полность задачу


 
Antol   (2005-05-29 19:19) [16]

по просьбам трудящихся Задача:
используя объекты, отобразить процесс деления неполовой клетки человека с полным набором вакуолей и органоидов.
вставлять картинки нельзя.


 
Defunct ©   (2005-05-29 19:22) [17]

Antol   (29.05.05 19:19) [16]

Видоизмените метод Draw и метод Fission в примере [7]


 
ferr ©   (2005-05-29 19:41) [18]

Что подразумевается под объектом? Экземпляр класса?
В свете:

>Antol   (29.05.05 17:47) [14][Ответить]
> А можно вместо объекта использовать картинку
> нарисованную с использованием canvas?


 
Antol   (2005-05-29 21:22) [19]

Я создала процедуру, которая рисует саму клетку с некоторыми вакуолями (в черновом варианте)

procedure kl (var x,y:integer);
begin
 with Form1.Canvas do
   begin
     ellipse (x-9*dx,y-5*dy,x+12*dx,y+10*dy);// &#234;&#235;&#229;&#242;&#234;&#224;
     Brush.Color:=ClOlive;
     ellipse (x,y,x+7*dx,y+7*dy);  //&#255;&#228;&#240;&#238;
     Brush.Color:=ClInactiveBorder;
     ellipse (x+2*dx,y+3*dy,x+4*dx,y+5*dy);  //&#255;&#228;&#229;&#240;&#246;&#229;
     Pen.width:=6;Pen.Color:=ClGray;
     arc(x-4*dx,y-dy, x+2*dx,y+5*dy,x-dx,y-dy, x-5*dx,y);//&#236;&#232;&#242;&#238;&#245;&#238;&#237;&#228;&#240;&#232;&#232;
     Pen.Color:=ClSkyBlue;
     Pen.width:=3;
     arc (x+5*dx,y-2*dy,x+9*dx,y+2*dy,x+10*dx,y,x+6*dx,y-2*dy,);//  &#227;&#238;&#235;&#252;&#228;&#230;&#232;
     arc (x+4*dx,y-dy,x+8*dx,y+3*dy,x+10*dx,y+dy,x+5*dx,y-dy);
    end;
end;

Она даже научилась ездить по экрану.

Вот она-то и должна делится.
Только как мне ее лучше сохранить - я сама не знаю.
Огромное спасибо всем за помощь.


 
Digitman ©   (2005-05-30 08:41) [20]


> Я создала процедуру


> Вот она-то и должна делится


процедура должна делиться ?
вот это новость !)


> У меня есть объект


где в [19] хоть что-либо напоминающее созданный именно тобой объект ?


 
SergP ©   (2005-05-30 08:48) [21]


>  [20] Digitman ©   (30.05.05 08:41)
>
> > Я создала процедуру
>
>
> > Вот она-то и должна делится
>
>
> процедура должна делиться ?
> вот это новость !)


И это еще не все....


> Она даже научилась ездить по экрану.



Страницы: 1 вся ветка

Текущий архив: 2005.06.14;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.037 c
4-1114276037
Виталик
2005-04-23 21:07
2005.06.14
Вопрос по логону.


3-1115524614
MickL
2005-05-08 07:56
2005.06.14
BLOB поле


11-1098524553
AlexR
2004-10-23 13:42
2005.06.14
Цвет текста в RichEdit e


1-1117099653
pavel_guzhanov
2005-05-26 13:27
2005.06.14
Работа с PopupMenu


9-1106580715
Trof
2005-01-24 18:31
2005.06.14
Ландшафт в 3dsmax.