{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "3d0f87bf",
   "metadata": {},
   "source": [
    "# 19-13 · Настоящий игровой цикл\n",
    "\n",
    "Практика к разделу [«Настоящий игровой цикл»](../../site/chapters/glava-19/19-13-nastoyaschij-cikl.html)."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "65dcf1fa",
   "metadata": {},
   "source": [
    "## Цель\n",
    "\n",
    "Запустить цепочку тиков через screen.ontimer() вместо busy-цикла."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d9ab5875",
   "metadata": {},
   "source": [
    "## Настройка (выполнить один раз)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "d393283b",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-03T00:53:47.068007Z",
     "iopub.status.busy": "2026-09-03T00:53:47.067823Z",
     "iopub.status.idle": "2026-09-03T00:53:47.232943Z",
     "shell.execute_reply": "2026-09-03T00:53:47.232385Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Экран готов.\n"
     ]
    }
   ],
   "source": [
    "import turtle\n",
    "\n",
    "RAZMER_SHAGA = 20\n",
    "GRANICA = 280\n",
    "\n",
    "screen = turtle.Screen()\n",
    "screen.title(\"Змейка\")\n",
    "screen.bgcolor(\"black\")\n",
    "screen.setup(width=600, height=600)\n",
    "screen.tracer(0)\n",
    "print(\"Экран готов.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "208edc3c",
   "metadata": {},
   "source": [
    "## Рабочий пример"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "e7c1e860",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-03T00:53:47.235223Z",
     "iopub.status.busy": "2026-09-03T00:53:47.234998Z",
     "iopub.status.idle": "2026-09-03T00:53:47.243233Z",
     "shell.execute_reply": "2026-09-03T00:53:47.241927Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Первый тик выполнен, остальные два запланированы через ontimer().\n"
     ]
    }
   ],
   "source": [
    "golova = turtle.Turtle()\n",
    "golova.speed(0)\n",
    "golova.shape(\"square\")\n",
    "golova.penup()\n",
    "golova.goto(0, 0)\n",
    "\n",
    "tiki = []\n",
    "\n",
    "def game_tick():\n",
    "    golova.setx(golova.xcor() + RAZMER_SHAGA)\n",
    "    tiki.append(golova.xcor())\n",
    "    screen.update()\n",
    "    if len(tiki) < 3:\n",
    "        screen.ontimer(game_tick, 200)\n",
    "\n",
    "game_tick()\n",
    "screen.update()\n",
    "print(\"Первый тик выполнен, остальные два запланированы через ontimer().\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ab702ad3",
   "metadata": {},
   "source": [
    "## Эксперимент 1 — дожидаемся запланированных тиков\n",
    "\n",
    "`ontimer()` только *планирует* вызовы. Чтобы они сработали, циклу событий нужно дать поработать — этим и занимается `screen.update()` в цикле ожидания ниже."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "2afc75ea",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-03T00:53:47.245848Z",
     "iopub.status.busy": "2026-09-03T00:53:47.245000Z",
     "iopub.status.idle": "2026-09-03T00:53:47.675463Z",
     "shell.execute_reply": "2026-09-03T00:53:47.674186Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tiki после ожидания: [20, 40, 60]\n",
      "Все три тика сработали — цепочка ontimer() довела себя до конца.\n"
     ]
    }
   ],
   "source": [
    "import time\n",
    "\n",
    "# Прокручиваем цикл событий Tkinter, пока не сработают оба\n",
    "# запланированных тика: screen.update() разбирает подошедшие таймеры.\n",
    "konec = time.monotonic() + 2.0\n",
    "while len(tiki) < 3 and time.monotonic() < konec:\n",
    "    screen.update()\n",
    "    time.sleep(0.01)\n",
    "\n",
    "print(\"tiki после ожидания:\", tiki)\n",
    "assert tiki == [20, 40, 60], tiki\n",
    "print(\"Все три тика сработали — цепочка ontimer() довела себя до конца.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7a1cc5a5",
   "metadata": {},
   "source": [
    "## Завершение (выполнить один раз, в самом конце)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "b5666f95",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-03T00:53:47.677403Z",
     "iopub.status.busy": "2026-09-03T00:53:47.677192Z",
     "iopub.status.idle": "2026-09-03T00:53:47.681731Z",
     "shell.execute_reply": "2026-09-03T00:53:47.680862Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Окно закрыто.\n"
     ]
    }
   ],
   "source": [
    "screen.bye()\n",
    "print(\"Окно закрыто.\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Cartesian Python 3.14",
   "language": "python",
   "name": "cartesian-python314"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.14.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
