I64 sc_1, sc_2; #define DROPS_NUM 0x2000 class Drop { I32 x, y; } drops[DROPS_NUM]; CDC *cur_dc; U0 DrawFrame(CTask *task, CDC *dc) { I64 w = task->pix_width, h = task->pix_height, cx = w >> 1, cy = h >> 1; dc->color = LTRED; GrLine(dc, cx - 20, cy - 50, cx, cy - 150); GrLine(dc, cx + 20, cy - 50, cx, cy - 150); dc->color = LTRED; GrLine(dc, cx - 100, cy - 100, cx, cy); GrLine(dc, cx + 100, cy - 100, cx, cy); if (Bt(kbd.down_bitmap, sc_1)) { dc->color = WHITE; GrRect(dc, cx - 2, cy - 2, 5, 5); } dc->color = BLACK; GrPrint(dc, cx + 10, cy, "Press '1'"); dc->color = LTRED; GrRect(dc, cx - 20, cy + 60, 41, 21); dc->color = LTRED; GrLine(dc, cx - 200, cy, cx, cy + 100); GrLine(dc, cx + 200, cy, cx, cy + 100); if (Bt(kbd.down_bitmap, sc_2)) { dc->color = WHITE; GrRect(dc, cx - 2, cy + 100 - 2, 5, 5); } dc->color = BLACK; GrPrint(dc, cx + 10, cy + 100, "Press '2'"); dc->color = LTRED; GrLine(dc, cx + 400, cy + 100, cx - 250, cy + 200); } U0 DrawDrops(CTask *, CDC *dc) { I64 i; dc->color = BLUE; for (i = 0; i < DROPS_NUM; i++) if (drops[i].y >= 0 && GrPeek(dc, drops[i].x, drops[i].y) == WHITE) GrPlot(dc, drops[i].x, drops[i].y); } U0 UpdateCurBase(CTask *task, CDC *dc) { cur_dc->color = ROP_EQU; dc->flags |= DCF_NO_TRANSPARENTS; GrBlot(cur_dc, -task->pix_left - task->scroll_x, -task->pix_top - task->scroll_y, dc); dc->flags &= ~DCF_NO_TRANSPARENTS; } U0 DrawIt(CTask *task, CDC *dc) { DrawFrame(task, dc); DrawDrops(task, dc); UpdateCurBase(task, dc); } U0 AnimateTask(I64) { I64 i, j, cur_drop = 0, c1, c2, x0, y0, x1, y1, w, h; while (TRUE) { w = Fs->parent_task->pix_width; h = Fs->parent_task->pix_height; for (i = 0; i < 2; i++) { j = 0; do { if (++cur_drop >= DROPS_NUM) cur_drop = 0; if (drops[cur_drop].y < 0) break; j++; } while (j <= DROPS_NUM); drops[cur_drop].x = RandU32%w; drops[cur_drop].y = 0; } for (i = 0; i < DROPS_NUM; i++) { if (drops[i].y >= 0) { if (drops[i].y >= h - 1) drops[i].y = -I32_MAX; else { x0 = x1 = drops[i].x; y0 = y1 = drops[i].y; if (GrPeek(cur_dc, x0, y0 + 1) == WHITE) y1++; else { c1 = GrPeek(cur_dc, x0 + 1, y0); c2 = GrPeek(cur_dc, x0 - 1, y0); if (c1 == WHITE && c2 != WHITE) x1++; else if (c2 == WHITE && c1 != WHITE) x1--; else if (c1 == WHITE && c2 == WHITE) { c1 = GrPeek(cur_dc, x0 + 1, y0 + 1); c2 = GrPeek(cur_dc, x0 - 1, y0 + 1); if (c1 == WHITE && c2 != WHITE) x1++; else if (c2 == WHITE && c1 != WHITE) x1--; else if (RandI16 >= 0) x1++; else x1--; } if (GrPeek(cur_dc, x1, y1 + 1) == WHITE) y1++; } if (GrPeek(cur_dc, x0, y0) == BLUE) { cur_dc->color = WHITE; GrPlot(cur_dc, x0, y0); } cur_dc->color = BLUE; GrPlot(cur_dc, x1, y1); drops[i].x = x1; drops[i].y = y1; } } } Sleep(10); } } U0 Init() { I64 i; MemSet(drops, 0, sizeof(drops)); for (i = 0; i < DROPS_NUM;i ++) drops[i].y = -I32_MAX; } U0 RainDrops() { I64 ch, sc; MenuPush( "File {" " Abort(,CH_SHIFT_ESC);" " Exit(,CH_ESC);" "}" "Play {" " Restart(,'\n');" " OpenUpper(,'1');" " OpenLower(,'2');" "}" ); SettingsPush; //See SettingsPush AutoComplete; WinBorder; WinMax; DocCursor; DocClear; cur_dc = DCNew(GR_WIDTH, GR_HEIGHT); sc_1 = Char2ScanCode('1'); sc_2 = Char2ScanCode('2'); Init; Fs->animate_task = Spawn(&AnimateTask, NULL, "Animate",, Fs); Fs->draw_it = &DrawIt; try { do switch (ch = KeyGet(&sc)) { case '\n': Init; break; } while (ch != CH_ESC && ch != CH_SHIFT_ESC); } catch PutExcept; SettingsPop; MenuPop; DCDel(cur_dc); } RainDrops;