/
Tags: языки программирования компьютерные технологии
ISBN: 978-5-9775-1779-9
Text
Санкт-Петербург
«БХВ-Петербург»
2024
УДК 004.43-053.2
ББК 32.973.26-018.1
Л17
Л17
Лазаревский И. В.
Мама, не отвлекай. Я Python учу! — СПб.: БХВ-Петербург, 2024. — 192 с.: ил.
ISBN 978-5-9775-1779-9
Эта книга + телефон — все, что нужно ребенку, чтобы полностью самостоятельно без помощи взрослых освоить основы программирования на языке Python,
написать десятки игр, интерактивных программ и поделиться ими в любых привычных мессенджерах и соцсетях.
Книгу отличает сверхбыстрый старт, удобство обучения, легкость изложения
и авторский юмор.
При этом новички узнают о командах, циклах, типах данных, переменных, условных выражениях, графических примитивах и координатах. Освоят игры и анимацию, работу со строками, комментарии, методы (функции), операторы сравнения,
случайные числа, условные выражения и многое другое. Электронный архив на сайте издательства содержит коды примеров и изображения эмодзи.
Для детей младшего и среднего школьного возраста
УДК 004.43-053.2
ББК 32.973.26–018.1
Группа подготовки издания:
Руководитель проекта
Зав. редакцией
Редактор
Компьютерная верстка
Корректор
Дизайн обложки
Евгений Рыбаков
Людмила Гауль
Анна Кузьмина
Людмилы Гауль
Светлана Крутоярова
Зои Канторович
«БХВ-Петербург», 191036, Санкт-Петербург, Гончарная ул., 20.
ISBN 978-5-9775-1779-9
© ООО «БХВ», 2024
© Оформление. ООО «БХВ-Петербург», 2024
Содержание
Я
Python ........................................ 4
Как запускать код примеров и решений ... 5
Юному программисту ........................... 6
#проект Тамагочи........................................97
#домашний проект Развитие проекта ...........102
#проект НЛО .............................................103
Чему мы научились .......................... 107
Часть I. Статичная графика: графические
примитивы ......................................... 7
Глава 1. Быстрый старт......................... 7
Часть III. Игры и продвинутое
программирование .......................... 109
#проект Первая программа .......................... 8
Глава 6. Игры ............................. 109
#проект Яркие цвета и скромная консоль ....12
FlappyRabbit .............................. 110
Глава 2. Графические примитивы
и комментарии .................................. 17
#проект Прыгающий заяц ..........................111
#проект Марик............................................18
#проект Привередливый динозавр ............120
#проект Ракета ...........................................23
#проект FlappyRabbit .................................126
Глава 3. Переменные.......................... 30
AlienStrike ................................. 133
#проект Снеговик ........................................31
#проект Нашествие пришельцев ...............134
#проект Встроенные переменные ...............39
#проект Молнии ........................................138
#проект Заяц и препятствия ......................117
#проект Цикл жизни ..................................143
Часть II. Простые игры и интерактивные
программы ....................................... 43
#проект Объединение ...............................146
Глава 4. Главный игровой цикл ............. 43
#проект Новые пришельцы ........................152
#проект Графический мини-редактор .........44
#проект Эксперименты с редактором .........49
#проект Охота на зайца ..............................52
#проект Война с пришельцами ..................149
#проект Энергия .......................................155
#проект Настоящие молнии.......................160
#проект Работа над ошибками ....................56
Глава 7. Основы работы со списками
в Python ......................................... 166
#проект Заяц и морковка ............................60
#проект Тимур и его яблоки .......................167
#проект Непредсказуемая морковь ............66
#проект Полезные списки .........................170
#проект Склонение слов .............................70
#проект Яблоки и червяки .........................175
#проект Бесконечный бег ...........................75
#проект Собака и кость ...............................81
Глава 8. Программирование
на десктопе .................................... 181
Глава 5. Тамагочи и НЛО...................... 85
#проект Программирование в браузере ....182
#проект Хитрая кость ..................................86
#проект Программирование в VS Code ......183
#проект Корабли и грузовики .....................89
#проект Различие библиотек p5 и p5py......186
#домашний проект Две кости .........................93
Ответы к задачам ....................................190
#проект Собака-считака .............................94
Благодарности ........................................192
3
Я
Python
— Почему мобильного телефона достаточно для изучения Python?
— Смартфон есть почти у каждого школьника.
+
— Программирование с телефона даст возможность изучить программирование в десятки раз
большему количеству детей. Наша цель — обучить
1 000 000 детей в России!
— Разработка на мобильных устройствах — это моментальный старт в программировании. Попробуйте сами — первую программу вы напишете меньше, чем за
1 минуту.
— А насколько профессиональный код получается?
— Это не только просто, быстро и понятно, но и профессионально! В части III
книги мы покажем, как работать с Python на ноутбуках и стационарных компьютерах.
Для пап-программистов: как это на Python в браузере?
Всё просто, мы используем дополнительный слой интерпретации — реализацию Brython. Эта библиотечка компилирует код на питоне в код на JS, который уже может выполниться в браузере без каких-либо танцев с бубнами и дополнительных настроек. А это позволяет новичкам любого уровня сразу начать программировать.
За графические возможности отвечает популярная библиотека p5js с 17 000 звездами на GitHub, адаптированная
для Python как p5py. На сайте она подключена автоматически. А для разработки на компьютере в конце книги будет
рассказано, как её скачать и установить в качестве модуля для Python.
4
Как запускать код примеров
и решений
Просканируй телефоном QR-код,
чтобы открыть программу с телефона!
Здесь адрес кода.
Если хочешь открыть код с компьютера,
просто введи в браузере этот адрес.
У каждого примера он свой.
А это сам код. Можешь набить его
вручную и запустить, если зайдёшь
по адресу p5py.khasang.ru/ide
Здесь отображается результат
работы кода.
Если программа не запустилась или есть ошибки, что делать?
ä Считай QR-код решения (в начале следующего шага у проекта или в
конце книги) и посмотри на рабочий пример.
ä Поищи допущенные опечатки.
ä Задай свой вопрос в сообществах t.me/p4kids или vk.com/
programmingforkids и поищи рекомендации здесь: p5py.khasang.ru/help
5
Юному программисту
Привет!
Меня зовут Игорь. И я написал для тебя крутотейшую книгу по основам
программирования на Питоне, Пайтоне, Python.
Называй его как хочешь, но это язык номер 1 как у профессиональных
программистов, так и у студентов, школьников (по индексу TIOBE 2022).
Я жду от тебя выдающихся результатов!
Ведь в основу книги лег мой восьмилетний опыт подготовки и проведения
сотен вебинаров на онлайн-курсах по программированию. Я вырастил
десятки Senior-разработчиков, которые работают в EPAM, Сбере, @mail.ru.
И, надеюсь, если ты заинтересуешься программированием, то со временем
тоже сделаешь это своей профессией.
Меня вот хлебом не корми, дай только сидеть и ночами кодить какойнибудь новый онлайн-проект на Python, JavaScript, Node.js, Svelte, Java,
PostgreSQL. Надеюсь, я когда-нибудь расскажу тебе и про остальные
профессиональные технологии, которые использую в работе. А пока начнём
с основ языка Python и графической библиотеки p5py.
И да, напиши мне письмо, как твои успехи: igor@khasang.ru
6
Часть I
Статичная графика:
графические
примитивы
Быстро и просто включимся в практическое обучение языку Python
на реальных примерах прямо на телефоне.
Напишем первую программу. Разберём основы графики.
Изучим понятие «переменная»,
написав несколько мини-игр.
Глава 1
Быстрый старт
Запустим первую программу прямо с обложки книги.
Разберём все команды. Изучим отличие консоли
от графического окна.
7
#проект Первая программа
Шаг 1/4.
Запустим первую
программу
И как мн
мне написать первую
программу?
Привет!
Я — Питон. Исполнитель программы.
Просто считай телефоном QR-код.
Или зайди в браузере по ссылке:
p5py.khasang.ru/ide/dt/384
В браузере откроется редактор кода.
Нажми кнопку
RUN , чтобы запустить программу.
Ага, открылось, запустилось!
И здесь просят вынести мусор...
Нажми кнопку × , чтобы отказаться
выносить мусор, закрыть окно
с результатом и вернуться к коду.
#ДЗ Поменяй текст "Вынеси мусор" на "Я занят!".
8
Шаг 2/4.
Исправим первую ошибку
#тема кавычки
Вм
Вместо
«Я занят» я написал, что я учу
Pyt
Python,
но, видно, что-то пошло не так?
Да, программа выполнилась с ошибкой. Давай посмотрим, что написано:
сано
о:
File __main__, line 7
text(Я учу Python, 60, 90)
^
SyntaxError: invalid syntax
Файл __main__, строка 7
text(Я учу Python, 60, 90)
^
Синтаксическая ошибка: неверный синтаксис
Обрати внимание на кавычки! Они, во-первых,
должны быть. Во-вторых, именно такие: " " (двойные).
Или такие: ' ' (одинарные).
Но не такие: « ».
С ошибочными кавычками или без них программа
точно не заработает!
Когда мы хотим вывести текст на экран, мы всегда заключаем его в кавычки.
Это как цитата в книге. Невежливо цитировать чужой текст без кавычек.
Вот и мы обязательно используем кавычки.
#ДЗ исправь ошибку в коде, добавь
правильные кавычки.
Есть решение
в конце книги.
9
Ш 3/4. Поменяем координаты
Шаг
#тема числа и координаты
#
Получилось!
Пол
А что значат эти числа: 40, 90?
Это координаты того места,
в которое текст на экране выводить.
400
0, 0
300
Вверх тормашками!
В геометрии начало координат —
внизу слева, а у нас — вверху слева!
А числа 40, 90 разве не нужно
тоже заключать в кавычки?
Нет, не нужно. В кавычки мы заключаем только текст. Мне важно отличать
числа от текста — ведь с ними можно делать слишком разные действия.
Например, числа можно умножать и делить друг на друга, а текст
(строки) нельзя. Буквы текста можно делать заглавными, или прописными,
а с числами так не получится.
#ДЗ Попробуй поменять координаты текста, например, укажи числа 0
для отступа от левого края и 30 от верхнего.
10
Шаг 4/4. Поменяем размер текста
#тема text_size()
Ага,
А
гаа, текст теперь вверху и слева!
А что значит число 40?
Имя команды text_size()
(размер текста) говорит само за себя :)
Огромный
текст
10
100
Ма-а-а-ленький текст
Не пропусти запятые и круглые скобки.
Запятыми мы разделяем уточнения к нашей команде.
В данном случае разделяем запятыми текст, который хотим вывести на экран,
и его координаты.
#ДЗ Попробуй поменять размер текста, например, укажи 5 для совсем
маленького текста или 100 для огромного.
11
#проект Яркие цвета и скромная
консоль
Шаг 1/5.
Поменяем цвет фона
#тема background()
Интересно,
И
нтер
ресно, а как получился
белый цвет фона у программы?
Команда background(255) (фон) устанавливает цвет фона в одну краску
серого оттенка от ярко-белого до чёрного.
255 — белый цвет, 100 — серый, 0 — это чёрный.
А как сделать фон цветным?
G
R
B
Любой цвет можно получить
из смеси трёх цветов:
красного, зелёного, синего.
RGB
Такой способ задания цвета называется RGB-моделью.
Сокращение от первых букв основных цветов:
Red (красный), Green (зелёный), Blue (синий).
Команда background(255, 0, 0) устанавливает цвет фона в три краски:
255 красной краски, 0 зелёной и 0 синей.
0 — отсутствие цвета, 255 — максимальное его количество.
#ДЗ Попробуй установить красный цвет фона.
12
Шаг 2/5.
Смешаем цвета
#тема RGB, #тема fill()
Вот,
В
от, я сделал красный цвет.
А как получить другой цвет?
Оранжевый цвет состоит из красного с примесью зелёного.
ого.
А жёлтый — из равного количества красного и зелёного. Смотри:
255, 0, 0
0, 255, 0
0, 255, 0
255, 255, 0
0, 0, 255
0, 255, 255
255, 0, 0
0, 100, 0
255, 100, 0
Напомню, что командой background(255, 100, 0) можно установить
255 красной краски, 100 зелёной и 0 синей.
0 — отсутствие цвета, 255 — максимальное его количество.
А как поменять цвет самого текста?
Чёрный на красном плохо читается.
Команда fill(255) (заливка) устанавливает цвет, как и команда background,
но не фона, а текста. Командой fill(255, 0, 0) можно установить
255 красной краски, 100 зелёной и 0 синей.
255, 100, 0
#ДЗ Попробуй установить оранжевый цвет фона
и белый цвет текста.
13
Ш 3/5.
Шаг
Установим размер окна
#тема
size() и библиотека p5py
#т
#
А эта коман
команда, как я понял,
меняет размер окна?
Да, команда size(375, 169) (размер) устанавливает размер
мер
окна. Первое число — ширина. А второе — высота.
А верхние строчки
что означают?
#ДЗ Попробуй сделать окно нестандартного
размера, например 100 на 600.
из_модуля p5py импортировать вообще_все
и_запустить()
from p5py import *
run()
Эти команды нужны, чтобы сказать Питону, что мы
хотим использовать модуль p5py (или еще говорят:
графическую библиотеку p5py ) и запустить работу этого
модуля. Вернёмся к этому в части III книги!
А пока просто будем писать в начале каждой программы.
Когда нам графическая библиотека не потребуется, эти
строчки можно будет опустить.
Порядок команд важен!
Ты же не хочешь сначала сварить картошку с приправами
и только потом её помыть?
Регистр букв (заглавные или строчные) важен!
background и Background для Python — два разных слова.
14
Шаг 4/5.
Установим
выравнивание текста
#тема text_align()
Я хоте
хотел
ел вывести
выве
текст в центре экрана.
Но текст вылез за пределы окна. Почему?
По умолчанию, когда указываем координаты текста, мы
ы
указываем координаты его левой нижней точки. Посмотри:
левая нижняя точка текста ровно посередине экрана.
Но можно добавить команду text_align(CENTER, CENTER)
(выравнивание_текста(ЦЕНТР, ЦЕНТР)), которая устанавливает
выравнивание текста по центру. Вот смотри:
А слово CENTER не нужно в кавычки брать?
Нет, так как это переменная. Мы разберёмся с переменными попозже!
Ещё могут быть следующие комбинации:
ä вместо первого CENTER можно указать LEFT (СЛЕВА) или RIGHT (СПРАВА);
ä вместо второго CENTER можно указать TOP (ВЕРХ) или BOTTOM (НИЗ).
#ДЗ Попробуй установить выравнивание текста
относительно ПРАВОЙ и НИЖНЕЙ границ текста.
15
Ш 5/5.
Шаг
Выведем текст в консоль
#тема print() и консоль
#
А можно на
написать ещё короче программу?
Да, можно написать очень короткую программу, если нам
нужно только текст выводить, вот так:
А почему здесь нет координат у текста?
И размера? И цвета, и выравнивания?
Это так называемая консоль. Она служит для вывода технической
информации и сообщений об ошибках. Поэтому здесь текст без оформления,
он просто выводится построчно — друг за другом, строка за строкой.
Эх, для игр такое не подойдёт. Если даже цвета нет. Я проверил,
добавил через запятую числа — они просто вывелись на экран.
Ага, но консоль очень полезна. Мы уже встречались с ней,
когда забыли кавычки указать.
#ДЗ Попробуй написать несколько команд print("
16
") подряд.
Глава 2
Графические
примитивы
и комментарии
Изучим возможности графической библиотеки p5py по рисованию линий,
кругов, прямоугольников, точек на примере пары проектов.
Освоим команды и их последовательности.
Научимся комментировать код.
#проект Марик
Шаг 1/4.
Рисуем белки глаз
#тема ellipse()
Привет, я Марик! Нарисуй, пожалуйста,
алуйста, меня.
Графическая библиотека p5py для Python содержит
множество команд для рисования.
Например, команда ellipse(100, 100, 50, 50) (эллипс)
нарисует круг или эллипс.
Первые два числа — координаты центра эллипса.
А третье и четвертое числа — его ширина и высота.
Если ширина и высота одинаковы, то получится круг.
Ну-ка проверю, ага:
Если сделать два таких кругляша, чуть вытянутых, то
получатся белки́ глаз. Вот так:
#ДЗ Попробуешь добавить чёрные зрачки?
18
Шаг 2/4.
Добавляем зрачки
#тема no_stroke()
Добавлю
Доб
бавлю зр
зрачки.
И нарисую лицо: большой эллипс телесного цвета — 250, 210, 165.
Вот только белки́ у меня перестали быть белыми.
лыми
Это я забыл выбрать заливку белым цветом fill(255) перед рисованием
белко́в. И они закрасились предыдущей выбранной заливкой телесного цвета.
А ещё примени команду no_stoke() (без_обводки), чтобы убрать
чёрную обводку вокруг моих глаз.
#ДЗ Попробуешь сделать белки́ глаз белыми
и убрать вокруг них чёрную обводку?
19
#тема Комментарии
Ура, получилось!
У
Но не очень удобно, когда вот так код весь вперемешку.
При беглом взгляде не разберешь: где лицо, а где зрачки...
Есть такая хорошая штука, как комментарии.
Это строчки, которые начинаются со знака #.
После этого знака можно писать всё, что угодно, — и никакой
ошибки не будет.
Ну-ка, попробую.
И правда, очень удобно.
20
Шаг 3/4.
Рисуем рот
Не забудь нарисовать мне рот!!
Это было
было легко!
л
Просто нарисовал эллипс чёрного цвета.
Хочешь, нарисую его слегка озадаченным?
Давай.
Нарисовал сверху чёрного рта цветной эллипс, как у лица.
Он закрыл часть рта, получилась лёгкая озадаченность:
21
Шаг 5/5.
Рисуем шапку
Шапку не забудь!!
Это было
было легко.
ле
Просто очередной эллипс красного цвета.
И сверху помпончик к шапке добавлю.
22
#проект Ракета
Шаг 1/4. Рисуем корпус ракеты
#тема rect()
#
Привет, я Ракета!
Теперь меня сделай!
Как я могу бороздить просторы Вселенной.
Начну с тво
твоего корпуса. Но как мне
нарисовать прямоугольник?
Команда rect(100, 100, 50, 50) (прямоугольник) пригодится.
Первые два числа — координаты левого верхнего угла.
А третье и четвёртое числа — его ширина и высота.
Готово! Команда рисования прямоугольника
очень похожа на команду рисования эллипса.
Вот только при рисовании эллипса мы указываем, где его центр,
а у прямоугольника — левый верхний угол.
#ДЗ На какой цвет попробуешь изменить
цвет корпуса?
23
Шаг 2/4.
Рисуем нос ракеты
Легко. Это ведь просто эллипс
вытянутый. Заодно уберу обводку
командой no_stroke() (нет_обводки).
Прямоугольник — это хорошо,
рошо,
только у меня ещё и обтекатель вверху.
Сделаешь?
И нарисую ещё полоску-прямоугольник, чтобы отделить
нос ракеты от тела.
#ДЗ Сможешь сделать полоску
чуть шире или у́же?
24
Шаг 3/4. Делаем стабилизаторы
#тема point(), #тема stroke_weight()
Это всего лишь два треугольника.
Треугольник состоит из трёх
точек. А как нарисовать точку?
Теперь мне нужны стабилизаторы.
заторы.
Командой point(90, 160) (точка).
В скобках указываем координаты. Кстати, эти уточнения, которые
мы передаем команде, называются параметрами команды.
Размер точки можно отрегулировать командой
stroke_weight(50) (вес_обводки).
Ага, точку нарисовал:
Параметром передаем размер точки.
А теперь предварительно три точки
для стабилизатора слева нарисую:
25
#тема line(), #тема triangle()
А как теперь
соединить
с
точки?
Команда line(90, 160, 70, 220) (линия) соединит две точки: (90, 160) и ((70, 220))
Первые два числа — координаты первой точки. А третье и четвёртое — второй.
Точки линиями соединил, но как мне залить серединку каким-нибудь цветом?
Команда triangle(90, 160, 70, 220, 50, 220) (треугольник) соединит три
точки: (90, 160), (70, 220) и (50, 220) — и зальёт треугольник цветом,
который в fill() указан.
Первые два числа — координаты первой точки, третье и четвёртое —
второй, пятое и шестое — третьей точки.
Заменил три команды
рисования линий одной —
рисование треугольника.
26
#ДЗ Сможешь сделать треугольник красным
и убрать лишние жирные точки?
#тема stroke()
#
Убрал лишние точки и залил треугольник красным
цветом. Ещё и второй стабилизатор сделал:
Добавил к ракете. И попробовал сделать третий стабилизатор.
Нарисовал
линию, но почемуу её не видно?
р
рае
рает
ет
Ты использовал вверху команду no_stroke() (нет_обводки). А она убирает
обводку у эллипсов и прямоугольников. А так как линии и точки не имеют
никакой заливки, то эта команда отключает их рисование.
Используй команду stroke(255) (заливка) или stroke(255, 10, 10),
чтобы установить цвет линии.
#ДЗ Сможешь сделать видимым третий стабилизатор?
27
Шаг 4/4.
Добавляем
иллюминатор Теперь мне нужен иллюминатор.р.
Готово! Сделал его в виде круга.
Го
Как его нарисуешь?
И до
добавил
д бавил ему обводку.
#ДЗ Сможешь добавить ракете огонь снизу??
28
Домашнее задание
#ДЗ Попробуешь запрограммировать
какой-нибудь свой рисунок?
Привидение?
Пришелец?
Снеговик?
Дом?
Инопланетянин?
Машина?
Как сохранить код и поделиться им?
Нажми кнопку
, чтобы сохранить программу.
В строке URL появится
ссылка на текущую
версию кода.
Скопируй её, чтобы
поделиться.
Перешли ссылку друзьям. Или поделись ей в сообществе p5py по ссылкам
на p5py.khasang.ru
А если хочешь переслать ссылку только
с результатом работы программы, но
без кода, то нажми кнопку
тогда,
когда твоя программа запущена.
Будет скопирована ссылка
только на результат работы.
29
Глава 3
Переменные
На примере перемещения рисунков
изучим необходимость введения понятия «переменные».
Научимся применять переменные:
записывать в них значения и считывать.
Изучим несколько переменных,
встроенных в графическую библиотеку p5py.
Это поможет нам двигать Снеговика, Ракету, Марика
и другие рисунки по всему экрану, изменяя координаты
лишь в одном месте программы.
#проект Снеговик
Шаг 1/3.
Нарисуем Снеговика
из трёх кружочков
Наступила зима, пришло время меня,
я,
Снеговика, лепить! Привет!
Готово!
#ДЗ Сможешь добавить мне, Снеговику,
глаза в виде точек и нос морковкой?
31
Шаг 2/3.
Передвинем
Снеговика вправо
Кажется, что на меня здесь солнце сильно светит.
ветит.
Переставь меня вправо, пожалуйста!
Передвинул!
Правда
Правда, в трёх местах пришлось число
менять вручную. Поменял 100 на 200.
Хорошо, что ты снеговик всего из трёх
кругов, а не ракета из пятидесяти
.
Пожа-а-алуйста! Ещё чуть правее
е :):).
.
Солнце нещадно палит
Поменял число 200 на 300 в трёх местах.
Как-то это уже утомительно становится
.
32
#тема Переменные
Утомительно? Это ты просто с переменными ещё
ё
не знаком! Как познакомишься — легко будет.
Целые грузовики одним махом перемещать сможешь.
Напиши вместо числа 300 букву x , а перед этим выражение: x = 300.
Сделал! А какой в этом толк?
Сде
Смотри, какая магия! Теперь, чтобы переставить меня,
нужно поменять всего одно число! Попробуй.
Поменял x = 300 на x = 50.
А ты и сдвинулся. Класс! Удобненько!
#ДЗ Попробуй сам сдвинуть Снеговика
на 80 пикселей или на 250.
33
#тема Инициализация
переменной
Что
Ч ты такое?
x = 100
Переменных много, их "зовут" не только х,
но и у, и z. Меня зовут x.
Я временное хранилище для числа 100 :).
Какое ещё такое временное
хранилище?
Переменчивая я, Переменная! Могу
хранить что угодно: любое число.
И зачем ты его хранишь?
А удобно, знаешь ли. Вот нужно
кому-то узнать, где рисовать круг
у Снеговика. А я и подскажу!
Как подскажешь? Ты говорить
умеешь?
Это я понял, вместо
Не, просто пиши моё имя вместо
числа, и всё.
ellipse(100, 300, 100, 100)
напишу
ellipse(x, 300, 100, 100)
Угу, напишу:
x = 100
ellipse(x, 300, 100, 100)
34
Ага! И не забудь про-ини-циа-лизи-ро-вать
меня! То есть присвоить мне какоенибудь значение до того, как спросить
меня о нём.
#тема Ошибка инициализации
А вот если забыл меня, переменную,
ную
проинициализировать, то будет ошибка у тебя
при запуске программы.
Ну-ка, прове
проверю. Исправлю
предыдущий код на такой:
# x = 50
Означает, что я закомментировал эту строку,
Python будет её просто игнорировать.
Ну мог бы и просто удалить.
Вот и ошибка:
NameError: name ‘x’ is not defined
Ошибка имени: имя ‘x’ не определено
Верните как было! :)
И обязательно присваивайте значение
переменной перед использованием.
35
Шаг 3/3.
Передвинем Снеговика вверх
#
#тема
Сложение переменной и числаа
На меня опять светит солнце. Передвинь меня повыше!
Как же с помощью одной x я могу
передвинуть тебя и вправо и повыше?
п
Привет! Я тоже переменная, зовут y!
Помогу тебе хранить отступ сверху!
Но постой, отступ сверху же у каждого круга свой.
Попробовал. У всех кружков отступ сверху 100. Не то.
Да, но ты можешь дать команду прибавлять
авлять y
к какому-нибудь числу.
ellipse(x, 300, 100, 100)
ellipse(x, y + 200, 100, 100)
#ДЗ Попробуй каждому кругу указать свою
координату по вертикали: y + 200, y + 150, y + 100.
36
#тема
#
Имена переменных
А переменны
переменным можно давать имена только
такие — однобуквенные, короткие?
Нет, конечно! Можно давать и длинные
е имена
имена,
главное — помнить правила.
1. Начинай имя переменной с буквы, не с числа. Если
нужно добавить число, добавляй его в конце имени:
вместо 4egg пиши egg4 (четвёртое яйцо).
2. Если имя хочется сделать из нескольких слов, пиши их
слитно или, ещё лучше, разделяй подчеркиванием «_»:
вместо my name пиши my_name или myname (мое имя).
3. Имена переменных старайся писать в нижнем регистре
(маленькими буквами):
вместо my NAME пиши my_name.
4. Некоторые имена переменных нельзя использовать. Про них
говорят, что они зарезервированы: например, def или for.
Полный их список можно узнать, если запустить такую программу:
37
Задание
Переменные, как ящики, можем в них что-то помещать, а можем и доставать из них.
Но правильнее говорить, что это записки/блокноты, в которые что-то пишем и из них читаем,
так как при чтении информация не стирается.
#ДЗ Сделай так, чтобы Снеговика можно было перемещать
не только по горизонтали, но и по вертикали с помощью
переменной.
#ДЗ Сможешь добавить переменную для изменения
размеров Снеговика?
#ДЗ (сложное) Сделай так, чтобы в переменной y
задавалось положение самой нижней точки снеговика.
Например, при высоте окна 300, если в y поместить 300, то
Снеговик будет как бы стоять на нижней границе окна.
38
#проект Встроенные переменные
Шаг 1/3.
Поместим Снеговика в центр
#тема
Деление
#
Люблю быть в центре! Напиши, пожалуйста, такой код,
д,
чтобы я всегда стоял в центре окна.
Легко, вот так:
Я использовал
испол
знак деления «/», чтобы разделить ширину и высоту
на 2 автоматически. Ну, чтобы в уме самому не считать.
А если сделать окно с результатом пошире?
Но вот если поменять размер окна, то неудобно. Приходится числа
в двух местах менять. Вот смотри:
39
#тема width и height
А ты попробуй использовать встроенные переменные::
width (ширина) хранит то число, которое указали первым
при вызове команды size(), то есть ширину окна;
height (высота) хранит то число, которое указали вторым
при вызове команды size(), то есть высоту окна.
Ух ты, удобно. Я даже сделал окно 220 на 260,
а оно всё само верно посчиталось:
А почему ты назвал width и height встроенными переменными?
Куда они встроены? И кто в них значения помещает?
Встроенные значит, что им ничего присваивать не надо,
система в них сама записала
нужные значения. А мы их только читать будем.
40
Шаг 2/3.
Растянем окно на весь экран
#тема window_width и window_height
#те
#т
Я ведь свою программу могу запускать на разных девайсах?
И на телефоне, и на компьютере?
Но если я укажу в команде size() маленький размер окна, как
у телефона, то на компе на весь экран программа не откроется.
А если укажу большой размер, как для компа, то для телефона это будет
слишком много.
Вот, например, здесь указал размер 200 на 300:
В команде size() используй встроенные переменные:
window_width (ширина_окна) хранит реальную ширину окна
(экрана) устройства, а window_height (высота_окна) — высоту.
Спасибо!
Результат работы моего
его
проекта теперь растянут
нут
на весь экран ноутбука
ка
и смартфона.
41
Шаг 3/3.
Расположим Снеговика
посередине экрана автоматически
Сможешь сделать так, чтобы я располагался всегда
посередине экрана по горизонтали?
Конечно, буду использовать знак деления «/»,
Коне
чтобы разделить width на 2.
#ДЗ Сможешь сделать так, чтобы окно вывода было
ло всегда
на весь экран, а Снеговик располагался всегда посередине экрана?
Но не только по горизонтали, а ещё и по вертикали!
42
Часть II
Простые игры
и интерактивные программы
Учимся выполнять код многократно, осваиваем основной графический цикл,
изучаем области видимости переменных
Глава 4
Главный
игровой цикл
На игровых примерах изучим основной синтаксис языка Python
и возможности графической библиотеки p5py: графический цикл, работу
с мышью и тачем на смартфонах, конкатенацию строк и чисел, работу
с переменными, остановку кода, получение случайных чисел,
ветвление кода, сравнение, целочисленное деление,
определение дистанции между объектами
для обработки столкновений.
И тогда мы сможем написать простой графический редактор,
мини-игры «Охота на зайца», «Заяц и морковка», «Собака и кость».
Сможем сделать так, чтобы Заяц бежал за морковкой и ловил её.
Сделаем расположение еды случайным на экране.
Научимся управлять собакой на экране прикосновением.
#проект Графический мини-редактор
Шаг 1/2.
Рисуем точку
#тема
mouse_x, mouse_y
#
Привет! Ты быстро учишься!
Но сможешь ли написать графический редактор?
Да, наверно. Но как бы мне узнать, где пальцем коснулись экрана телефона
или где мышка на экране? Я бы написал такой код:
Но мне непонятно, что написать вместо координата_по_горизонтали?
Попробуй использовать встроенные переменные:
mouse_x (мышка_x) хранит положение по горизонтали
мышки или координату прикосновения пальца к экрану,
mouse_y (мышка_y) — то же самое, но по вертикали.
Получилось! Но кружок
ужок рисуется в углу и не реагирует
на прикосновение к экрану. Почему?
44
#тема
Повторение кода
Я расскажу тебе, что происходит во время выполнения
программы и как исправить ошибки.
Чтобы выполнить твой код, я читаю все строчки
сверху вниз и последовательно их выполняю.
А когда дохожу до последней, то прекращаю работать.
Значит,
Значит, н
нужно как-то повторить всю программу сначала!
А то получается, что ты один раз узнал координаты мышки.
Один раз точку нарисовал, и всё.
Верно!
Но не нужно всю программу повторять. Достаточно повторить
выполнение только одной строчки. Какой же?
Нужно как-то повторить point(mouse_x, mouse_y).
Верно!
Чтобы выполнить много раз только часть кода,
придётся обозначить его начало и конец.
Как-нибудь вот так?
45
Шаг 2/2.
Рисуем точку только там, где мышка
#тема def draw():
Отлично!
А теперь вместо повтори следующие команды много-много раз:
напиши def draw():
Готово:
Ух ты, запустилось! Теперь я вожу пальцами по экрану
телефона и остаётся след! А если запущу программу
на компьютере, то вижу след от мышки!
#ДЗ А что ты нарисуешь в своём графическом редакторе?
Сможешь ли поменять чёрный цвет на другой?
46
#тема Библиотека p5py
Но я вообще не понял, почему def draw():
означает:
повтори следующие команды много-много раз:
Детально мы с этим разберёмся позже
позже,
когда изучим функции.
Сейчас же важно знать, что один «голый» Python мало кто
из программистов использует.
Почти всегда мы используем вспомогательный код,
который ранее написали другие программисты.
Такой код называют библиотеками или модулями.
Это ты вот про эти строчки, которые мы
пишем почти в каждой программе сверху?
from p5py import *
run()
Да, p5py — это и есть название нашей библиотеки,
которая содержит всякие прикольные команды.
С их помощью мы и можем так просто рисовать.
Получается, эти команды тоже из p5py?
size(400, 300)
background(255)
stroke_weight(50)
Верно, как и команда draw (рисовать). Это имя
придумали создатели библиотеки. Могли назвать
show() или superpuper(), но назвали draw().
47
#тема def
Про
П
ро dr
draw понял, просто такое имя придумали.
А def что значит?
def — это сокращение от слова define (определить). Так
программисты говорят, когда нужно выделить в коде
специальный блок кода — функцию. Так и говорят —
определить функцию.
Код, который многократно повторяется, мы ещё называем
главным игровым циклом.
Я что-то краем уха слышал про циклы, зацикливание. Мне даже
мама иногда говорит: «Ты, кажется, зациклился на своей игре» :)
def draw(): — это про циклы?
Похоже, но не совсем. С циклами мы позже разберёмся.
draw() — это функция.
А def draw(): — это определение функции draw().
Сейчас пока важно просто запомнить:
я буду бесконечно повторять строчки кода с отступами,
перед которыми стоит def draw():.
#ДЗ Попробуй вместо рисования точками
и
реализовать рисование квадратами.
48
#проект Эксперименты с редактором
Ш 1/2.
Шаг
Исправим ошибку
#тема
Блок кода и 4 пробела
#
Ты говорил, что будешь бесконечно повторять
строчки кода с отступами, перед которыми стоит def draw():.
Ну да.
Я решил рисовать красным цветом, добавил команду stroke()
с отступом. Но почему-то появляется ошибка, смотри:
Важно, чтобы отступы были одинаковыми. У нас принято
вставлять ровно 4 пробела. А на компьютере можно нажать
клавишу табуляции, тогда сразу 4 пробела добавятся.
Ага, а у меня перед строчкой stroke() было два пробела.
Сделал везде 4:
49
#тема Порядок команд
Я тут случайно блок draw() разместил посреди остального кода,
а программа всё равно заработала. Смотри:
Да, def-блоки (функции) можно разместить
ть
в коде почти где угодно:
Но мы будем располагать их в самом низу. Так легче читать
код. Сразу видим, что будет выполнено сначала и один раз,
а что будет повторяться много-много раз.
#ДЗ Попробуй разместить функцию draw() в самом низу кода.
50
Шаг 2/2.
Убираем очистку фона
Я тут весь код, который относится к рисованию квадратом,
переместил внутрь блока draw() вот так:
Но теперь квадрат не оставляет след! Я двигаю-двигаю
вигаю пальцем,
а квадрат за ним следует, как будто прилип. Почему?
У тебя команда заливки фона белым цветом background(255))
идёт первой командой внутри draw(). И что получается?
Что каждый раз перед тем, как рисовать квадрат, ты заливаешь весь фон
белым цветом, тем самым стирая предыдущую картинку. Понятно. Вот так
починил. Теперь я могу рисовать не точкой, а квадратом:
#ДЗ Попробуй вместо рисования квадратами
реализовать рисование треугольниками.
#ДЗ Попробуй сделать редактор паутинок, рисуяя
линии из центра окна к координатам мышки.
51
#проект
Охота на зайца
Шаг 1/4.
Узнаем, сколько раз выполняется код
#тема
frame_count
#
Я тебе, конечно, верю. Но всё же, как
проверить, что код выполняется только один раз?
Возьмём, например, такой
кой код:
Выполняется он скучно, просто выводит число
ло 1.
1 :(
Так всё идеа-а-ально! Встроенная переменная frame_count
как раз и хранит количество выполнения кода.
То есть, если я помещу её внутрь def draw():, то...
То увидишь, как числа на экране быстро сменяют друг друга.
52
Шаг 2/4.
Научим зайца бегать
Давай поохотимся на зайцев.
зайцев
Мммм, люблю зайчатину...
Это я уже знаю! Будет написано, что заяц пробежал
всего 1 круг. Так ты легко догонишь зайца.
Хорошо, Заяц решил накачать мышцы, заняться бегом и убежать
от меня. Давай узнаем, сколько кругов он пробежал?
Знаю-знаю, просто внутрь def draw(): поместим зайца.
И теперь он во-о-он сколько кругов может пробежать.
Марафонец какой-то получился.
я.
#ДЗ Сможешь сделать так, чтобы не только
двигался?
числа менялись, но и сам значок
53
Шаг 3/4.
Остановим код и поймаем зайца
#тема no_loop()
Давай продолжим охотиться на зайцев.
айцев
Хочешь, я поймаю зайца одной командой?
Даже если он вечно бежит в def draw():?
Да, смотри. Есть команда no_loop().
Она останавливает выполнение программы.
Хм, поймал. И правда, программа остановилась.
Но когда заяц успел 2 круга пробежать?
Код же сразу был остановлен!
54
Шаг 4/4.
Найдём первый круг зайца
#тема Порядок выполнения кода
Когда заяц успел пробежать первый
й круг?
Давай дополнительно выведем количество запусков кода.
Но разместим команду перед draw().
А ещё выведем чуть левее, с отступом в 30 пикселей,
чтобы было видно. Вот так:
text(frame_count, 30, 80)
А-а-а. Теперь вижу: вот она — единичка. Получается, сначала
ты сделал подготовительную работу, выполнил команды:
from p5py import *
run()
size(300, 300)
background(255)
text(frame_count, 30, 80)
это и было первое выполнение.
Верно. А потом я взялся за функцию draw())
и захотел выполнять её бесконечно.
Но тут встретил команду no_loop() и прекратил
выполнять блок draw().
55
#проект
Работа над ошибками
Шаг 1/4.
Найдём, в чём ошибка с отступами
#ошибка Отступы без оглавления
Как можно исправить ошибку в следующем коде?
де?
module __main__ line 7
text("Программа запущена", 50, 60)
^
IndentationError: unexpected indent
модуль __main__ строка 7
text("Программа запущена", 50, 60)
^
Ошибка отступа: неожиданный отступ
Ошибка отступа: неожиданный отступ
У команды size() нет отступа, а вот у команды background() отступ
неожиданно появился. Ты не ожидал его и не знаешь, что с ним делать.
Так что яснее ясного. Отступы есть, а заголовка в виде def draw(): нет.
Нужно или добавить def draw():, или убрать отступы.
56
Шаг 2/4.
Исправим ошибку с отступами
#тема
Два варианта решения
#
Первое решение. В нём я добавил def draw():.
Второе решение. А в этой попытке исправить ошибку убрал лишние отступы:
Обрати внимание, что программа в этих двух вариантах
работает по-разному!
Да, в первом решении она работает бесконечно. А во втором — только
один раз. То есть исправить-то ошибку можно двумя способами, но какой
из них лучше — может сказать только тот, кто написал исходный вариант
программы. Я же не знаю, что он хотел сделать.
57
Шаг 3/4.
Исправим ошибку с отступами
#ошибка def без последующих отступов
Как думаешь, где ошибка в следующем
м коде?
module __main__ line 8
text("Программа запущена", 50, 60)
^
IndentationError: expected an indented block
модуль __main__ строка 8
text("Программа запущена", 50, 60)
^
Ошибка отступа: ожидается блок с отступом
Ошибка отступа: ожидается блок с отступом
Ну раз есть def draw():, то понятно, что «ожидается
блок с отступом» ниже.
Значит, нужно сделать отступы после def draw():.
Поправлю вот так:
58
Шаг 4/4.
Исправим ошибку с двоеточием
#тема Синтаксическая ошибка
А здесь найдёшь ошибку??
File __main__, line 6
def draw()
^
SyntaxError: invalid syntax
Файл __main__, строка 6
определить рисование()
^
Синтаксическая ошибка: неверный синтаксис
Синтаксическая ошибка: неверный синтаксис
Синтаксическая ошибка — это значит, что где-то пропущено что-то основное:
ное:
двоеточие, круглая скобка, запятая или ещё что-то в этом духе...
Двоеточие... Точно, пропущено двоеточие после def draw()!
Поправлю вот так:
59
#проект
Шаг 1/4.
Заяц и морковка
Сделаем зайца, бегущего за морковкой
#ошибка
#
Отступы без оглавления
Давай напишем программу, где не я буду охотиться
ться
на зайца, а он будет ловить морковку.
Начну я с такого кода — нарисую бегущего зайца:
А это код с рисованием морковки:
#ДЗ И теперь осталось объединить
эти два кода в один. Сможешь?
60
Шаг 2/4.
Узнаем, когда заяц добежал
Конечно! Вот объединённый код.
Теперь у меня есть и бегущий заяц, и морковка.
Но я не знаю, как выяснить, что заяц добежал до морковки!
Это просто. Запусти такой код:
Ух ты! Теперь, когда заяц добежал до морковки, код останавливается.
61
#тема if, #тема == )
А что означает if? И почему сразу два знака =?
if x == 200:
no_loop()
если переменная «х» равна 200, то
останови_код()
Получается так:
если x равно 200, то выполни такие команды:
no_loop()
А если x будет не равно 200, то что?
Просто не буду выполнять блок внутри if, и всё.
Сразу перейду к следующей команде после блока if.
Кстати, мы равно в школе вот так пишем: =.
Да, в математике так. Но в Python один символ «=»
означает присвоение, помнишь?
Поэтому для сравнения чисел на равенство используют
двойной знак равенства: «==».
Этот блок if чем-то похож на описание блока def draw():.
Тоже есть двоеточие и отступы.
Да, ведь это тоже блок кода. Если условие верно,
то выполнить блок кода. А блок кода мы выделяем
четырьмя пробелами.
62
Шаг 3/4.
/
Улучшим код, введём переменную
#тема
#
Магические числа
И ещё у нас число 200 — координата морковки
ковки
по горизонтали — дважды встречается. Это плохо.
И чем плохо?
Плохо тем, что легко ошибиться, и если захотим сдвинуть морковку,
то можем по невнимательности поменять 100, скажем, на 200 только в одном
месте. И программа будет работать неправильно.
Числа, которые встречаются без описания, называются на сленге
магическими числами, так как при чтении кода часто «без магии» не понятно,
что они обозначают и откуда взялись.
Вот в коде ниже заяц не добегает до морковки:
Тогда введу переменную и назову её «морковка_х» или кратко просто mx.
Помещу в неё число 200. А дальше везде вместо числа 200 буду использовать mx.
63
Шаг 4/4.
Сделаем так, чтобы заяц
«съел»
морковку
«с
А сможешь сделать так, чтобы морковка
рковка
пропадала, когда заяц её съест?
Конечно, мне нужно в блок, который выполняется при
совпадении координат зайца и морковки, добавить очистку
экрана и рисование зайца. Так я избавлюсь от морковки.
Ты лучше покажи :)
#ДЗ Сейчас, когда Заяц съедает морковку,
фон становится серым. Сможешь сделать так, чтобы
он оставался зелёным?
64
Задание
#ДЗ Сделай так, чтобы Заяц бежал справа налево.
#ДЗ Сможешь заменить зайца и морковку на питона
и зайца?
#ДЗ Сможешь сделать так, чтобы заяц бежал
за морковкой сверху вниз?
#ДЗ А чтобы заяц бежал за морковкой по диагонали?
Из левого верхнего угла в правый нижний?
65
#проект
Непредсказуемая морковь
Шаг 1/2.
Отобразим морковку в случайном месте
#тема Команда randint() из модуля random
А сможешь сделать так, чтобы моя морковка
появлялась в случайном месте?
Ну... дай подумать... Мне нужно было бы написать вместо mx = 200
что-то вроде mx = получить_случайное_число()
Верно мыслишь! Для этого в Python есть модуль random. Он, как
наш модуль p5py, но у него есть свои полезные команды. Его нужно
добавить в самом верху программы. Импортировать вот так:
import random
А там, где хочешь получить случайное число, написать
mx = random.randint(50, 300)
Тогда в переменную mx сохранится случайное число от 50 до 300.
Написал, но у меня получилась бешеная морковка! Не так,
как я хотел! Она всё время туда-сюда дёргается.
66
Шаг 2/2.
Вылечим бешеную морковку
#тема
#
инициализация
А бешеная она у тебя потому, что ты присвоение
не там разместил.
Ну что значит не там?! Всё же работает!
Смотри, def draw(): у тебя выполняется много раз в секунду.
И что получается? В какой момент в mx помещается случайное число?
А-а-а-а. То есть при каждом твоём движении у меня в mx помещается
новое случайное число. Вот морковь и выглядит дёрганной.
А чтобы исправить, я вынесу присвоение mx случайного числа за
пределы повторяющейся def draw():.
Пусть один раз в самом начале туда сохранится случайное число,
и всё. И не надо его каждый раз менять.
Я знаю, что ты хотел бы попробовать сделать так, чтобы после съедания
зайцем морковки она в новом месте появлялась. Для этого нам потребуется
изучить тему #global. Через пару проектов как раз изучим!
67
#тема Команда rand() из модуля p5py,
#тема Число с плавающей точкой
#
Кстати, импорт модуля random и команда
нда
mx = random.randint(50, 300)
будут работать и без модуля p5py.
Ну-ка, проверю на новом проекте.
Ух ты! При каждом запуске кода получаю новое значение от 50 до 300!
Ага, и вдобавок в модуле p5py есть своя команда для случайного значения.
Её даже чуть короче писать:
rand(50, 300)
Вот только возвращает она не целое значение, а, как мы говорим,
число с плавающей точкой.
Вижу-вижу. Число, а после точки «плавает»» ещё куча цифр
цифр.
68
#тема Команда int(), #тема Вложенные команды
Но число всегда можно превратить в целое
ши:
командой int() (от integer — целое). Просто напиши:
mx = rand(50, 300)
mx = int(mx)
Проверяю...
Работает, но не выглядит как-то проще или короче :(
А эти команды можно вкладывать друг в друга, как матрешки::
mx = int(rand(50, 300))
В этом случае сначала выполнится самая вложенная команда: rand(50, 300),
она рассчитает или, как мы говорим, вернёт случайное число,
но с плавающей точкой.
И ээто число уже попадает на вход команде int(), которая его превращает
в привычное нам целочисленное.
#ДЗ Попробуй в коде с морковкой заменить randint()
из модуля random на rand() из модуля p5py.
69
#проект
Шаг 1/5.
Склонение слов
Просклоняем: круг, круга, кругов
А помнишь, мы писали, сколько заяц кругов пробежал?
И там некрасиво получается: 1 круг, 2 круг, 5 круг.
Так ведь не говорят.
Зная о блоках if, я теперь могу просклонять слово «круг».
Но что-то много кода получается :(
И слишком быстро заяц бежит! Не успеваю прочитать.
И приходится слово «круг» дважды выводить, иначе для
кругов больше 5 слово «круг» вообще не отображается.
70
Шаг 2/5. Просклоняем круги от 1 до 20
#тема Сравнение >, >= <=, #тема frame_rate()
(())
Простая команда frame_rate(1) обяжет рендеритьь
(выполнять отрисовку) только 1 кадр в секунду!
А если мы хотим выводить слово «круга» только для чисел
от 2 до 4, то напишем как в математике: 2 <= x <= 4.
Что значит: x больше либо равен 2 и меньше либо равен 4.
Тогда получилось так:
Я ещё добавил: если x больше либо равен 5, то записывать
«кругов». И ещё добавил остановку на 20, так как пока
не придумал, как склонять круги больше 20.
Обрати внимание, что писать важно >= (больше либо равно).
А если написать => (равно либо больше), будет ошибка.
Кстати, вместо x >= 5 (x больше либо равен 5)
можно написать x > 4 (x больше 4),
если с целыми числами работаем.
71
Шаг 3/5.
Убираем повторяющийся код
#тема Принцип DRY
И ещё у тебя код много раз повторяется. Если захочешь
очешь
перенести весь вывод, скажем, немного правее или левее, то
придётся менять координаты в пяти местах! Легко ошибиться.
В программировании есть принцип DRY (don’t repeat
yourself — не повторяйся).
Он очень простой: старайся избегать повторяющегося кода
там, где в разных местах программы одно и то же написано.
Я помню, мы так со снеговиком делали. Переменную вводили. Здесь
тоже введу две переменные: они укажут, куда выводить текст.
Хочешь подсказку? Можно и одной
переменной обойтись, если в неё сохранить
слова «круг», «круга», «кругов».
1. Объявил переменную s.
2. Когда 5 <= x <= 20, сохраняю в s слово «кругов».
3. Закомментировал временно остановку кода.
Но появилась ошибка:
72
Шаг 4/5. Исправим ошибку )
#тема Ошибка UnboundLocalError
UnboundLocalError: "local variable 's' referenced
d
before assignment"
Несвязанная локальная ошибка: "ссылка на локальную
переменную s перед присвоением"
То есть: попытались прочитать из переменной до того,
как в неё что-то записали.
Когда x станет больше 20, то ни одно из условий
не выполнится! Что тогда будет храниться в переменной s?
Эээ... ничего?
Вот именно! А что делать с этим «ничего» — не понятно.
Помнишь, как в анекдоте...
Магазин, в котором можно купить всё. Пришёл тролль:
— А можно купить два кило «ничего»?
— Можно!
Тролля заводят в подвал, выключают свет.
— Что видишь?
— Ничего.
— Бери два кило и уматывай.
Вернул остановку кода :)
73
Шаг 5/5. Работа с консолью
#тема
#
Союз and, #тема Союз or
Кстати, если мы работаем только с текстом,
ом то
проще всего работать с консолью, то есть вместо
text() использовать print().
Убрал команды text() и внизу добавил print().
Смотри, выражение 2 <= x <= 4 состоит из двух: 2 <= x И x <<= 4.
Поэтому его можно заменить на 2 <= x and x <= 4,
где используется союз and (и).
Ещё кроме союза and можно использовать союз or (или).
Где он может быть полезным?
Ну, например, если x равен 1 ИЛИ x равен 21, то s = «круг».
Вот, расширил склонение до 31:
#ДЗ Попробуй в коде заменить двойное сравнение
2 <= x <= 4 сравнением с союзом and.
74
#проект
Бесконечный бег
Шаг 1/4.
Поменяем draw() на цикл for
#тема
Цикл for
#
Если тебе не нужно работать с графикой, можно
о
не использовать модуль p5py и функцию draw().
А как же тогда код с бегущим зайцем будет выполнен несколько раз?
Давай начнём с простого. Скажем, выведем пять раз слово hello в консоль.
Но это можно автоматизировать циклом. Запусти следующий код:
Запустил! Действительно, пять раз выводит слово hello.
А что означает запись for i in range(5)?
для переменной i в диапазоне(5):
# выполни следующий код
То есть весь код, который указан с отступом в блоке for будет выполнен
столько раз, сколько указано числом в круглых скобках у range().
#ДЗ Поменяй в только что рассмотренном примере
число 5 на другое, например на 1 или 10.
75
#тема Переменная в цикле
Цикл for (для) чем-то похож на блок if (если)).
Только блок if выполняется один раз.
А блок for может выполниться много раз.
Удобно! Но для чего переменная i? Как ею пользоваться?
Смотри, переменная i внутри цикла будет менять значения от 0 и до
числа, которое указано в range(), но за исключением этого числа.
Например, для range(5) переменная i сначала будет 0, затем 1, 2, 3, 4.
Вот так:
С нуля? Очень странно.
Да, исторически так сложилось.
Почему именно с нуля, а не с единицы, будет понятней,
когда массивы изучим.
76
#тема
#
Ошибка NameError
И как же мне заменить draw() на for? Вот, беру такой код:
Убирай из него всё, что относится к модулю p5py
5 :
import, run(), def draw():, frame_count, no_loop().
А блок draw замени на блок for.
А c frame_count что делать?
Так у тебя теперь будет переменная i, она и будет пробегать
от 0 до 30. Можешь её назвать x, чтобы привычнее было.
Всё убрал. Код красивый и короткий. Только одна
ма-а-аленькая проблемка: он не работает.
77
Шаг 2/4.
Исправим ошибку
#тема Ошибка NameError
NameError: name 's' is not defined
Ошибка имени: имя ‘s’ не определено
В цикле for x in range(30): переменная x
пробегает какие значения?
Ты говорил, что от 0 до... до... 29 (до 30, но не включая 30). И
с нуля, я запомнил, потому что это странно.
А для нуля у тебя print() что выведет?
Ха-ха, «ничего» — вспомнил анекдот.
Значит, нужно условие для нуля добавить. А ещё в цикле
указать вместо 30 число 31.
Вот только очень длинная строчка с этими or.
Ору просто с неё.
Глупая шутка, or -> ору... Прости
78
Шаг 3/4.
Сделаем строчки короче
#тема PEP 8 и правила оформленияя
У меня есть правила оформления. Называются PEP 8 —
Python Enhancement Proposal
(предложение по улучшению Python номер восемь).
По ним длинную строчку в if можно разбить на две или
больше, но придётся использовать круглые скобки вот так:
Или так:
Мне понравилось разбивать
М
б
строки. Р
Разбил
б даже на три:
#ДЗ Попробуй все строчки с if разбить на две.
79
Шаг 4/4.
Сделаем цикл до 100
#тема Целочисленное деление
#
Я заметил закономерность!
Для чисел, оканчивающихся на 1, нужно писать «круг».
На 2, 3, 4 — «круга».
На 0, 5, 6, 7, 8, 9 — «кругов».
За исключением 11, 12, 13, 14 — для них всегда «кругов».
А как узнать, на какую цифру заканчивается число?
Пригодится целочисленное деление: //.
Обозначается двойным знаком деления.
Например, 4 / 3 == 1.3333333333333333,
а 4 // 3 == 1.
Чтобы узнать, на какую цифру оканчивается число x, нужно x
нацело разделить на 10. Получим число десятков. Затем из x
вычесть число десятков, умноженное на 10. Получим искомую
цифру. Проще написать: x - (x // 10) * 10.
Получился такой код:
#ДЗ Используя модуль p5py и функцию draw(),
сделай так, чтобы заяц пробегал круги бесконечно.
80
#проект
Шаг
Ш 1/4.
Собака и кость
Сами по себе
Хочу написать игру, где буду управлять собакой с помощью
прикосновения пальца к экрану или мыши на компьютере так,
чтобы поймать кость.
Очень похоже на прошлую игру с зайцем, но только вместо координат
200, 200 написал, как в графическом редакторе — mouse_x и mouse_y.
Тогда при рисовании собаки она всегда будет отображаться там,
где я прикасаюсь к экрану (или где щёлкаю мышкой).
А как будешь проверять, что собака поймала кость?
ть?
81
Шаг 2/4.
Трудная охота
Да вот просто сравню координаты кости и собаки, смотри:
Но только очень трудно поймать кость — плохо работает.
Почему?
Это не программа плохо работает, а сравнение
ение
у тебя очень требовательное. Сейчас программа
останавливается, только если координаты кости и
собаки совпали в точности. А этого сложно достичь!
Ага, чуть-чуть промазал, и уже не ловит. Что же делать?
82
Шаг 3/4.
Кусь на расстоянии
#тема
dist()
#
Нужно определить дистанцию (расстояние) между
ежду
собакой и костью. И если будет меньше, скажем, 20,
значит, собака поймала кость!
Ой, определять дистанцию как-то очень скучно.
Там ведь теорема Пифагора, да?
Вообще, да, но в нашем случае — нет.
В библиотеке p5py есть простая команда dist().
Ей нужно передать координаты обоих объектов,
а она сама посчитает расстояние:
dist(x1, y1, x2, y2)
где x1, y1 — координаты первого объекта;
x2, y2 — координаты второго объекта.
Готово! Я догадался использовать знак «<»
(меньше), чтобы сравнить дистанцию с числом 20.
#ДЗ Сделай так, чтобы собака ловила кость
на расстоянии 50 пикселей!
83
Шаг 4/4.
Ам, и съела
рамма
А сможешь сделать так, чтобы не просто программа
остановилась, а собака последним прыжком
набросилась на кость?
То есть просто оказалась в месте с теми же координатами,
что и у кости? Ну, это просто: если дистанция между ними
будет меньше 20, то сначала очищу экран, а затем нарисую
об
собаку,
но не там, где мышка, а в точке с координатами кости.
Готово!
#ДЗ Сделай так, чтобы собака
ка
говорила «Ам», когда поймает кость,
то есть на экране должен появиться
такой текст.
84
Глава 5
Тамагочи и НЛО
Изучим важнейшие темы: область видимости переменной, глобальные,
локальные переменные, переменные-тёзки.
Будем менять из главного игрового цикла переменные, которые хранят
энергию, здоровье, положение врагов в игре.
И тогда при написании игры, например про нападение пришельцев,
сумеем сделать так, чтобы эти пришельцы двигались.
Сможем хранить значения с количеством сбитых пришельцев,
оставшихся у нас жизней и энергии для выстрелов.
А ещё в игре вроде FlappyBird без применения этих тем
не смогли бы сделать так, чтобы птичка взлетала
при прикосновении к экрану
и падала сама по себе.
#проект
Шаг 1/3.
Хитрая кость
Поместим случайные
значения в ex, ey
Хочу сделать полноценную игру!
Такую, чтобы после съедания кость снова появилась в случайном месте.
Для этого в тот момент, когда собака поймала кость, присваиваю
случайные значения переменным ex и ey:
Но кость почему-то появляется в том же самом месте!
И не хочет появляться в новом случайном месте.
Давай подумаем, какие команды выполняются перед
командой вывода кости на экран: text(" ", ex, ey)
Хм... А-а, понятно. Перед text(" ", ex, ey)
всегда выполняются
ex = 150
ey = 200
Поэтому кость всегда будет рисоваться в точке (150, 200).
86
Шаг 2/3.
Вынесем инициализацию в начало
#тема
#
UnboundLocalError
О’кей. Я помню, что код вне draw() выполняется только
один раз. А мне и нужно, чтобы в ex, ey числа 150 и 200
сохранились только один раз. Поэтому строчки
ex = 150
ey = 200
помещу сразу после команды size().
Но при запуске возникает такая ошибка:
UnboundLocalError: "local variable 'ex' referenced before assign
assignment"
nnment
nt"
t"
Несвязанная локальная ошибка: "ссылка на локальную переменную 'ex'
перед присвоением"
То есть ты попытался использовать переменную ex до того,
как поместил в неё значение.
Неч
Нечестно!
Я же поместил в неё значение!
В са
самом верху, смотри, ну вот же, чёрным
по белому напечатал:
ex = 150
ey = 200
У тебя какие-то неправильные
переменные, ничего не помнят!
таблетки
Может, они
забыли принять?
87
Шаг 3/3. Исправим ошибку с обновлением
#тема Объявление переменных глобальными
Давай я тебе сначала расскажу главное правило:
Если в функции draw() хочешь менять
какие-либо переменные, то обязательно
объяви их глобальными.
Чтобы переменные объявить глобальными, в начале
ле
def draw(): нужно добавить первыми строчками:
global ex
global ey
Ух ты! Прямо игра получилась!
Как только ловлю собакой кость — очередная кость появляется
в новом месте.
Я же говорил, что всё дело в
88
таблетках.
#проект
Корабли и
грузовики
Шаг 1/4.
Определяем переменные
#тема Глобальные и локальные переменныее
Представь себе море и
острова. По морю грузы перевозят
возят
корабли. А на островах —
грузовики.
Функция draw(), как остров. Если бы были другие функции,
они тоже были бы островами. Весь код вокруг функций — море.
Переменные-корабли мы называем глобальными,
а грузовики — локальными.
Я понял: переменные хранят значения, как корабли и грузовики — товары.
Как же узнать, какая переменная — грузовик, а какая — корабль?
Если переменная создается в море, то это корабль,
а если на острове — грузовик.
А создается тогда, когда мы первый раз присваиваем
переменной значение.
Создал глобальную переменную-корабль c именем admiral,
который перевозит "Рыбу":
Создал локальную переменную-грузовик с именем jora,
который перевозит "Кокосы":
89
Шаг 2/4.
Проверим области видимости
переменных
Давай проверим, видно ли локальную переменнуюннуюгрузовик из моря, то есть снаружи draw().
Нет, не видно. Ошибка отображается:
NameError: name 'jora' is not defined
Ошибка имени: имя ‘жора’ не определено
Все грузовички ездят по своему острову,
и за пальмами их из моря не видать.
А видно ли глобальную переменнуюкорабль с острова, то есть внутри draw()?
Видно!
А вот корабли плавают вокруг, и их
можно с любого острова увидеть.
90
Шаг 3/4.
Ш
«Ломаем» систему и чиним
#тема Переменные-тёзки
Смотри, я сломал систему!
Смог в переменную-грузовик jora поместить груз "Бананы" в море,
то есть вне draw(). Я заставил грузовик плавать!
Нет, ты не заставил грузовик плавать :)
Просто ты создал корабль с таким же именем,
как и у грузовика — jora.
И теперь у тебя появились переменные-тёзки. Только
одна тёзка — грузовик, а другая — корабль.
Две разные переменные с одним именем? Меня жизнь к такому не готовила :)
Хотя, есть же в нашем школьном классе две Милы и две Вероники.
Получается, что с острова, то есть из draw(), никак не поменять значение
в глобальной переменной-корабле?
Ведь если я что-то присвою в admiral внутри draw(), то это просто станет
локальной переменной-грузовиком-тёзкой?
Вот теперь у меня два адмирала: один — глобальный,
а другой — локальный. И это разные переменные!
91
Шаг
Ш 4/4.
Превращаем локальное
в глобальное
#тема
#
Ключевое слово global
А если я захочу из draw() вывести значение глобальной
переменной, а потом её поменять, то будет ошибка:
Да, так как в любом случае при изменении переменной admirall
внутри острова draw() она считается локальной.
я.
А в локальную переменную ты ничего не записал до прочтения.
И чтобы такого не происходило, можно явно запретить мне
создавать переменные-тёзки. Сказать, что переменная admiral —
глобальная, и всё тут. Вот так:
А если переменных несколько, то по правилам PEP 8
нужно писать global отдельно на каждой строке:
global название_переменной1
global название_переменной2
Но для экономии места в книге будем иногда писать
на одной строчке через запятую:
global название_переменной1, название_переменной2
#ДЗ Создай новый проект и сделай так, чтобы по экрану
.
слева направо плыла картинка корабля
92
#домашний проект
Две кости
#ДЗ Одной костью я наигралась.
А сможешь сделать так, чтобы у меня было две кости:
одна побольше, а другая поменьше?
Возьми за образец прошлый код, вот этот:
Что-то сложно, дашь подсказку?
Для первой кости уже есть переменные: ex, ey. Осталось
придумать ещё две переменные для второй кости,
например ex2, ey2.
А дальше почти весь код придётся удвоить.
93
#проект
Шаг 1/3.
Ш
Собака-считака
Определяем переменную bone
Сможешь сделать счётчик костей, которые я съела?
Буду соревноваться с друзьями.
Первым шагом добавим переменную, в которой будем
хранить количество костей. Назовем её, скажем, bone и сразу
поместим в неё число 0.
Переменная
bone
Глобальная?
А дальше выведу переменную bone
на экран, вот так:
94
Будет хранить
количество костей
Глобальная
Шаг 2/3.
Увеличим значение переменной
#тема
#
Инкремент
Осталось увеличивать число,
которое хранит переменная bone.
Но я не знаю, как это сделать.
Нужно написать так:
bone = bone + 1
Это означает: пусть bone сохранит в себе число, которое
равно тому, что хранила в себе bone раньше, плюс один.
Увеличение переменной часто называют «инкремент».
Сделал. Разместил увеличение переменной внутри if.
Ведь как только кость поймали, сразу и переменную нужно увеличить.
Но у меня снова та же ошибка-а-а-а-а!
95
Шаг 3/3.
Исправим ошибку
Смотри, ты меняешь значение переменной:
ой:
й
bone = bone + 1
Но при этом не указал, что она глобальная!
Запомни простое правило на ближайшее время:
для всех переменных указывать, что они глобальные.
А, хорошо, допишу так:
global ex
global ey
global bone
Или можно сокращенно: global ex, ey, bonee
Но только между нами
это не по PEP-овски.
Ура!!! Заработало!!!
Теперь ты можешь съесть кость. После этого кость появится в новом
месте. А ещё показывается, сколько еды уже поглощено.
96
#проект Тамагочи
Шаг 1/4.
Добавим голод
А теперь,
тепер наоборот, хочу сделать так, чтобы у собаки
чувство голода увеличивалось само по себе, а игрок
успевал накормить собаку, пока она совсем не оголодала!
Кто мы?
Переменные!
Первым шагом добавим переменную,
нную
в которой будем хранить голод. Назовем её,
скажем,
с
hungry и сразу поместим туда число 0.
Что мы делаем? Храним значения!
Какие мы?
Глобальные!
Дальше я знаю! Просто выведем
переменную hungry на экран также,
как и выводили в прошлый раз bone:
97
Шаг
Ш 2/4.
Увеличим голод
#тема
#
Инкремент
Осталось увеличивать число, которое хранит переменная
hungry. И теперь я знаю, как это сделать.
Нужно написать так:
hungry = hungry + 1
Это означает: сложить значение hungry с 1 и поместить
обратно в hungry. Так hungry увеличится на единицу.
Кстати, код можно укоротить. Вместо:
hungry = hungry + 1
записать
hungry += 1
Это просто короткая запись, чтобы меньше кода набивать руками.
Ага, спасибо! А ещё global hungry нужно обязательно добавить.
Я помню!
98
Шаг 3/4.
Остановим игру при большом голоде
#тема
#
Правило «если — if»
Теперь нужно оканчивать игру, когда голод стал равен,
скажем, числу 200. Останавливать игру — значит применить
команду no_loop(). Но куда её написать?
Есть такое программистское правило: если ты используешь слово
«если» или «когда», то скорее всего нужно применить конструкцию if.
И это логично, ведь if переводится как «если».
Готово! Написал так:
if hungry == 200:
no_loop()
Но теперь игра всё время останавливается на 199, сколько бы
костей я не поймал!
Смысл-то тогда ловить кость?
99
Шаг
Ш 4/4.
Обнулим голод
Теперь, если собака съела кость,
то чувство голода нужно обнулять!
Есть такое программистское правило...
авило
Да-да, я помню. Я использовал слово «если», значит,
где-то нужно использовать if.
И он у меня уже есть, вот такой:
if dist(mouse_x, mouse_y, ex, ey) < 20 :
Значит, я просто внутрь него добавлю обнуление
переменной hungry. Сброшу голод в ноль.
Ура-а-а! Всё заработало!!!
100
#тема Два блока def draw()
#
Я тут подумал, а можно ли два блока draw() сделать?
Чтобы как-то разделить код. В одном draw() — про кость,
в другом — про собаку, например... Ну-ка, проверяю:
Нет! Два draw() нельзя! Это связано с тем, что draw() — это команда
оманда
или, как мы ещё говорим, функция. А не должно быть команд
с полностью одинаковыми именами и разным содержимым.
Если будет два draw(), то первый я проигнорирую!
Ну это понятно, похоже на дрессировку собак. Если под командой «фас!»
я буду иметь в виду иногда «вперёд», а иногда «лежать», то собака запутается
ется
и не будет меня слушаться. С Питонами, похоже, как и с собаками :)
Шшшш... Осторош-ш-ш-шнее с ш-ш-шуточками!
101
#домашний проект Развитие проекта
#ДЗ Сможешь усложнить игру для игрока? Сделай так,
чтобы игра заканчивалась, когда голод стал равным 100.
#ДЗ Сможешь сделать так, чтобы в конце игры появилась
надпись «Собака обиделась и надула в тапок»?
#ДЗ Сможешь усложнить игру для игрока? Сделай так,
чтобы когда собака поймала кость, голод бы не сбрасывался
бы в ноль, а уменьшался, скажем, на 20.
#ДЗ Очень сложное задание — мини-проект. Когда игра
оканчивается, картинка собаки начинает убегать.
102
#проект НЛО
Шаг 1/4.
Заготовка
Начну с заготовки, в которой будут только функция draw()
На
и чёрный фон. Чтобы такого сделать?
Добавь меня
ня :)
О, привет! Точно, пусть появится НЛО.
Готово! Вынес x из функции draw() наружу.
Не забудь
сделать
переменную x
глобальной! Ведь
я буду лететь!
103
Шаг
Ш 2/4.
Пусть НЛО летит
И полетели! Добавлю увеличение x на 3.
Кое-кто кое-что
что
забыл. Я ни на
что не намекаю,
кроме global :)
Да-да, я снова забыл global. Спасибо!
Ура, я лечу...
#ДЗ Сможешь сделать так, чтобы я летел справа налево??
Хм. Во-первых, придётся вычитать 3, а не прибавлять.
Во-вторых, в начале x присвоить не 0, а, скажем, 300.
104
Шаг 3/4.
Ш
НЛО застряло
А сделай так, чтобы я вжж-вжж
вжж
туда-сюда летал.
Перевожу на программистский: если ты долетел до правого края
экрана, то должен как бы оттолкнуться и полететь назад. Хмм...
Шшш... Помнишь правило: если — если?
Да-да, раз использовал слово если, значит, нужно использовать if.
if долетел_до правого края экрана:
полететь_назад
Узнать долетел_до_правого_края_экрана просто, это если х больше 300:
if x > 300:
полететь_назад
А как полететь назад?
Если просто уменьшать x на 3 (чтобы полететь назад),
ты почему-то застреваешь в точке 300. Почему?
Подтверждаю.
аю
Я застрял.
105
Шаг 4/4.
НЛО летит обратно
НЛО застревает, так как сначала я увеличиваю
ю x на 3.
Потом проверяю, больше ли x чем 300, и если да,
то уменьшаю x на 3.
Получается: когда НЛО долетело, х не меняется.
И что же делать?
Есть такое простое правило — правило Лазаревского: если что-то меняется,
то нужна переменная, чтобы это изменение хранить.
А что у нас меняется, кроме координаты?
Направление?
Молодец! Значит, нужна переменная, которая будет хранить направление.
Скажем, 3 при движении направо и –3 при движении налево.
В математике, кстати, такую переменную часто называют dx от слов «delta x»,
то есть «приращение х».
Уменьшение же переменной — это тоже увеличение, только со знаком
«минус».
И не забудь global :)
Ура-а-а!
106
#ДЗ Сделай так, чтобы я отражался от левой стенки.
Чему мы научились
В главе 5 мы узнали про глобальные и локальные переменные,
про переменные-тёзки.
Научились избегать ошибок, объявляя переменные глобальными,
чтобы их можно было менять из главного игрового цикла draw().
Это дало нам возможность сделать НЛО летающим
и отталкивающимся от стенок.
А ещё мы смогли сделать игру, где собака ловит кость.
Узнали, что такое инкремент, и научились составлять его краткую запись.
Запомнили, что не стоит делать два draw() в одной программе.
Выучили правило «если — if»
и правило «если что-то меняется — создавай переменную».
Часть III
Игры и продвинутое
программирование
Поздравляю! Мы освоили основы языка Python и библиотеки p5py.
Теперь можно написать несколько игр, а заодно изучить более сложные темы:
else, True, False, input(), not, and, text_width().
Глава 6
Игры
Напишем пару новых игровых проектов:
•
FlappyRabbit — заяц, который
перепрыгивает препятствия;
•
AlienStrike — пришельцы и молнии.
FlappyRabbit
Напишем игру — аналог старой
и очень популярной игры FlappyBird.
Вместо летающей птички у нас будет заяц,
который прыгает, если нажать пальцем на экран
или нажать кнопку мышки.
Чем дольше нажимаем на экран, тем выше
прыгает заяц.
Когда прекращаем нажимать, заяц падает вниз,
в траву.
Заяц как бы бежит сквозь препятствия:
внизу на него надвигаются трава или
а сверху — ветки дерева.
Важно с ним не столкнуться, иначе игра
заканчивается!
Чтобы можно было соревноваться
с друзьями, отобразим, сколько
метров заяц пробежал.
кактус,
#проект Прыгающий заяц
Шаг 1/6.
Сделаем падающего зайца
Хочу создать игру про прыгающего зайца. Справа на него будут надвигаться
кактусы-препятствия. А после нажатия на экран (на мобильном) или нажатия
кнопки мышки (на десктопе) заяц будет их перепрыгивать.
Сначала просто нарисую зайца примерно по центру экрана:
Кстати, чтобы вручную не рассчитывать центр
р экрана,
экрана
можно просто разделить ширину экрана на 2:
x = width / 2
y = height / 2
Спасибо, так и сделаю. Как раз мне переменная y понадобится,
ведь заяц будет падать вниз, если на экран не нажали.
А значит, и y у него менять нужно будет.
111
Шаг
Ш 2/6.
Сделаем прыгающего зайца
#тема
#
else, #тема mouse_is_pressed
Теперь сделаю так, чтобы заяц подпрыгивал при нажатии кнопки
мышки или тапе по экрану. Придётся ввести новую переменную — dy.
исал:
Но как узнать, что нажали кнопку мышки? Я бы так написал:
if мышка_нажата:
dy = -1
Да, как раз так. В библиотеке p5py есть встроенная переменная,
ременная
которая хранит «нажали кнопку мышки или нет»:
if mouse_is_pressed:
dy = -1
Готово! Но теперь при нажатии кнопки мыши заяц просто меняет
направление и «летит» вверх. А мне нужно, чтобы, как только
мышку отпустили, он продолжил падать. То есть так:
if мышка_нажата:
dy = -1
а если не нажали_мышку:
dy = 1
Да, можно вместо «а если не нажали_мышку»
написать else (иначе). Получится так:
if mouse_is_pressed:
dy = -1
else:
dy = 1
#ДЗ Сможешь придумать, как сделать так, чтобы обойтись без else?
112
2
Шаг 3/6.
Добавим гравитацию
Отлично, сработало!
Но ме-е-едленно как-то заяц движется. Могу ускорить,
если вместо 1, скажем, 9 напишу. Но хотелось бы,
чтобы с ускорением заяц падал.
Чтобы заяц падал с ускорением, нужно не просто сразу в dy число 9
поместить, а увеличивать сам dy. Это уже из курса физики :)
Написал dy = dy + 1.
Теперь более натуралистично падает! И вовсе ваша
физика не сложная.
113
Шаг
Ш 4/6.
Добавим траву внизу
А сейчас надо сделать так, чтобы внизу травка была... Всё просто,
будет у меня зелёный прямоугольник. Заведу себе переменную, назову
dline. И буду в ней хранить местоположение, где трава начинается.
И хорошо бы, чтобы заяц ниже неё не падал...
#ДЗ Сможешь сделать так, чтобы положение травы было
не фиксировано 400, а рассчитывалось как 4/5 высоты экрана?
114
Шаг 5/6. Исправим ошибку.
Поменяем местами сравнения
Вот здесь любопытно получается. Заяц на травку упал,
а снова поднять вверх я его не могу. Сколько ни нажимай на экран —
не реагирует. Интересно, почему?
Просмотри порядок выполнения команд сверху вниз. Сначала
ала ты
проверяешь, нажата ли кнопка мышки, и записываешь в dy число -9,
если именно так и было.
Но после этого проверяешь, находится ли заяц в траве. И если так,
то обнуляешь его скорость, записывая в dy ноль.
Ааа... то есть неважно, нажимаю я на экран или нет. Если заяц в траве,
его скорость всегда обнулится.
Значит, нужно поменять местами сравнения. Сначала узнать, не находится ли
милый зайчик в травке. И если находится, то обнулить его скорость.
И только после этого проверять нажатие на экран или нажатие кнопки
мышки: если нажали, то установить скорость «минус девять».
115
1
Шаг
Ш 6/6. Исправим ошибку
с тонущим зайцем
Теперь заяц медленно погружается в траву. Занятный эффект!
Это потому, что я сначала проверяю — не в траве ли заяц? Потом проверяю,
нажата ли кнопка мышки. И если не нажата, то в блоке else: медленно
увеличиваю dy. А я бы всё же хотел его остановить.
Придётся мне сначала увеличить скорость зайца, а потом уже решать, что
с ней сделать: обнулить, например, если травы коснулся, или присвоить -9,
если экрана коснулись.
116
#проект Заяц и препятствия
Шаг 1/3.
Ш
Добавим препятствия сверху
Пришло время лететь препятствиям. Начну с веток сверху.
Это будет обычный вытянутый прямоугольник, его и нарисую.
Для левой верхней точки возьму координату, равную ширине экрана,
чтобы препятствие не было видно в начале игры. Сделаю эту переменную
глобальной. Ведь если препятствие будет двигаться, значит, значение
переменной будет меняться. Координата по вертикали будет равна нулю, ведь
это верхняя точка прямоугольника.
Ширина всегда будет равна 30. А высота пусть будет равна 200. Хотя потом
можно их случайными сделать. Ну и каждый ход буду вычитать из ex единичку,
чтобы прямоугольник смещался. Получилось неплохо!
#ДЗ Сможешь сделать так, чтобы ширина
прямоугольника была случайной?
117
Шаг
Ш 2/3.
Добавим новые
появляющиеся препятствия
п
Теперь надо сделать так, чтобы при выходе
препятствия за границу экрана появлялось бы
новое препятствие.
Ну, это легко. Достаточно сравнить координату
по горизонтали с нулём. И если меньше нуля, снова
сделать её равной ширине экрана.
#ДЗ Сможешь сделать так, чтобы ветки
сверху двигались с разной скоростью?
118
Шаг 3/3.
Сделаем высоту препятствия
случайной
А ещё сделаю так, чтобы высота препятствия случайно менялась.
Для этого после того, как прямоугольник уедет за край экрана, присвою
случайное значение:
eh = rand(dline / 4, dline / 2)
dline — это у меня расстояние от верха до травы. Значит, случайное
значение у меня будет от четверти до половины этого расстояния.
#Д Я добавил работу с новой переменной eh, но ошибка
#ДЗ
возникла. Что я забыл? Можешь помочь исправить?
Подсказка: ты опять забыл сделать переменную глобальной.
119
#проект Привередливый динозавр
Шаг 1/3.
Определим 50% вероятность
#тема True и False
Хочу игру про динозавра! Предложим случайным
образом еду́, а он будет есть только съедобное.
Если больше 50, то съедобное. Иначе — нет.
нет
О’кей. Я написал программку, чтобы проверить.
В переменную a поместил rand(100).
В переменную result поместил результат сравнения:
больше ли a, чем 50?
А затем вывел в консоль a и result.
Но там для числа 65 написано True, а для 24 выводится
False. Это что?
#ДЗ Запусти программу несколько раз.
Убедись, что для чисел больше 50 выводится
True, а для чисел меньше 50 выводится False.
120
#тема Сравнение чисел
True (Правда) и False (Ложь) — это тоже значения, которые
оторые
может хранить переменная. Если мы выполняем обычные
вычисления с числами, умножаем, делим, складываем,
вычитаем, вроде 5 + 2 * 4, то результат такого вычисления
тоже число, и это число сохраняется в переменную.
Числа можно не только умножать, делить, складывать
и вычитать. Их ещё можно сравнивать друг с другом.
Например, правда ли, что 5 > 2?
Ну да, 5 > 2 — правда.
Поэтому если мы напечатаем 5 > 2, то увидим слово True.
А правда ли, что 5 > 100?
Нет, 5 > 100 — НЕПРАВДА.
Неправда означает Ложь, правда?
Поэтому если мы напечатаем 5 > 100, то
увидим слово False.
#ДЗ Выведи в консоль результат работы
сравнения 5 > 100.
121
#тема
#
Пустая строка — это Ложь
Слушай, я тут захотел поэкспериментировать и написал
if 2 + 2:
Должна ведь появиться ошибка, а её нет.
Это как так? Вот смотри:
Да, тут я хитро работаю. Змеи же вообще хитрые существа
естваа :))
Когда я проверяю условие в if-блоке, то считаю Правдой любое
положительное или отрицательное число, а Ложью — число 0!
#ДЗ Поменяй 2 + 2 на 2 - 2 или на 0 и
убедись, что в консоль будет выведено "ложь".
А ещё я считаю Правдой любую не пустую строку, например
"питон", "код", "обожаю".
А Ложью считаю пустую строку, она записывается вот так: ""!
#ДЗ Поменяй 2 + 2 на "" и убедись,
что в консоль будет выведено "ложь".
#ДЗ Поменяй 2 + 2 на "привет" и убедись,
что в консоль будет выведено "правда".
122
Шаг 2/3.
Появление динозавра
#тема булевы переменные
Представь, что if — это привередливый Динозавр.
Перед тем, как что-то съесть, он спрашивает себя: «Это вообще съедобно?»
И если отвечает «да, съедобно», то есть True, то выполняет блок после if:,
а если нет — то блок после else:.
tasty_food — вкусная_еда
Зачем хранить в переменных числа, я уже знаю: без этого
никак игру не напишешь. Но тут я увидел, что ты сохранил
в переменную не число, а True.
Зачем хранить в переменных True и False? И главное, как
использовать потом, кроме как выводить на экран?
Так можно связать разные блоки в программе. Кстати, такие переменные
называют булевы (boolean).
Например, у нас будет всеядный динозавр. Ест всё, что угодно, кроме камней.
Запусти следующий код:
#ДЗ Запусти код и введи слово «камень» (без кавычек и с маленькой
буквы). Убедись, что динозавр считает камень несъедобным.
Запусти ещё раз и введи что-нибудь другое. Убедись, что это динозавр
готов съесть :)
123
#тема
#
Порядок выполнения
к
команды
input()
Я тут новую команду увидел — input(). И, конечно,
догадался, что это!
Она выводит окно и ждёт, пока пользователь что-нибудь в него
введёт. А результат сохраняет в переменную. Я угадал?
Молодец! Именно так.
Обращу, разве что, твоё внимание на один момент.
Если ты запускаешь код в браузере, то окошко с результатом
появится только после выполнения всего кода.
Вот в следующем коде сначала будут два вопроса подряд
и только потом вывод на экран.
В конце книги я расскажу ещё об этом :)
#ДЗ Запусти код и убедись, что он сначала
дважды спросит про еду и только потом
откроет консоль и выведет в неё текст.
124
Шаг 3/3.
#тема not
Кормим динозавра
Но если ты будешь использовать input() внутри
def draw():, то интерактивность получится.
Смотри:
Обрати внимание, если нажали кнопку Отменить или ввели
пустую строчку, то в переменной food будет пустая строка.
А пустая строка — это False.
Чтобы превратить False в True, я использую отрицание —
ключевое слово not.
».
Тогда если food хранит Ложь, то not food выдаст «правда».
Ага, работает!
Ага
#ДЗ Поменяй код так, чтобы, если была введена пустая строчка
или нажата кнопка Отменить, то слово «съедобно» не выводилось бы вовсе.
#ДЗ Попробуй заменить работу с input() на работу с rand().
Сделай так, чтобы в половине случаев в food сохранялось «камень»,
а в половине, скажем, «ананас».
125
#проект FlappyRabbit
Шаг 1/4.
Сделаем препятствия
тто сверху, то снизу
Вернусь к игре FlappyRabbit. Теперь я хочу, чтобы в половине
случаев куст был снизу, а в половине — сверху. Ну, сверху, наверное,
не куст, а ветки дерева. В них тоже важно не врезаться при прыжке.
Для этого левый верхний угол будет иметь отступ
по вертикали, равный нулю, или я его рассчитаю как
разницу между положением земли и высотой куста.
#ДЗ Нарисуй вместо веток дерева сверху облака. Для этого сделай
верхние прямоугольники шире и раскрась голубым цветом.
126
Шаг 3/3.
Ш
Проверим столкновение
Осталось только запрограммировать столкновение и останавливать
игру, если заяц коснулся куста снизу или веток дерева сверху.
Раз я использовал слово «если», значит,
мне потребуется блок if.
Или даже много-много блоков if:
127
#тема
#
Матрёшка из вложенных условий
Вот что я написал:
Заяц окажется внутри прямоугольника, если координата по горизонтали
зайца будет больше, чем координата по горизонтали левой верхней точки
прямоугольника. То есть напишу так:
if x > ex:
no_loop()
Но при этом x зайца должен быть меньше, чем x правой стороны
прямоугольника.
x правой стороны прямоугольника — это x левой стороны плюс ширина.
Значит, напишу так:
if x < ex + ew:
no_loop()
Оба условия должны выполниться одновременно, значит,
я напишу if внутри if:
if x > ex:
if x < ex + ew:
no_loop()
Всё то же самое нужно проверить и для вертикали.
Получится четыре вложенных if:
if x > ex:
if x < ex + ew:
if y > ey:
if y < ey + eh:
no_loop()
128
#тема Союз and
Кстати, код можно сократить.
Если должно выполниться условие 1 И условие 2 И условие 3
И условие 4 одновременно,
то можно (да-да) либо сложить «матрёшку» в виде
вложенных if, либо соединить условия в одном if
с помощью союза and (переводится как раз как «И»).
То есть вместо
if x > ex:
if x < ex + ew:
if y > ey:
if y < ey + eh:
no_loop()
получится просто
if x > ex and x < ex + ew and y > ey and y < ey + eh:
no_loop()
129
12
Шаг 3/4.
Учтём границы
п столкновении
при
Задуманное нами столкновение не очень естественно
твенно
выглядит. Ведь заяц сталкивается с кустом или ветками
не своим центром, а краями.
Вместо центра зайца нужно учитывать его краешки.
Понял, спасибо.
Тогда добавлю переменную s, которая будет хранить размер зайца.
И вместо x > ex напишу x + s / 2 > ex,
то есть к центру зайца добавлю половину его ширины.
Вроде бы и лучше, но теперь он как-то «заранее»
сталкивается, на расстоянии.
130
#тема
#
text_width()
Придётся сделать самый продвинутый шаг — узнать
нать
настоящую ширину зайца с помощью команды:
text_width("
")
Готово!
Я ещё из ширины зайца вычел 20 пикселей,
просто на глаз :),
а в месте столкновения вывел картинку «БАХ».
131
Шаг
Ш 4/4.
Добавим счётчик
и отобразим результат игры
По
Последним шагом добавлю счётчик, демонстрирующий, сколько
километров пролетел заяц :)
Просто буду выводить на экран количество кадров, которые прошли.
Мои поздравления!
Игра FlappyRabbit готова, как мы,
у
программисты, говорим, к релизу!
Я научил зайца прыгать, а кусты и ветки дерева — двигаться, создаваяя
ощущение, будто это заяц пробирается через препятствия. А ещё
останавливаю игру, если заяц столкнулся с чем-нибудь. И сделал подсчёт
очков, чтобы можно было соревноваться с друзьями — кто дольше
продержится в игре.
132
AlienStrike
Напишем игру.
Простой, но полноценный вариант home
defence: бегут враги, тапом по экрану
стреляем по ним молниями.
Когда много попадаем, оружие
«перегревается» и начинает мазать.
Есть запас энергии для молний, которые
тоже заканчиваются.
Есть счётчик жизней и уничтоженных
врагов.
Если враг «прорвался» и нанёс урон,
то для компенсации точность оружия
восстанавливается.
Молнии бывают белого и синего цвета,
а ещё небо мерцает вспышками.
#проект Нашествие пришельцев
Шаг 1/4.
Добавим пришельца
Внимание-внимание!
е!!
Ваша планета скоро будет
захвачена!
Интересная мысль!
Нарисую пришельца.
Сделай, пожалуйста, так, чтобы
я двигался, вызывая страх.
Легко! Вместо фиксированной координаты 200
поставлю случайное число, вот так:
Эй, я здесь как-то нервно дёргаюсь. Можно так,
чтобы я медленно и страшно надвигался?
134
Шаг
Ш 2/4.
Пришелец в движении
Конечно, просто сделаю глобальную переменную, назову её,
скажем, ex. Изначально присвою ей число, равное ширине
экрана, а потом буду отнимать единицу.
У-у-у-у! Я ужасный инопланетянин! Я испепелю вашу Землю! Эй, Мастер, а что
это за мной след какой-то тянется? Я же не кошка из мема с цветным хвостом.
Готово, убрал хвост! Достаточно было очищать экран.
Хотя с цветным хвостом ты мне больше нравишься.
135
Шаг
Ш 3/4.
Пришельцы
снова
с
и снова
Слушай, я здесь какой-то одинокий получился.
ся.
я
Пролетел и исчез. Но нас много! Как только один
исчезает, появляется следующий. Сделай так, а?
Легко! Как только твоя координата по горизонтали
меньше нуля, присвою ей снова ширину экрана.
Господин Разработчик, не хочу выглядеть придирчивым, но сейчас
я исчезаю тогда, когда только половина меня вышла за пределы экрана.
Как будто я чего-то испугался. Не, так не пойдёт, я смелый!
И появляюсь я сейчас не постепенно, нагоняя страх, а сразу — бах,
и половину меня видно.
Придётся проверять не центр тебя, а правый край. Для этого
к центру ex прибавлю половину твоего размера.
А когда появляешься, буду сдвигать тебя ещё правее —
на половину твоей ширины.
136
6
Шаг 4/4.
Отнимаем жизни
О-о-отлично, Мастер!
Настал самый страшный момент. Если меня не удалось
сбить! А, кстати, никому никогда не удастся сбить
такого храброго меня. А если меня не удалось сбить,
то я отнимаю жизни у игрока!
Помню правило Лазаревского: если что-то меняется, то нужна
переменная. Раз здесь будут меняться жизни, значит, добавлю
переменную lives и присвою ей число 10. Пусть будет 10 жизней.
А уменьшать переменную на единицу буду уже в готовом блоке if.
Хм, только ошибка какая-то. Где я напортачил?
Наверное, ты не хочешь терять жизни
ни :))
Поэтому забыл сделать переменную lives
глобальной — добавить global?
#ДЗ Исправь ошибку. Сделай переменную lives глобальной.
137
#проект Молнии
Шаг 1/4.
Появление молний
Внимание-внимание! Обороняйтесь,
ь,
мы идём вас захватывать!
Ой-ой! Я буду защищаться!
Стрелять молниями!
Начну, пожалуй, новый проект для удобства.
А потом объединю предыдущий и новый.
В новом проекте сначала просто нарисую
молнию в виде линии.
Но чёрную
ё
молнию на тёмном
ё
фоне
ф
плохо видно, да и не бывает
б
чёрных молний. Поэтому сделаю линию белой, ну и фон чёрный.
138
#тема Синтаксические и логические
ошибки
А теперь сделаю так, чтобы молния рисовалась
лишь при нажатии на экран:
Только она не рисуется
Вроде же всё правильно
сделал, никакая ошибка не отображается. В чём же дело?
Ошибки бывают двух типов: синтаксические и логические. Синтаксические
ческие
я могу найти сам и показать тебе, где они. Это такие ошибки:
неправильные отступы, опечатки, пропуск скобок и подобные.
А вот логические я не могу определить. Они потому и называются
логическими, что зависят от логики, которую ты имел в виду,
когда код программировал.
Я её сам нашёл! Забыл, что без def draw(): код только
один раз выполняется. Вот так нужно:
139
13
Шаг
Ш 2/4.
Удар молнии
Кхе-кхе-кхе, у тебя молния в однуу
точку всегда бьёт!
И то верно, так никто тебя не победит. Поэтому заменю
фиксированные числа 200 и 150 на mouse_x и mouse_y.
Вот только теперь узоры какие-то.
Ах, да. Это как со следом от тебя, Инопланетянин. Нужно экран
очищать перед рисованием молнии. Вот так:
Классно получилось!
Прикасаешься пальцем к экрану, а сверху
как будто молния бьёт.
140
Шаг 3/4.
Разнообразные молнии
Будет красиво, если размер молнии будет
случайно меняться. Молнии же не бывают
одной толщины.
Это я получил случайное число от 1 до 15,
сохранил его в переменную w.
А затем установил ширину линии, равную числу, которое w хранит.
А ещё молнии бывают более или менее яркими.
Поэтому добавлю случайную прозрачность. Сначала получу
случайное число от 10 до 255 и сохраню его в переменную a.
А потом установлю белый цвет с прозрачностью, хранящейся
в переменной a.
141
Шаг
Ш 4/4.
Вспышки в небе
А ещё небо от вспышек белым иногда становится.
Как бы эт
это закодить? Да просто изредка буду заливать фон белым цветом.
Как бы только это «изредка» определить?
if изредка:
background(255)
Случайные числа помогут тебе, о, юный падаван! Сначала получи
учи
случайное число от 0 до 100. А потом сравни его, скажем, с числом 95.
Очевидно, что оно редко будет больше 95 :)
Готово:
А ещё изредка буду молнию синим цветом рисовать (на картинках видел)
для большей драматичности. Вот так получилось:
142
#проект Цикл жизни
Шаг 1/3.
Рисуем сердечки
А жизни хочу отображать сердечками, а не числом.
Вот, в новом проекте вывел сердечко на экран:
Сердечек должно быть несколько. Количество будет хранить переменная
lives. Правда, я понятия не имею, как повторить вывод сердечек lives раз.
Я могу, конечно, просто скопировать строку пять раз вот так:
Но это ведь я вручную сделал. А мне нужна
а-вто-ма-ти-за-ци-я.
А помнишь цикл for? Мы его использовали,
овали
когда заяц круги нарезал?
143
Шаг
Ш 2/3.
Встреча с ошибкой
Точно, цикл for! Тогда, если мне нужно вывести пять раз
То
сердечки, я напишу такой код:
Хм, выводится только одно!
Цикл почему-то не работает!
Работает, работает! Просто ты пять раз выводишь
одишь
картинку сердца на одно и то же место.
И что же делать? Мне нужно вывести сердце каждый раз
с небольшим отступом от предыдущего.
Вот для этого и пригодится переменная i. Можно
умножать её, скажем, на число 20.
Тогда при первом выполнении цикла i равна нулю,
при умножении на 20 будет ноль.
При втором выполнении цикла i равно одному,
при умножении на 20 будет 20.
А-а-а-а, понял. Дальше будет 40, затем 60 и 80.
То, что нужно.
144
Шаг 3/3.
Исправим ошибку
Да, я цикл внутри себя превращаю
ащаю
вот в такой код:
Ура! Получилось вот так:
#ДЗ Попробуй расставить сердечки по вертикали.
145
#проект Объединение
Шаг 1/3.
Объединяем
пришельцев, молнии и жизни в один код
Ну что, у меня теперь есть три программы: полёт
Пришельца, стрельба молниями и отображение сердечек.
Пришло время объединить их.
#ДЗ Попробуй объединить три программы в одну.
146
6
Шаг 2/3.
Добавляем конец игры
Эй, у тебя нечестная игра! Когда все сердечки
дечки
заканчиваются, игра не останавливается!
Да я ещё не сделал конец игры.
Напишу с нуля, как бы он выглядел.
Во-о-от, теперь, если переменная lives равна
нулю, то есть меньше единицы, то пишет
конец игры и останавливает игру командой
no_loop().
#ДЗ Попробуй заменить число 0 любым числом и проверь,
что надпись о конце игры не появилась.
#ДЗ Попробуй заменить сравнение lives < 1 сравнением
lives с нулем с помощью двойного знака равенства. Проверь,
что программа работает как и прежде.
147
Шаг 3/3.
Объединяем два кода в один
#ДЗ Объедини два кода в один:
#ДЗ Исправь ошибку: сейчас первое сердце
почти вылезло за край экрана. Как поправить?
148
#проект Война с пришельцами
Шаг 1/3.
Опасные молнии
Ха-ха-ха, у тебя замечательная игра!
Я тебя победить могу, а ты меня — нет!
Молнии-то твои не работают!
Точно, стрелять стреляют, но ничего не происходит.
А надо так: если расстояние между концом молнии
и Пришельцем меньше половины его размера, то...
То конец игры, и я победил!
Нет-нет-нет, хитрый какой!
То я увеличу счётчик сбитых
пришельцев. Его я буду хранить в переменной killed (сбитые).
А координаты пришельца снова изменю так, чтобы он за
пределами экрана оказался. Как будто новый появился.
А окончание молнии у меня хранится в переменных mouse_x,
mouse_y, так что всё просто.
Проверю на новом проекте, как работает:
#ДЗ Отобрази на экране количество сбитых пришельцев.
пришельцев
149
Ш
Шаг 2/3.
Почти работает
Ну то был код без молний, не интересно.
Ну,
П
оэтому объединю код и посмотрим, что получится:
Поэтому
Молнии стреляют! Пришельцы сбиваются! Жизни уменьшаются,
уменьшаются если
Пришелец прошёл весь экран. Игра оканчивается, если жизней не остаётся.
Всё отлично!
150
Шаг 3/3.
Тестирование
Эй-эй-эй! Вовсе не отлично!
Если ты нажмёшь пальцем на экран и потом его уберёшь,
то я каждый раз буду погибать, когда до этого места дойду!
Мы так не договаривались!
Тоже подключусь к тестированию. Запустил твой код
на компьютере в браузере. Так там Пришельцы сбиваются просто
от наведения мышки. Даже нажимать кнопку мышки не надо.
Молния не появилась, а Пришелец уже уничтожен.
Так-так. Раз программа запустилась, значит,
синтаксических ошибок нет. Хм, значит, это
логический баг. Посмотрим-посмотрим.
А-а, так я должен проверять попадание молнии, только
когда кнопка мышки нажата или когда пальцем экрана
коснусь, а сейчас это всегда делаю.
Вот так бы исправил:
#ДЗ Сможешь сам добавить эту проверку?
151
#проект Новые пришельцы
Шаг 1/3.
Сделаем пришельцев разного размера
А сделай так, чтобы если кого-то из нас подбили,
и,,
новый появлялся бы другого размера.
Легко! Добавлю всего одну строчку в блок if,
где дистанция проверяется:
es = rand(30, 100)
И раз меняешь значение переменной es, то сделай es глобальной
ьной
й :))
Готово!
152
Шаг 2/3.
Неожиданное появление
Слушай, мы какие-то слишком предсказуемые
ся
получились. Всё время в одном месте появляемся.
Сделай, чтобы мы в неожиданных местах появлялись.
Тоже просто! Добавлю ещё одну строчку в тот же блок if:
ey = rand(0, height)
Готово:
Не работает! Ничего не изменилось.
#ДЗ Сможешь сам найти, в чём ошибка?
153
Ш
Шаг 3/3.
Исправим ошибку
Опять логическая ошибка где-то в коде.
О
Вот только где?
А по каким координатам ты Пришельца выводишь?
ь?
Ах, да, спасибо. У него же сейчас координата по вертикали всегда 100!
И в сравнении с молнией — тоже всегда 100.
Нужно сделать глобальную переменную ey и поменять везде 100 на ey.
154
#проект Энергия
Шаг 1/5.
Добавим энергии
Что-то у игрока молний бесконечное
чное
количество... Никакого азарта!
Ну ладно, вот мой старый код с молниями. На нём
отлично можно потренироваться с энергией:
Добавлю переменную energy (энергия). Изначально пусть
у игрока энергия будет равна 1000.
А при каждом ударе молнии буду энергию уменьшать на 1.
Ну и отображу энергию просто в виде числа.
155
Ш
Шаг 2/5.
Добавим запрет на стрельбу
Вот только текст с числом плохо видно... И запрета
стрелять нет, когда энергия закончилась.
Тогда
Т
весь код со стрельбой помещу в блок if. Если энергии
достаточно,
д
доста
аточно, ттогда только стрелять разрешу. И цвет белый для текста поставлю.
А если энергия закончилась, то напишу «нет энергии».
#ДЗ Сможешь снова объединить код?
156
Шаг 3/5. Отобразим энергию полоской
#тема Команда remap()
#
В играх энергия часто в виде полосочки отображается.
Я себе тоже так хочу.
Вот, например, если энергия равна 500, то есть половина
от 1000 осталась, то полосочка в половину экрана.
Ширину прямоугольника можно определить простой
математической формулой. Ну, или в библиотеке p5py есть уже
готовая команда remap(). У неё четыре параметра.
ä Первый — само число. У тебя это переменная energy.
ä Второй и третий — исходный диапазон. У тебя это от 0 до 1000.
ä Четвёртый и пятый — желаемый диапазон. У тебя это от 0 до
ширины экрана.
157
15
Шаг 4/5.
Отобразим количество
сбитых
пришельцев
с
#тема Команда str()
#
В
Выведу
ещё количество подбитых пришельцев. У меня есть как раз
переменная killed (сбиты). И опять в новом проекте потренируюсь:
п
Если просто число вывожу, то всё получается. А если пытаюсь перед
числом
ислом вывести строчку с эмоджи, то ошибка возникает. Почему?
TypeError: "Can't convert int to str implicitly"
Ошибка типа: "Не удаётся неявно преобразовать int в str""
Я не знаю, как сложить строку и число. Разрешаю складывать
только строки со строками или числа с числами!
158
Ш
Шаг 5/5.
1)
2)
3)
4)
Объединим код
Ну что, у меня теперь есть четыре программы:
полёт пришельца со стрельбой молниями и отображением сердечек;
разрешение стрельбы, только когда есть достаточно энергии и нажали
на экран;
полоска с количеством энергии;
отображение количества сбитых пришельцев.
Объединю-ка их.
#ДЗ Сейчас число, отображающее
количество сбитых пришельцев,
мерцает в цвет текущей молнии.
Сможешь сделать его всегда одного
цвета?
159
#проект Настоящие молнии
Шаг 1/5.
Ш
Делаем заготовку для молнии
ии
и
и
Какая-то я у тебя ненастоящая молния получилась.
ась.
Да ладно! Ты же и с разной толщиной, и с разной
прозрачностью появляешься!
Настоящая молния хотя бы из трёх сегментов
состоит. А у тебя прямая линия, фи!
Ну и как сделать тебя из трёх сегментов-то? Начну с простой
линии. Только начало и конец вынесу в переменные:
mx1, my1 — первая точка, начало линии.
А так как всего четыре точки нужно, то координаты конца
молнии назову mx4, my4.
Только замершая линия какая-то скучная. Добавлю динамики:
перенесу рисование в def draw():, а в mx4, my4 вместо 100
и 500 буду сохранять то, что хранится в mouse_x, mouse_y.
160
Шаг 2/5.
Разбиваем молнию
на два сегмента
Ну, теперь вместо одной линии пусть будут две. Начало первой
линии, как и раньше, — mx1, my1. А mx4, my4 — теперь координаты
конца второй линии.
Так как молния непрерывна, то соединяться линии будут средней
точкой: mx2, my2.
Я её случайной сделаю, вот так:
Только смотри, у меня серединка получилась
ась
ниже точки удара! Так не бывает!
Поправил, надо было для вертикальной координаты средней точки
брать случайное число от 0 до координаты конца молнии:
161
Шаг 3/5.
Разбиваем молнию
на три сегмента
Похожим образом ещё одну точку и линию добавлю:
П
А теперь я вон какая ненастоящая получаюсь..
Линии иногда пересекаются, а у меня так не бывает!
Хорошо, вертикальную координату третьей точки буду брать
в диапазоне от my2 до my4, вот:
162
2
Шаг 4/5.
Делаем молнию стройной
А ещё я чересчур широка-а-я! Я что — полная??
Я слежу за фигурой!
Хм, и правда, из-за rand(width) иногда
ты шириной во весь экран!
Да-да, сделай, пожалуйста, меня поу́же!
Хорошо, введу переменную и назову её light_width (ширина_молнии).
А координаты по горизонтали у обеих средних точек будут равны
точке удара плюс-минус случайное число, не больше этой ширины.
Теперь могу менять значение light_width
и делать тебя то шире, то у́же :).
Лучше то стройной, то ещё стройнее.
163
Шаг 5/5.
Финальный штрих всего проекта
#ДЗ Объедини основной код и продвинутые молнии.
и
164
# Домашки
Я сам написал большую и сложную игру!
Такой тип игр называют «защита башни».
На игрока нападают пришельцы. Они могут двигаться
с разной скоростью, появляться в разных частях экрана
и быть разных размеров.
Пришельцев можно сбивать молнией, которая появляется,
если тапнуть по экрану. Я даже попробовал сделать
специальные эффекты: молния меняет свой цвет, размер,
положение и прозрачность.
А ещё добавил счётчик энергии, жизней игрока
и количества сбитых пришельцев.
#ДЗ Сделай так, чтобы иногда летели
, а иногда
#ДЗ Сделай так, чтобы иногда летели
.
.
И их сбивать не нужно!
Если не собьёшь, то, долетая до левой части экрана, они
пополняют запас энергии.
#ДЗ Сделай так, чтобы иногда летели
. И если их
собьёшь, то игра сразу должна остановиться.
165
Глава 7
Основы работы
со списками в Python
Изучим списки (массивы) и циклы в Python,
как обычно,
на примере игровых проектов.
Это позволит нам писать игры
со множеством повторяющихся элементов.
Например, мы можем сделать звездопад,
пушку, стреляющую несколькими пулями,
или игру-ферму,
где нужно собирать яблоки.
#проект Тимур и его яблоки
Шаг 1/3.
Добавим ребёнка
Привет! Я Тимур и очень люблю яблоки. И не люблю
лю
ю
червяков в них. Сделай для меня игру, пожалуйста.
Хорошо, я сделаю так, чтобы тебе летели яблоки, ты их
ловил, но старался избегать червяков. Иначе игра закончится.
Сначала я просто нарисовал тебя:
Эй, знаешь, на одном месте скучно сидеть. А как я буду
перемещаться?
Перенёс рисование в функцию draw() и координаты для тебя беру
из координат прикосновения к экрану:
167
Шаг 2/3.
Добавим яблоко
А теперь добавь яблоко!
ко!
Легко! Просто вывел его
Л
на экран справа:
А двигаться оно как сможет?
Переменные, которые хранят координаты яблока, сделаю
глобальными. И буду уменьшать на 1 его координаты:
168
8
Шаг 3/3.
Добавим движение и конец игры
р
Эх, если яблоко ушло за пределы экрана, а я не успелл
его поймать, то оно пропало навсегда.
Я его сейчас верну! Просто добавлю проверку: если координата
яблока меньше нуля, то присвою ему число, равное ширине экрана.
А если я съел яблоко? То что?
Сделай, пожалуйста, чтобы была
надпись «Победил»!
Хорошо,
Х
Хоро
о
проверю дистанцию между тобой и яблоком
и завершу игру победой.
169
#проект Полезные списки
Шаг 1/5.
Создаём список и выводим
на экран #тема append()
Но я хочу много
яблок, а не одно! Скажем, 10 или 100.
100
0
Придётся для хранения горизонтальных координат яблок
аж 100 переменных создавать. Ох, неохота.
Можно сделать переменную-список командой
ндой
й
applex = []. Она будет хранить много значений.
А как складировать эти много значений в неё? Как обычно,
вот так: applex = 10?
Нет, добавить, скажем, число 100 можно командой
applex.append(100), а 101 — applex.append(101). (append — добавить).
100
101
Получится список из двух элементов.
Сделал, работает! А пока просто вывел в консоль весь список
командой print().
#ДЗ Попробуй добавить в список ещё какие-нибудь числа,
например 102, 103.
170
0
Шаг 2/5.
Два
Создаём список в цикле
яблока — слишком мало. Сделай хотя бы десяточек.
чек
Ага, я помню цикл for, и что переменная i в нём пробегает значения от 0 до
указанного в range(), но не включая его. Вот, добавил числа от 100 до 109:
Отлично! У тебя получилась переменная-список applex
le ,
которая хранит координаты сразу для 10 яблок:
100
101
102
103
104
105
106
107
108
109
#ДЗ Попробуй создать список в 100 элементов и добавить
в него случайные значения.
171
Шаг 3/5.
Читаем значения из списка
#тема Индекс
А как ты мне из своего списка
достанешь?
яблоко-то
око то
Хм, я просто название списка в print() указал, он весь
и вывелся. А как отдельный элемент достать — не знаю.
Каждый элемент в списке имеет свой персональный номер
номер.
Мы называем его индексом.
Индексы
Самый первый элемент имеет индекс 0, второй — индекс 1,
третий — индекс 2 и так далее.
0
1
2
3
4
5
6
7
8
9
100
101
102
103
104
105
106
107
108
109
Значения
Поэтому 3-й по порядку элемент, который у нас содержит
число 102, будет иметь индекс 2. И чтобы его достать, нужно
указать этот индекс в квадратных скобках после названия
списка: applex[2].
Хорошо, просто попробовал для тренировки вывести третий
элемент, который под индексом 2, командой applex[2].
#ДЗ Попробуй достать самый первый и самый последний
элементы из списка и вывести их в консоль.
172
2
Шаг 4/5.
Меняем значения в списке
А ты так и будешь каждое
яблоко по одному доставать?
ть?
Попробовал сразу в цикле доставать элементы и выводить
их на экран. А заодно для проверки и индекс их вывел:
А
яблоки будут двигаться?
ся?
Чтобы яблоки двигались, мне нужно у каждого элемента уменьшать значение
на единицу. Сделал, как с обычными переменными. Всё получилось:
#ДЗ Попробуй достать только первый элемент
и увеличить его, скажем, на 80.
#ДЗ Попробуй, используя библиотеку p5py,
ещё и вывести эти яблоки на экран в разных местах.
173
Шаг 5/5.
Удаляем элемент, узнаём длинуу
ссписка #тема remove(), #тема len()
А если я съел
яблоко, оно же должно
но же
пропасть из этого самого списка?
Ага, но не само оно, а его ко-ор-ди-на-ты. И ещё я не умею
Аг
пока удалять элементы из списка...
Есть две команды удаления:
del applex[2] — удаляет элемент с индексом 2 (3-й по порядку);
)
applex.remove(103) — удаляет само число 103 из списка, если оно есть.
Не перепутай!
0
1
2
3
4
5
6
7
8
9
100
101
102
103
104
105
106
107
108
109
Удалил число 103 из списка. Пришлось только вручную менять
range(10) на range(9), элементов же стало на один меньше.
Есть команда len(applex) (от length — длина).
Она возвращает длину списка.
174
4
#проект Яблоки и червяки
Шаг 1/5.
Добавим два яблока
Ну, так где мои
яблоки?
и?
С
Сейчас
появятся. Командой applex = [] указал, что теперь
в ней будет хранится не одна координата яблока, а много.
Поместил координаты пока только для двух яблок: width и 200.
Помести
П
И до
добавил цикл
л по размеру списка, где теперь вывожу
сами яблоки:
#ДЗ Попробуй добавить больше яблок.
175
Шаг 2/5.
Добавим много яблок
Моих
яблок опять всего два-а-а...
а
Ну, не расстраивайся, сделать много яблок —
Н
всего пара строчек:
Только я что-то сразу побеждаю при прикосновении
к любому яблоку. А сделай лучше так, чтобы они исчезали.
Заменил окончание игры на удаление координаты
яблока из списка, но... Но почему-то ошибка возникает!
176
Шаг 3/5.
Исправим ошибку с удалением
#тема IndexError, #тема range()
Давай посмотрим на ошибку:
module __main___draw_25 line 20, in draw for i in range(len(applex)):
IndexError: 'list index out of range'
модуль __main___draw_25 строка 20, в draw для i в диапазоне (len(applex)):
Ошибка индекса: 'индекс списка вне диапазона'
Смотри, если ты удаляешь координаты яблока из списка,
он уменьшается. А цикл всё так же перебирает яблоки
до старого количества. Первый вариант решения —
пробежать по циклу в обратном порядке:
range(len(applex) - 1, -1, -1) — перебирает числа от длины
списка минус один до нуля (то есть до –1, не включая его),
с шагом –1.
А почему от длины
минус один?
Ну, если у тебя список длиной 10 элементов,
то индекс последнего элемента какой?
Ах, да-да. Он на единицу меньше. То есть равен девяти. Ведь индексы
для десяти элементов такие: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. Починил:
177
#тема for для списков, #тема пуст ли список
окк
А ещё можно использовать хитрый цикл for,
который перебирает элементы в списке.
for x in applex:
переберёт все элементы в списке applex, в каждом проходе
цикла сохраняя очередной элемент в переменной x.
З
Звучит
очень хитро, но попробую.
Ха, получилось. И очень просто:
А игру теперь нужно оканчивать, когда все яблоки
съедены, то есть список applex пуст. Но как это узнать?
Так можно проверить,
что список НЕ пуст:
if applex:
А вот так, что список
пуст:
if not applex:
Добавил проверку и окончание игры.
178
Шаг 4/5.
Появление червяка
Ха-ха-ха. Теперь время появиться мне!
не!!
Изи. Твою координату буду хранить в переменной
под именем enemyx (враг х).
И сделай, чтобы
бы
ы
я двига-а-а-лся!
179
Шаг 5/5.
Ш
Добавим окончание игры
А если меня коснулся, напиши: «Проиграл!»
ал!»
!
Ну, это просто, сделаю проверку на дистанцию
Н
ю
между тобой и ребёнком.
Спасибо за игру! Но последний шаг можно было
ыло
и не делать! Приятнее всегда выигрывать.
#ДЗ Попробуешь сделать так, чтобы яблоки
летели не по одной линии, а на разной высоте?
#ДЗ Попробуешь сделать так, чтобы червяков
было несколько и летели они на разной высоте?
180
0
Глава 8
Программирование
на десктопе
Эта глава для более опытных разработчиков —
для тех, у кого уже установлен Python на компьютере и кто умеет устанавливать
дополнительные библиотеки, программы, среды разработки.
Рассмотрим особенности реализации графической библиотеки p5
для работы в профессиональной среде разработки
(integrated development environment, IDE), чтобы сделать первый шаг
к профессиональному программированию.
Покажем на практике, что весь код, создаваемый нами с первой главы, —
это полноценный код на Python, с которым опытный разработчик может
продолжить работать привычным ему образом.
Покажем лёгкость и плавность перехода от программирования на смартфонах
к программированию на компьютерах в больших IDE.
Рассмотрим клавиатурные сокращения,
которые позволяют ускорить разработку при программировании
в браузере на компьютере: запуск, сохранение, останов кода.
#проект Программирование
в браузере
Шаг 1/1.
Клавиатурные сокращения
Привет! Я Ноутбук :) Твой гид в восьмой главе.
лавве.
Эта глава для продвинутых пользователей,
поэтому я кратко расскажу тебе, как
программировать на Python с нашей привычной
графической библиотекой на десктопе.
Кстати, проекты можно запускать
не только на телефоне, но ещё
и на компьютере в браузере.
Если и там и там браузер —
в чём разница?
На компьютере есть клавиатура, поэтому
доступны клавиатурные сокращения:
для Windows:
<Win>+<Shift>+<R> — запустить код;
<Esc> — закрыть результат работы кода;
<Win>+<S> — сохранить код;
для Mac:
<Cmd>+<Shift>+<R> — запустить код;
<Esc> — закрыть результат работы кода;
<Cmd>+<S> — сохранить код.
182
#проект Программирование
в VS Code
Шаг 1/3.
Ш
Установка Python и p5
Мой друг говорит, что у него уже установлен Python
на компьютере. Он может как-то работать с нашей
библиотекой p5py?
Да, можно скачать Python и библиотеку p5py себе на компьютер и запускать
скаать
код без браузера. Чтобы понять эту главу, твой друг должен уметь работать
с терминалом/командной строкой.
Предварительно кратко повторим, как установить Python:
1.
2.
3.
4.
5.
Идём на официальный сайт Python — python.org/downloads.
Нажимаем кнопку Download и скачиваем файл — установщик Python.
Запускаем установщик Python.
Ставим все галочки при установке.
И устанавливаем.
А теперь нужно установить библиотеку p5 с официального сайта библиотеки:
p5.readthedocs.io в разделе установки: https://p5.readthedocs.io/en/latest/install.html
Сначала надо установить библиотеку GLFW.
Для Windows скачай файлы с этой страницы: https://www.glfw.org/ download.html
И запомни путь, куда установилась библиотека GLFW.
Далее к системному пути следует добавить каталог установки GLFW.
Сначала найди диалоговое окно настроек Переменные среды. Далее найди
и выдели переменную PATH (путь) и нажми кнопку редактирования. Добавь
каталог установки GLFW в конец списка и сохрани настройки.
Обязательно добавь файлы *.dll и *.a
(например, \<путь к glfw>\glfw-3.2.1.bin.WIN64\lib-mingw-w64).
На Mac для установки библиотеки GLFW: используйте команду
brew install glfw
Далее установи саму библиотеку p5 командой в терминале:
pip install p5 --user
183
Шаг 2/3.
Установка VS Code
А код где писать?
Раньше это делали просто в браузере.
Р
Код на Python можно писать почти в любом текстовом редакторе
оре
(кроме разве что Word):
Notepad++, Sublime Text, Atom.
Но наиболее удобно использовать текстовые редакторы,
адаптированные для программистов, их ещё называют
интегрированными сре́дами разработки
(integrated development environment или IDE).
Одни из самых популярных — VS Code и PyCharm.
Сначала нужно скачать и установить VS Code
с официального сайта:
https://code.visualstudio.com
Сам VS Code представляет собой сочетание проводника
по файлам, текстового редактора и даже имеет кнопку
запуска файла с кодом на Python.
На следующем шаге как раз напишем код в VS Code.
184
Шаг 3/3.
Запуск проекта
Давай для проверки запустим какой-нибудь
минимальный проект.
1. Создай файл и назови его как угодно, например min_ex.py.
ex py
Важно, чтобы расширение у файла было .py.
2. Введи в этот файл код, который я привёл ниже.
3. Запусти его, а я позже объясню его.
Нажми кнопку с треугольной стрелкой,
кой
чтобы запустить.
185
#проект Различие библиотек p5 и p5py
Шаг 1/4.
Ш
Отличия в запуске кода
ЕЕсть ли отличия в том, как оформить код
в разных библиотеках?
Да, есть несколько отличий. Когда пишем код
ко
од
на стационарном компьютере, используем правила:
1. Название p5, вместо p5py, вот так:
from p5 import *
2. Команду run() размещаем самой последней строчкой.
3. Появляется новая функция
setup(). В неё помещаем
команды, которые раньше
располагали вне draw(), например
size(). Получается так:
def setup():
size(400, 400)
4.
4 А вот определение глобальных
переменных не меняется, они
по-прежнему остаются «снаружи»,
вне всех функций.
186
6
Ш
Шаг 2/4.
Транслируем сложный код
А все ли команды одинаковы в мобильной
библиотеке p5py и десктопной p5?
Одни команды придётся переименовать,
овать
а другие не будут работать вовсе.
Вместо команды rand() нужно
использовать команду random_uniform().
Любые команды рисования, вроде ellipse(), rect()
и других, будут работать только в функции draw().
Установить скорость отрисовки в p5 можно так:
run(frame_rate=1)
А давай для примера какой-нибудь более сложный код
перенесём на десктопную версию Python с библиотекой p5.
Попробуй сам бегающего снеговика перенести.
сти
Готово:
187
Шаг 3/4.
Работа с текстом
А с текстом работа одинаковая?
Для изменения размера текста нужно применить
ить
дополнительные команды, чтобы подгрузить шрифт.
Сначала применим команду create_font(),
чтобы создать нужный шрифт.
Затем командой text_font() подгрузим его
как активный.
Можно ещё сохранить во временную глобальную
переменную, например f, чтобы быстрее
переключать разные шрифты:
188
8
Шаг 4/4.
Работа с эмоджи
Слушай, а эмоджи на десктопе
отображаются просто квадратиками!
В текущей десктопной версии библиотеки p5 работа с эмоджи
не поддерживается. Смотри на p5py.khasang.ru новости о её обновлении.
А пока работу с эмоджи можно заменить работой с картинками. В глобальную
ую
ю
переменную, скажем, img, командой load_image() загрузи картинку.
img = load_image('1666.png')
В setup() установи image_mode("CENTER"), если нужно разместить картинку
по центру.
В draw() там, где нужно вывести картинку на экран, используем команду
image(img, 200, 300, 100, 100),
где img — переменная, в которую сохранили картинку,
200 и 300 — координаты куда выводить,
100 и 100 — ширина и высота.
Архив картинок для основных эмоджи можно скачать в Интернете
или в приложении к книге.
189
Ответы к задачам
Глава 1
#проект Первая программа:
https://p5py.khasang.ru/ide/
dt/591
Глава 3
#проект Снеговик
Шаг 3/3. Передвинем
Снеговика вверх: https://
p5py.khasang.ru/ide/dt/592
Задание 2: https://p5py.
khasang.ru/ide/dt/593
Глава 4
#проект Эксперименты
с редактором
Шаг 2/2. Убираем очистку
фона
Задание 1: https://p5py.
khasang.ru/ide/dt/596
Задание 2: https://p5py.
khasang.ru/ide/dt/597
Задание 3: https://p5py.
khasang.ru/ide/dt/594
#проект Встроенные
переменные: https://p5py.
khasang.ru/ide/dt/595
#проект Заяц и морковка
Задание 1: https://p5py.
khasang.ru/ide/dt/599
Задание 4: https://p5py.
khasang.ru/ide/dt/600
#проект Склонение слов
Шаг 5/5. Работа с консолью
https://p5py.khasang.ru/ide/
dt/603
#проект Охота на зайца
Шаг 2/4. Научим зайца
бегать
https://p5py.khasang.ru/ide/
dt/598
190
#проект Бесконечный бег
Шаг 4/4. Сделаем цикл
до 100
https://p5py.khasang.ru/ide/
dt/604
#проект Непредсказуемая
морковь
#проект Собака и кость
Шаг 4/4. Ам и съела
https://p5py.khasang.ru/ide/
dt/602
https://p5py.khasang.ru/ide/
dt/605
Ответы к задачам
Глава 5
#проект Корабли и грузовики
Шаг 4/4. Превращаем
локальное в глобальное
#домашний проект
Две кости
https://p5py.khasang.ru/ide/
dt/606
https://p5py.khasang.ru/ide/
dt/607
#проект Тамагочи.
#ДЗ Развитие проекта
#проект НЛО
Задание 3: https://p5py.
khasang.ru/ide/dt/608
Шаг 2/4. Пусть НЛО летит:
https://p5py.khasang.ru/ide/
dt/610
Задание 4: https://p5py.
khasang.ru/ide/dt/609
Шаг 4/4. НЛО летит
обратно: https://p5py.
khasang.ru/ide/dt/611
Глава 6
#проект Цикл жизни
Шаг 3/3. Исправляем
ошибку
#проект Заяц и препятствия
Шаг 2/3. Добавим новые
появляющиеся препятствия
https://p5py.khasang.ru/ide/
dt/616
https://p5py.khasang.ru/ide/
dt/612
#проект Энергия
Шаг 5/5. Объединим код
#проект Динозавр
Шаг 3/3. Кормим Динозавра
https://p5py.khasang.ru/ide/
dt/613
https://p5py.khasang.ru/
result/dt/618
#проект Настоящие молнии
Шаг 5/5. Финальный штрих
всего проекта
https://p5py.khasang.ru/ide/
dt/349
Глава 7
#проект Полезные списки
Шаг 4/5. c Меняем значения
в списке
#проект Яблоки и червяки
Шаг 5/5. Добавим окончание
игры
https://p5py.khasang.ru/ide/
dt/619
Задание 1: https://p5py.
khasang.ru/ide/dt/622
191
Благодарности
Хочу выразить благодарность огромному количеству людей, без
которых эта книга не была бы такой крутой.
Спасибо жене и дочке за то, что они есть. Мой безусловный
источник счастья.
Спасибо отцу за Радио-86РК в мои 10 лет. Basic, Asm, чёрнобелый экран только в текстовом режиме, запись программ на
магнитофон и ввод шестнадцатеричных кодов из журналов —
этого было достаточно, чтобы влюбить меня в программирование
навсегда.
Спасибо Илье за интерес к программированию в его 10 лет, ведь
именно для него ещё в далеком 2013 году я написал свою первую
книгу по программированию для детей «Яша учится программировать». А затем, увлекшись, стал вести онлайн- и оффлайнкурсы по программированию следующие 10 лет.
Благодарю редакцию «БХВ-Петербург». И особенно Евгения
Рыбакова за множество ценнейших замечаний в течение полугода
работы над книгой. В том числе и за идею, как сделать книгу ещё
структурированнее и проще для восприятия. Хотя, да, это повлекло
большие модификации в течение многих дней. Я выбросил кучу
станиц и написал десятки новых. Но без этого книга не была бы
столь простой, выверенной и яркой.
Спасибо всем студентам, кто учился у меня программированию
в Khasang в 2015–2022 годах. И всем преподавателям, которые
помогали мне вести курсы (Сергею Кузнецову, Марине Вильтовской,
Андрею Турубчуку, Андрею Полякову и другим) — благодаря вам
у меня было время пробовать новое и экспериментировать.