Программирование игр на ассемблере (Часть 1)

Дата публикации 22 окт 2002

Программирование игр на ассемблере (Часть 1) — Архив WASM.RU

--> Введение

Я уверен, что многие из вас, уже задумывались о создании игр. Многие из вас провели немало часов в интернете, в поисках какой-либо информации о том, как писать игры на чистом ассемблере. Но, к сожалению, такой информации почти нет, а тем более на русском. Я думаю, что этот туториал пополнит ряды русскоязычной документации и надеюсь, что он вам понравится.

--> О чем этот туториал ?

Этот туториал посвящен разработке игры полностью на ассемблере. В нем будет рассмотрен широкий круг вопросов - от структурированного кода до графических аспектов.

--> Для кого это ?

В широком смысле - для тех, кто хотел бы научиться тому, чего возможно не знал прежде... Да и вообще мало кто знает, что полностью виндовское приложение можно написать на чистом ассемблере.

--> Что для этого надо ?

Единственное требование - это способность читать. Однако, если вы желаете писать и транслировать исходный код, то вам понадобится компилятор MASM 6.12+. Вы также можете скачать пакет MASM32, в котором есть все, что вам понадобится.
MASM32v7 можно взять здесь:
http://www.movsd.com/ или
http://wasm.ru/tools/7/masm32v7.zip или
http://spiff.tripnet.se/~iczelion/files/masm32v7.zip.

--> Почему Ассемблер?

Общеизвестно, что любой компилятор генерит код, в котором неизбежно присутствуют баги. Ассемблер - трудный язык как для понимания, так и для написания, что особенно справедливо для DOS'а. С приходом Windows многое меняется.

В чтении труден не только ассемблер, даже в Cи бывают такие дебри, что сам черт ногу сломает. Читабельность исходников зависит от квалификации программиста и умения комментировать код. Вообще-то тут еще надо разобраться, что сложнее: сложить 2 переменные на ассемблере или проследить иерархию какой-нибудь виртуальной функции? Здесь комментарий решает все.
Помните: то, что известно вам, не значит, что это же известно другим.

Далее, проблема в переносимости. Предоставленный язык ассемблера не переносим на другие платформы. Есть, конечно, способ обойти это, который позволяет вам писать код для любой x86 платформы, но его описание не входит в рамки этого туториала. Большинство игрушек пишутся под винды. Это означает, что код привязан к DirectX и к WIN32API, следовательно вы не сможете переносить код, во всяком случае, без некоторой доработки.

Конечно, ассемблер труден в понимании. На этой странице будут показаны его основы. Писать ассемблерный код под Windows, особенно с MASM, очень просто. Это подобно написанию некоторого кода на C. Попытайтесь, и я уверен, что вы не будете разочарованы.

--> Основы Win32 ASM

Если Вы уже знакомы с языком ассемблера под windows, то можете пропустить этот раздел. Он является важным дополнением. Для его обсуждения, предполагается, что вы по крайней мере знакомы с x86 архитектурой.

Первое, что вам нужно понять, это команды (инструкции).

  • MOV
    • Эта инструкция копирует значение из одного места в другое. Вы можете копировать только из регистра в регистр, из памяти в регистр или из регистра в память. Но с помощью этой инструкции, вы не можете копировать напрямую из памяти в память.
      Код (Text):
      1.  
      2. Пример:
      3.  
      4.     MOV EAX, 30
      5.     MOV EBX, EAX
      6.     MOV my_var1, EAX
      7.     MOV DWORD PTR my_var, EAX
      В первой строке число 30 копируется в регистр EAX. Во второй строке регистр EAX копируется в регистр EBX. В 3-ей строке регистр EAX копируется в память. В 4-ой строке регистр EAX копируется в то место памяти, куда УКАЗЫВАЕТ пойнтер my_var , причем префикс DWORD указывает на то, что пересылаются 4 байта.

  • ADD & SUB
    • Эти две инструкции выполняют сложение и вычитание, соответственно.
      Код (Text):
      1.  
      2. Пример:
      3.     ADD EAX, 30
      4.     SUB EBX, EAX
      Прибавляем 30 к содержимому регистра EAX, а затем вычитаем полученное значение из регистра EBX.

  • MUL & DIV
    • Эти две инструкции выполняют умножение и деление, соответственно.
      Код (Text):
      1.  
      2. Пример:
      3.     MOV EAX, 10
      4.     MOV ECX, 30
      5.     MUL ECX
      6.     XOR EDX, EDX
      7.     MOV ECX, 10
      8.     DIV ECX
      Рассмотрим пример: сначала загружаем в EAX=10 и в ECX=30. EAX по умолчанию всегда один из 2-х сомножителей, посему третья команда (в ней вы явно указываете второй сомножитель) перемножает EAX и ECX. Результат от умножения (произведение) будет находится в EAX:EDX. Перед выполнением деления, сначала Вы должны очистить регистр EDX, что и делает команда XOR, выполняя исключающее ИЛИ с самим собой. После деления, целая часть результата будет находится в EAX, а остаток (если есть) в EDX.

Вообще инструкций очень много, но этих пока достаточно для начала. Вероятно мы будем использовать и некоторые другие, но их не сложно понять, если только вы поняли основные. Теперь нам нужно разобраться с правилами вызова функций. Мы будем использовать стандартные правила, такие же как Win32 API. Что это значит, а то, что мы помещаем параметры в стек справа налево и нам также не надо будет заботиться об очистке стека от параметров, все это будет для нас прозрачно. Для вызова функции мы будем использовать псевдо-оператор INVOKE.

Далее, есть одна проблема с вызовом функций Windows. Чтобы использовать invoke, вы должны иметь прототип функции.

Вообще, MASM обеспечивает высокий уровень синтаксиса при написании. В нем есть конструкции, позволяющие писать логику If-Then-Else и циклы For loops аналогично сишным конструкциям.

--> Разработка

А теперь пришло время для проектирования игры. Этим процессом часто пренебрегают и сразу кидаются кодировать то, что пришло в голову. Хотя такой подход иногда и проходит, но чаще всего проваливается.

Как говорится, сначала было слово. Для написания игры нужно представить в голове, как она будет работать. Иногда просто полезно описать СЛОВАМИ то, что вы хотите видеть в своей игре.

Простая часть закончена, теперь нужно продумать все детали. Будут ли в игре элементы соревнования? Нужны ли опции сохранения/загрузки? Сколько уровней? Что должно происходить в конце уровня? Имеется ли вводный экран? И еще много, много вопросов.

После этого нужно будет приниматься за наброски уровней. Какой должен быть экран и интерфейс? Это не обязательно должно быть точно так, но это даст реальную картину, как должна выглядеть финальная версия игры.

--> Код

Всегда имеет смысл насыщать код возможно большим количеством комментариев, чем лично я, например, всегда пренебрегаю.

Далее следует примерная схема организации ассемблерного игрового кода:

Код (Text):
  1.  
  2. ;###########################################################################
  3. ;###########################################################################
  4. ; ABOUT SPACE-TRIS:
  5. ;
  6. ;   Главная секция - WinMain и т.д.
  7. ;
  8. ;           - WinMain()
  9. ;           - WndProc()
  10. ;           - Main_Loop()
  11. ;           - Game_Init()
  12. ;           - Game_Main()
  13. ;           - Game_Shutdown()
  14. ;
  15. ;###########################################################################
  16. ;###########################################################################
  17.  
  18. ;###########################################################################
  19. ;###########################################################################
  20. ; THE COMPILER OPTIONS
  21. ;###########################################################################
  22. ;###########################################################################
  23.  
  24.         .386
  25.         .MODEL flat, stdcall
  26.         OPTION CASEMAP :none   ; case sensitive
  27.  
  28. ;###########################################################################
  29. ;###########################################################################
  30. ; THE INCLUDES SECTION
  31. ;###########################################################################
  32. ;###########################################################################
  33.  
  34.         ;==================================================
  35.         ; хидеры для Windows structs,
  36.         ; unions, constants
  37.         ;==================================================
  38.         INCLUDE Includes\Windows.inc
  39.  
  40.         ;================================================
  41.         ; хидеры для Window calls
  42.         ;================================================
  43.         INCLUDE \masm32\include\comctl32.inc
  44.         INCLUDE \masm32\include\comdlg32.inc
  45.         INCLUDE \masm32\include\shell32.inc
  46.         INCLUDE \masm32\include\user32.inc
  47.         INCLUDE \masm32\include\kernel32.inc
  48.         INCLUDE \masm32\include\gdi32.inc
  49.  
  50.         ;====================================
  51.         ; хидеры Direct Draw
  52.         ;====================================
  53.         INCLUDE Includes\DDraw.inc
  54.  
  55.         ;===============================================
  56.         ; либы
  57.         ;================================================
  58.         INCLUDELIB \masm32\lib\comctl32.lib
  59.         INCLUDELIB \masm32\lib\comdlg32.lib
  60.         INCLUDELIB \masm32\lib\shell32.lib
  61.         INCLUDELIB \masm32\lib\gdi32.lib
  62.         INCLUDELIB \masm32\lib\user32.lib
  63.         INCLUDELIB \masm32\lib\kernel32.lib
  64.  
  65.         ;=================================================
  66.         ; хидеры с прототипами
  67.         ;=================================================
  68.         INCLUDE Protos.inc
  69.  
  70. ;###########################################################################
  71. ;###########################################################################
  72. ; LOCAL MACROS
  73. ;###########################################################################
  74. ;###########################################################################
  75.  
  76.         szText MACRO Name, Text:VARARG
  77.                 LOCAL lbl
  78.                 JMP lbl
  79.                 Name DB Text,0
  80.                 lbl:
  81.         ENDM
  82.  
  83.         m2m MACRO M1, M2
  84.                 PUSH             M2
  85.                 POP               M1
  86.         ENDM
  87.  
  88.         return MACRO arg
  89.                 MOV      EAX, arg
  90.                 RET
  91.         ENDM
  92.  
  93.         RGB MACRO red, green, blue
  94.                 XOR      EAX,EAX
  95.                 MOV      AH,blue
  96.                 SHL      EAX,8
  97.                 MOV      AH,green
  98.                 MOV      AL,red
  99.         ENDM
  100.  
  101.         hWrite MACRO handle, buffer, size
  102.                 MOV      EDI, handle
  103.                 ADD      EDI, Dest_index
  104.                 MOV      ECX, 0
  105.                 MOV      CX, size
  106.                 ADD      Dest_index, ECX
  107.                 MOV      ESI, buffer
  108.                 movsb
  109.         ENDM
  110.  
  111.         hRead MACRO handle, buffer, size
  112.                 MOV      EDI, handle
  113.                 ADD      EDI, Spot
  114.                 MOV      ECX, 0
  115.                 MOV      CX, size
  116.                 ADD      Spot, ECX
  117.                 MOV      ESI, buffer
  118.                 movsb
  119.         ENDM
  120.  
  121. ;#################################################################################
  122. ;#################################################################################
  123. ;  глобальные переменные
  124. ;#################################################################################
  125. ;#################################################################################
  126.  
  127. ;#################################################################################
  128. ;#################################################################################
  129. ; External variables
  130. ;#################################################################################
  131. ;#################################################################################
  132.  
  133. ;#################################################################################
  134. ;#################################################################################
  135. ; BEGIN INITIALIZED DATA
  136. ;#################################################################################
  137. ;#################################################################################
  138.  
  139.     .DATA
  140.  
  141. ;#################################################################################
  142. ;#################################################################################
  143. ; BEGIN CONSTANTS
  144. ;#################################################################################
  145. ;#################################################################################
  146.  
  147. ;#################################################################################
  148. ;#################################################################################
  149. ; BEGIN EQUATES
  150. ;#################################################################################
  151. ;#################################################################################
  152.  
  153.         ;=================
  154.         ;Utility Equates
  155.         ;=================
  156. FALSE           EQU  0
  157. TRUE            EQU  1
  158.  
  159.  
  160. ;#################################################################################
  161. ;#################################################################################
  162. ; BEGIN THE CODE SECTION
  163. ;#################################################################################
  164. ;#################################################################################
  165.  
  166.   .CODE
  167.  
  168. start:
  169.  
  170. ;########################################################################
  171. ; WinMain Function
  172. ;########################################################################
  173.  
  174. ;########################################################################
  175. ; End of WinMain Procedure
  176. ;########################################################################
  177.  
  178. ;########################################################################
  179. ; Main Window Callback Procedure -- WndProc
  180. ;########################################################################
  181.  
  182. ;########################################################################
  183. ; End of Main Windows Callback Procedure
  184. ;########################################################################
  185.  
  186. ;========================================================================
  187. ;========================================================================
  188. ; THE GAME PROCEDURES
  189. ;========================================================================
  190. ;========================================================================
  191.  
  192. ;########################################################################
  193. ; Game_Init Procedure
  194. ;########################################################################
  195.  
  196. ;########################################################################
  197. ; END Game_Init
  198. ;########################################################################
  199.  
  200. ;########################################################################
  201. ; Game_Main Procedure
  202. ;########################################################################
  203.  
  204. ;########################################################################
  205. ; END Game_Main
  206. ;########################################################################
  207.  
  208. ;########################################################################
  209. ; Game_Shutdown Procedure
  210. ;########################################################################
  211.  
  212. ;########################################################################
  213. ; END Game_Shutdown
  214. ;########################################################################
  215.  
  216. ;######################################
  217. ; THIS IS THE END OF THE PROGRAM CODE #
  218. ;######################################
  219. END start
  220.  
. . .

Вот мы и подошли к концу первой статьи. А теперь хорошая новость - весь скучный материал в основном позади. Есть еще и плохая новость - вы не видели код, который будет в следующей статье. :smile3: © Chris Hobbs, пер. UniSoft


0 79.501
archive

archive
New Member

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