Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Игры";
Текущий архив: 2004.11.14;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.55 MB
Время: 0.035 c
14-1098881227
Snip
2004-10-27 16:47
2004.11.14
Права в NTFS


1-1098907717
Jolik
2004-10-28 00:08
2004.11.14
Как сделать в TListView...


1-1099401968
Жекасиымси
2004-11-02 16:26
2004.11.14
утилита FC


10-1062767704
karan
2003-09-05 17:15
2004.11.14
Общие вопросы по DCOM


3-1097758099
star
2004-10-14 16:48
2004.11.14
сортировка





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский