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

Вниз

Работа с памятью   Найти похожие ветки 

 
Proger   (2004-06-26 16:09) [0]

Возмоно это ламерский вопрос, но у меня есть проблемка в написании
движка.Предположим есть тип TSprite и Sprite1, Sprite2 этого типа,
я пишу:
 Sprite1 := Sprite2;
 Я так понял здесь передаётся адрес Sprite2, из-за чего естественно
при манипуляциях с Sprite1 меняется и Sprite2 и наоборот.Вроде понятно
выразился.


 
Proger   (2004-06-26 16:12) [1]

Sorry.Забыл сказать в чём проблема, хотя и сами наверное
догадались, короче нужно чтоб такой фигни небыло.


 
GuAV ©   (2004-06-26 16:16) [2]

Рекомендую почитать про классы. и про assign.

> Я так понял здесь передаётся адрес Sprite2, из-за чего естественно
> при манипуляциях с Sprite1 меняется и Sprite2 и наоборот

заместо "и" писать "только", т.е. Sprite1 уже не меняется


 
Anatoly Podgoretsky ©   (2004-06-26 16:49) [3]

Proger   (26.06.04 16:12) [1]
Не делай так


 
MrAngel   (2004-06-26 17:21) [4]

Если хочешь что бы было обыкновенное присваивание значений свойств и полей то сделай так Sprite1.Assign(Sprite2);


 
Proger   (2004-06-26 18:45) [5]

2 MrAngel.Неполучается ,т.к в классе TSprite нет метода Assign:-(
2 GuAV ©.Не подкинешь ссылок на подобную тему?


 
Огромное Кулясище   (2004-06-26 20:01) [6]

2 Anatoly Podgoretsky:

Почему такой совет?


 
Anatoly Podgoretsky ©   (2004-06-26 20:10) [7]

Утереняя память


 
Anatoly Podgoretsky ©   (2004-06-26 20:11) [8]

Первый указатель равен второму - зачем два одинаковых указателя?


 
Proger   (2004-06-26 20:18) [9]

2 Anatoly Podgoretsky ©.В том то и дело, что я немогу сделать
чтоб Sprite1 небыл указателем на Sprite2, ну или что то типа
того :-)


 
cyborg ©   (2004-06-26 21:44) [10]

Move()


 
Proger   (2004-06-27 00:11) [11]

2 cyborg ©.Блин и твой метод неподходит.Вот кусок кода:
if (GetAsyncKeyState(VK_Space) <> 0) and (P2Count2 >= RocketTime) then
 begin
   P2Count1 := GetTickCount;
   Rocket.X := Pad2.X + Pad2.GetSprWH div 4;
   Rocket.Y := Pad2.Y + 32;
   Rocket.MoveAngle := 90;
   Rocket.SetFramePos(1);
   for i := 0 to R2.GetListLength do
     if R2.GetSpr(i) = nil then
     begin
       R2.SetSpr(Rocket, i);
       break;
     end;
 end;

procedure TSpriteList.SetSpr(Spr: TSprite; Pos: word);
begin
 if Num > Length then Num := Length;
 Move(Spr, SprList[Pos], SizeOf(Spr));
end;


 
GuAV ©   (2004-06-27 00:48) [12]


> Не подкинешь ссылок на подобную тему?

по Assign TPersistent+F1
по классам class+F1->About class types, отсюда и далее


 
GuAV ©   (2004-06-27 00:56) [13]


> SizeOf(Spr)

SizeOf(Spr)=4

>  if Num > Length then Num := Length;

к чему это?


 
Огромное Кулясище   (2004-06-27 01:00) [14]

2 Anatoly Podgoretsky:

Как же утерянная? Это же именно указатели, мы же разорились только на адрес, не на вторую копию.

Допустим, некий модуль, имеющий статус движка, работает с каким-то компонентом (PaintBox, например). Внутри он имеет глобальную переменную этого класса. При инициализации движка пользователь укажет, какой именно PaintBox формы использовать путём присвоения указателей.


 
MrAngel   (2004-06-27 03:28) [15]

