You are here
Прогулка по лунолётам. 3 - Оживляем "Кон-тики"
Все прогулки: первая, вторая, третья и четвёртая.
На предыдущей прогулке мы успешно запрограммировали модель, позволяющую управлять лунолётом в динамике вблизи безвоздушных планет. Однако, вывод оперативной информации о полёте представлял собой только поток ежесекундно меняющихся цифр. Пришла пора добавить графику и перейти в двумерное пространство.
Возможности даже UserRPL (у SysRPL они выше) по работе с графикой весьма богаты: отображение функций, точнее, их кривых, рисование на уровне примитивов "линия", "дуга", "прямоугольник", "круг", вывод двоичных графических объектов в определенное место экрана, анимация по заданной последовательности изображений и многое другое.
Тем не менее, UserRPL не ориентирован на вывод графики в динамическом режиме. Если вы попробуете делать это стандартными способами - очистить экран, добавить объекты, сохранить экран, показать, повторить в цикле - то картинка начнет мерцать. Скорости обработки не хватает.
Поэтому для динамики потребуется не совсем стандартный подход, накладывающий некоторые ограничения. Суть его в том, что мы не очищаем экран всякий раз, а инвертируем точки по двум состояниям объекта: предыдущему и текущему. "Исключающее ИЛИ" с предыдущим состоянием погасит точки, оно же высветит их для текущего. Это касается двоичных объектов (GROB). Из функций рисования такими свойствами обладает лишь TLINE. Её то мы и будем использовать для обрисовки "Кон-тики" под разными углами атаки.
Для рисования векторного изображения лунолёта нам должно хватить восьми точек. Для простоты расчетов возьмём полярную систему координат с центром, вокруг которого будет вращаться корабль.
Вот необходимая нам математика.
Наша задача - отработать блок отрисовки лунолёта, поэтому программа (см. прикрепленный файл и текст ниже) будет упрощенной. Не будем пока реализовывать блок расхода топлива, расчета координат и многочисленных проверок. Ограничимся управлением стрелками: приращение ускорения будем всё так же производить вертикальными, а горизонтальные подключим для изменения угла атаки. Выведем также значения вертикальной и горизонтальной скоростей.
Кнопки "A" и "Q" будут служить для выхода из программы. Кнопка "M" позволяет переключать приращение угла между 1 и 10 (см. цифру справа от значения Δα).
Обратите внимание на использование стека, локальных переменных и организацию подпрограмм. Нам это всё обязательно понадобится на следующей прогулке.
Пробуем набрать скорость в вертикальном полете
Начинаем отклоняться вправо
Лунолёт под углом 45°
Снимки экрана получены с эмулятора. На реальном устройстве графика смотрится гораздо чётче.
Не совсем пока ясна концепция показа траектории. Как нагляднее мог бы выглядеть такой показ: просто кривая, построенная по контрольным точкам с изменением масштаба при выходе за пределы координатной сетки, или еще что-то?
На следующей прогулке нам предстоит решить этот вопрос и добавить все недостающие реалистичному симулятору блоки для полёта.
%%HP: T(0)A(D)F(.); « PUSH 1.62 'g' STO @ Lunar acceleration of gravity, m/sec2 0. 'a' STO @ Current acceleration 0. 'an1' STO @ Acceleration N-1 (previous step) 0.5 'da' STO @ Acceleration increment 0. 'ac' STO @ angle of climb in degrees 0. 'acn1' STO 1. 'dac' STO @ Angle increment 1. 'dacn1' STO 0. 'u' STO @ vertical velocity 0. 'un1' STO 0. 'v' STO @ horisontal velosity 0. 'vn1' STO 1. 'dt' STO @ Maneuver discrete time in sec @ Points to draw lunar ship 20. 'alpha1' STO 20. 'alpha2' STO 10. 'r1' STO 12. 'r2' STO 11. 'r3' STO 8. 'r4' STO 4. 'r5' STO 100. 'x0' STO 30. 'y0' STO @ Application flags 0 'tostop' STO 1 'toinit' STO « 1 \->GROB PICT UNROT REPL » 'showrepl' STO « \-> valn1 valn coord toinit « IF toinit valn1 valn \=/ OR THEN IF toinit NOT THEN PICT coord valn1 1 \->GROB GXOR END PICT coord valn 1 \->GROB GXOR END » » 'showgxor' STO « \-> r phi « r phi COS * x0 + R\->B y0 r phi SIN * - R\->B 2 \->LIST » » 'getpoint' STO « \-> phi « r1 180 alpha1 - phi - getpoint r1 alpha1 phi - getpoint r3 0 phi - getpoint r2 alpha2 NEG phi - getpoint r2 180 alpha2 + phi - getpoint r3 180 phi - getpoint r4 90 phi - getpoint r5 270 phi - getpoint \-> p1 p2 p3 p4 p5 p6 p7 p8 « p1 p2 TLINE p2 p3 TLINE p3 p4 TLINE p3 p6 TLINE p5 p6 TLINE p1 p6 TLINE p1 p7 TLINE p2 p7 TLINE x0 R\->B y0 R\->B 2 \->LIST p8 TLINE » » » 'showship' STO DEG DO IF toinit THEN 0. 100 XRNG 0. 50 YRNG ERASE DRAX LABEL {#0d, #0d} PVIEW {#10d, #0d} "a:" showrepl {#10d, #7d} "\GD\Ga:" showrepl {#10d, #14d} "Vx:" showrepl {#10d, #21d} "Vy:" showrepl END an1 a {#23d, #0d} toinit showgxor IF toinit dac dacn1 \=/ OR ac acn1 \=/ OR THEN acn1 \->STR " \177" dacn1 \->STR + + ac \->STR " \177" dac \->STR + + {#23d, #7d} toinit showgxor END vn1 2 RND v 2 RND {#23d, #14d} toinit showgxor un1 2 RND u 2 RND {#23d, #21d} toinit showgxor @ Calculate points as a function of "ac" IF toinit ac acn1 \=/ OR THEN IF toinit NOT THEN acn1 showship END ac showship END dt WAIT @ Prevoius iteration values a 'an1' STO ac 'acn1' STO v 'vn1' STO u 'un1' STO dac 'dacn1' STO WHILE KEY REPEAT \-> k « CASE k 25 == THEN a da + 'a' STO END k 34 == THEN ac dac - 'ac' STO END k 35 == THEN a da - 'a' STO END k 36 == THEN ac dac + 'ac' STO END k 41 == THEN IF dac 1 == THEN 10 ELSE 1 END 'dac' STO END k 11 == k 51 == OR THEN 1 'tostop' STO END END » END v a dt * ac SIN * + 'v' STO u a ac COS * g - dt * + 'u' STO 0 'toinit' STO UNTIL tostop 1 == END { 'g', 'a', 'an1', 'da', 'ac', 'acn1', 'dac', 'dacn1' 'v', 'vn1', 'u', 'un1', 'dt', 'tostop', 'toinit' 'alpha1', 'alpha2' 'r1', 'r2', 'r3', 'r4', 'r5', 'x0', 'y0', 'showrepl', 'showgxor', 'getpoint', 'showship' } PURGE POP » HOME 'Lunar' PURGE 'Lunar' STO
Прикрепленный файл | Размер |
---|---|
![]() | 3.71 KB |