Разработка игрового Windows-приложения

Курсовая работа

Целью данной курсовой работы является создание игрового приложения в соответствии с постановкой задачи по теме «Разработка игрового Windows-приложения» по дисциплине «Разработка Windows-приложений». Данная программа осуществляет вывод на экран случайным образом падение различных фигур и главного персонажа. Входными данными является управление падающими фигурами и персонажем.

Назначение программы — развлечение играющих, совершенствование их координации и логического мышления. Программа может применяться в качестве игровой на IBM-PC совместимых ЭВМ.

Идея игрового процесса была навеяна двумя компьютерными играми — Тетрис и Небулус.

При разработке игрового приложения был использован объектно-ориентированный язык программирования Visual C#. Математическая часть программы была создана с помощью двумерной матрицы, объекта падающей фигуры и объекта персонажа. Графическое отображение было реализовано с помощью стандартных графических возможностей ОС Windows.

игровой приложение программный

В разделе «Введение» данной курсовой работы была приведена краткая история игры «Тетрис». Как видно этой компьютерной игре более 25 лет (рисунок 1.1.1).

Кроме этого было приведено краткое описание игры «Небулус» (рисунок 1.1.2).

Рисунок 1.1.1 -Первая версия игры тетрис 1984 год ЭВМ Электроника-60

Рисунок 1.1.2 -Игра «Nebulus»на Commodore-64

История игры Тетрис начинается в июне 1985 года. Тетрис был изобретен Алексеем Пажитновым, а затем был интегрирован на IBM-PC ЭВМ Вадимом Герасимовым. После чего игра Тетрис начала распространяться по всей Москве, а затем уже и по всему миру. Сначала она была доставлена в Венгрию, где венгерские программисты интегрировали Тетрис для Apple II и Commodore 64.

Игра была замечена в мире, и несколько представителей крупных компаний, обращались к автору Тетриса, чтобы купить права на распространение игры. Алексей подписывает контракт с Mirrorsoft UK и Spectrum Holobyte, предоставляя им права на компьютерным версии Тетрис. После того, как первые копии Тетриса для домашних компьютеров были преданны, игра приобрела популярность среди населения и стала самой продаваемой компьютерной игрой в Англии и США в 1988 году.

«Nebulus» — это игра-платформер, с некоторыми уникальными особенностями. Герой игры, небольшое зелёное создание по имени Пого (Pogo), должен уничтожить восемь башен, построенных в море. Сама игра происходит на одной из башен за раз. Пого начинает у основания башни, ему требуется найти путь наверх. Башня сложена из кирпича и имеет цилиндрическую форму, по внешней стороне башни проходят лестницы и платформы, связанные лифтами, иногда встречаются горизонтальные туннели, ведущие сквозь башню на другую её сторону.

13 стр., 6428 слов

По физике «Игра и игровые технологии обучения. Организационно-деятельностные ...

... обучения, индивидуализация и дифференциация обучения, наглядность, доступность подачи информации в игре полностью реализуется. Игровая технология выгодно отличается от других методов обучения тем, что позволяет ученику ... данной технологии во внеурочное время. Конечно, игра не должна являться самоцелью, не должна проводиться только ради развлечения детей. Она обязательно должна быть дидактической, т. ...

Наиболее заметная особенность игры — в том что персонаж, стоя на месте или двигаясь, всегда остаётся в центре экрана, вместо этого башня и фон поворачивается либо двигается вверх и вниз.

Взяв за основу эти две игры, было решено разработать смешанный геймплей и его программную реализацию под названием «Лестница в небо» со следующими правилами игры:

Игровое поле состоит из 20 клеток по ширине и 60 по высоте, что напоминает прямоугольный стакан в игре «Тетрис». На дне этого поля находиться главный герой игры, которого необходимо привести на верх виртуального стакана. Для этого игроку необходимо выстроить лестницу из 6 видов фигур тримино, которые падают сверху. Игрок может двигать фигуры по горизонтали и вращать их. Кроме того, игроку необходимо управлять персонажем, который способен передвигаться по горизонтали и преодолевать препятствия в одну клетку по вертикали. Дополнительную сложность придает «время жизни» клеток, на которых стоит персонаж, тем самым разрушая их. Если игрок опоздал убрать персонажа с клетки, то она рушиться, а персонаж проваливается и падает, пока не встретиться с ближайшей снизу фигурой. После заполнения половины поля фигурами, камера перемещается на три клетки вверх. Поражение наступает в случае исчезновения персонажа из поля зрения игрока, поэтому игроку необходимо постоянно следить и управлять персонажем так, чтобы этого не произошло. В связи с этим добавляется еще одно условие проигрыша: невозможность перемещения персонажа в связи с блокированием его движений фигурами. Игра имеет три уровня сложности: «Легко», «Норма» и «Сложно». Они влияют на скорость обрушения фигур под персонажем.

Существует множество способов реализации данной программы. Их можно разделить по функциональности:

  • математическое описание движений фигур;
  • графическое отображение движений фигур;

— В математической части рассматриваются основные принципы и законы движений фигур. Это самая важная часть программы. От неё зависит правильная работоспособность программы. Для её реализации можно использовать различные алгоритмы. Например описать движение фигуры двумя линейными функциями. Одна будет отвечать за расположение фигуры по горизонтали, другая по вертикали. Меняя за определенные промежутки времени значения переменных этих функций, будет меняться положение фигуры на плоскости. Третья функция будет отвечать за очистку полностью заполненных горизонталей. И четвертая за движение персонажа. Основными недостатками этого способа является объявление большого числа переменных, отвечающих за описание уже упавших фигур, и создание большого числа дополнительных функций, отвечающих за поворот фигур вокруг своей оси.

Другой способ математического описания заполнения игрового поля — создание двумерной матрицы n*k. А для управления персонажем и падением фигур использовать соответствующие функции.Для падающих фигур необходимо три переменных: положение по горизонтали, положение по горизонтали и угол поворота вокруг своей оси. А для персонажа две — только положение на плоскости. В момент столкновения фигуры с построенной платформой, она добавляется в массив, что делает ее статичной, а объект, отвечающий за падение фигур, перенастраивается и процесс повторяется.

19 стр., 9492 слов

«Компьютерные игры в образовательно-воспитательном процессе»

... компьютерных технологий наложило определенный отпечаток на развитие личности современного ребенка. Применение компьютеров оказывает большое влияние на воспитание ребенка и его восприятие окружающего мира. Появление компьютерных игр ... направления, задачи и содержание воспитательно-образовательной работы с детьми могут быть обеспечены развивающими компьютерными играми. В настоящее время разработаны и ...

Кроме этих способов, есть еще ряд других, но данные здесь являются наиболее удобными и производительными. Для данной игры был выбран второй способ математического описания.

Для графического отображения также существует множество способов. Например, двигать на плоскости рисунки целых фигур. Сложность метода проявляется во время поворота. Тут необходимо использовать либо алгебраические вычисления, либо хранить каждую фигуру несколькими экземплярами разных ротаций. Следствием этого является неэкономное использование ресурсов ЭВМ. Дополнительные проблемы появляются, когда необходимо уничтожать заполненные линии или отдельные блоки.

Другой способ подразумевает хранение по одному блоку из каждой фигуры (необходимо для отображения фигур разных цветов) и отображать их по отдельности в соответствии с заполнением массива и падающей фигуры. Этот способ упрощает поворот фигур, сгорание линий и отдельных блоков. Именно этот способ был использован в данной программе. Отличием является только визуализация — выводятся не рисунки блоков, а примитивы, доступные в графической оболочке Windows.

