Как сделать программу лабиринт

Аннотация: В лекции рассматривается создание приложения, в котором используются большинство возможностей OpenGL, рассмотренные в предыдущих лекциях.

Цель лекции: Создать приложения на C# и Object Pascal , моделирующие перемещение наблюдателя в лабиринте.

Примеры на C# (WinForms) и Object Pascal (Delphi)

Пример № 13.1 Программа «Лабиринт» (вариант 1). Пример реализует программу, моделирующую перемещение наблюдателя в помещении.

Пример № 13.2 Программа «Лабиринт» (вариант 2). Пример дополняет пример 13.1: выполняется наложение текстур на стены, добавлена вращающаяся сфера с текстурой.

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

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

Уроки Scratch / Делаем игру Лабиринт Кошка и Мышка (Часть 1)

Создание базового приложения

Первоначально рассмотрим создание приложения, в котором не будет использоваться освещение и стены будут иметь различный цвет. Для моделирования нахождения наблюдателя в помещении потребуется использовать перспективную проекцию. Параметры перспективной проекции необходимо задать таким образом, чтобы боковые границы области видимости были меньше расстояния до боковых стен. Дальнюю границу области видимости расположим дальше, чем расстояние между самыми удалёнными друг от друга стенами, чтобы наблюдатель всегда мог видеть границу помещения лабиринта (листинги 13.1 и 13.2 ).

private void glControl1_Resize(object sender, EventArgs e)
Листинг 13.1. Обработчик события Resize формы для программы Лабиринт на C#

procedure TfrmGL.FormResize(Sender: TObject); begin glViewport(0, 0, ClientWidth, ClientHeight); glMatrixMode(GL_PROJECTION); glLoadIdentity; glFrustum(-0.5, 0.5, -0.5, 0.5, 0.5, 50); glMatrixMode(GL_MODELVIEW); InvalidateRect(Handle, nil, False); end;
Листинг 13.2. Обработчик события OnResize формы для программы Лабиринт на Object Pascal

Для описания расположения координат стен в программе на C# будет использоваться массив структур типа PointFloat . Тип PointFloat объявлен в программе:

public struct PointFloat < public double X; public double Y;
Листинг 13.3. Объявление структуры PointFloat в программе на C#

В программе на Object Pascal для описания координат стен используется тип TPointFloat, который объявлен в модуле OpenGL.pas:

Type TPointFloat = record x, y: Single; end;
Листинг 13.4. Объявление типа данных TPointFloat в модуле OpenGL.pas (Object Pascal)

Для определения каждой стены в программе будет использоваться массив структур типа Wall в программе на C# ( пример 13.5) и типа TWall в программе на Object Pascal ( пример 13.6).

Как создать игру ЛАБИРИНТ в Scratch 3 (часть 1)

public struct Wall
Листинг 13.5. Объявление структуры Wall в программе на C#

type TWall = record l, r: Integer; c: TColor; end;
Листинг 13.6. Объявление структуры TWall в программе на Object Pascal

Читайте также:
Программа измерения энергопотребление компьютера

Поля структуры имеют следующие значения:

  • l, r – левая и правая границы стены, которые определяются индексами элементов массива coners ;
  • c – цвет стены, который используется при отображении стен в режиме без освещения.

Координаты стен могут быть определены в виде массивов ( пример 13.7 и пример 13.8).

// координаты углов стен PointFloat[] coners = new []< new PointFloat, new PointFloat, new PointFloat, new PointFloat, new PointFloat, new PointFloat >; // расположение стен в лабиринте Wall[] plan = new[] < new Wall, new Wall, new Wall, new Wall, new Wall >;

Листинг 13.7. Определение массивов coners и plan для хранения данных о расположении стен лабиринта на C#

const coners: array [0..5] of TPointFloat = ( (x:-10; y:-10), (x:-10; y: 10), (x: 10; y: 10), (x: 10; y:-10), (x: 0; y:-10), (x: 0; y: 0)); plan: array [0..4] of TWall = ( (l:0;r:1;c:clRed),(l:1;r:2;c:clGreen), (l:2;r:3;c:clYellow),(l:3;r:0;c:clBlue), (l:4;r:5;c: clAqua));

