строим двухмерное счастье ПАЛАГИН АНТОН Спецвыпуск: Хакер, номер #064, стр. 064-076-3 Листинг «Начало игры» //Удаляем ненужные ресурсы заставки mResourceManager->DeleteResources(«TitleScreen»); //Инициализируем игровое поле m_board.reset( new Board(this) ); mWidth = IMAGE_LEFT_PANEL->GetWidth() + 320 + BORDER_SIZE; m_board->Resize(0, 0, mWidth, mHeight); mWidgetManager->AddWidget( m_board.get() ); SetFocusToBoard(); события игры Игра управляется событиями, которые генерируются пользователем с помощью мыши (выбор кнопок в главном меню) и клавиатуры. Все игровое поле делится на две части: главное меню и «стакан», куда падают фигуры. Обе части игрового поля, как и само игровое поле, являются виджетами, то есть элементами интерфейса. Левая часть (меню) — тоже виджет, но, кроме того, она может принимать команды от нажатий кнопок главного меню. Все элементы интерфейса инициализируются в виртуальном методе AddedToManager, удаляются в методе RemovedFromManager. Листинг «Инициализация виджетов» void LeftPanel::AddedToManager(WidgetManager* theWidgetManager) { Widget::AddedToManager(theWidgetManager); //Рассчитываем размеры кнопок int width = IMAGE_BUTTON_AQUA->GetWidth(); int height = mHeight — IMAGE_BUTTON_AQUA->GetHeight(); //Создаем кнопку m_newGame = CreateButton(BUTTON_NEW_GAME, «New Game», mWidth/2 — width/2, height); //Добавляем кнопку к менеджеру виджетов theWidgetManager->AddWidget( m_newGame.get() ); } Если пользователь нажимает мышкой на кнопку-виджет, то генерируется соответствующее событие, которое обрабатывается методом ButtonDepress. Листинг «Обработка событий виджетов» void LeftPanel::ButtonDepress(int theId) { switch(theId) { case BUTTON_NEW_GAME: m_app->OnNewGame(); break; case BUTTON_PAUSE: m_app->OnPauseGame(); break; } } Эти события являются глобальными событиями игры. Например, начинается новая игра, игровой процесс ставится на паузу и т.д. Управление движением фигур в стакане осуществляется при помощи клавиатуры. Эти события обрабатываются в виртуальном методе KeyDown (листинг «Обработка кнопок клавиатуры») и являются локальными событиями, которые влияют на логику игры: фигура крутится и перемещается влево-вправо. Листинг «Обработка кнопок клавиатуры» void Board::KeyDown(KeyCode theKey) { Widget::KeyDown(theKey); switch(theKey) { case KEYCODE_SPACE: m_app->m_gameDriver.Rotate(); break; case KEYCODE_LEFT: m_app->m_gameDriver.Left(); break; case KEYCODE_RIGHT: m_app->m_gameDriver.Right(); break; case KEYCODE_DOWN: m_app->m_gameDriver.Drop(); break; } } игровой цикл С того момента, когда пользователь нажимает кнопку New Game, начинается непрерывный игровой цикл, на каждой итерации которого падает текущая фигура, на «заполненность» проверяются линии в стакане и условия окончания игры, прорисовываются фигуры всех фигур в стакане. Эти итерации происходят в методе Update() класса GameDriver. Листинг «Игровая итерация» //Если игра закончена или еще не начата, то итерация не выполняется |