Форум: "Игры";
Текущий архив: 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