Дело в том что если нет этого Assign, то надо его самому писать.
Внутри делаешь обыкновенные присваивания типа поле1 := поле2 и т.д.

Всё очень просто до безобразия.


 
GrayFace ©   (2004-06-27 04:39) [16]

Наверняка, единственный способ - создавать новый объект и заполнять вручную.


 
cyborg ©   (2004-06-27 09:10) [17]


> [11] Proger   (27.06.04 00:11)

Всё подходит, справку нужно читать внимательно!

Move(Sprite2,Sprite1,SizeOf(TSprite))
Если Sprite - указатель, то:
Move(Sprite2^,Sprite1^,SizeOf(TSprite))


 
Proger   (2004-06-27 23:31) [18]

2 MrAngel.Дык я так и делал а она...
2 cyborg.Попробую


 
smb   (2004-06-28 09:51) [19]

Как же утерянная? Это же именно указатели, мы же разорились только на адрес, не на вторую копию.
Насколько я понимаю, дело в том, что сначала было два экземпляра класса и два указателя на них, после присвоения указателей один экземпляр заимел два указателя, другой остался без оных вообще. Вот и получилась утерянная память.


 
Proger   (2004-06-28 10:04) [20]

2 cyborg ©.Попробавал, опять хрень какая-то
 Предположим я заношу спрайт Rocket c одними параметрами в ячейку SprList[0], далее в SprList[0], где находится
скопированая ракета параметр скорости перемещения увеличивается,
в то же время увиличивается параметр скорости и у ROCKET????
Из-за чего после занесения Rocket например в ячейку SprList[1]
скорость перемещения будет такая же как и в SprList[0] >:-0


 
MrAngel   (2004-06-28 11:58) [21]

cyborg © так не пойдет. Не пойдёт если внутри класса есть поля-указатели (Pointer)

Proger   не правильно пробовал :-)
Допустим надо Sprite1 := Sprite2;
Тогда:
Sprite1.Pole1 := Sprite2.Pole1;
Sprite1.Pole2 := Sprite2.Pole2;
Sprite1.Pole3 := Sprite2.Pole3;
Sprite1.Property1 := Sprite2.Property1;
Sprite1.Property2 := Sprite2.Property2;
Sprite1.Property3 := Sprite2.Property3;

И т.д.


 
cyborg ©   (2004-06-28 12:15) [22]

Мне неизвестно что такое TSprite у него, объект или запись. Так же что в него входит. Я сказал как данные перенести, а работу мозга никто не отменял.


 
Vladimir "Chainik"   (2004-06-28 12:49) [23]

smb   (28.06.04 09:51) [19]
... сначала было два экземпляра класса и два указателя на них, после присвоения указателей один экземпляр заимел два указателя, другой остался без оных вообще. Вот и получилась утерянная память

Уважаемый smb, не мог бы ты поподробней объяснить мне чайнику, каким образом происходит утечка памяти. Ведь когда Proger делает следующее Sprite1 := Sprite2; происходит по сути копирование содержимого переменной Sprite2 в переменную тогоже типа Sprite1, и о каких указателях тогда здесь идет речь?
Второе. Даже при использовании указателей на объекты Sprite1 и Sprite2, при Sprite1 := Sprite2 происходит передача адреса, да второй объект остается без адреса, но второй то указатель можно ведь приравнять к nil.
приношу извинения за тон, просто меня очень заинтриговал данный вопрос


 
Vladimir "Chainik"   (2004-06-28 12:53) [24]

[23]
... второй объект остается без адреса ...
следует читать ... второй объект остается без указателя...

Пожалуйста поправте если я не прав


 
Proger   (2004-06-28 13:07) [25]

