#24.2 pascal Управление "сценой": примеры кода и технических приёмов для простой анимации и "игр"
Primary tabs
Задача этого урока - познакомить вас с техническими деталями, которые хотя и не входят в основную программу нашего курса базовой алгоритмической подготовки, тем не менее позволят проще управлять консольной программой, напр. не нажимая каждый раз Enter, при вводе каких-либо данных.
Почему эти детали не входят в программу - потому что научиться понимать структуру кода/основные идеи программирования можно и без них, но с ними программы будут куда более "реальными" и настоящими ;)
Прежде чем начать вникать в примеры ниже, посмотрите урок по простейшей анимации в консоли.
Пример №1 -- перемещение символа по экрану
Если использовать обычный способ ввода данных, который известен нам из курса, управлять позицией символа на виртуальной сцене мы можем как-то так:
uses Crt; // импортираем модуль Crt procedure drawFrame(skin: char; position: integer); var i: integer; begin for i:=1 to (position-1) do write(' '); writeln(skin); end; procedure getNewPosition(var position: integer; var command: char); begin readln(command); if (command = '2') then position := position + 1 else if (position > 1) then position := position - 1; end; // * var position: integer; skin, command: char; begin skin := '*'; // внешний вид command := '1'; // последняя введенная команда position := 1; // текущая позиция while(command <> 'q') do begin ClrScr(); // обновляем "кадр" drawFrame(skin, position); // рисуем очередной кадр getNewPosition(position, command); // обрабатываем ввод end; writeln('Программа завершена!'); readln(); end.
Примечание: для лучшего понимания см.:
- видео-разбор по данному коду.
- уточнение: видео: почему в примере перешли от функции к поцедуре
Пример №2 - ввод символа без нажатия Enter
Управление позицией символа можно сильно упростить, если не перейти от readln(), который требует нажатия Энтер для получения значения символьного типа к функции ReadKey() из модуля Crt:
uses Crt; // импортираем модуль Crt procedure drawFrame(skin: char; position: integer); var i: integer; begin for i:=1 to (position-1) do write(' '); writeln(skin); end; procedure getNewPosition(var position: integer; var command: char); begin command := ReadKey(); // вместо readln(command) if (command = '2') then position := position + 1 else if (position > 1) then position := position - 1; end; // * var position: integer; skin, command: char; begin skin := '*'; // внешний вид command := '1'; // последняя введенная команда position := 1; // текущая позиция while(command <> 'q') do begin ClrScr(); // обновляем "кадр" drawFrame(skin, position); // рисуем очередной кадр getNewPosition(position, command); // обрабатываем ввод end; writeln('Программа завершена!'); readln(); end.
-- это сделает уже более похожим на то, как оно происходит в реальных программах/играх, что мы используем в жизни.
Для лучшего понимания можно посмотреть:
Пример №3 - Продолжаем работу программы/анимацию сцены, даже если пользователь бездействует, но при этом в готовности обработать команду
Обычная ситуация - вы ничего не делаете, но на экране меняется сцена, как добавиться этого - ведь - на выручку приходит функция keypressed() (опять же из модуля Crt), которая возвращает булево значение, показывающее нажата ли сейчас какая-нибудь клавиша или нет.
Перепишем предыдущий пример пример используя новую изученную возможность:
uses Crt; // импортираем модуль Crt procedure drawFrame(skin: char; position: integer); var i: integer; begin for i:=1 to (position-1) do write(' '); writeln(skin); end; procedure handleCommand(var position: integer; var command: char); begin command := ReadKey(); // вместо readln(command) if (command = '2') then position += 1 else if (position > 1) then position -= 1; end; // * var position: integer; skin, command: char; begin skin := '*'; // внешний вид command := '1'; // последняя введенная команда position := 1; // текущая позиция while(command <> 'q') do begin ClrScr(); // обновляем "кадр" drawFrame(skin, position); // рисуем очередной кадр Delay(500); {далее высчитываем новую позицию только если клавиша нажата, иначе просто отрисовываем кадр заново без изменений } if (keyPressed()) then handleCommand(position, command); // обрабатываем ввод end; writeln('Programma zavershena!'); readln(); end.
По этому коду:
- Видео разбор - обновляем сцену даже если пользователь ничего не делает
- если часто нажимать клавишу "2" (команда "вправо"), а потом перестать, то из-за задержки обработки ( в т.ч. из-за вызова Delay() в потоке ввода накопятся символы и даже после того как мы перестанем нажимать "2" (вправо) звездочка продолжить двигаться вправо, но потом стабилизируется.
Воспроизвести такое накопление символов в потоке ввода (а он условно "открыт" всегда, вне зависимости от того вызван ли его чтение в программе или нет), можно, например, с помощью кода:
uses Crt; var a, i, j: integer; c: char; begin a := 1; // начни вводить символы с клавитуры // используем цикл для того, чтобы успеть ввести много символов for i:=1 to 2000 do begin for j:=1 to 1000000 do a := a + 1; a := 1; end; // начинаем читать поток ввода через ReadKey() writeln('Start reading'); for i:=1 to 10 do begin c := ReadKey(); writeln(); writeln(c); end; writeln('Programma zavershena!'); readln(); end.
- Log in to post comments
- 1188 reads