Сторінка 3 з 3

Re: Конкурс BASIC 10 Liner Contest

Додано: 18 квітня 2023, 14:28
Nick
Обчислювальний GO TO

Цікавою особливістю ZX BASIC є те, що номер рядка можна взяти зі змінної або виразу:

Код: Виділити все

GO TO 7*(k$="")
є чинним оператором. Він переходить до рядка 7, якщо змінна k$ є порожньою, і до рядка 0 в іншому випадку. Зверніть увагу, що номер рядка має бути цілим. Такий самий підхід працює і з GO SUB.
У інших діалектах схожий ефект досягається за допомогою операторів ON ... GOTO та ON ... GOSUB.

Re: Конкурс BASIC 10 Liner Contest

Додано: 18 квітня 2023, 14:29
Nick
Визначайте функції

Оператор DEF FN, присутній у більшості діалектів, можна використовувати для стиснення коду. Якщо один і той самий параметризований вираз використовується багато разів у вашій грі на BASIC, визначте його як функцію. Наприклад, навігаційний код клавіатури (MS BASIC) із уявної гри для двох гравців

Код: Виділити все

1k$=INKEY$
2u=u+(k$="a"ANDu>28)-(k$="d"ANDu<228):v=v+(k$="w"ANDv>28)-(k$="s"ANDv<228)
3x=x+(k$="j"ANDx>28)-(k$="l"ANDx<228):y=y+(k$="i"ANDy>28)-(k$="k"ANDy<228)
можна переписати як

Код: Виділити все

0DEFFNK(P,A$,B$)=P+(k$=A$ANDP>28)-(k$=B$ANDP<228)
1k$=INKEY$:u=FNK(u,"a","d"):v=FNK(v,"w","s"):x=FNK(x,"j","l"):y=FNK(y,"i","k")
зекономивши 80 символів!

Re: Конкурс BASIC 10 Liner Contest

Додано: 18 квітня 2023, 18:39
Nick
Симетрія всюди

Нас оточує симетрія. Люди, тварини, рослини, майже все на Землі та поза її межами є симетричним. Це рівною мірою стосується і багатьох штучних об’єктів, таких як автомобілі чи літаки.
Дзеркальне відображення — це різновид симетрії. Астронавт, повернутий ліворуч, є дзеркальною версією самого себе, повернутого праворуч. Гоночний автомобіль, що рухається по екрану (вперед), можна повернути на 180 градусів, щоб транспорт рухався в протилежному напрямку.
SCRSHOT2.PNG
Ви можете використовувати цю особливість для оптимізації розміру гри. Розглянемо визначення спрайту кулі в MSX BASIC:

Код: Виділити все

0 SCREEN2:FORI=1TO8:READX:A$=A$+CHR$(X):NEXT:SPRITE$(0)=A$
1 DATA&B00111100
2 DATA&B01111110
3 DATA&B11111111
4 DATA&B11111111
5 DATA&B11111111
6 DATA&B11111111
7 DATA&B01111110
8 DATA&B00111100
Використовуючи вертикальну симетрію, він перетворюється на:

Код: Виділити все

0 SCREEN2:FORI=1TO4:READX:A$=CHR$(X)+A$+CHR$(X):NEXT:SPRITE$(0)=A$
1 DATA&B11111111
2 DATA&B11111111
3 DATA&B01111110
4 DATA&B00111100
Подібним чином ми можемо створити реактивний винищувач, спрямований вгору і вниз за єдиним шаблоном:

Код: Виділити все

0 FORI=1TO8:READX:A$=A$+CHR$(X):B$=CHR$(X)+B$:NEXT:SPRITE$(0)=A$:SPRITE$(1)=B$
1 DATA&B00011000
2 DATA&B00011000
3 DATA&B00111100
4 DATA&B01111110
5 DATA&B11111111
6 DATA&B00011000
7 DATA&B00111100
8 DATA&B01111110
Нотація &B в операторах DATA використовується для ілюстрації, десяткові числа дають більш компактне представлення.

Re: Конкурс BASIC 10 Liner Contest

Додано: 18 квітня 2023, 18:48
Nick
Щуролов

Як і в серіалі "Кремнієва долина", алгоритми стиснення можуть чарівним чином перетворити щось велике у маленьке. Єдина проблема полягає в тому, що декомпресор займає програмний простір, тому потрібен ідеальний баланс між складністю декомпресора та ступенем стиснення. Універсального рецепту не існує, але алгоритми RLE часто дають хороші результати.
Розглянемо спрайт танкової гармати з моєї гри NLAW:
  0 □□□□□□□□□□□□□□□□ 0
  0 □□□□□□□□□□□□□□□□ 0
  0 □□□□□□□□□□□□□□□□ 0
  0 □□□□□□□□□□□□□□□□ 0
255 ■■■■■■■■■■■□■■■■ 239
255 ■■■■■■■■■■■□■■■■ 239
  0 □□□□□□□□□□□□□□□□ 0
  0 □□□□□□□□□□□□□□□□ 0
  0 □□□□□□□□□□□□□□□□ 0
  0 □□□□□□□□□□□□□□□□ 0
  0 □□□□□□□□□□□□□□□□ 0
  0 □□□□□□□□□□□□□□□□ 0
  0 □□□□□□□□□□□□□□□□ 0
  0 □□□□□□□□□□□□□□□□ 0
  0 □□□□□□□□□□□□□□□□ 0
  0 □□□□□□□□□□□□□□□□ 0
Він видається ідеальним для RLE-компресії: 4×0, 2×255, 14×0, 2×239, 10×0. Ми будемо кодувати дані як:

256 * (лічильник - 1) + значення

отримавши DATA768,511,3328,495,2304. Всього 25 символів, щоб визначити спрайт 32×32.

Зрозуміло, що багато спрайтів відрізняються лише деталями, наприклад:
□□□□□□□■■■□□□□□□ □□□□□□□■■■□□□□□□
□□□□□□■■■■■□□□□□ □□□□□□■■■■■□□□□□
□□□□□□■□□□■□□□□□ □□□□□□■□□□■□□□□□
□□□□□□■□□□■□■□□□ □□□□□□■□□□■□■□□□
□□□□□■■■□■■■□□□□ □□□□□■■■□■■■□□□□
□□□□■■■■■■■■■□□□ □□□□■■■■■■■■■□□□
□□□■■■■■■■■■■■□□ □□□■■■■■■■■■■■□□
□□□■■□■■■■■■■■□□ □□□■■■■■■■■□■■□□
□□□□□□■■■■■□■■□□ □□□■■□■■■■■□□□□□
□□□□□□■□■□■□■■□□ □□□■■□■□■□■□□□□□
□□□□□□■■■■■■□□□□ □□□□□■■■■■■□□□□□
□□□□□■■■■■■■□□□□ □□□□□■■■■■■■□□□□
□□□□□■■■□■■■■□□□ □□□□■■■■□■■■□□□□
□□□□□■■■□□■■■□□□ □□□□■■■□□■■■□□□□
□□□□■■■□□□□□□□□□ □□□□□□□□□□■■■□□□
□□□□■■■□□□□□□□□□ □□□□□□□□□□■■■□□□
Якщо деякі байти збігаються з відповідними у попередньому спрайті, ми кодуємо дані як:

-(лічильник - 1)

що дає -6 для фрагмента 8×7 пікселів у верхньому лівому куті.
Завдяки вищеописаному підходу я зберіг близько двох рядків коду у відзначеній нагородами грі NLAW.
Для визначення ковбойської графіки в моїй грі на тему Дикого Заходу була використана зовсім інша техніка. Зображення описувалося лініями сканування, де два значення вказують початкові та кінцеві координати. Від’ємний початок запобігає переходу до наступної лінії сканування (використовується абсолютне значення). Нульовий кінець - це ознака зупинки.
SCRSHOT4.PNG
Важко втиснути багато рівнів у десять рядків, якщо кожен рівень представляє інший лабіринт або місцевість. Часто можна запакувати рівні у бітові мапи, подібно до спрайтів (наприклад, повітря=&B00, вода=&B01, сходи=&B10, цегла=&B11). Також застосовуються методи стиснення, описані вище.
Зовсім інший підхід — процедурна генерація. Він рідко використовується з BASIC, оскільки такі алгоритми, як правило, повільні. Однак у моїй грі Escape! для Mattel Aquarius була реалізована процедурна генерація 5 рівнів.
SCRSHOT1.PNG