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

Вниз

Проблема с динамическим массивом   Найти похожие ветки 

 
Zeqfreed   (2003-12-14 13:28) [0]

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

...
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;...

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


 
Anatoly Podgoretsky ©   (2003-12-14 13:35) [1]

Лезешь за пределы выделенной памяти. Используй High


 
Zeqfreed   (2003-12-14 13:40) [2]

А поподробней?..


 
Anatoly Podgoretsky ©   (2003-12-14 13:43) [3]

А справка у тебя есть?
И еще желательно также использовать и Length


 
Zeqfreed   (2003-12-14 13:46) [4]

Справка-то есть! Но неужели трудно написать как надо!!!


 
Anatoly Podgoretsky ©   (2003-12-14 13:47) [5]

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


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

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


 
Anatoly Podgoretsky ©   (2003-12-14 14:07) [7]

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


 
MrAngel   (2003-12-14 14:19) [8]

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

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

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

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

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


 
Zeqfreed   (2003-12-14 14:38) [9]

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

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


 
Zeqfreed   (2003-12-14 14:41) [10]

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

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


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

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 := 0 to 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;

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


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


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


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


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

Нет, 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, но если оставлять её равной нулю то тоже получается ошибка!


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

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


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

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

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


 
Unknown user ©   (2003-12-15 19:25) [16]

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


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


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 считаю более правильным.


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

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


 
Unknown user ©   (2003-12-16 18:44) [19]

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


 
MrAngel   (2003-12-17 17:32) [20]

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


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


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


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

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


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

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


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

2 Unknown User

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

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


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

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

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



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

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

Наверх




Память: 0.53 MB
Время: 0.117 c
4-1075476396
GrayFace
2004-01-30 18:26
2004.04.11
Как управлять Winamp ом?


14-1081995157
Думкин
2004-04-15 06:12
2004.04.11
С днем рождения! 15 апреля.


14-1082440980
XAOC
2004-04-20 10:03
2004.04.11
что это такое и с чем его есть??????????????????


1-1082701946
Stas
2004-04-23 10:32
2004.04.11
Access и MDICHILD


1-1082653159
EugeneKo
2004-04-22 20:59
2004.04.11
Баги в Decision Cube. Есть другие инструменты?