{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "977d523f",
   "metadata": {},
   "source": [
    "# 20-04 · Движение и клавиши\n",
    "\n",
    "Практика к разделу [«Управляем объектом с клавиатуры»](../../site/chapters/glava-20/20-04-peremeshenie-klavishi.html)."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8eb84cb9",
   "metadata": {},
   "source": [
    "## Цель\n",
    "\n",
    "Двигать персонажа изменением координат и обработать событие клавиши."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4b3cdbdd",
   "metadata": {},
   "source": [
    "## Про игровой цикл в этом ноутбуке\n",
    "\n",
    "В обычном `.py`-файле игровой цикл — это `while rabotaet:`, где `rabotaet` становится `False`, когда пользователь закрывает окно. В автоматически выполняемом ноутбуке некому закрыть окно, поэтому здесь мы прогоняем фиксированное число кадров через `for _ in range(N):` — логика каждого отдельного кадра (движение, отрисовка, `clock.tick()`) при этом точно такая же, как в настоящей игре."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "93c88a7a",
   "metadata": {},
   "source": [
    "## Рабочий пример — движение"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "0142b168",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-03T10:11:58.335663Z",
     "iopub.status.busy": "2026-09-03T10:11:58.335507Z",
     "iopub.status.idle": "2026-09-03T10:11:58.673435Z",
     "shell.execute_reply": "2026-09-03T10:11:58.672831Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "pygame-ce 2.5.8 (SDL 2.32.10, Python 3.14.6)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Позиция игрока после 10 кадров: 100\n"
     ]
    }
   ],
   "source": [
    "import pygame\n",
    "\n",
    "pygame.init()\n",
    "screen = pygame.display.set_mode((600, 400))\n",
    "clock = pygame.time.Clock()\n",
    "\n",
    "x_igroka = 50\n",
    "skorost_x = 5\n",
    "\n",
    "for kadr in range(10):\n",
    "    x_igroka += skorost_x\n",
    "    screen.fill((0, 0, 0))\n",
    "    pygame.draw.rect(screen, (100, 200, 255), (x_igroka, 180, 40, 40))\n",
    "    pygame.display.flip()\n",
    "    clock.tick(60)\n",
    "\n",
    "print(\"Позиция игрока после 10 кадров:\", x_igroka)\n",
    "pygame.quit()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "63914d3d",
   "metadata": {},
   "source": [
    "## Проверка результата"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "b4905081",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-03T10:11:58.676955Z",
     "iopub.status.busy": "2026-09-03T10:11:58.676787Z",
     "iopub.status.idle": "2026-09-03T10:11:58.680430Z",
     "shell.execute_reply": "2026-09-03T10:11:58.679516Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Верно: игрок сдвинулся на 50 пикселей за 10 кадров.\n"
     ]
    }
   ],
   "source": [
    "assert x_igroka == 50 + 5 * 10\n",
    "print(\"Верно: игрок сдвинулся на\", 5 * 10, \"пикселей за 10 кадров.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bc2548f0",
   "metadata": {},
   "source": [
    "## Эксперимент 1 — событие KEYDOWN"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "2480f65f",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-03T10:11:58.681999Z",
     "iopub.status.busy": "2026-09-03T10:11:58.681828Z",
     "iopub.status.idle": "2026-09-03T10:11:58.815794Z",
     "shell.execute_reply": "2026-09-03T10:11:58.815356Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Прыжок! (клавиша SPACE обработана)\n"
     ]
    }
   ],
   "source": [
    "import pygame\n",
    "\n",
    "pygame.init()\n",
    "screen = pygame.display.set_mode((600, 400))\n",
    "\n",
    "# программно создаём событие нажатия клавиши, как это сделала бы клавиатура\n",
    "sobytie = pygame.event.Event(pygame.KEYDOWN, key=pygame.K_SPACE)\n",
    "pygame.event.post(sobytie)\n",
    "\n",
    "for event in pygame.event.get():\n",
    "    if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:\n",
    "        print(\"Прыжок! (клавиша SPACE обработана)\")\n",
    "\n",
    "pygame.quit()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0ca28da1",
   "metadata": {},
   "source": [
    "## Эксперимент 2 — get_pressed() для непрерывного движения"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "b9ac995a",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-03T10:11:58.818990Z",
     "iopub.status.busy": "2026-09-03T10:11:58.818767Z",
     "iopub.status.idle": "2026-09-03T10:11:58.962242Z",
     "shell.execute_reply": "2026-09-03T10:11:58.961454Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Тип результата get_pressed(): <class 'pygame.key.ScancodeWrapper'>\n",
      "Стрелка влево зажата: False\n"
     ]
    }
   ],
   "source": [
    "import pygame\n",
    "\n",
    "pygame.init()\n",
    "screen = pygame.display.set_mode((600, 400))\n",
    "\n",
    "klavishi = pygame.key.get_pressed()\n",
    "# в реальном приложении это будет True, если клавиша действительно зажата;\n",
    "# здесь просто проверяем, что функция возвращает объект, с которым можно так работать\n",
    "print(\"Тип результата get_pressed():\", type(klavishi))\n",
    "print(\"Стрелка влево зажата:\", klavishi[pygame.K_LEFT])\n",
    "pygame.quit()"
   ]
  }
 ],
 "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
}
