Обычно yabasic воспринимают как что-то базовое для текстовых программ, но на нём можно строить вполне серьёзные ретро 3D-сцены
В этой программе реализован вращающийся 3D-куб, который:
Управляется с клавиатуры.
В этой программе реализован вращающийся 3D-куб, который:
- Летает сам по себе: он отскакивает от невидимых границ экрана и плавно приближается/удаляется.
- Имеет два режима: каркасный (Wireframe) и сплошной (Solid) с красивой цветной заливкой граней.
- Правильно отрисовывает глубину: здесь используется Алгоритм художника (Painter's Algorithm). Программа вычисляет среднюю глубину каждой грани, сортирует их от дальних к ближним и рисует именно в таком порядке. Благодаря этому ближние грани перекрывают дальние, и куб всегда выглядит объёмным.
- Пробел — переключение между каркасом и цветными гранями.
- Стрелки ← / → — толкнуть куб влево или вправо (меняет скорость полета).
- Стрелки ↑ / ↓ — принудительно приблизить или отдалить куб.
- + / - — изменить скорость вращения.
- Esc — выход (нажимать, когда фокус на окне терминала).
Код: Выделить всё
open window 400, 400
clear screen
// Вершины куба (от -1 до 1)
dim vertices(8,3)
vertices(1,1) = -1: vertices(1,2) = -1: vertices(1,3) = -1
vertices(2,1) = 1: vertices(2,2) = -1: vertices(2,3) = -1
vertices(3,1) = 1: vertices(3,2) = 1: vertices(3,3) = -1
vertices(4,1) = -1: vertices(4,2) = 1: vertices(4,3) = -1
vertices(5,1) = -1: vertices(5,2) = -1: vertices(5,3) = 1
vertices(6,1) = 1: vertices(6,2) = -1: vertices(6,3) = 1
vertices(7,1) = 1: vertices(7,2) = 1: vertices(7,3) = 1
vertices(8,1) = -1: vertices(8,2) = 1: vertices(8,3) = 1
// Ребра
dim edges(12,2)
edges(1,1) = 1: edges(1,2) = 2
edges(2,1) = 2: edges(2,2) = 3
edges(3,1) = 3: edges(3,2) = 4
edges(4,1) = 4: edges(4,2) = 1
edges(5,1) = 5: edges(5,2) = 6
edges(6,1) = 6: edges(6,2) = 7
edges(7,1) = 7: edges(7,2) = 8
edges(8,1) = 8: edges(8,2) = 5
edges(9,1) = 1: edges(9,2) = 5
edges(10,1) = 2: edges(10,2) = 6
edges(11,1) = 3: edges(11,2) = 7
edges(12,1) = 4: edges(12,2) = 8
// Грани
dim faces(6,4)
data 1, 2, 3, 4, 6, 7, 8, 5, 1, 5, 8, 4, 2, 3, 7, 6, 1, 2, 6, 5, 4, 3, 7, 8
for f = 1 to 6
for v = 1 to 4
read faces(f,v)
next v
next f
// Цвета
dim colors(6,3)
data 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 0, 255, 0, 255, 0, 255, 255
for f = 1 to 6
for c = 1 to 3
read colors(f,c)
next c
next f
dim px(8), py(8), pz(8)
dim face_z(6), order(6)
backcolor 0,0,0
color 255,255,255
// Параметры анимации
angle_x = 0.5
angle_y = 0.5
angle_z = 0
speed = 1.0
mode = 1
focal_length = 100
// НОВЫЕ ПАРАМЕТРЫ ДВИЖЕНИЯ
center_x = 200
center_y = 200
zoom_scale = 4000
vel_x = 3.0 // Скорость полета влево/вправо
vel_zoom = 50.0 // Скорость приближения
do
clear window
angle_x = angle_x + 0.02 * speed
angle_y = angle_y + 0.03 * speed
angle_z = angle_z + 0.01 * speed
// ЛОГИКА АВТОДВИЖЕНИЯ
// Двигаем куб
center_x = center_x + vel_x
zoom_scale = zoom_scale + vel_zoom
// Отскок от стенок (учитывая размер куба, примерно 80-100 пикселей)
if center_x > 280 or center_x < 120 then
vel_x = -vel_x
end if
// Отскок по глубине (зум)
if zoom_scale > 6000 or zoom_scale < 1500 then
vel_zoom = -vel_zoom
end if
// 1. Поворот и проецирование
for i = 1 to 8
x = vertices(i,1)
y = vertices(i,2)
z = vertices(i,3)
ny = y * cos(angle_x) - z * sin(angle_x)
nz = y * sin(angle_x) + z * cos(angle_x)
y = ny : z = nz
nx = x * cos(angle_y) - z * sin(angle_y)
nz = x * sin(angle_y) + z * cos(angle_y)
x = nx : z = nz
nx = x * cos(angle_z) - y * sin(angle_z)
ny = x * sin(angle_z) + y * cos(angle_z)
x = nx : y = ny
px(i) = zoom_scale * x / (z + focal_length) + center_x
py(i) = zoom_scale * y / (z + focal_length) + center_y
pz(i) = z
next i
// 2. Отрисовка
if mode = 1 then
color 255, 255, 255
for j = 1 to 12
v1 = edges(j,1)
v2 = edges(j,2)
line px(v1), py(v1) to px(v2), py(v2)
next j
else
for f = 1 to 6
v1 = faces(f,1)
v2 = faces(f,2)
v3 = faces(f,3)
v4 = faces(f,4)
face_z(f) = (pz(v1) + pz(v2) + pz(v3) + pz(v4)) / 4
order(f) = f
next f
for i = 1 to 5
for j = i + 1 to 6
if face_z(order(i)) < face_z(order(j)) then
tmp = order(i)
order(i) = order(j)
order(j) = tmp
end if
next j
next i
for i = 1 to 6
f = order(i)
v1 = faces(f,1)
v2 = faces(f,2)
v3 = faces(f,3)
v4 = faces(f,4)
color colors(f,1), colors(f,2), colors(f,3)
fill triangle px(v1),py(v1) to px(v2),py(v2) to px(v3),py(v3)
fill triangle px(v1),py(v1) to px(v3),py(v3) to px(v4),py(v4)
color 0,0,0
line px(v1),py(v1) to px(v2),py(v2)
line px(v2),py(v2) to px(v3),py(v3)
line px(v3),py(v3) to px(v4),py(v4)
line px(v4),py(v4) to px(v1),py(v1)
next i
end if
// 3. Интерфейс
color 255, 255, 255
if mode = 1 then
text 10, 380, "Mode: Wireframe"
else
text 10, 380, "Mode: Solid Colors"
end if
text 10, 365, "Speed: " + str$(speed) + " | X-Vel: " + str$(vel_x)
text 10, 350, "Keys: SPACE (mode), +/- (spin), Arrows (push/zoom), ESC"
pause 0.02
// 4. Обработка клавиш
k$ = inkey$(0.001)
if k$ = "esc" or k$ = chr$(27) then
break
elseif k$ = " " or k$ = "space" then
mode = 3 - mode
elseif k$ = "+" or k$ = "=" then
speed = speed + 0.2
elseif k$ = "-" then
speed = speed - 0.2
elseif k$ = "left" then
// Толкаем влево
vel_x = vel_x - 2.0
elseif k$ = "right" then
// Толкаем вправо
vel_x = vel_x + 2.0
elseif k$ = "up" then
// Приближаем
zoom_scale = zoom_scale + 500
elseif k$ = "down" then
// Отдаляем
zoom_scale = zoom_scale - 500
end if
// Ограничители, чтобы не улетел в космос
if speed < 0.2 speed = 0.2
if speed > 5.0 speed = 5.0
if vel_x > 12.0 vel_x = 12.0
if vel_x < -12.0 vel_x = -12.0
if zoom_scale < 500 zoom_scale = 500
if zoom_scale > 8000 zoom_scale = 8000
loop
close window
end