2 MrAngel.Ты частично прав, сначала я так и сделал и
вроде бы работает правильнее(скорость у остальных ракет не меняет
ся, НО почему то параметр текущего кадра анимации передаётся
остальным спрайтам.Наверное я как-то неправильно изъясняюсь,
поэтому наверное в близшайшем времени выложу исходники движка и
бета версии игрухи на нём.


 
Proger   (2004-06-28 13:29) [26]

2 Vladimir.Впринципе наверное и можно каждый устанавливать
указатель Sprite2 в nil, но тогда придётся каждый раз
заново Create"ить этот Sprite2.


 
MrAngel   (2004-06-28 13:41) [27]

Не ну, а больше просто ни как. Если мы имеем дело с классами, то ни как. А вижу только один способ - тот, что я указал выше.

Если бы был тип record, то тоже обыкновенным копированием из памяти в память не получится, если есть внутри переменные типа поинтер. Ну в смысле получится, но это будет не полное копирование, а частичное, так как будут переменные, которые указывают на одну и ту же область памяти.

Вывод один писать свой собственный "Ассигн", который будет поддерживать "все особенности созданного класса".


 
smb   (2004-06-28 14:42) [28]

Vladimir "Chainik"
Скажу чесно. Я не знаю точно, что если Sprite1 := Sprite2, то передаётся указатель на экземпляр класса. Но судя по вопросу и следующим постам - это так.
роисходит по сути копирование содержимого переменной Sprite2 в переменную
Не переменную, а экзепляр класса. В том то и дело, что происходит не копирование содержимого, а передача адреса Sprite2 Sprite1.
Вот как я понял:
Представь, страницу, на которой ссылка на два разных сайта. Если у одной ссылки поменять адрес, то обе ссылки будут указывать на сайт1, но ведь сайт2 никуда не денется.
Я могу быть не прав, но именно так я понял фразу "Утерянная память" by Anatoly Podgoretsky. Память занята.
второй то указатель можно ведь приравнять к nil
Остается первый объект без указателя. И после приравнивания к nil занятой памяти лучше не станет.
Я все это говорю, исходя из предыдущих постов.
Что касается самой проблемы, я думаю лучше использовать запись. Ну вкрайнем случае как одно из полей класса, и присваивать их.


 
Vladimir "Chainik"   (2004-06-28 15:41) [29]

[28]
Спасибо, теперь понялчто ты имел ввиду.
по идее это можно лечить следующим образом
var ptr1:pointer;
begin
....
ptr1:=Sprite1;
Sprite1:=Sprite2;
Sprite2:=ptr1;
....
end;


[1]
Еще раз перечитал вопрос о проблеме, и у меня несколько озарило, а именно Progr фактически работает с указателями на некоторый объект типа TSprite, и в момент когда он производит приравнивание двух экземпляров этого класса у него происходит следующее:
указатель на Sprite1 заменяется указателем на Sprite2, в результате имеем следующую не совсем хорошую для автора вопроса ситуацию, а именно получается эквивалент операции UNION (объединение) из Си, т.е. работая с одним экземпляром класса он автоматически изменяет и второй экземпляр.
Вариант лечения подобной ситуации см. выше


 
Proger   (2004-06-28 22:13) [30]

2 Vladimir.Опять глюк со скоростями ракет, пишу так:
Ptr := SprList[Pos];
SprList[Pos] := Spr;
Spr := Ptr;


 
Servelat ©   (2004-06-28 22:34) [31]

2 Proger
>Вроде понятно выразился.
Нет, не понятно.
Че такое Rocket? Если он объявлен как некий класс TRocket, то
 Предположим я заношу спрайт Rocket c одними параметрами в ячейку SprList[0], далее в SprList[0], где находится
скопированая ракета параметр скорости перемещения увеличивается,
в то же время увиличивается параметр скорости и у ROCKET????

это будет верно. Тогда тебе надо каждый раз писать Rocket:=TRoket.Create; изменять его свойства как хочешь, потом добавлять в твой список. При новой ракете, сново Create"ить рокет и т.д. Тогда в списке на каждой ячейке будет свой экземпляр класса TRocket. А так у тебя есть список указателей, которые указывают на один экземпляр класса. При изменении любого (Rocket или SprList[0]) изменятся все.


 
Proger   (2004-06-28 22:44) [32]

2 Servelat ©.А кроме как Create"ить нет способов?


 
Servelat ©   (2004-06-28 22:46) [33]

2 Proger
Я не знаю, что ты хочешь получить. Если тебе надо несколько ракет, то надо создавать несколько экзэмпляров класса TRocket, т.е. "Create"ить".


 
Servelat ©   (2004-06-28 22:47) [34]

2 Proger
Я не знаю, что ты хочешь получить. Если тебе надо несколько ракет, то надо создавать несколько экзэмпляров класса TRocket, т.е. "Create"ить". У каждого экземпляра свои свойства, координаты и т.п.


 
Proger   (2004-06-28 22:49) [35]

2 Servelat ©.А почему тогда глюк если я пишу:
 SprList[...] := TSpriteList.Create(...);
 SprList[...].Поле1 = Spr.Поле1;
 SprList[...].Поле2 = Spr.Поле2;
 ...


 
Servelat ©   (2004-06-28 23:27) [36]

Выложи исходник куда-нить, или на мыло мне пошли.
Почему ты делаешь SprList[...] (тут "..." это число, как я понял) :=TSpriteList.Create? Надо делать TRocket.Create, а дальше присваивать поля, примерно так:
SprList[0]:=TRocket.Create;
TRocket(SprList[0]).X:=1;
TRocket(SprList[0]).Y:=2; //устанавливаешь свойства

Приведение в виде TRocket(SprList[...]) нужно, если у тебя SprList объявлен как array of pointer. Если как-то иначе, то по ситуации. Если что не понятно, все таки пошли исходник мне, или выложи куда, а то не слишком ясно, что ты хочешь.


 
Proger   (2004-06-28 23:37) [37]

2 Servelat ©.Отослал


 
Proger   (2004-06-29 18:19) [38]

2 Servelat ©.Письмо получил, но с текстом косяк какой-то.Попробовал каждый раз Create"ить TRocket, потом делаю
SprList[...] := Rocket, потом Rocket.Destroy и после этого
SprList[...] := nil.Как быть?


 
Megabyte-CeerCop ©   (2004-07-22 14:39) [39]

Если попытаюсь помочь, то только запутаю всех окончательно.
А вообще интересно чем этот поиск истины закончится.
Может еще не поздно начать эту ветку с нуля? переформулировав более точно вопрос.


 
ПсихЪ_задумчивый   (2004-07-22 15:06) [40]

Пока читал - запутался окончательно... (:
Так что нижеследующее скорее всего к ветке не относится.
1. Каждая картинка загружается один раз в массив спрайтов SprArr класса TSprite. Класс пишется вручну.

SetLength( SprArr, SprCount ); // SprCount - число спрайтов
for i := 0 to SprCount - 1 do
begin
 SprArr[i] := TSprite.Create();
 SprArr.LoadFromFile( IntToStr( i )+".bmp" ); // это к примеру
end;

2. Когда нужно сделать много ракет, то мы делаем:

SetLength( RocetArr, RocetCount );
for i := 0 to RocetCount - 1 do
begin
 RocetArr[i] := TRocet.Create(); // Тут можно сразу параметры задать
 RocetArr[i].SpritePointer := @SprArr[ROCET_SPRITE_NUMBER];
end;

При отрисовки ракет:

for i := 0 to RocetCount - 1 do
 // Если у тебя SpritePointer : TPointer;
 TSprite( RocetArr.SpritePointer ).Draw( RocetArr.SprX, RocetArr.SprY );
 // Если SpritePointer : PSprite; (PSprite : ^TSprite), тогда
 RocetArr.SpritePointer.Draw( RocetArr.SprX, RocetArr.SprY );


Вот, вряд ли это кому-нибудь пригодится. А про спрайты ещё добавлю, что удобнее делать единый интерфейс управления массивом спрайтов, что-то типа SpriteList.



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

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

Наверх




Память: 0.57 MB
Время: 0.034 c
3-1097490239
JohnS
2004-10-11 14:23
2004.11.14
EhLib + сортировка


14-1098623973
Verg
2004-10-24 17:19
2004.11.14
А какой сегодня церковный празник?


4-1097030056
_Konstantin
2004-10-06 06:34
2004.11.14
Как определить платформу


14-1098792989
yet another student
2004-10-26 16:16
2004.11.14
Виртульные машины Бека/Кнута


14-1099077782
VID
2004-10-29 23:23
2004.11.14
Разыскивается книга.