При разработке программы игры «Лестница в небо» для описания математической части алгоритма был использован двумерный массив, размерностью 20*60. Для создания графической части программы использовались графические возможности языка C#.

Массив — это индексированный набор объектов одного типа. В языке С# массивы несколько отличаются от массивов в C++ и других языках, поскольку они являются объектами, что наделяет их полезными методами и свойствами. В С# определен синтаксис объявления объектов типа Array. Однако фактически создается объект типа System.Array. Таким образом, С# предоставляет программисту идеальные условия: за простым синтаксисом в стиле С кроется объявление класса, дающее экземплярам массива доступ к методам и свойствам класса System. Array.

В создании алгоритма использовался массив как математический аналог поля игры «Тетрис». Каждая ячейка массива соответствует определенной области поля игры. Каждая область поля игры может быть заполнена фигурой или быть пустой. Соответственно, каждая область поля может принимать семь значений: нуль — пустота, все остальные — номера цветов блоков. Для этих целей можно использовать целочисленные переменные. Каждая фигура имеет определенную форму и занимает несколько областей поля игры. Следовательно в массиве, ячейки, соответствующие заполненным областям поля, будут иметь номер цвета этой фигуры. Для ячеек соответствующих пустым областям будет присвоено значение нуль. Каждая горизонталь поля тетриса соответствует строке двумерного массива, а вертикаль — столбцу. Движение фигур производится через равные промежутки времени, т. е происходит повторение алгоритма через равные промежутки времени. Равные промежутки времени можно обеспечить с помощью обсчета ресурсоёмкого алгоритма (например вычисление ряда Фибоначчи) или использовать элемент языка С# таймер (который был использован в данной программе).

7 стр., 3168 слов

Разработка компьютерной игры ‘Лабиринт’

... разработки компьютерной игры «Лабиринт», по заданной теме курсовой работы, была выбрана наиболее оптимальная среда реализации BorlandC++ Builder 6.0.Это система объектно-ориентированного программирования ... приложения расширенным стандартом языка ... массив чисел, который в будущем будет представлять собой лабиринт. Далее разработан алгоритм определения местоположения персонажа в массиве, вывода лабиринта ...

Каждый тик таймера будет происходить повторение алгоритма движения фигуры. Это представлено как последовательное изменение значений в классе падающей фигуры и, если необходимо, ячейках массива.

Чтобы игра была работоспособной, необходимо каждой ячейки массива каждый тик таймера присваивать значения, соответствующие областям поля. Т.к. количество ячеек велико (их 1200), удобно было использовать циклические конструкции. Это позволило сократить программный код и количество ошибок в нем. Для этих целей был использован оператор for(Листинг 7).

Цель игры — добраться персонажем до определенной высоты на игровом поле, кроме того выход персонажа за пределы экрана, является поражением. Для слежения за координатами персонажа был использован оператор if (Листинг 7).

Математическая часть алгоритма строится на минимальном числе элементов: двумерный массив, таймер, логическая переменная, циклическая конструкция и условная конструкция (Листинг 7).

Синтаксис записи этих элементов в языке C# прост, что делает алгоритм достаточно простым.

GDI+ — интерфейс графических устройств. Приложения с графикой, игры, Computer Aided Design/Computer Aided Manufacture (CAD/CAM — проектирование/производство с помощью компьютера), программы для рисования, для создания графиков и многие другие типы приложений требуют от разработчиков написания кода для работы с графикой. Использование создаваемых пользователем управляющих элементов также предполагает работу с графикой. Посредством своей библиотеки классов компания Microsoft сделала написание кода для работы с графикой как никогда простым.

Возможности GDI +:

Работу с отдельными частями рисунков

Рисование изображения

Вывод на печать

Предварительный просмотр

Пространство имен Drawing2D

Пространство имен Imaging

В классе Graphics инкапсулированы поверхности рисования GDI+. Есть три основных типа поверхностей рисования:

Окна и управляющие элементы на экране

Страницы, посылаемые на принтер

Растровые изображения в памяти

Игра «Лестница в небо» требует изображение областей поля в виде в квадратов. Для этого была использована структура языка C# Rectangle (прямоугольник).

Для ее описания необходимы координаты верхнего левого угла прямоугольника (что соответствует значениям вертикали и горизонтали поля игры), а также его размеры.

Для заполнения определенной области рисунка цветом возможно использование класса Brush. Класс Brush — это абстрактный класс. Для создания экземпляра класса Brush исользуются классы, производные от класса Brush, такие как SolidBrush. Класс Brush находится в пространстве имен System. Drawing. Класс SolidBrush несет в себе информацию о закрашивании фигуры сплошным цветом.

Для вывода фонового изображения и рисунка персонажа использовался класс Image и метод класса GraphicsDrawImage.

Алгоритм построения изображений имеет некоторые особенности. В первую очередь стоит заметить, что изображение выводиться на экран не сразу, а только после того как будет сформировано в так называемом заднем буфере. Данная техника не является новинкой в компьютерной графике и используется довольно давно для вывода динамических изображений. Суть алгоритма состоит в том, что создается два буфера: «передний» который непосредственно связан с экраном и «задний» на котором формируется каждый новый кадр. По завершении построения кадра, буферы меняются местами — задний становиться передним и автоматически выводится на экран, передний становиться задним и используется для построения нового кадра. Этот процесс продолжается бесконечно. Его использование необходимо, потому что при постоянной перерисовке всех изображений непосредственно на экран, изображения перекрывающие друг друга создают эффект мерцания. Алгоритм двойной буферизации исключает этот эффект.

29 стр., 14268 слов

Использование обучающих компьютерных игр в учебном процессе общеобразовательной ...

... компьютерная программа, освоение клавиатуры и т.д. Создано также немало компьютерных игр, которые успешно применяются для формирования навыков чтения, письма и счета. Исходя из вышесказанного, можно утверждать, что внедрение обучающих игр в образовательный процесс ...

Принцип построения изображения поля игры прост. На задний буфер выводится фоновое изображение поля, выполняющее также задачу очистки экрана. Далее с помощью циклической конструкции происходит чтение из видимой на экране части массива. Каждая ячейка хранит номер цвета блоков. Пустая ячейка содержит значение нуль. Если проверяемая ячейка хранит значение отличное от нуля, на экран выводится блок соответствующего цвета. Координаты ячейки массива умножаются на ширину и высоту блока, и записываются в структуру Rectangle для последующего вывода на экран. По такому же алгоритму выводится и падающая фигура. Различие состоит в том, что к отступам слева и сверху прибавляются координаты фигуры на поле, изменением которых управляет игрок. После этого выводится изображение персонажа. Все объекты имеют координаты в пределах массива 20×60. При переводе координат на экранные перемещение фигур и персонажа становятся резкими, поэтому было решено ввести дополнительные — экранные координаты, которые меняются каждый тик таймера, в то время, как координаты на поле меняются каждый десятый тик.

При разработки программы предполагалось использование среды Microsoft Visual C# 2012. Эта среда разработки программного обеспечения содержит набор шаблонов, которые часто используют при разработки программ. В программе я использовал только шаблон формы — Form и шаблон системного таймера Timer. Это облегчило задачу в написании программы, так как часть кода была сгенерирована автоматически.

Приведенные выше принципы и элементы стали основой алгоритма.

