Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Проблема с динамическим массивом [Delphi, Windows]


Страницы:   1 2

Zeqfreed ©   (2003-12-14 13:28:00) 

Вот собственно код.

...
type
TSprite = class
 FRect : TRect;
 x,y,w,h : Integer;
 Visible : Boolean;
 procedure Show(const DestSurf,SourceSurf : IDirectDrawSurface7;
                      Params : Integer = DDBLTFAST_WAIT or
                      DDBLTFAST_SRCCOLORKEY);
end;

var
sprites : array of TSprite;
SpriteCount : Integer;...

...procedure AddSprite(Visible : Boolean;w,h,x,y : Integer;Rect : TRect);
begin
SetLength(sprites,SpriteCount);
sprites[SpriteCount] := TSprite.Create; //Здесь происходит ошибка
sprites[SpriteCount].x := x;
sprites[SpriteCount].y := y;
sprites[SpriteCount].w := w;
sprites[SpriteCount].h := h;
sprites[SpriteCount].FRect := Rect;
sprites[SpriteCount].Visible := Visible;
SpriteCount := SpriteCount + 1;
end;...

Пожалуйста, помогите выяснить в чём проблема? Может быть предложите свой вариант.


MrAngel   (2003-12-18 21:52:00) [1]

Кстати связный список - тоже вариант, по крайней мере он будет быстро работать. Тут мгновенно решается проблема удаления элементов по выбору.

Если делать удаление из массива, там надо делать смещение данных. Что кстати и делает TStringList и TList.


Free Advisor   (2003-12-18 10:35:00) [2]

2 Unknown User

> А заводить глобальную переменную SpriteCount, хранящую длину
> массива -это не есть хороший стиль программирования.

 Имхо, хороший стиль программирования в данном случае - это реализация массива связным списком, двунаправленным, для удобства. Ж) Только вопрос в том, нужно ли это? Для начинающих и ленивых вполне сойдет array of TBotva;$)
 И еще насчет "хорошего тона", Аксиома оптимизации: мы либо выигрываем в скорости, проигрывая в памяти, либо наоборот - третьего не дано.


_drew_   (2003-12-18 02:26:00) [3]

Какие массивы ? При работе с классами или объектами массивы не нужны. Для этого и нужно создавать необходимые свойства и методы.


cyborg   (2003-12-17 21:13:00) [4]

А что будет, если спрайт удаляется? Это придётся весь массив переделывать.
Для спрайтов используй на худой конец TStringList, а лучше сам делай свои списки.


MrAngel   (2003-12-17 17:32:00) [5]

Ну не знаю... Тут в общем то всё зависит от ситуации. Если спрайты гоняются туда сюда (а не держатся в памяти) то лучше с переменной. Ну а если ни достаточно редко создаются или удаляются то можно и через SetLength и прочие процедуры.


> Вот деланье этого:
> SetLength(sprites,SpriteCount);
> при каждом создании спрайта есть ужасно.


А как же иначе? Как же иначе, если заранее не известно количество спрайтов ? На пример ситуация с динамическими генерируемыми спрайтами (небо), где во время игры их количество должно меняться. Как же тогда здесь ?


Unknown user   (2003-12-16 18:44:00) [6]

2 MrAngel. Если ты создашь больше 100 000 спрайтов -то возможно заметишь разницу в 1 мс. Настолько вот медленнее :). А заводить глобальную переменную SpriteCount, хранящую длину массива -это не есть хороший стиль программирования.


cyborg   (2003-12-16 18:43:00) [7]

Вот деланье этого:
SetLength(sprites,SpriteCount);
при каждом создании спрайта есть ужасно.


MrAngel   (2003-12-16 18:06:00) [8]


procedure AddSprite(Visible : Boolean;w,h,x,y : Integer;Rect : TRect);
begin
 INC(SpriteCount);
 SetLength(sprites,SpriteCount);
 sprites[SpriteCount-1] := TSprite.Create;
 sprites[SpriteCount-1].x := x;
 sprites[SpriteCount-1].y := y;
 sprites[SpriteCount-1].w := w;
 sprites[SpriteCount-1].h := h;
 sprites[SpriteCount-1].FRect := Rect;
 sprites[SpriteCount-1].Visible := Visible;
end;

procedure DeleteSprites();
var
 i : Integer;
begin
 for i := 0 to SpriteCount-1 do
   if Assigned(sprites[i]) then FreeAndNil(sprites[i]);
end;


Вот...  это с использованием SpriteCount, если через High и Length, то будет медленней на количество тактов вызова этих процедур минус один (примерно). Поэтому вариант с SpriteCount считаю более правильным.


Unknown user   (2003-12-15 19:25:00) [9]

Я бы посоветовал так добавлять спрайт - SetLength(Sprites,Length(Sprites)+1). Затем with Sprites[High(Sprites)] do ... и вперед заполнять значения полей объекта. И еще для объектов предпочтительней исп. TList. А для написания своей игры сначала изучи основы программирования, иначе твой первый камень о который ты споткнулся будет не последним и не самым большим.


Mihey   (2003-12-15 14:29:00) [10]

> Возможно это из-за того, что изначально я ставлю SpriteCount в 1, но если оставлять её равной нулю то тоже получается ошибка!

Зачем меняешь SpriteCount??? Сколько создал - столько и удаляй.


Anatoly Podgoretsky   (2003-12-15 14:00:00) [11]

Zeqfreed   (15.12.03 13:56) [13]
Для этого переменная не нужна, есть функция Length и ошибок не будет связанных с глобальной переменной.


Zeqfreed   (2003-12-15 13:56:00) [12]

Нет, MrAngel, это ты не понял! Переменная SpriteCount служит лишь для того, чтобы задать новую длинну массива в процедуре AddSprite(), и в этой процедуре она увеличивается и при следующем вызове длинна массива устанавливается на еденицу больше.

2Mihey:
Я пробовал:

procedure DeleteSprites();
var
i : Integer;
begin
for i := 0 to High(sprites) do
begin
sprites[i].Destroy;
end;
end;

Получается ошибка?!
Возможно это из-за того, что изначально я ставлю SpriteCount в 1, но если оставлять её равной нулю то тоже получается ошибка!


MrAngel   (2003-12-14 17:14:00) [13]


> Почему надо sprite[SpriteCount-1] := TSprite.Create;?
> Ведь если учесть, что SpriteCount = 0, то получим
> sprite[-1] := TSprite.Create;!!!


Ну если SpriteCount = 0 то зачем тогда вообще создавать TSprite ?
Понял теперь смысл ?


Mihey   (2003-12-14 15:44:00) [14]

2 Zeqfreed:

Допустим у тебя в массиве N элементов. То есть, если все элементы сосчитать, то будет N. Представь, что у тебя на столе N дискет. Теперь тебе их нужно будет пронумеровать. И пронумеровать начиная с 0. То есть, первая дискета будет иметь номер 0, вторая дискета номер 1, n-ная дискета будет иметь номер n-1.

Рассмотрим твой случай. Ты задаёшь длину массив атак:

SetLength(sprites, SpriteCount);

Теперь сделаем то, что тебе советовали - открыть справку. Читаем про SetLength:

procedure SetLength(var S; NewLength: Integer);

NewLength - это новая длина. Это количество элементов в массиве. Представь, что число SpriteCount элементов пронумерованы с нуля. Какой будет индекс у самого верхнего элемента? Правильно, SpriteCount-1. Поэтому процедуру удаления нужно переписать так:

procedure DeleteSprites();
var
i : Integer;
begin
for i := 0to High(sprites) do
begin
 sprites[i].Destroy;
end;
end;

Учти, что High возвращает не длину, а индекс самого верхнего элемента. То есть, это то же самое, что:

procedure DeleteSprites();
var
i : Integer;
begin
for i := 0 to SpriteCount-1 do
begin
 sprites[i].Destroy;
end;
end;

Всё, удачи тебе.


Zeqfreed   (2003-12-14 14:41:00) [15]

P.P.S Конечно же перед завершением я освобождаю массив.
Скорее всего неправильно!?:

procedure DeleteSprites();
var
i : Integer;
begin
for i := 1 to High(sprites) do
 begin
  sprites[i].Destroy;
 end;
end;


Zeqfreed   (2003-12-14 14:38:00) [16]

Почему надо sprite[SpriteCount-1] := TSprite.Create;?
Ведь если учесть, что SpriteCount = 0, то получим
sprite[-1] := TSprite.Create;!!!

P.S. Когда я заменил SpriteCount : Integer; на SpriteCount : Integer = 1; всё заработало, но при завершении программы выводится "EInvalidPointer"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


MrAngel   (2003-12-14 14:19:00) [17]

Народ да вы что ?!?!

Уже сразу ошибку налицо видно !!!
Надо не sprites[SpriteCount] := TSprite.Create;

а  sprites[SpriteCount-1] := TSprite.Create;
и так далее для всех строк.

Индексирования в массивах ВСЕГДА идут с нуля.
Между прочим это относится к азам программинга, и динамические массивы описаны в книгах для "чайников".

Стыдно, господа, очень стыдно !!!


Anatoly Podgoretsky   (2003-12-14 14:07:00) [18]

В справке все нормально описано и даже есть пример и меня не поймут если я буду его сюда копировать.


Zeqfreed   (2003-12-14 13:54:00) [19]

Да в справке ведь ничего толкового не написано!
Ну или может это я просто такой тупой. Исправь ПОЖАЛУЙСТА мой код и напиши так, чтобы он работал.


Anatoly Podgoretsky   (2003-12-14 13:47:00) [20]

А, так ты предлвгаешь мне скопировать сюда из справки?


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо