Выбрать главу

-- в Pure.hs

initPure :: Sense -> [Event] -> Pure

20.6 Детализируем дальше

Вот так на самом интересном месте… Мы вынуждены прерваться. Я надеюсь, что вы уловили основную

идею метода и сможете закончить эту игру самостоятельно. Вся логика игры будет описана в модуле Pure. hs.

Причём в этом модуле будут только чистые функции. Осталось примерно 1000 строк кода. Я не буду выпи-

сывать своё решение, если вы где-то запнётесь или у вас что-то не будет получаться, вы можете свериться с

ним (оно входит в код, что прилагается с книгой).

20.7 Краткое содержание

В этой главе мы посмотрели на две интересные библиотеки. Физический движок Hipmunk и графическую

библиотеку OpenGL и узнали метод укрощения императивного кода. Мы разделили состояние игры на две

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

те параметры, которые необходимы для реализации логики игры. Все функции, отвечающие за логику игры

являются чистыми. Параметры императивной части не обновляются сразу, сначала мы делаем с них снимок,

потом передаём этот снимок в чистую часть, и она разбирается с тем как их обновлять. Части общаются между

собой на специальных маленьких языках, которые закодированы в типах. Это язык наблюдений (Event), язык

реакций (Query) и язык отрисовки игрового мира (Picture).

20.8 Упражнения

Закончите код игры. Или, возможно, при знакомстве с Hipmunk у вас появилась идея новой игры с неве-

роятной динамикой. Ещё лучше! Напишите её. При этом продумайте проект игры так, чтобы IO-типы не

разбежались по всей программе.

304 | Глава 20: Императивное программирование

Глава 21

Музыкальный пример

В этой главе мы напишем музыкальный секвенсор. Мы будем переводить нотную запись в midi-файл с

помощью библиотеки HCodecs. Она предоставляет возможность создания midi-файлов по описанию в Haskell.

При этом описание напоминает описание самого формата midi. Мы же хотим подняться уровнем выше и

описывать музыку нотами и композицией нот.

21.1 Музыкальная нотация

Для начала зададимся выясним: а что же такое музыка с точки зрения нашего секвенсора? Мы ищем

представление музыки, термины, в которых было бы удобно мыслить композитору. При этом необходимо

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

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

сэмплов, поскольку мы не сможем реализовать это представление в рамках midi. За ответом обратимся к

истории.

Нотная запись в европейской традиции

В европейской традиции принято описывать музыку в виде нотной записи. Нотный лист состоит из серии

нотных станов. Нотный стан состоит из пяти линеек. Каждая линейка обозначает определённую высоту. Нота

состоит из обозначения длительности и высоты. Разные длительности обозначаются штрихами и цветом

ноты, а высоте соответствует расположение на нотном стане.

Рис. 21.1: Буквенные обозначения высоты ноты

По длительности ноты различают на: целые, половины, четверти, восьмые, шестнадцатые и так далее.

Каждая последующая длительность в два раза меньше предыдущей. Длительность измеряется в долях от

такта. Такты обозначаются сплошной линией, которая перечёркивает все пять линеек нотного стана. По

высоте ноты, зависят от двух целых чисел, это номер октавы и номер ступени лада. В ладе обычно всего 12

ступеней. Их обозначают разными именами. Например в латинской нотации их обозначают так:

0

1

2

3

4

5

6

7

8

9

10

11

C

C

D

D

E

F

F

G

G

A

A

B

C

D

D

E

E

F

G

G

A

A

B

B

do

re

mi

f a

sol

la

ti

В самом нижнем ряду расположены имена нот. Во втором и четвёртом – обозначения нот с диезами и

с бемолями. Одна и та же нота может обозначаться по-разному. Буквами обозначают ноты тональности до

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