Для реализации данного курсовой работы был выбран язык программирования Visual C#. Язык основан на строгой компонентной архитектуре и реализует передовые механизмы обеспечения безопасности кода. Язык программирования C# объединил лучшие черты целого ряда предшественников, а именно ветви языков B — C — C++.

От языка программирования C++ языком C# унаследованы следующие механизмы: «перегруженные» операторы, небезопасные арифметические операции с плавающей точкой, а также ряд других особенностей синтаксиса.

Несмотря на весьма существенные различия между компонентной объектной моделью COM (основного стандарта Microsoft для компонентного проектирования и реализации программного обеспечения) и моделью Java Beans, базовым стандартом Sun Microsystems для компонент (зависимой от языка реализации), язык программирования C# имеет довольно много общего с языком Java.

Перечислим наиболее характерные черты сходства языков программирования C# и Java. Прежде всего, оба языка относятся к категории объектно-ориентированных и предполагают единственность наследования. Другими важными особенностями, которые сближают языки программирования C# и Java, являются механизмы интерфейсов, обработки исключительных ситуаций, а также процессов или «нитей» (threads).

5 стр., 2212 слов

Разработка программы ‘Текстовый редактор’

... курсовой работы была разработана программа для создания и редактирования текстовых документов. В процессе проектирования использовались методологии модульного и объектно-ориентированного программирования. Для разработки данной программы ... средство можно разбить на подсистемы, взаимодействующие друг с другом в соответствии с рисунком 2. Рисунок 2 - Структура программы Подсистема управления текстом ...

«Сборка мусора» и пространства имен реализованы в этих двух языках сходным образом. Оба языка программирования характеризуются сильной (строгой) типизацией и динамической загрузкой кода при выполнении программы.

Но несмотря на то, что целый ряд конструктивных синтаксических механизмов и особенностей реализации унаследован языком программирования C# от прародителей (C++ и Java), возможности этого нового языка программирования не ограничиваются суммой возможностей его исторических предшественников.

К числу принципиально важных решений, которые реализованы корпорацией Microsoft в языке программирования C#, можно отнести следующие:

  • компонентно-ориентированный подход к программированию (который характерен и для идеологии Microsoft.net в целом);
  • свойства как средство инкапсуляции данных (характерно также в целом для ООП);
  • обработка событий (имеются расширения, в том числе в части обработки исключений, в частности, оператор try);
  • унифицированная система типизации (соответствует идеологии Microsoft.net в целом);
  • делегаты (delegate — развитие указателя на функцию в языках C и C++);
  • индексаторы (indexer — операторы индекса для обращения к элементам класса-контейнера);
  • перегруженные операторы (развитие ООП);
  • оператор foreach (обработка всех элементов классов-коллекций, аналог Visual Basic);
  • механизмы boxing и unboxing для преобразования типов;
  • атрибуты (средство оперирования метаданными в COM-модели);
  • прямоугольные массивы (набор элементов с доступом по номеру индекса и одинаковым количеством столбцов и строк).

Приведенные выше особенности языка C# повлияли на выбор языка программирования и соответственно среды.net для программы.

При создании программного алгоритма «Лестница в небо» на начальном этапе была разработана блок-схема игры. В ней было описана последовательность работы алгоритма игры (рисунок 2.2.1 и рисунок 2.2.2).

Рисунок 2.2.1 — Блок-схема программы

Рисунок 2.2.2 -Блок-схема программы

При запуске приложения «Лестница в небо» происходит объявления двух двумерных массивов, с последующим их заполнением пустыми значениями. Далее происходит выбор фигуры с помощью генератора случайных чисел и запускается таймер, что дает начало игровому процессу. В соответствии с выбранной фигурой происходит установка параметров объекта падающих фигур. Тело этого цикла представляет собой сдвиг фигуры на клетку вниз, если это возможно, иначе она добавляется в первый массив как занятая область и во второй, как параметры прочности этой области. После заполнения массивов происходит случайный выбор новой фигуры и установка новых параметров объекта падающих фигур. Также внутри цикла происходит проверка на нажатие клавиш «Влево», «Вправо», «Вверх», «A», «D», в соответствии с которыми происходит управление игровым процессом. Далее происходит уменьшение параметра прочности блока на котором стоит персонаж (клетка нише).

7 стр., 3100 слов

Программы подготовки летного персонала: crm, loft, cfit, alar ...

... MANAGEMENT (Предупреждение Возникновения Опасных Условий); COMPANY RESOURCE MANAGEMENT (Управление Ресурсами Авиакомпании). Название «CRM» впервые появилось в 1972 после катастрофы Eastern Airlines 401 ... культуры авиакомпании, ориентированной на безопасность. Благодаря научно – техническому прогрессу, коммерческая авиация сегодня - самый надежный вид транспорта. Но дальнейший рост безопасности ...

Если прочность равна нулю, то блок исчезает, а персонаж падает на ближайший снизу блок. Если фигура установлена выше половины поля, то происходит перемещение экрана выше на 3 клетки. Условие окончания игры если персонаж окажется за пределами экрана больше, чем на 3 клетки.

Одной из самых важных функций любого языка программирования является предоставление возможностей для управления программой в ручную. Это подразумевает создание пользовательского интерфейса.

Выводимыми данными являются данные сообщаемые пользователю, а вводимыми являются те данные, которые пользователь сообщает программе.

Выводимые данные в программе представлены в виде графического отображения окна игры (Рисунок 2.3.1)

Рисунок 2.3.1 — Окно игры

Вводимыми данными представлены в виде программного кода, который необходимо выполнить при определенных действиях пользователя. А именно:

  • нажатиеклавиш Left, Right, Up, A, D, Space, Esc;
  • работа пользователя с главным меню.

На этапе разработки алгоритма необходимо определить последовательность действий, которые надо выполнить для получения результата. Если задача может быть решена несколькими способами и, следовательно, возможны различные варианты алгоритма решения, то программист, используя некоторый критерий, например, скорость решения алгоритма, выбирает наиболее подходящее решение. Результатом этапа разработки алгоритма является подробное словесное описание алгоритма или его блок-схема.

После того как определены требования к программе и составлен алгоритм решения, алгоритм записывается на выбранном языке программирования. В результате получается исходная программа. Составление текста программы, наверное, самый сложный из этапов, требующий наибольшего внимания. Чтобы этот текст был понятен пользователю и составителю, используются комментарии.

Отладка — это процесс поиска и устранения ошибок. Ошибки в программе разделяют на две группы: синтаксические (ошибки в тексте) и алгоритмические. Синтаксические ошибки — наиболее легко устраняемые. Алгоритмические ошибки обнаружить труднее. Этап отладки можно считать законченным, если программа правильно работает на одном-двух наборах входных данных.

Лестница в небо — это игра, средство развлечения. Поэтому, при разработке интерфейса пользователя необходимо учесть ряд особенностей:

Интерфейс должен быть интуитивно понятен простому пользователю компьютера.

Цветовая схема не только должна не раздражать человека, но и вызывать положительные эмоции.

Рассмотрим первый пункт.

Программа предназначена для приятного проведения свободного времени. Она не должна иметь сильно сложную систему управления. Поэтому, меню игры содержит минимум различных параметров, необходимых для запуска игрового процесса. Каждому пункту меню присвоено название, соответствующее функциональному назначению. Это облегчает работу пользователя.

Что же касается второго пункта, здесь применены в меру яркие рисунки, не раздражающие человеческий глаз, плавный шрифт текста, подобный тому, что используется во множестве детских мультфильмов, что делает игру более привлекательной для детей (Рисунок 2.5.1).

