Статьи по разработке игр на QSP
Массивы уже не те
Как ведут себя массивы сейчас
Начать следует с того, что в «классическом» плеере версии 5.7.0 и ниже, а так же в Quest Navigator 0.0.28 и AeroQSP, в одном элементе массива можно хранить как текстовое, так и числовое значение. Вот как это выглядит:
mass[0]=12
$mass[1]="груша"
mass[1]=45
При этом мы спокойно можем получить и числовое, и текстовое значение по указанному индексу:
*pl mass[1]
Правда это создаёт ряд дополнительных трудностей. Например, каков будет размер массива в нашем примере?
arrsize('mass')
В обоих случаях arrsize
выдаст ответ 2
. И нам может показаться, что так и должно быть, ведь скорее всего мы имеем дело с двумя массивами: текстовым и числовым. Но на самом деле массив один. Ведь если мы будем добавлять только текстовые значения, размер «числовой части» массива так же увеличится.
mass[0]=12
$mass[1]="груша"
mass[1]=45
$mass[2]="слива"
$mass[3]="апельсин"
arrsize('$mass')
arrsize('mass')
В этом примере оба arrsize
вернут 4
. Это показывает, что мы имеем дело с одним и тем же массивом, который позволяет под одним индексом хранить элементы двух типов, а если мы не задали какой-то элемент явно, то его значение будет значением по умолчанию. Для числовых элементов значение по умолчанию 0
, для текстовых — ""
(пустая строка).
Такое поведение массива весьма просто представить в виде таблицы:
| элемента | $mass | mass |
|----------|------------|------------|
| 0 | 'яблоко' | 12 |
|----------|------------|------------|
| 1 | 'груша' | 45 |
|----------|------------|------------|
| 2 | 'слива' | |
|----------|------------|------------|
| 3 | 'апельсин' | |
Для удобства восприятия мы не внесли в таблицу значения элементов, которые не были явно заданы. Однако, как было сказано выше, при попытке использовать значения этих элементов, мы получим значения по умолчанию. В данном случае для числовых элементов это будут нули.
Может показаться, что такое поведение массива не только правильно, но и удобно, поскольку позволяет использовать одно имя для хранения и текстовых и числовых значений. Некоторые авторы, знающие о таком поведении, делали, например, такие вещи:
| элемента | $unit | unit |
|----------|---------------|------------|
| 0 | 'пехотинец' | 300 |
|----------|---------------|------------|
| 1 | 'гвардеец' | 670 |
|----------|---------------|------------|
| 2 | 'лучник' | 1500 |
|----------|---------------|------------|
| 3 | 'артиллерист' | 10 |
То есть в одном массиве хранили и наименования юнитов, и их количество.
Однако данным способом Вы могли пользоваться, только когда явно указывали числовой индекс элемента массива. Если написать такой код:
mass[]=12
$mass[]="груша"
mass[]=45
arrsize('$mass')
arrsize('mass')
— уверенность в том, какое значение вернёт arrsize
пропадает.
Для тех, кто ещё не знает: пустые квадратные скобки после имени массива означают, что мы хотим работать с последним элементом массива, и нам не важен его номер.
И тут происходит интересная штука. В момент, когда мы пытаемся последнему элементу присвоить значение, плеер создаёт новый элемент указанного типа и уже ему присваивает значение. Таким образом каждая такая команда генерирует в массиве элементы обоих типов, но лишь одному присваивается значение:
| элемента | $mass | mass |
|----------|------------|------------|
| 0 | 'яблоко' | |
|----------|------------|------------|
| 1 | | 12 |
|----------|------------|------------|
| 2 | 'груша' | |
|----------|------------|------------|
| 3 | | 45 |
Мы снова не вписали в таблицу значения элементов, которые не задавали, однако mass[0]
и mass[2]
вернут нам нули, если мы попробуем их использовать, а $mass[1]
и $mass[3]
вернут пустые строки (это соответствует их значениям по умолчанию).
Таким образом оба arrsize
вернут нам значение 4
, хотя мы явно задавали только два числовых и два текстовых элемента.
Как массивы будут себя вести
Новая версия плеера ещё не вышла, но всё ниже следующее будет работать в ней так. (Уже работает в плеере qSpider)
Теперь под одним индексом можно хранить либо только текстовое, либо только числовое значение. Мы своего рода объединили столбцы нашей таблицы:
| элемента | $mass | mass | | элемента | $mass или mass |
|----------|------------|------------| \ |----------|----------------|
| 0 | 'яблоко' | | -----------\ | 0 | 'яблоко' |
|----------|------------|------------| \ |----------|----------------|
| 1 | | 12 | / | 1 | 12 |
|----------|------------|------------| -----------/ |----------|----------------|
| 2 | 'груша' | | / | 2 | 'груша' |
|----------|------------|------------| |----------|----------------|
| 3 | | 45 | | 3 | 45 |
Это означает, что код:
mass[]=12
$mass[]="груша"
mass[]=45
arrsize('$mass')
arrsize('mass')
будет работать так же, как и работал. Т.е. каждая операция присвоения создаёт новый элемент в массиве, которому мы присваиваем либо строку, либо текст. И в данном случае мы создадим четыре разных элемента массива, два из которых будут текстового типа, два — числового.
Немного по-другому поведёт себя наш изначальный код:
mass[0]=12
$mass[1]="груша"
mass[1]=45
arrsize('$mass')
arrsize('mass')
Здесь, присвоив элементу сначала текстовое, а затем числовое значение, мы «затрём» изначальное текстовое значение числовым. В результате работы этого кода мы получим массив из двух элементов, и оба элемента будут числовыми — arrsize
вернёт 2
в обеих командах.
Чтобы закрепить новые знания, рассмотрим другой наш пример:
mass[0]=12
$mass[1]="груша"
mass[1]=45
$mass[2]="слива"
$mass[3]="апельсин"
arrsize('$mass')
arrsize('mass')
Здесь, как и в предыдущем примере, числовые значения «затрут» текстовые для элементов 0
и 1
, а в элементах 2
и 3
будут текстовые значения. Соответственно обе команды arrsize
вернут значение 4
.
В виде таблицы мы можем представить это так:
| элемента | $mass или mass |
|----------|----------------|
| 0 | 12 |
|----------|----------------|
| 1 | 45 |
|----------|----------------|
| 2 | 'слива' |
|----------|----------------|
| 3 | 'апельсин' |
Если мы попытаемся использовать текстовые значения элементов 0
и 1
, то получим значения по-умолчанию, то есть — ""
(пустые строки). Аналогично, если мы попытаемся использовать числовые значения элементов 2
и 3
, то получим числовые значения по-умолчанию — 0
(нули).
Возможно пока Вы этого не заметили, но это очень масштабное изменение, которое потребует от некоторых авторов существенно изменить свои привычки в программировании на QSP.
Что можно и нужно сделать
Автор этой статьи уже ощутил на себе вес изменений в работе массивов.
Протестировав «Вереницу миров или выводы из закона Мёрфи» на плеере qSpider, который уже использует новую версию библиотеки, я (не без помощи Werewolf`а и Byte`а) обнаружил ошибки логики в коде, которые скрадывались в плеерах версии 5.7.0. именно благодаря тому, что под одним индексом в массиве можно было хранить и текстовое, и числовое значение. К счастью, эти ошибки легко поправить.
Если Вы где-либо использовали запись в массив под одним индексом и числовых и текстовых значений, Вам так же следует исправить это. Особенно критично исправить в проектах, разработка которых затянется на ближайшие год-два.
Предложенный пример, где названия и количество юнитов хранились в одном массиве, больше работать не будет.
| элемента | $unit | unit |
|----------|---------------|------------|
| 0 | 'пехотинец' | 300 |
|----------|---------------|------------|
| 1 | 'гвардеец' | 670 |
|----------|---------------|------------|
| 2 | 'лучник' | 1500 |
|----------|---------------|------------|
| 3 | 'артиллерист' | 10 |
!!! так делать нельзя !!!
И наш совет таков: не используйте и текстовые, и числовые значения элементов в одном массиве. Лучше завести два массива. Отдельно для текстовых и числовых значений:
unit_count[0]=337
Помимо изменений в массивах нас ждёт ещё целый ряд изменений, но они менее глобальны, и о них мы поговорим в следующих статьях.
Всем успехов в написании игр, и не бойтесь кажущейся сложности!
Памятка по изменениям в работе массивов:
Статья написана по мотивам:
- статьи Pseudopod`а trello.com/.../одновременное-использование-arri-и-arri
- и поста Byte`а qsp.org/index.php...&Itemid=57
Статья доступна и на других ресурсах: