§ Демонстрация и код


1#include <qblib.c>
2
3// Статичное небо
4void starfeld() {
5
6    cls();
7    srand(1);
8    for (int i = 0; i < 255; i++) pset(rand()%320, rand()%200, rand()%256);
9    circlef(240, 100, 16, 240);
10}
11
12int main(int argc, char* argv[]) {
13
14    screen(13);
15
16    float x0 = 0, y0 = 0, r = 1;
17    float al = 0, rx = 0, ry = 0, rz = 0;
18
19    int cl;
20    for (int i = 0; i < 256; i++) palette(i, i, i, i);
21
22    while (sdlevent(EVT_REDRAW)) {
23
24        starfeld();
25
26        // Движение вперед, шаги
27        al += 0.01;
28        y0 = -0.92 + abs(sin(10*al) * 0.02);
29        rz = sin(10*al) * 0.01;
30
31        float tx, ty, tz;
32        for (int y = -99; y <= 100; y++)
33        for (int x = -160; x < 160; x++) {
34
35            float   dx = (float)x / 200,
36                    dy = (float)y / 200,
37                    dz = 1;
38
39            // Поворот Y
40            tx = dx*cos(ry) - dz*sin(ry);
41            tz = dz*cos(ry) + dx*sin(ry);
42            dx = tx; dz = tz;
43
44            // Поворот X
45            tz = dz*cos(rx) - dy*sin(rx);
46            ty = dy*cos(rx) + dz*sin(rx);
47            dz = tz; dy = ty;
48
49            // Поворот Z
50            tx = dx*cos(rz) - dy*sin(rz);
51            ty = dy*cos(rz) + dx*sin(rz);
52            dx = tx; dy = ty;
53
54            // Точка пересечения с цилиндром
55            float a =  dx*dx + dy*dy;
56            float b = (dx*x0 + dy*y0)*2;
57            float c = x0*x0 + y0*y0 - r*r;
58            float d = b*b - 4*a*c;
59
60            if (d >= 0) {
61
62                d = sqrt(d);
63
64                // Корни уравнения
65                float t1 = (-b + d) / (2*a);
66                float t2 = (-b - d) / (2*a);
67                float t;
68
69                // Зависит от того, находимся ли внутри цилиндра
70                if (c > 0)
71                     t  = (t1 < t2) ? t1 : t2;
72                else t  = (t2 < t1) ? t1 : t2;
73
74                // Ближайший перед камерой
75                if (t1 < 0 && t2 > 0)
76                    t = t2;
77
78                // Нет точки пересечения, пропуск
79                if (t1 < 0 && t2 < 0) {
80                    cl = 0;
81                }
82                else {
83
84                    // Расчет координат пересечения
85                    float _x = x0 + dx*t,
86                          _y = y0 + dy*t,
87                          _z =      dz*t;
88                    float _a = atan2(_y, _x);
89
90                    // Коррекция текстуры
91                    if (_a < 0) _a = -_a;
92                    if (_z < 0) _z = -_z;
93
94                    // Расчет текстуры
95                    float tex =  (((int)(_a*r*256) ^ (int)(r*128*(_z + al)))%256);
96
97                    // Непрозрачность или прозрачные области
98                    if (tex < 64 && (_x < -0.2 || _x > 0.2)) continue;
99
100                    // Уровень освещенности
101                    float lt = 2/_z;
102                          lt = lt > 1 ? 1 : lt;
103
104                    cl = tex*lt;
105                    if (cl > 255) cl = 255;
106                }
107
108
109            } else {
110                cl = 2;
111            }
112
113            pset(x + 160, 100 - y, cl);
114        }
115    }
116
117    return 0;
118}