Листинг 13.8. Определение массивов coners и plan для хранения данных о расположении стен лабиринта на Object Pascal

Источник: intuit.ru

Реализация простейших игровых приложений на примере игры «Лабиринт»

Центр цифрового образования детей

Не секрет, что все дети любят играть в компьютерные и мобильные игры, а также что многие из них хоть раз да задумывались над созданием собственной игры. Но для создания собственной игры нужно знать, как минимум, основы программирования на одном из языков, владеть навыками 3D-моделирования и работой с игровым движком.
В качестве языка программирования для создания их первых простейших игр мы используем Scratch. Scratch — это визуальный язык программирования, специально разработанный для детей. Во-первых, он доступен онлайн и не требует установки чего-либо.
Во-вторых, это интегрированная среда, рисуешь код и сразу его исполняешь, сразу же видно результат.
В-третьих, он заточен на создание игр, в нем уже существует библиотека спрайтов и фонов, а также специальные “игровые” операторы, вроде “Повернуть, если врезался в стену”.
После данного занятия ученики станут ближе к воплощению своей идеи в проектировании и программировании первой игры. На занятии ребята создадут игру с главным героем, задачей которого будет добраться до выхода из лабиринта.

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

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

Для данного проекта лучшего всего использовать спрайт “Ball” в виде главного действующего лица, поскольку он симметричен и у игрока не будет проблем, связанных с тем, что при повороте спрайт задевает стенки лабиринт. В качестве конечной точки лабиринта воспользуемся спрайтом “Cake”. Вы можете использовать любые спрайты.

Читайте также:
Программа жить или умереть

На текущем этапе у нас есть изображение лабиринта и два спрайта. Следующим этапом будет добавление блоков для движения спрайта “Ball” по лабиринту для этого нужно выбрать спрайт в списке снизу левым кликом. Например, на рисунке выше у нас выбран спрайт “Cake”. Это можно понять по синему выделению и корзинке правее и чуть выше значка спрайта.

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

Поскольку по умолчанию все спрайты после добавление в Scratch повернуты в направлении 90 (вправо), то нам нужно, чтобы спрайт при нажатии поворачивался в соответствии со стрелкой. Делаем это с помощью блока “Повернуться в направлении” из вкладки “Движение”. После этого мы кликаем левым щелчком по цифрам, принадлежащим этим блокам. Откроется окно, с выбором направления. Здесь нам нужно просто перетащить стрелку в соответствующем направлении.

Следующим этапом будет добавление условия, чтобы при касании стенки лабиринта наш возвращался в начальное положение. Для этого мы будем использовать блок “Если-то” из кладки управление. В качестве условия мы воспользуемся блоком “Касается цвета” из вкладки “Сенсоры”. А в качестве команды, если условие оказывается верным будет блок “перейти” из вкладки “движение”. Чтобы задать координаты начала уровня достаточно расположить спрайт “Ball” в нужной позиции и тогда при перетаскивании блока “Перейти” он перетащится с нужными координатами.

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

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

Источник: it-cube48.ru

Неприлично простая реализация неприлично простого алгоритма генерации лабиринта

Продолжение этой статьи об очень простом алгоритме генерации прямоугольных лабиринтов. В этой статье я приведу мою реализацию алгоритма на С++, а также покажу несколько дополнительных функций, которые породил мой скучающий мозг. Если осмелитесь продолжить читать, убедитесь, что ознакомились с моей предыдущей статьей. Глянули? Молодцы, продолжаем.

Где же код?

Начнем с начала — подтягиваем стандартные библиотеки, объявляем функции.

#include #include #include using namespace std; bool deadend(int, int, int**, int, int); // Вспомогательная функция, определяет тупики void visual(int**, int, int); // Изображение результата с помощью консольной графики void mazemake(int**, int, int); // Собственно алгоритм const int wall = 0, pass = 1;

