Годовой архив: 2014

Генерация лабиринта и его прохождение

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

(далее…)

Генератор уровней

Я решил что следующую игру буду делать с генерируемыми уровнями и сделал некоторые наброски алгоритма для рандомной генерации лабиринтов из связанных комнат разных размеров. Процесс генерации выглядит следующим образом:

Сам алгоритм проще описать картинками нежели кодом:

(далее…)

Многомерные динамические массивы и многомерные векторы

Решил написать для себя маленькую шпаргалку по созданию двухмерного и трёхмерного динамического массива и таких же многомерных векторов (STL vector), но понял, что она будет полезна не только мне, поэтому я решил поделиться ей с вами :)

Двухмерный вектор

#include <vector>
using std::vector;

#define HEIGHT 5
#define WIDTH 3

int main() {
  vector<vector<double> > array2D;

  // Устанавливаем размерность (HEIGHT x WIDTH)
  array2D.resize(HEIGHT);
  for (int i = 0; i < HEIGHT; ++i)
      array2D[i].resize(WIDTH);

  // Помещаем некоторые значения
  array2D[1][2] = 6.0;
  array2D[3][1] = 5.5;

  return 0;
}

(далее…)

Игра «Escape From Space Shredder»

cut_1

Это моя вторая игра :)

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

Сторителинг:

Главный герой — это космический скафандр, оснащённый искусственным интеллектом. Он является членом команды орбитальной станции Протей, состоящей из двоих: из скафандра и его лучшего друга астронавта Джейка.

Однажды экипаж корабля принимает посылку с Земли, в которой помимо научного оборудования, находится робот, отправленный в качестве помощника. Они включают его, но…он выходит из строя и нападает на них. Бракованный робот силой заталкивает скафандр в машину по утилизации космического мусора, а астронавта берёт в заложники.

Герой должен вырваться из плена, пройдя все уровни утилизации и спасти астронавта!

Escape_From_Space_Shredder_2014_09_01_17_18_35_899

Escape_From_Space_Shredder_2014_09_01_17_22_55_972

Escape_From_Space_Shredder_2014_09_01_17_23_03_595

Escape_From_Space_Shredder_2014_09_01_17_23_38_622

Escape_From_Space_Shredder_2014_09_01_17_23_58_839

Проект написан на С++ в Qt Creator с использованием SFML и Box2d.
Весь арт нарисован моими сестрёнками, за что им отдельное спасибо. :)
Вся музыка в игре за авторством DST.

Поддерживаемые платформы Windows / Linux.

Игра принимает участие в Games Jam 2014, так что игру можно пощупать ;) вот ссылка https://gamesjam.org/989/. (на конкурсе демо-версия с урезанным количеством уровней)

Полную версию игры можно приобрести здесь:

Фигуры

Введение

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

Общие свойства фигур

Трансформация (позиция, поворот, масштаб)

Это свойство является общим для всех графических классов SFML, поэтому они описаны в отдельном руководстве: (пока тут ссылка на не переведённый оригинал).

Цвет

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

sf::CircleShape shape(50);

// задаём фигуре зелёный цвет
shape.setFillColor(sf::Color(100, 250, 50));

graphics-shape-color

 

(далее…)

Текст и шрифты

Загрузка шрифта

Перед рисованием текста, вам нужно загрузить шрифт. Для работы со шрифтами используется специальный класс sf::Font. Он поддерживает три главных операции: загрузка шрифта, получение из него глифов (визуальных символов) и чтение его атрибутов.

Начнём с загрузки. Самый простой способ загрузить шрифт, это загрузить его из файла на диске, сделать это можно при помощи функции loadFromFile().

sf::Font font;
if (!font.loadFromFile("arial.ttf"))
{
 // ошибка...
}

(далее…)

Спрайты и текстуры

Термины

Вероятно вы уже знакомы с этими терминами, но всё же давайте кратко их определим.

Текстура — это изображение. Мы же называем изображение «текстурой» из-за его специфической роли: их наносят на 2D объекты.

Спрайт — это текстурированный прямоугольник.

graphics-sprites-definition

Загрузка текстуры

(далее…)

Рисование 2D объектов

Окно для рисования

Для рисования объектов с помощью графического модуля, вам необходимо использовать специальный класс окна: sf::RenderWindow. Этот класс является наследником класса sf::Window и обладает всем методами класса родителя. Всё что вы изучили о sf::Window (создание, обработка событий, настройка частоты кадров, смешанное использование с OpenGL и т.д.), применимо и к sf::RenderWindow.

Помимо этого, sf::RenderWindow имеет методы облегчающие задачу рисования объектов. В этом уроке мы сосредоточимся на двух таких методах: clear() и draw(). Они просты как и их названия: clear() очищает окно выбранным цветом, а draw() рисует любой переданный ему объект.

Так выглядит типичный главный цикл с окном визуализации (render window):

(далее…)

Клавиатура, мышь и джойстик

Введение

Этот урок объясняет как получить доступ к глобальным ресурсам (global inputs): клавиатуре, мыши и джойстику. Не следует путать их с событиями: ресурсы в режиме реального времени позволяют запросить глобальные состояния клавиатуры, мыши и джойстика в любое время («Эта кнопка нажата в данный момент?», «Где мышь?»). В то время как события уведомляют вас когда что-то происходит («Эта кнопка была нажата», «Мышь переместилась»).

Клавиатура

Класс, предоставляющий доступ к состоянию клавиатуры, — sf::Keyboard. Он содержит только один метод isKeyPressed(), который проверяет текущее состояние клавиши (нажата или отпущена). Это статический метод, и поэтому вам не нужно создавать экземпляр класса sf::Keyboard что бы воспользоваться им.

Эта функция напрямую считывает состояние клавиатуры игнорируя факт, что ваше окно активно или неактивно.

if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
{
 // нажата клавиша влево: сдвинем нашего героя
 character.move(1, 0);
}

Коды клавиш определены в перечислении sf::Keyboard::Key.

Коды некоторых клавиш могут отсутствовать или быть неправильно интерпретированы в зависимости от ОС и раскладки клавиатуры. Это будет улучшено в следующих версиях
SFML.

(далее…)

События

Введение

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

Тип sf::Event

Прежде чем перейти к событиям, важно понять что из себя представляет тип sf::Event и как правильно им пользоваться. sf::Event — это объединение, а значит, что только один из членов этого объединения допустим (т.е. существует) в данный момент времени (все элементы объединения хранятся в одной области памяти; за подробностями — в любой учебник по с++). Допустимым членом является тот, который соответствует типу события, например event.key для события KeyPressed. Попытка считывания другого члена приведёт к неопределённому поведению (скорее всего вы получите недопустимые или случайные значения). Поэтому никогда не пытайтесь использовать член события, который не соответствуют типу этого события.

Экземпляры sf::Event в качестве аргументов принимаются методом pollEvent() (или waitEvent()) класса sf::Window. Только две эти функции могут предоставить допустимые события, любая попытка использовать sf::Event без предварительного успешного вызова pollEvent() (или waitEvent()) приведёт к такому же неопределённому поведению, о котором говорилось выше.

Для большей ясности, вот так выглядит типичный цикл с использованием событий:

sf::Event event;

// пока имеются события в очереди...
while (window.pollEvent(event))
{
    // проверка типа события...
    switch (event.type)
    {
        // закрытие окна
        case sf::Event::Closed:
            window.close();
            break;

        // нажатие клавиш
        case sf::Event::KeyPressed:
            ...
            break;

        // мы не обрабатываем другие типы событий
        default:
            break;
    }
}

(далее…)