GBA ASM - День 13: Эффекты со спрайтами

Дата публикации 10 авг 2006

GBA ASM - День 13: Эффекты со спрайтами — Архив WASM.RU

Какие именно эффекты со спрайтами?

Мы рассмотрим следующие: вертикальный и горизонтальный кувырок (flip), мозаику, вращение и масштабирование. Тем не менее, относительно вращения, я не буду рассказывать о SIN() и COS(), поэтому мы тольо обсудим что и где поместить в данных для поворота/масштабирования, а остальное вам придётся додумать самим. Я мог бы обсудить создание таблицы значений для массива вращения, но это не слишком вписывается в тему данного Дня.

Флаги кувырка

Это настолько просто, что я даже не буду давать полный пример. Флаг вертикального кувырка - это бит #12 в атрибуте 0. Необходимые константы уже содержатся в sprites.h:

- VERTICAL_FLIP
- HORIZONTAL_FLIP

Флаг горизонтального кувырка - это бит #13 в атрибуте 0. Чтобы включить флаг кувырка, вам нужно поместить содержимое первых 32-х битов OAM-элемента спрайта в регистр и поEORить (то же самое, что и поXORить) его с VERTICAL_FLIP или HORIZONTAL_FLIP. Ок, вот немного кода:

Код (Text):
  1.  
  2. ldr r2,=OAM
  3. ldr r3,[r2] ; загружаем r3 из памяти
  4. ; вышеприведённое загрузить r3 атрибутом 0 и атрибутом 1, т.к. регистр
  5. ; 32-х битный, а OAM-атрибуты 16-ти битные.
  6. eor r3,r3,VERTICAL_FLIP   ; XORим r3 с VERTICAL_FLIP и помещаем значение в r3.
  7. ; EOR и XOR - это одно и то же, главное помните, что инструкция называется EOR.
  8. str r3,[r2]  ; сохраняем модифицированные атрибуты обратно в OAM.

Этот код включает флаг вертикального кувырка. Я думаю, вы поняли идею, и сможете включить флаг горизонтального кувырка самостоятельно.

Мозаика

Регистр мозаики находится по адресу 0x400004C. Регистр 16-ти битный, биты #15-12 - это вертикальная мозаика, а #11-8 - горизонтальная. Другие биты предназначются для бэкграунда. Кроме инициализации REG_MOSAIC, нам также понадобится установить флаг мозаики в атрибуте 0. Его можно включить, заменив в коде выше VERTICAL FLIP на MOSAIC. Обратите внимание, что вы можете сORить их с помощью символа '|'. Вот изменённый пример:

Код (Text):
  1.  
  2. ; иницилизируем регистр мозаики
  3. ldr r4,=REG_MOSAIC
  4. ldr r3,=0x1200  ; 1 для горизонтальной, 2 для вертикальной, ничего для
  5.                 ; бэкграунда
  6. str r3,[r4]   ; сохраняем его
  7.  
  8. ldr r2,=OAM
  9. ldr r3,[r2] ; загружаем r3 из памяти
  10. ; вышеприведённое загрузить r3 атрибутом 0 и атрибутом 1, т.к. регистр
  11. ; 32-х битный, а OAM-атрибуты 16-ти битные.
  12. eor r3,r3,MOSAIC   ; XORим r3 с MOSAIC и помещаем значение в r3.
  13. ; EOR и XOR - это одно и то же, главное помните, что инструкция называется EOR.
  14. str r3,[r2]  ; сохраняем модифицированные атрибуты обратно в OAM.

И вуаля! У вас есть мозаичный спрайт.

Вращение

Я надеюсь, что вы прочитали День 3 C-туториала на ThePernProject.COM, потому что если нет, всё это будет достаточно нелегко. Идите, и прочитайте его.

...
...

Прочитайте ещё раз :smile3:.
...
...

Думаете, что вы его поняли? Если нет, то неважно, так как я всё равно собираюсь объяснить это сам.

Чтобы с чего-то начать, скажу, что есть нечто под названием "данные вращения" (Rotation Data), в каждом элементе которых есть 4 16-ти битных "пятна". Поняли? Хорошо.

Данные вращения находятся в OAM. Как, спросите вы, разве в OAM не атрибуты спрайтов? Я отвечу: да. Помните, что случилось с атрибутом 3? Мы никогда его не использовали, в то время, как этот атрибут 3 и является данным вращения. Вот маленькая диаграма, показывающая отображение OAM на элементы вращения данных и pa, pb, pc, pd, о которых рассказывается в Дне 3 на ThePernProject:

Код (Text):
  1.  
  2. Sprite 0 Att#0
  3. Sprite 0 Att#1
  4. Sprite 0 Att#2
  5. Sprite 0 Att#3 - Элемент данных вращения #0 - 16bit "spot"#1 - pa
  6. Sprite 1 Att#0
  7. Sprite 1 Att#1
  8. Sprite 1 Att#2
  9. Sprite 1 Att#3 - Элемент данных вращения #0 - 16bit "spot"#2 - pb
  10. Sprite 2 Att#0
  11. Sprite 2 Att#1
  12. Sprite 2 Att#2
  13. Sprite 2 Att#3 - Элемент данных вращения #0 - 16bit "spot"#3 - pc
  14. Sprite 3 Att#0
  15. Sprite 3 Att#1
  16. Sprite 3 Att#2
  17. Sprite 3 Att#3 - Элемент данных вращения #0 - 16bit "spot"#4 - pd
  18.  
  19. Sprite 4 Att#0
  20. Sprite 4 Att#1
  21. Sprite 4 Att#2
  22. Sprite 4 Att#3 - Элемент данных вращения #1 - 16bit "spot"#1 - pa
  23. Sprite 5 Att#0
  24. Sprite 5 Att#1
  25. Sprite 5 Att#2
  26. Sprite 5 Att#3 - Элемент данных вращения #1 - 16bit "spot"#2 - pb
  27. Sprite 6 Att#0
  28. Sprite 6 Att#1
  29. Sprite 6 Att#2
  30. Sprite 6 Att#3 - Элемент данных вращения #1 - 16bit "spot"#3 - pc
  31. Sprite 7 Att#0
  32. Sprite 7 Att#1
  33. Sprite 7 Att#2
  34. Sprite 7 Att#3 - Элемент данных вращения #1 - 16bit "spot"#4 - pd
  35. ---- И в таком духе продолжается дальше по всему OAM ----

Я поинмаю, что эта диаграмма получилось довольно большой, но я надеюсь, что она хорошо иллюстрирует расположение данных вращения. Обратите, что любой спрайт может использовать любой элемент данных вращения. Есть 32 элемента, то есть 32 спрайта могут вращаться/масштабироваться.

Тогда что нам нужно поместить в каждое из 16-ти битных "пятен" (pa, pb, pc, pd)? Ок, ThePernProject даёт нам несколько очень неплохих уравнений:

Код (Text):
  1.  
  2. spot 1 - pa needs to be the COSine of the angle.
  3. spot 2 - pb needs to be the SINe of the angle.
  4. spot 3 - pc needs to be the NEGATIVE SINe of the angle.
  5. spot 4 - pd needs to be the COSine of the angle.

Здесь есть ещё кое-что, но оно относится к вращению, которое мы рассмотрим в другой раз.

Обратите внимание, что "пятно" 3 должно быть отрицательным синусом угла, и это то, что делает вращение таким сложным (по крайней мере для меня). Чтобы инициализировать "пятна", нужно получить атрибуты 2 и 3 какого-либо спрайта, очистить атрибут 3 и "пятно" с помощью AND, а затем установить новое значение с помощью OR. Помните, это 16-ти битные числа, поэтому если мы просто инициализируем атрибут 3 нужным значением, мы можем случайно обнулить атрибут 2.

Чтобы облегчить эту задачу, я сделал несколько (на самом деле, довольно много) новых define'ов в sprites.h. Они предназначаются для данных вращения и выглядят как PA_0, PB_0, PC_0, PD_0. Замените '0' номером элемента данных вращения, который вы хотите использовате. Держите в уме, что в sprites.h они определены до PD_19 включительно.

Также, чтобы сделать все это проще, так нам нужно только изучить, как вращать спрайты, мы не будем контролировать обнуление атрибута 2 (мне следует написать соответствующий день о байтовых масках). Вместо этого, мы просто используем спрайт #0 и элемент данных вращения #0. Таким образом, мы можем безболезненно обнулять атрибут 2, так как он и так должен быть равен 0.

Начнём кодирование!

Я надеюсь, что у вас ещё остался sprit.asm из Дня 5. Держите его и дальше, потому что он понадобится в будущем ещё не раз. Давайте глянем на код!

Код (Text):
  1.  
  2. ;;--- НАЧАЛО КОДА ---;;
  3. @include screen.h  
  4. @include dma.h  
  5. @include keypad.h
  6. @include <a href="/archive/pub/26/files/sprites.h">sprites.h</a>
  7.  
  8. b start
  9. @include sprit.asm
  10. start
  11.  
  12. ldr r1,=REG_DISPCNT
  13. ldr r2,=(MODE_1|BG2_ENABLE|OBJ_ENABLE|OBJ_MAP_1D)
  14. str r2,[r1]
  15.  
  16. ldr r1,=REG_DMA3SAD
  17. ldr r2,=pallete
  18. str r2,[r1]
  19. ldr r1,=REG_DMA3DAD
  20. ldr r2,=OBJPAL
  21. str r2,[r1]
  22. ldr r1,=REG_DMA3CNT
  23. ldr r2,=(128|DMA_32NOW)
  24. str r2,[r1]
  25.  
  26. ldr r1,=REG_DMA3SAD
  27. ldr r2,=obj
  28. str r2,[r1]
  29. ldr r1,=REG_DMA3DAD
  30. ldr r2,=CHARMEM
  31. str r2,[r1]
  32. ldr r1,=REG_DMA3CNT
  33. ldr r2,=(512|DMA_32NOW)
  34. str r2,[r1]
  35. ;;--- СТОП КОПИРОВАНИЕ ---;;

Полагаю, вы должны понять, что здесь происходит.

Код (Text):
  1.  
  2. ;;--- ПРОДОЛЖЕНИЕ КОДА ---;;
  3. ldr r1,=OAM
  4. ldr r2,=((SQUARE|COLOR_256|30))|((SIZE_32|(0&lt;&lt;9)|10)&lt;&lt;16)
  5. str r2,[r1]
  6. ;;--- СТОП КОПИРОВАНИЕ ---;;

Здесь есть кое-что новенькое. Количество данных вращения сдвигается на 9, чтобы оказаться в правильном "пятне". Мы используем элемент данных вращения #0.

Код (Text):
  1.  
  2. ;;--- ПРОДОЛЖЕНИЕ КОДА ---;;
  3. ldr r1,=PA_0    ; сохранение будет происходить в PA.
  4. ldr r2,=70&lt;&lt;16  ; COS(45 градусов) = 0.70, в первом байте регистра, который
  5. str r2,[r1]     ; работает с числами с фиксированной запятой в данных вращения.
  6.  
  7. ldr r1,=PB_0    ; сохранение будет происходить в PB
  8. ldr r2,=70&lt;&lt;16  ; SIN(45 градусов) = 0.70. так же как и в предыдущем случае.
  9. str r2,[r1]    
  10.  
  11. ldr r1,=PC_0    ; сохранение будет происходить в PC
  12. ldr r2,=0       ; Отрицательный SIN(45 degrees) = -0.70
  13. sub r2,r2,70    ; вычитаем 70 от 0, чтобы получить отрицательное значение, и
  14. mov r2,r2,lsl 16   ; сдвигаем, чтобы получить только необходимые 16 бит.
  15. str r2,[r1]
  16.  
  17. ldr r1,=PD_0    ; сохранение будет происходить в PD
  18. ldr r2,=70&lt;&lt;16  ; COS(45 градусов) = 0.70 снова.
  19. str r2,[r1]  ; сохраняем в атрибуты  #2&3 спрайта 3.
  20. ;;--- СТОП КОПИРОВАНИЕ ---;;

Обратите внимание, что мы работаем с 16-ти битными числами с фиксированной запятой, поэтом нам нужны эти 3 сдвига на 16 бит не только для того, чтобы получить значение в нужной части регистра, но также и потому, что 70 - это 0.70 и должно находиться в дробной части числа.

Код (Text):
  1.  
  2. ;;--- ПРОДОЛЖЕНИЕ КОДА ---;;
  3. infin
  4.  
  5. ldr r1,=KEYS           ; первые 3 строки проверяют, нажата ли клавиша A.
  6. ldr r1,[r1]            ; эти строки включают флаг вращения
  7. ands r1,r1,#KEY_A      ; и флаг двойного размера.
  8. ldreq r1,=OAM          ; однократное нажатие включает эти два флага.
  9. ldreq r2,[r1]          ; получаем атрибуты 0 & 1 спрайта.
  10. eoreq r2,r2,#(ROTATION_FLAG|SIZE_DOUBLE)  ; устанавливаем биты флагов с помощью
  11.                                           ; инструкции EOR (аналог XOR).
  12. streq r2,[r1]
  13. ; Обратите внимание, что последние 4 строки выполняются только, если нажата
  14. ; клавиша A.
  15.  
  16. b infin
  17. ;;--- КОНЕЦ КОДА ---;;

Компилируйте и запускайте! Я надеюсь, что вам всё понятно.

Обзор этого дня

Я рад, что доделал этот День, было весело. Да, 13 - счастливое число, вы знаете? Хе-хе. Пока. © Mike H, пер. Aquila


0 801
archive

archive
New Member

Регистрация:
27 фев 2017
Публикаций:
532