Все еще очень просто, как я и люблю. В main мы сможем определить габариты лабиринта в переменных height и width (напоминаю, что размеры лабиринта исключительно нечетные, издержки алгоритма). Эти параметры можно вынести за пределы main и сделать их константами или просто глобальными переменными, программа от этого не пострадает.

Читайте также:
Какие программы нужны для 3d печати

int main()

Собственно, вот и весь main. Весь лабиринт без проблем сохраняется в двухмерный динамический массив, с которым мы и работаем. После выполнения функции mazemake, в массив maze сохраняется готовый лабиринт, в котором 0 — это стена, а 1 — это проход.

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

bool deadend(int x, int y, int** maze, int height, int width) < int a = 0; if(x != 1)< if(maze[y][x-2] == pass) a+=1; >else a+=1; if(y != 1) < if(maze[y-2][x] == pass) a+=1; >else a+=1; if(x != width-2) < if(maze[y][x+2] == pass) a+=1; >else a+=1; if(y != height-2) < if(maze[y+2][x] == pass) a+=1; >else a+=1; if(a == 4) return 1; else return 0; >

Немного по deadend. Эта функция возвращает значение true если крот в тупике, иначе — false.

Почему дважды if, а не логическое И? Очень просто — первая проверка — на присутствие рядом внешней непроницаемой стены. Непроницаема она по нескольким причинам — мы так сделали, выбрав именно эти габариты, соответственно выделили память для массива (управление памятью, аняня ^>^), да и не очень-то проверишь (-1)-ый элемент массива. Также, обратите внимание на фигурные скобки после первичного if — else относится именно к нему, а другой способ записать это мне неизвестен.

void visual(int** maze, int height, int width) < for(int i = 0; i < height; i++)< for(int j = 0; j < width; j++) switch(maze[i][j])< case wall: coutcout cout

Что еще нужно для счастья? Следующая остановка — mazemake.

void mazemake(int** maze, int height, int width) < int x, y, c, a; bool b; for(int i = 0; i < height; i++) // Массив заполняется землей-ноликами for(int j = 0; j < width; j++) maze[i][j] = wall; x = 3; y = 3; a = 0; // Точка приземления крота и счетчик while(a < 10000)< // Да, простите, костыль, иначе есть как, но лень maze[y][x] = pass; a++; while(1)< // Бесконечный цикл, который прерывается только тупиком c = rand()%4; // Напоминаю, что крот прорывает switch(c)< // по две клетки в одном направлении за прыжок case 0: if(y != 1) if(maze[y-2][x] == wall)< // Вверх maze[y-1][x] = pass; maze[y-2][x] = pass; y-=2; >case 1: if(y != height-2) if(maze[y+2][x] == wall) < // Вниз maze[y+1][x] = pass; maze[y+2][x] = pass; y+=2; >case 2: if(x != 1) if(maze[y][x-2] == wall) < // Налево maze[y][x-1] = pass; maze[y][x-2] = pass; x-=2; >case 3: if(x != width-2) if(maze[y][x+2] == wall) < // Направо maze[y][x+1] = pass; maze[y][x+2] = pass; x+=2; >> if(deadend(x,y,maze,height,width)) break; > if(deadend(x,y,maze,height,width)) // Вытаскиваем крота из тупика do < x = 2*(rand()%((width-1)/2))+1; y = 2*(rand()%((height-1)/2))+1; >while(maze[y][x] != pass); > // На этом и все. >

Слишком просто?

В общем-то да, так и есть. До неприличия просто. Здесь есть все те же двойные if, по той же причине. Даже посетовать не на что. Разве что костыль в виде счетчика.

Если он ранит ваши чувства — добро пожаловать во вторую главу нашего повествования.

Фичи и штуки-дрюки

Комнаты

Рейтинг
( Пока оценок нет )
Загрузка ...
EFT-Soft.ru