Рисунок 2.5.1- Главное меню игры

73 стр., 36242 слов

Разработка системы контроля и управления доступом к охраняемым объектам

... и пощрений. Качество выполнения этой совокупности задач зависит от вида СКУД, её функциональности и удобства работы с самой системой. Данная компьютерная система должна иметь простой и ... выхода с территории предприятия или офиса. ­ Автономность работы системы. СКУД оснащается системой бесперебойного питания, что позволяет не прерывать работу в случае отключения электричества в здании. Также система ...

Тестирование программы — это этап, на котором проверяется, как ведет себя программа на как можно большем количестве входных наборов данных, в том числе и на заведомо неверных.

Основные принципы организации тестирования:

1) необходимой частью каждого теста должно являться описание ожидаемых результатов работы программы, чтобы можно было быстро выяснить наличие или отсутствие ошибки в ней;

2) следует по возможности избегать тестирования программы ее автором, т.к. кроме уже указанной объективной сложности тестирования для программистов здесь присутствует и тот фактор, что обнаружение недостатков в своей деятельности противоречит человеческой психологии (однако отладка программы эффективнее всего выполняется именно автором программы);

3) по тем же соображениям организация — разработчик программного обеспечения не должна “единолично ” его тестировать (должны существовать организации, специализирующиеся на тестировании программных средств);

4) должны являться правилом доскональное изучение результатов каждого теста, чтобы не пропустить малозаметную на поверхностный взгляд ошибку в программе;

5) необходимо тщательно подбирать тест не только для правильных (предусмотренных) входных данных, но и для неправильных (непредусмотренных);

6) при анализе результатов каждого теста необходимо проверять, не делает ли программа того, что она не должна делать;

7) следует сохранять использованные тесты (для повышения эффективности повторного тестирования программы после ее модификации или установки у заказчика);

8) тестирования не должно планироваться исходя из предположения, что в программе не будут обнаружены ошибки (в частности, следует выделять для тестирования достаточные временные и материальные ресурсы);

9) следует учитывать так называемый “принцип скопления ошибок”: вероятность наличия не обнаруженных ошибок в некоторой части программы прямо пропорциональна числу ошибок, уже обнаруженных в этой части;

10) следует всегда помнить, что тестирование — творческий процесс, а не относиться к нему как к рутинному занятию.

При тестировании программы была выполнена только часть приведенных выше принципов. Тестирование выявило некоторые ошибки, часть из которых была исправлена, а другие хоть и не соответствовали начальной идее игры сделали игровой процесс более интересным.

игровой приложение программный

Аппаратные требования:

Необходимый объем ОЗУ 64 Мб и графическим адаптером, поддерживающим режим 800х600 и выше, глубина цвета 32 бит. Необходимое место на жестком диске 10 Мб. Клавиатура, мышь.

Программные требования:

Операционная система семейства Windows: XP (32/64) /Vista (32/64) /7 (32/64) с установленным пакетом Microsoft .Net Framework 3.5 или новее.

Запускаем приложение Stairway.exe (рисунок 3.2.1):

Рисунок 3.2.1 — главное меню игры

Для того чтобы начать игру необходимо нажать пункт меню «Начать». Игроку открывается страница меню с выбором уровня сложности. После выбора одного из уровней сложности (легко, норма, сложно) необходимо нажать пункт «Вперед» (рисунок 3.2.2).

Это запустит игровой процесс.

Рисунок 3.2.2 — меню выбора уровня сложности

Так же в главном меню игры есть пункт «Помощь», содержащий краткий список управляющих клавиш (рисунок 3.2.3)

11 стр., 5235 слов

Разработка развивающей игры для смартфонов под управлением операционной ...

... система разрешений. Пользователю перед установкой демонстрируются разрешения, которые необходимо предоставить приложению для его работы. Эти разрешения включают в себя доступ к телефонным службам, сети, ... разделение. Конечно, список возможностей Android не исчерпывается упомянутыми мной. Однако для разработки игр они будут наиболее важны. Архитектура Android формируется из набора компонентов. ...

Рисунок 3.2.3 — помощь в управлении

Для выхода из программы необходимо нажать на пункт в главном меню «Выход». Так же можно посмотреть сведения о программном продукте и разработчике пункт главного меню «Авторы» (рисунок 3.2.4).

Рисунок 3.2.4 — страница меню «Автор»

В данной курсовой работе была выполнена поставленная задача — создание игрового приложения. При помощи этой программы можно приятно провести время, совершенствовать координацию и развивать логическое мышление. Программа не занимает много места и не требовательна к установленному программному обеспечению.

игровой приложение программный

1. Нортроп, Т. Основы разработки приложений на платформе Microsoft .NET Framework. Учебный курс Microsoft. Перевод с англ./ Т. Нортроп, Ш. Уилдермьюс, Б. Райан. М. : «Русская редакция», 2007. 864 с.

a. Шилдт, Г. C#, учебный курс. / Г. Шилдт. СПб. : Питер, 2003. 512 с.

2. Робинсон, С. C# для профессионалов. Том 1. / С. Робинсон, О. Корнес, Д. Глин, Б. Харвей. М. :Лори, 2003. 1002 с.

3. Жарков В.А. Компьютерная графика, мультимедиа и игры на VisualC# 2005. — М.: Жарков пресс, 2005. — 812с.

4. http://www.excode.ru/art6225p1.html

5. Грегори К. Использование Visual C++ 6. Специальное издание.- М., СПб.; К.: Издательский дом «Вильямс», 2000 г.

6. Черносвитов А.,Visual C++ и MFC. Курс MCSD для профессионалов. СПб: Издательство «Питер», 2000.

7. Шилдт Г. Самоучитель С++. BHV Санкт-Петербург, 1998.

8. Березин Б.И., Березин С.Б. Начальный курс С и С++. М.: Диалог-МИФИ,1998.

9. Подбельский В.В. Программирование на языке Си++. М.: Финансы и статистика, 1999.

10. Паппас К., Мюррей У. Полное руководство по Visual C++ 5. Мн.:ООО “Поппури”, 1999.

11. Робинсон, С. C# для профессионалов. Том 2. / С. Робинсон, О. Корнес, Д. Глин, Б. Харвей. М. :Лори, 2003. 998 с.

12. Троелсен, Э. Язык программирования C# 2005 и платформа .NET 2.0, 3-е издание.: Пер с англ. / Э. Троелсен. М. : ООО «И.Д. Вильямс», 2007. 1168 с.

Приложение

Листинг 1 — класс Form

public partial class Form1 : Form

{

string[] names = new string[] { «Stan», «Kyle», «Eric» };

  • int personage = 0;
  • int mode = 5;
  • Menu men, help, auth, selp, loadscr;
  • Game game;
  • SoundPlayer BGSong;

public Form1()

{

BGSong = new SoundPlayer();

  • BGSong.Stream = Properties.Resources.NineEleven;
  • BGSong.Load();
  • InitializeComponent();
  • this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
  • timer1.Interval = 16;
  • loadscr = new Menu(this.ClientSize.Width, this.ClientSize.Height, this.Handle, Properties.Resources.LoadScreen);
  • loadscr.AddButton(null, 0, 0, 400, 400);
  • loadscr.AddAnim(73, 277, 263, 19);
  • men = new Menu(this.ClientSize.Width, this.ClientSize.Height, this.Handle, Properties.Resources.Title);
  • men.AddButton(Properties.Resources.btStart, 3, 225, 100, 35);
  • men.AddButton(Properties.Resources.btHelp, 1, 270, 100, 35);
  • men.AddButton(Properties.Resources.btAuthor, 2, 318, 100, 35);
  • men.AddButton(Properties.Resources.btQuit, 3, 362, 100, 35);
  • help = new Menu(this.ClientSize.Width, this.ClientSize.Height, this.Handle, Properties.Resources.Help);
  • help.AddButton(Properties.Resources.btBack, 1, 369, 100, 35);
  • auth = new Menu(this.ClientSize.Width, this.ClientSize.Height, this.Handle, Properties.Resources.Authors);
  • auth.AddButton(Properties.Resources.btBack, 1, 369, 100, 35);
  • selp = new Menu(this.ClientSize.Width, this.ClientSize.Height, this.Handle, Properties.Resources.SelectChar);
  • selp.AddButton(Properties.Resources.btBack, 1, 369, 100, 35);
  • selp.AddButton(Properties.Resources.btPrev, 72, 258, 41, 55);
  • selp.AddButton(Properties.Resources.btNext, 300, 255, 41, 55);
  • selp.AddButton(Properties.Resources.btSelect, 317, 368, 100, 35);
  • selp.AddImg(Properties.Resources.Stan_Title, 150, 200);
  • selp.AddImg(Properties.Resources.Kyle_Title, 150, 200);
  • selp.AddImg(Properties.Resources.Eric_Title, 150, 200);

}

private void timer1_Tick(object sender, EventArgs e)

{

if (mode == 0) men.Draw(); else

if (mode == 2) help.Draw();

else

if (mode == 3) auth.Draw();

else

if (mode == 4)

{

for (int i = 0; i < selp.counti; i++)

selp.imgs[i].visible = false;

  • selp.imgs[personage].visible = true;
  • selp.Draw();

}

else

if (mode == 5)

{

loadscr.Draw();

} else

if (mode == 1)

{

if (game.stroke() == -1)

timer1.Enabled = false;

else

if (game.pause == true) timer1.Enabled = false;

}

}

private void Form1_KeyDown(object sender, KeyEventArgs e)

{

if (mode == 1)

{

if (game.win != true)

game.KeyIn(e);

else

{

if (e.KeyCode == Keys.Escape)

{

game = null;

  • mode = 0;
  • timer1.Enabled = true;

}

return;

}

if (game.pause == false) timer1.Enabled = true; else

if (e.KeyCode == Keys.Escape)

{

game = null;

  • mode = 0;
  • timer1.Enabled = true;

}

if (mode==0) BGSong.PlayLooping();

} else

if (mode == 4)

{

if (e.KeyCode == Keys.Left) personage—;

  • if (e.KeyCode == Keys.Right) personage++;
  • if (personage <
  • 0) personage = selp.counti — 1;
  • personage %= selp.counti;
  • if (e.KeyCode == Keys.Enter)

{

game = new Game(this.ClientSize.Width, this.ClientSize.Height, this.Handle, names[personage]);

  • mode = 1;

}

}

}

private void Form1_MouseMove(object sender, MouseEventArgs e)

{

if (mode == 0) men.MouseP = new Point(e.X, e.Y);

  • if (mode == 2) help.MouseP = new Point(e.X, e.Y);
  • if (mode == 3) auth.MouseP = new Point(e.X, e.Y);
  • if (mode == 4) selp.MouseP = new Point(e.X, e.Y);
  • if (mode == 5) loadscr.MouseP = new Point(e.X, e.Y);

}

private void Form1_MouseDown(object sender, MouseEventArgs e)

{

}

private void Form1_MouseClick(object sender, MouseEventArgs e)

{

int i;

if (mode == 0)

{

i = men.getBut();

if (i != -1)

{

if (i == 0) mode = 4;

  • if (i == 1) mode = 2;
  • if (i == 2) mode = 3;
  • if (i == 3) this.Close();

}

}

else

if (mode == 2)

{

i = help.getBut();

if (i != -1)

{

if (i == 0) mode = 0;

}

}

else

if (mode == 3)

{

i = auth.getBut();

if (i != -1)

{

if (i == 0) mode = 0;

}

}

else

if (mode == 4)

{

i = selp.getBut();

if (i != -1)

{

if (i == 0) mode = 0;

  • if (i == 1) personage—;
  • if (i == 2) personage++;
  • if (personage <
  • 0) personage = selp.counti — 1;
  • personage %= selp.counti;

if (i == 3)

{

game = new Game(this.ClientSize.Width, this.ClientSize.Height, this.Handle, names[personage]);

  • mode = 1;

}

}

}

else

if (mode == 5)

{

i = loadscr.getBut();

if (i != -1)

{

if (i == 0)

{

BGSong.PlayLooping();

  • mode = 0;

}

}

}

}

private void Form1_Load(object sender, EventArgs e)

{

}

private void Form1_KeyUp(object sender, KeyEventArgs e)

{

if (mode==1)

if ((e.KeyCode == Keys.A) || (e.KeyCode == Keys.D)) game.KeyUp();

}

}

Листинг 2 — класс Personage

public class Personage

{

public int strong;

  • public Point Coords;
  • public Point Need;
  • public Point CP;
  • public Image[] Img;
  • public int Pos = 0;
  • public int anim = 0;

public Personage(string fn)

{

Coords = new Point(1, 19);

  • Need = new Point(1, 19);
  • Img = new Image[3];

if (fn == «Stan»)

{

strong = 1;

  • Img[0] = Properties.Resources.Stan;
  • Img[1] = Properties.Resources.StanL;
  • Img[2] = Properties.Resources.StanR;

} else

if (fn == «Kyle»)

{

strong = 2;

  • Img[0] = Properties.Resources.Kyle;
  • Img[1] = Properties.Resources.KyleL;
  • Img[2] = Properties.Resources.KyleR;

} else

if (fn == «Eric»)

{

strong = 3;

  • Img[0] = Properties.Resources.Eric;
  • Img[1] = Properties.Resources.EricL;
  • Img[2] = Properties.Resources.EricR;

}

}

public bool Move(int[,] Map, int ys, int sizey)

{

bool res = false;

  • Pos = 0;
  • if ((Need.X >
  • Coords.X) && (Coords.X + 1 <
  • 20))

if (Map[Coords.X + 1, Coords.Y] == 0)

{

if ((Map[Coords.X + 1, Coords.Y-1] == 0))

if ((Map[Coords.X + 1, Coords.Y + 1] != 0) || (Map[Coords.X + 1, Coords.Y + 2] != 0) || (Coords.Y == sizey — 1 + ys))

{

if (Map[Coords.X + 1, Coords.Y + 1] == 0) Coords.Y++;

  • Coords.X++;
  • Pos = 2;
  • res = true;

}

}

else

{

if (Map[Coords.X + 1, Coords.Y — 1] == 0)

{

Coords.X++; Coords.Y—;

  • Pos = 2;
  • res = true;

}

}

if ((Need.X < Coords.X) && (Coords.X — 1 >= 0))

if (Map[Coords.X — 1, Coords.Y] == 0)

{

if ((Map[Coords.X — 1, Coords.Y — 1] == 0))

if ((Map[Coords.X — 1, Coords.Y + 1] != 0) || (Map[Coords.X — 1, Coords.Y + 2] != 0) || (Coords.Y == sizey — 1 + ys))

{

if (Map[Coords.X — 1, Coords.Y + 1] == 0) Coords.Y++;

  • Coords.X—;
  • Pos = 1;
  • res = true;

}

}

else

{

if (Map[Coords.X — 1, Coords.Y — 1] == 0)

{

Coords.X—; Coords.Y—;

  • Pos = 1;
  • res = true;

}

}

if (res == true) anim += 180; else Need = Coords;

  • return res;

}

}

Листинг 2 — класс people

public class people

{

public Image Img;

  • public Point Coords;
  • public Point Need;
  • public int move;

public people(Bitmap bm, Point coord, int mov)

{

Img = bm;// Image.FromFile(filename);

  • Coords = coord;
  • move = mov;

}

public bool Move()

{

bool res=false;

  • if ((Coords.X != Need.X) || (Coords.Y != Need.Y)) res = true;
  • if (Coords.X <
  • Need.X) Coords.X+=move;
  • if (Coords.X >
  • Need.X) Coords.X-=move;
  • if (Coords.Y <
  • Need.Y) Coords.Y+=move;
  • if (Coords.Y >
  • Need.Y) Coords.Y-=move;
  • if (Math.Abs(Coords.X — Need.X) <= move) Need.X = Coords.X;
  • if (Math.Abs(Coords.Y — Need.Y) <= move) Need.Y = Coords.Y;
  • return res;

}

}

public class lemniscates

{

int a;

  • float pi, f, dt ,r, x, y;
  • Point Center;
  • int Radius;

public lemniscates(Point center, int radius)

{

pi = (float)Math.PI;

  • dt = pi / 600;
  • f = -pi;
  • a = 4;
  • Center = center;
  • Radius = radius;

}

public Point iter()

{

Point Coord=Center;

  • double cos = Math.Cos(f);
  • r = (float)(cos);
  • x = (float)( Radius * Math.Cos(f));
  • y = (float)( r* Radius * Math.Sin(f));
  • Coord = new Point((int)(Center.X + x), (int)(Center.Y — y));
  • f += (float)(1/180.0f*Math.PI);// dt;
  • if (f >
  • 2 * Math.PI) f = 0;
  • return Coord;

}

}

Листинг 3 — класс Buttons

public class Buttons

{

public int left, top;

  • int width, height;
  • public Image img;

public Buttons(Bitmap bm, int Left, int Top, int Width, int Height)

{

img = bm;// Image.FromFile(filename);

  • left = Left;
  • top = Top;
  • width = Width;
  • height = Height;

}

public bool checkmouse(Point MP)

{

if (((MP.X >= left) && (MP.X <= left + width)) && ((MP.Y >= top) && (MP.Y <= top + height))) return true; else return false;

}

}

Листинг 4 — класс Img

public class Img

{

public int left, top;

  • public Image img;
  • public bool visible;

public Img(Bitmap bm, int Left, int Top)

{

img = bm;// Image.FromFile(fn);

  • visible = true;
  • left = Left;
  • top = Top;

}

}

Листинг 5 — класс An

public class An

{

public int left, top, width, height;

  • public Image img;
  • public bool visible;
  • public int iter=0;

public An(int Left, int Top, int Width, int Height)

{

visible = true;

  • left = Left;
  • top = Top;
  • width = Width;
  • height = Height;
  • iter = -width;

}

int trimdown(int i, int j)

{

if (i < j) i = j;

  • return i;

}

int trimup(int i, int j)

{

if (i > j) i = j;

  • return i;

}

public void Draw(Graphics g)

{

//g.FillRectangle(new SolidBrush(Color.White), new Rectangle(left, top, width, height));

  • g.FillRectangle(new SolidBrush(Color.White), new Rectangle(trimdown(left + iter, left), top, width + iter — 2*trimdown(iter,0), height));
  • //iter = (iter+1)%width;
  • iter++;
  • if (iter >
  • width) iter = -width;

}

}

Листинг 6 — класс Menu

public class Menu

{

Graphics Screen;

  • Bitmap BackBuffer;
  • Graphics DrawingArea;
  • int countb;
  • public int counti;
  • public Image Bg;
  • Buttons[] but;
  • public Img[] imgs;
  • public An anim;
  • public Point MouseP;

public Menu(int Width, int Height, IntPtr Handle, Bitmap bm)//string filename)

{

BackBuffer = new Bitmap(Width, Height);

  • Screen = Graphics.FromImage(BackBuffer);
  • DrawingArea = Graphics.FromHwnd(Handle);
  • countb = 0;
  • counti = 0;
  • Bg = bm;//Image.FromFile(filename);
  • but = new Buttons[100];
  • imgs = new Img[100];

}

public void AddAnim(int left, int top, int width, int height)

{

anim = new An(left, top, width, height);

}

public void AddButton(Bitmap bm, int left, int top, int width, int height)

{

but[countb++] = new Buttons(bm, left, top, width, height);

}

public void AddImg(Bitmap bm, int left, int top)

{

imgs[counti++] = new Img(bm, left, top);

}

public void Draw()

{

Screen.DrawImage(Bg,0,0);

  • for (int i = 0;
  • i <
  • counti;
  • i++)

if (imgs[i].visible) Screen.DrawImage(imgs[i].img, imgs[i].left, imgs[i].top);

  • for (int i = 0;
  • i <
  • countb;
  • i++)

if ((but[i].checkmouse(MouseP)) && (but[i].img!=null)) Screen.DrawImage(but[i].img, but[i].left, but[i].top);

  • if (anim!=null) anim.Draw(Screen);
  • DrawingArea.DrawImageUnscaled(BackBuffer, 0, 0);

}

public int getBut()

{

for (int i = 0; i < countb; i++)

if (but[i].checkmouse(MouseP)) return i;

  • return -1;

}

}

Листинг 7 — класс Game

public class Game

{

string[] names = new string[] { «Стэн», «Кайл», «Эрик»};

  • string[] Texts = new string[] { «Поражение», «Пауза», «Нажмите ESC, чтобызакончитьигру», «Победа», «Нажмите Space, чтобыпродолжить», «{0} погиб», «{0} неуспел», «Нетместадляблоков» };
  • public Color[] Cols = new Color[] { Color.DarkRed, Color.DarkBlue, Color.DarkGreen, Color.Silver, Color.Purple, Color.Orange };

public int[, ,] figs = new int[,,]{ //1

{

{0,1,0},

{0,1,1},

{0,0,0}

},

{

{0,1,1},

{0,1,0},

{0,0,0}

},

{

{0,1,1},

{0,0,1},

{0,0,0}

},

{

{0,0,1},

{0,1,1},

{0,0,0}

},

/////////////////////////////////////////////////////////// 2

{

{0,0,1},

{0,1,0},

{1,0,0}

},

{

{1,0,0},

{0,1,0},

{0,0,1}

},

{

{0,0,1},

{0,1,0},

{1,0,0}

},

{

{1,0,0},

{0,1,0},

{0,0,1}

},

////////////////////////////////////////////////////////// 3

{

{0,1,0},

{1,0,1},

{0,0,0}

},

{

{0,1,0},

{0,0,1},

{0,1,0}

},

{

{0,0,0},

{1,0,1},

{0,1,0}

},

{

{0,1,0},

{1,0,0},

{0,1,0}

},

////////////////////////////////////////////////////////// 4

{

{0,0,0},

{1,1,1},

{0,0,0}

},

{

{0,1,0},

{0,1,0},

{0,1,0}

},

{

{0,0,0},

{1,1,1},

{0,0,0}

},

{

{0,1,0},

{0,1,0},

{0,1,0}

},

////////////////////////////////////////////////////////// 5

{

{0,1,0},

{0,1,0},

{1,0,0}

},

{

{1,0,0},

{0,1,1},

{0,0,0}

},

{

{0,0,1},

{0,1,0},

{0,1,0}

},

{

{0,0,0},

{1,1,0},

{0,0,1}

},

////////////////////////////////////////////////////////// 6

{

{0,1,0},

{0,1,0},

{0,0,1}

},

{

{0,0,0},

{0,1,1},

{1,0,0}

},

{

{1,0,0},

{0,1,0},

{0,1,0}

},

{

{0,0,1},

{1,1,0},

{0,0,0}

},

};

  • int sizex = 20;
  • int sizey = 20;
  • int sizebx = 20, sizeby = 20;
  • int[,] Map = new int[20, 60];
  • int[,] MapT = new int[20, 60];
  • Personage Er;
  • SoundPlayer Start,OnMove,Kenny_Win, thump, crash;
  • int countf = 0;
  • figure[] LastFigs = new figure[1000];
  • Image Bg;
  • Image[,] blocks = new Image[6, 4];
  • Image[] Clouds = new Image[4];
  • Graphics Screen;
  • Bitmap BackBuffer;
  • Graphics DrawingArea;
  • figure Fig;
  • Random rnd = new Random();
  • int prch = 60;

////////////////////////////////////

people Kenny;

  • lemniscates lim;

////////////////////////////////////

public Game(int Width, int Height, IntPtr Handle, string pername)

{

Start = new SoundPlayer();

  • Start.Stream = Properties.Resources.Start;
  • OnMove = new SoundPlayer();
  • OnMove.Stream = Properties.Resources.Eric_S;
  • Kenny_Win = new SoundPlayer();
  • Kenny_Win.Stream = Properties.Resources.Kenny_yahow;
  • thump = new SoundPlayer();
  • thump.Stream = Properties.Resources.thump;
  • crash = new SoundPlayer();
  • crash.Stream = Properties.Resources.hitbullet;
  • for (int i = 0;
  • i <
  • sizex;
  • i++) Map[i, 20] = -1;
  • BackBuffer = new Bitmap(Width, Height);
  • Screen = Graphics.FromImage(BackBuffer);
  • DrawingArea = Graphics.FromHwnd(Handle);
  • Fig.Index = rnd.Next(6);
  • Fig.Coords = new Point(sizex / 2, 0);
  • Fig.CP = new Point(sizebx * Fig.Coords.X, sizeby * Fig.Coords.Y);
  • Bg = Properties.Resources.bg;
  • Kenny = new people(Properties.Resources.Kenny, new Point(100, 100),2);
  • lim = new lemniscates(new Point(Width/2, 100), 100);
  • Clouds[0] = Properties.Resources.Cloud1;
  • Clouds[1] = Properties.Resources.Cloud2;
  • Clouds[2] = Properties.Resources.Cloud3;
  • Clouds[3] = Properties.Resources.Cloud4;
  • Er = new Personage(pername);
  • Er.CP = new Point(Er.Coords.X * sizebx — Er.Img[0].

Width / 2, Er.Coords.Y * sizeby + sizeby — 50);

  • Start.Play();

}

bool checkblock(int n) // n-направление: 1-вниз, 2- влево, 3-вправо

{

int[,] Move = new int[3, 2] { { 0, 1 }, { -1, 0 }, { 1, 0 } };

  • bool maybe = true;
  • int minl = 3;
  • int minr = 0;
  • int minb = 0;
  • for (int x = 0;
  • x <
  • 3;
  • x++)

for (int y = 0; y < 3; y++)

{

if (figs[Fig.Index * 4 + Fig.Rotate, y, x] != 0)

{

// Определение крайних точек фигуры

if (minl > x) minl = x;

  • if (minr <
  • x) minr = x;
  • if (minb <
  • y) minb = y;
  • int xt = Fig.Coords.X + x + Move[n, 0];
  • int yt = Fig.Coords.Y + y + Move[n, 1];
  • if ((xt >= 0) && (xt <
  • sizex) && (yt >= 0) && (yt <
  • sizey + ys))

if (Map[xt, yt] != 0) maybe = false;

}

}

if (minl + Fig.Coords.X + Move[n, 0] < 0) maybe = false;

  • if (minr + Fig.Coords.X + Move[n, 0] == sizex) maybe = false;
  • if (minb + Fig.Coords.Y + Move[n, 1] == sizey + ys) maybe = false;
  • return maybe;

}

void Draw()

{

for (int x = 0; x < 3; x++)

for (int y = 0; y < 3; y++)

{

if (figs[Fig.Index * 4 + Fig.Rotate, y, x] != 0)

{

int xt = Fig.Coords.X + x;

  • int yt = Fig.Coords.Y + y;
  • if ((xt >= 0) && (xt <
  • sizex) && (yt >= 0) && (yt <
  • sizey + yp))

{

Map[xt, yt] = 1 * (Fig.Index + 1);

  • MapT[xt, yt] = prch;

}

}

}

LastFigs[countf++] = Fig;

}

int x = 40, a = 10, ys = 0;

  • int l = 0;

void deleterow()

{

for (int i = 0; i < sizex; i++)

for (int j = 59; j > 0; j—)

{

Map[i, j] = Map[i, j — 1];

}

for (int i = 0; i < sizex; i++)

for (int j = 59; j > 0; j—)

{

MapT[i, j] = MapT[i, j — 1];

}

}

void deleterownum(int num)

{

for (int i = 0; i < sizex; i++)

for (int j = num; j > 0; j—)

{

Map[i, j] = Map[i, j — 1];

}

for (int i = 0; i < sizex; i++)

for (int j = num; j > 0; j—)

{

MapT[i, j] = MapT[i, j — 1];

}

}

void ReDrawMap()

{

for (int i = 0; i < sizex; i++)

for (int j = 0; j < sizey; j++)

{

if (Map[i, j] > 0)

{

Color cf = Cols[Map[i, j] — 1];

  • Color cd = Color.White;
  • // if (MapT[i, j] < 19)

int alpha = (int)((MapT[i, j] / (float)prch) * 255);

  • cd = Color.FromArgb(alpha, cd.R, cd.G, cd.B);
  • cf = Color.FromArgb(alpha, cf.R, cf.G, cf.B);
  • Screen.FillRectangle(new SolidBrush(cf), new Rectangle(i * sizebx, j * sizeby + yp % sizeby, sizebx, sizeby));
  • Screen.DrawRectangle(new Pen(cd), new Rectangle(i * sizebx, j * sizeby + yp % sizeby, sizebx, sizeby));

}

}

}

void checkRow()

{

int num = -1;

  • for (int y = 0;
  • y <
  • 59;
  • y++)

{

int i = 0;

  • for (int x = 0;
  • x <
  • sizex;
  • x++)

{

if (Map[x, y] > 0) i++;

}

if (i == sizex)

{

num = y;

  • break;

}

}

if (num != -1)

{

deleterownum(num);

  • if (num >= Er.Coords.Y)

{

Er.Need = Er.Coords;

  • Er.Coords.Y += 1;

}

}

}

int yp = 0;

  • int angl = 0;
  • public bool left = false;
  • public bool right = false;
  • public bool pause = false;
  • public bool win = false;
  • Point ER1;

void outtext(int x, int y, string Text, int size)

{

Font fnt = new Font(«Comic Sans MS», size);

  • for (int i = 0;
  • i <
  • 360;
  • i += 90)

Screen.DrawString(Text, fnt, new SolidBrush(Color.Black), new Point((int)(x + Math.Cos(i / 180.0 * 3.14) * 2), (int)(y + Math.Sin(i / 180.0 * 3.14) * 2)));

  • Screen.DrawString(Text, fnt, new SolidBrush(Color.Yellow), new Point(x, y));

}

int timeout = 0;

public int stroke()

{

int result = 0;

if (l == 0)

{

int proch=0;

  • for (int i = 1;
  • i <
  • 4;
  • i++)

{

if (Map[Er.Coords.X, Er.Coords.Y + i] != 0)

proch++;

  • else break;

}

if (Er.Coords.Y <19)

MapT[Er.Coords.X, Er.Coords.Y + 1]-=(4-proch)*Er.strong;

  • if ((MapT[Er.Coords.X, Er.Coords.Y + 1]<=0) && (Er.Coords.Y <19))

{

timeout = 0;

  • crash.Play();
  • for (int y = 1;
  • y <= 1;
  • y++)

{

for (x = -1; x <= 1; x++)

{

int xl;

  • int yl;
  • yl = Er.Coords.Y + y;
  • xl = Er.Coords.X + x;
  • if ((xl >= 0) && (xl <
  • 20) && (Map[xl,yl]>0))

Map[xl, yl] = 0;

}

}

int yt = 0;

do

{

yt++;

}

while (Map[Er.Coords.X, Er.Coords.Y+yt] == 0);

  • Er.Need = Er.Coords;
  • Er.Coords.Y += yt-1;

}

}

angl++;

  • Screen.DrawImage(Bg, new Point(0, -930 + yp));
  • Screen.DrawImage(Clouds[2], new Point(-100 + (int)(Math.Sin(angl / 180.0 * 3.14) * 80), 250 — 930 + yp));
  • Screen.DrawImage(Clouds[3], new Point(-200 + (int)(Math.Cos(angl / 180.0 * 3.14) * 80), 250 — 930 + yp));
  • ReDrawMap();

if (win!=true)

for (int i = 0; i < 3; i++)

for (int j = 0; j < 3; j++)

{

if (figs[Fig.Index * 4 + Fig.Rotate, j, i] == 1)

{

Screen.FillRectangle(new SolidBrush(Cols[Fig.Index]), new Rectangle(i * sizebx + Fig.CP.X, j * sizeby + Fig.CP.Y, sizebx, sizeby));

  • Screen.DrawRectangle(new Pen(Color.White), new Rectangle(i * sizebx + Fig.CP.X, j * sizeby + Fig.CP.Y, sizebx, sizeby));

}

}

if (Fig.Coords.X * sizebx < Fig.CP.X) Fig.CP.X -= 4;

  • if (Fig.Coords.X * sizebx >
  • Fig.CP.X) Fig.CP.X += 4;
  • if (Fig.Coords.Y * sizeby <
  • Fig.CP.Y) Fig.CP.Y -= 2;
  • if (Fig.Coords.Y * sizeby >
  • Fig.CP.Y) Fig.CP.Y += 2;
  • Point ErL=Er.CP;
  • if (Er.Coords.X * sizebx — Er.Img[0].

Width / 2 < Er.CP.X) Er.CP.X -= 2;

  • if (Er.Coords.X * sizebx — Er.Img[0].

Width / 2 > Er.CP.X) Er.CP.X += 2;

  • if (Er.Coords.Y * sizeby + sizeby — 50 <
  • Er.CP.Y) Er.CP.Y -= 2;
  • if (Er.Coords.Y * sizeby + sizeby — 50 >
  • Er.CP.Y) Er.CP.Y += 2;
  • if ((ErL!=Er.CP)) timeout=0;
  • Screen.DrawImage(Er.Img[Er.Pos], new Point(Er.CP.X, Er.CP.Y + (int)(Math.Cos(Er.anim / 180.0f * Math.PI))));
  • Screen.DrawImage(Kenny.Img, new Point(Kenny.Coords.X, Kenny.Coords.Y — 930 + yp) );
  • if (Kenny.Move() == false)

{

if (win != true)

Kenny.Need = lim.iter();

else

Kenny.Need = new Point(Er.CP.X, Er.CP.Y + 930 — yp-40);

}

checkRow();

  • Screen.DrawImage(Clouds[0], new Point(-100 + (int)(Math.Sin(angl / 180.0 * 3.14) * 120), 300 — 930 + yp));
  • Screen.DrawImage(Clouds[1], new Point(-100 + (int)(Math.Cos(angl / 180.0 * 3.14) * 120), 300 — 930 + yp));

if (pause == true)

{

outtext(170, 160, Texts[1], 24);

  • outtext(70, 220, Texts[2], 12);
  • outtext(70, 240, Texts[4], 12);
  • result = 2;

}

if ((Kenny.Move() == false) && (win == true) && (Kenny.Need == new Point(Er.CP.X, Er.CP.Y + 930 — yp — 40)))

{

outtext(150, 160, Texts[3], 24);

  • outtext(70, 220, Texts[2], 12);
  • DrawingArea.DrawImageUnscaled(BackBuffer, 0, 0);
  • return 2;

}

DrawingArea.DrawImageUnscaled(BackBuffer, 0, 0);

  • if (ys * sizeby > yp)

{

yp += 2;

  • Er.Coords = ER1;
  • if (yp % sizeby == 0) deleterow();

}

if (l == 0)

{

if ((Er.Need == Er.Coords) && (sizey — Er.Coords.Y > Er.strong)) timeout++;

  • Er.Move(Map, ys, sizey);
  • if (Er.CP.Y / sizeby > sizey + 1) // GAME OVER

{

outtext(130, 160, Texts[0], 24);

  • if (Er.CP.Y / sizeby >
  • sizey + 1) outtext(160, 220, String.Format(Texts[6], names[Er.strong — 1]), 14);
  • outtext(80, 250, Texts[2], 12);
  • DrawingArea.DrawImageUnscaled(BackBuffer, 0, 0);
  • win = true;
  • return -1;

}

if ((Er.Coords.Y < 10) && (ys == 46) && (win!=true))

{

Er.Need = Er.Coords;

  • Kenny_Win.Play();
  • win = true;

}

if (win == false)

{

if (checkblock(0) == false)

{

if (Fig.Coords.Y < 10)

{

int inc = 0;

  • if (ys + 3 <= 46) inc = 3;
  • else inc = 46 — ys;
  • ys += inc;
  • Er.Need = Er.Coords;
  • Er.Coords.Y += inc;
  • ER1 = Er.Coords;

}

thump.Play();

  • Draw();
  • Fig.Index = rnd.Next(6);
  • Fig.Coords.X = sizex / 2;
  • Fig.Coords.Y = 0;
  • Fig.CP = new Point(sizebx * Fig.Coords.X, sizeby * Fig.Coords.Y);

}

else

Fig.Coords.Y += 1;

}

}

l = (l + 1) % 10;

if (l%5 == 0)

{

left = false;

  • right = false;

}

return result;

}

public void KeyUp()

{

Er.Need = Er.Coords;

}

public void KeyIn(KeyEventArgs e)

{

if (e.KeyCode == Keys.Space) pause = !pause;

  • if ((e.KeyCode == Keys.Left) && (left == false))

{

if (checkblock(1))

Fig.Coords.X—;

  • left = true;

}

if ((e.KeyCode == Keys.Right) && (right == false))

{

if (checkblock(2))