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

Вниз

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

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

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


 
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


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

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


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

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


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

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


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

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


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

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


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

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


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

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


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

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


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

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


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

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


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

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


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

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


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

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


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

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

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

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

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

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


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


 
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;

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


 
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 ?
Понял теперь смысл ?


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


 
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 и ошибок не будет связанных с глобальной переменной.


 
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??? Сколько создал - столько и удаляй.


 
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. А для написания своей игры сначала изучи основы программирования, иначе твой первый камень о который ты споткнулся будет не последним и не самым большим.


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


 
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);
при каждом создании спрайта есть ужасно.


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

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


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

2 MrAngel. Если ты создашь больше 100 000 спрайтов -то возможно заметишь разницу в 1 мс. Настолько вот медленнее :). А заводить глобальную переменную 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);
> при каждом создании спрайта есть ужасно.


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


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

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


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


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


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

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


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

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


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

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


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

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


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

2 Unknown User

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

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


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

2 Unknown User

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

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


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

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

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


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

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

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



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

Форум: "Игры";
Текущий архив: 2004.04.11;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.58 MB
Время: 0.043 c
14-1082031385
p0tia
2004-04-15 16:16
2004.05.09
Переменная time


3-1082025465
Flahas
2004-04-15 14:37
2004.05.09
exel..


1-1082602945
ORMADA
2004-04-22 07:02
2004.05.09
TCustomPanel


14-1081788868
Mishenka
2004-04-12 20:54
2004.05.09
Где достать Help для RxLib?


6-1078998524
hexbat
2004-03-11 12:48
2004.05.09
ГОСПОДА МАСТЕРА, ПОМОГИТЕ РАЗОБРАТЬСЯ С XML ЗАПРОСАМИ





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский