Примеры игр на си с исходниками. Исходные тексты игр (240)

Примеры игр на си с исходниками. Исходные тексты игр (240)
Примеры игр на си с исходниками. Исходные тексты игр (240)
118.0 Kb новый

2D-игра написана на JavaScript ES6 HTML5, 17-уровней.

Прислал: xAtom | JavaScript | Любая ОС

  • Змейка(WinAPI) 255.8 Kb

    Игра 2D, написана на WinAPI, в среде CodeBlocks 17.12(unicode) на C++14.

    Прислал: xAtom | Visual C++ | Windows NT/2000/XP/Vista/7

  • xzGame - крестики нолики 3.9 Kb

    крестики нолики со вкусом))
    сами увидите обязательно прочитете тхт файл

    [email protected]
    по любому вопросу

    Прислал: kalandar | C/C++ | Windows NT/2000/XP/Vista/7

  • 501

    Пример простой Raycast графики с возможностью перемещения по карте, и вращения камеры, на ассемблере компилятор FASM, работает в реальном режиме. Используется 13h видео режим BIOS 320х200, 256 цветовой режим.

    Используются прерывания BIOS
    - INT 10h
    - INT 16h

    Возможности графической оболочки:
    - Заливка экрана
    - Рисование спрайтов
    - Рисования прямоугольников (простых линий)
    Особенности графической оболочки
    - Небольшой вес, простота
    - Использование видео буфера для создания фрейма

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

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

    Исходник игры (source):
    http://catcut.net/CAPB
    Канал ютуб:
    https://www.youtube.com/ТипаПрограммист
    Сайт проекта:
    http://neosoft.pp.ua

    Прислал: Типа Программист | Assembler | Любая ОС

  • Исходники программы ConfigIL2 5265.1 Kb

    Исходники программы для настройки параметров игры Ил-2. Язык программирования VB6. В архиве все неоходимые файлы и ресурсы, в том числе подключаемые библиотеки.

    Прислал: Alik044 | Visial Basic | Windows NT/2000/XP/Vista/7

  • City Race 12255.4 Kb

    Игра каких-то даунов из команды Gravity Games, игра не очень, вся баганутая. В этой 2Д гонке есть повреждение машин, турбо и т.п. Игра создана на Construct 2.

    Прислал: adminds | документ | Любая ОС

  • Гусеничный робот 1637.6 Kb

    2D-игра Гусеничный робот, 12-уровней игра создана в среде Eclipse для Android.

    Прислал: xAtom | Java | Другая ОС

  • Ассемблер клеточный автомат, игра 501

    Клеточный автомат, или игра "жизнь" на ассемблере, компилятор FASM, работает в реальном режиме. Используется 13h видео режим BIOS 320х200, 256 цветовой режим. Данный код работает на голом железе в реальном режиме.


    http://catcut.net/tihx


    http://catcut.net/7Nqw

    [email protected]

    Сайт проекта:
    http://neosoft.pp.ua

    Прислал: Типа Программист | Assembler | Любая ОС

  • Ассемблер игра шашки 501

    Заготовка для создания игры шашки на ассемблере, компилятор FASM, работает в реальном режиме. Используется 13h видео режим BIOS 320х200, 256 цветовой режим.
    В этом исходнике нету условий победы, поражения, а так-же нету дамок.

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

    Исходник можно скачать здесь:
    http://catcut.net/5ZGy
    Так-же есть канал проекта, где иногда появляються видео, исходники новых программ:
    https://www.youtube.com/channel/UCTVn_Azy0WTDGAh7OYNReJg?view_as=subscriber

    И да у канала есть свой сервер с иходниками, где в основном исходники на ассемблере (почти все мусор), а так-же есть на С++, операционная система на Си, и программа на Паскале:
    http://catcut.net/7Nqw
    При желании добавить свой исходник на сервер, пишите мне на почту:
    [email protected]
    (Да да анонимность не мой конек...)

    Сайт проекта:
    http://neosoft.pp.ua

    Прислал: Типа Программист | Assembler | Любая ОС

  • Приключение шарика 1537.6 Kb

    2D-игра Приключение шарика, 25 уровней. Для Android, игра создана при помощи Eclipse.

    Прислал: xAtom | Java | Другая ОС

  • Простая игра на ассемблере, кто вытянет спичку последним. 501

    Простая игра на двоих проиграет тот кто тянет спичку последним.
    (Игра простая, но преимущество, возможен ее запуск без ОС)

    Исходник можно скачать здесь:
    http://catcut.net/YMqw
    Так-же есть канал проекта, где иногда появляються видео, исходники новых программ:
    https://www.youtube.com/channel/UCTVn_Azy0WTDGAh7OYNReJg?view_as=subscriber

    И да у канала есть свой сервер с иходниками, где в основном исходники на ассемблере (почти все мусор), а так-же есть на С++, операционная система на Си, и программа на Паскале:
    http://catcut.net/7Nqw
    При желании добавить свой исходник на сервер, пишите мне на почту:
    [email protected]
    (Да да анонимность не мой конек...)

    Прислал: Типа Программист | Assembler | Другая ОС

  • Простая графическа игра на ассемблере. 501

    Простая игра на ассемблере, компилятор FASM, работает в реальном режиме. Используется 13h видео режим BIOS 320х200, 256 цветовой режим. Примитивная коллизия по ширине, высоте.

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

    Исходник можно скачать здесь:
    http://catcut.net/KMqw

    Так-же есть канал проекта, где иногда появляються видео, исходники новых программ:
    https://www.youtube.com/channel/UCTVn_Azy0WTDGAh7OYNReJg?view_as=subscriber

    И да у канала есть свой сервер с иходниками, где в основном исходники на ассемблере (почти все мусор), а так-же есть на С++, операционная система на Си, и программа на Паскале:
    http://catcut.net/7Nqw
    При желании добавить свой исходник на сервер, пишите мне на почту:
    [email protected]
    (Да да анонимность не мой конек...)

  • Видеоигры на протяжении уже более 30 лет активно развиваются, начиная от геймплея и графических возможностей, вплоть до продвинутых систем искусственного интеллекта и восприятия пользователями подаваемого разработчиками материала. Киберспорт, в свою очередь, является полноценным видом спорта с многомиллионными призами и миллиардными оборотами. А сама индустрия видеоигр неустанно набирает обороты, являясь одной из наиболее кассовых и массовых ответвлений сферы развлечений. А ко всему этому человечество пришло от примитивнейшей реализации «тенниса», запускавшейся на осциллографе.


    Я, как первокурсник, решил в рамках изучения базовых консольных возможностей C/C++ возможно запрограммировать "классическую" ASCII-игру, требующую от игрока скорости мышления, непрерывного взаимодействия с игрой, а также обладающую несложной графической частью, которую игрок мог бы интерпретировать в некое подобие трехмерного изображения.


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

    Вдохновление

    На заре появления на рынке мобильных телефонов с монохромными дисплеями выделилась игра «Space Impact», прошивавшаяся в аппаратах Nokia. Она отлично вписалась в ограниченные возможности тогдашних сотовых. После введения простых игр в мобильные телефоны – продажи аппаратов резко возросли, а мобильный гейминг постепенно стал популярным, и сейчас вполне конкурирует со индустрией «взрослых» ААА-проектов.


    «Space Impact» и послужила основой для моей первой игры ввиду своей легкости исполнения и популярности в начале 2000-х.

    Особенности «Space Invader»

    В первую очередь – легковесность программы. Исполняемый файл занимает менее 100 кб и будет работать, как задумано, практически на любом компьютере под OC Windows с пакетом Visual C++.


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


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


    Наипростейший интуитивно понятный интерфейс, не требующий описания или инструкций по использованию.


    • Подпункт «Новая игра» - запускает новый игровой сеанс.
    • Подпункт «Продолжить» - загружает последнюю сохраненную игру из бинарного файла в директории исполняемого файла и запускает игровой сеанс с использованием полученных данных.
  • Пункт «Помощь» - инструкции по работе с приложением и его описание. Пролистываются по нажатию стрелок на клавиатуре.
  • Пункт «Зал славы» - список лидеров игровых сессий, загружается из бинарного файла в директории исполняемого файла и форматированно выводится в консоль.
  • Пункт «Выход» - выход из приложения.
  • Сдвигающийся влево «мир» с динамической скоростью. «Мир» содержит рандомные поля сверху и снизу толщиной в 1 или 2 символа. Также между полями рандомно появляется «космический мусор», отображаемый символом «¤», являющийся препятствием для игрока.
  • Прижатый к левому краю окна «космический корабль». Корабль смещается с помощью стрелок на клавиатуре вверх и вниз, по нажатию пробела выпускает снаряд, уничтожающий «космический мусор» по касанию.
  • «Приборная панель» вверху консоли, отображающая пройденный километраж, текущую скорость и количество оставшихся попыток.
  • Как работает «Space Invader»?

    При запуске приложения возникает заставка-анимация. Она состоит из 6 заранее отформатированных символьных массивов, сменяющихся через каждые 200мс.


    Начальная заставка – итоговый слайд


    Далее идет обращение в функцию главного меню с параметром 1(целое число). Функция отображает меню с выделенным угловыми скобками пунктом меню, номер которого совпадает с входным параметром. Пунктов в меню 4, соответственно входной параметр может различаться от 1 до 4. При нажатии стрелки вниз происходит рекурсивное обращение с инкрементированным входным параметром в том случае, если входной параметр меньше 4, с параметром 1, если входной параметр равен 4. При нажатии Space или Enter происходит обращение к функции, соответствующей выделенному пункту меню.


    void StartMenu(int switcher) { system("cls"); switch (switcher) { case 1: cout << "\n\n\n << ИГРАТЬ! >> << "\n\n\n ИГРАТЬ!\n\n << ПОМОЩЬ! >> << "\n\n\n ИГРАТЬ!\n\n ПОМОЩЬ!\n\n << ЗАЛ СЛАВЫ >> << "\n\n\n ИГРАТЬ!\n\n ПОМОЩЬ!\n\n ЗАЛ СЛАВЫ\n\n << ВЫХОД >>"; break; } int choice = _getch(); if (choice == 224) choice = _getch(); if (choice == 72) if (switcher != 1) StartMenu(switcher - 1); else StartMenu(4); if (choice == 80) if (switcher != 4) StartMenu(switcher + 1); else StartMenu(1); if (choice == 13 || choice == 32) { if (switcher == 1) GameMenu(1); if (switcher == 2) Help(0); if (switcher == 3) TopChart(); if (switcher == 4) _exit(0); } }


    Главное меню (вход в функцию выполнен с параметром 1)


    При обращении к функции, соответствующей пункту «Игра» запускается функция, аналогичная по функционалу, но выбор есть только из 2-х пунктов. Соответственно, входной параметр будет 1 или 2, и при нажатии любой из стрелок (вверх или вниз) нам необходимо лишь сменить цифру на «противоположную». Наиболее оптимизированным будет вариант отнимания входного параметра от 3 (3 – 1 = 2, 3 – 2 = 1).


    void GameMenu(int switcher) { system("cls"); if (switcher == 1) cout << "\n\n\n\n\n << НОВАЯ ИГРА! >> << "\n\n\n\n\n НОВАЯ ИГРА!\n\n << ПРОДОЛЖИТЬ! >>"; int choice = _getch(); if (choice == 224) choice = _getch(); if (choice == 72 || choice == 80) GameMenu(3 - switcher); if (choice == 27) StartMenu(1); if (choice == 13 || choice == 32) Game(switcher); }


    Дополнительное меню (вход в функцию выполнен с параметром 1)


    Теперь к основному – процессу игры. При выборе подпункта «Новая игра» - запускается новый игровой сеанс. Создается двумерный массив, размерностью 14 строк на 50 столбцов. Первая строка выделяется под приборную панель. Первый прибор – количество пройденных километров, оно равно количеству обновлений консоли (изначально консоль обновляется раз в 80мс, с каждым обновлением этот параметр декрементируется, пока не достигнет значения 25).


    int odometerBuf = odometer, odometerDigitLength; for (odometerDigitLength = 0; odometerBuf != 0; odometerBuf /= 10, odometerDigitLength++);//вычисление количества цифр на одометре for (int i = odometerDigitLength, odometerBuf = odometer; i >= 0; i--, scr[i] = odometerBuf % 10 + "0", odometerBuf /= 10);//прорисовка одометра на приборную панель scr = "К"; scr = "М";//дописывание "КМ" odometer++;//наращение одометра

    Второй прибор, текущая скорость, являет собой формулу - 1000/скорость обновления консоли. Скорость измеряется в километрах в секунду. Таким образом, изначально корабль движется со скоростью 12км/с, и через некоторое время достигает отметки в 40 км/с.


    speed = 1000 / timer;//обновление спидометра int speedBuf = speed; for (int i = 42; speed != 0; i--, scr[i] = speed % 10 + "0", speed /= 10);//прорисовка спидометра на приборную панель scr = "К"; scr = "М"; scr = "/"; scr = "С";//дописывание "КМ/С"

    Третий прибор отображает количество оставшихся попыток, изначально их 3. Попытки отображаются символом «&».


    for (int i = 50; lifes > 0; i--, lifes--, scr[i] = "&");


    Приборная панель в начале игрового сеанса


    Следующие 2 строки, как и последние 2 – являются полями игры. Декорации полей выбираются случайным образом, могут состоять из 3-х символов или пробела. Крайние строки всегда полностью заполнены, а вторая и предпоследняя содержит символы, отличные от пробела лишь в тех местах, где эти символы «растут» из других.


    char borderSymbols = { "†", "‡", "¤", " " }; for (int aboveBelow = 0; aboveBelow < 50; aboveBelow++)//прорисовка верхнего и нижнего полей (2 + 2) { scr = borderSymbols; if (scr == "‡") scr = "¤"; scr = borderSymbols; if (scr == "‡") scr = "¤"; }


    Приборная панель и поля в начале игрового сеанса


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


    scr = "\\"; scr = "\\";//прорисовка корабля scr = "3"; scr = "="; scr = "="; scr = "/"; scr = "/";

    Управлять ним можно стрелками вверх и вниз.


    if (_kbhit())//если клавиша была нажата { control = _getch();//переменная примет ее значение if (control == 224) control = _getch(); } if (control == 72)//при движении корабля вверх if (scr == "\\" || scr == "\\" && scr == "¤" || scr == "\\" && scr == "¤")//если корабль врезался в верхнее поле - игра окончена if (lifes > 1) { cout << "\a"; lifes--; weaponPos = 7; GameStart(scr, lifes, &timer); Sleep(1000); } else GameOver(odometer); else { for (int i = 2; i < 13; i++)//корабль смещается на элемент выше for (int j = 0; j < 49; j++) if (scr[i][j] == "3" || scr[i][j] == "\\" || scr[i][j] == "=" || scr[i][j] == "/") { scr[j] = scr[i][j]; scr[i][j] = " "; } weaponPos--; } if (control == 80)//при движении корабля вниз if (scr == "/" || scr == "/" && scr == "¤" || scr == "/" && scr == "¤")//если корабль врезался в нижнее поле - игра окончена if (lifes > 1) { cout << "\a"; lifes--; weaponPos = 7; GameStart(scr, lifes, &timer); Sleep(1000); } else GameOver(odometer); else { for (int i = 12; i > < 49; j++) if (scr[i][j] == "3" || scr[i][j] == "\\" || scr[i][j] == "=" || scr[i][j] == "/") { scr[j] = scr[i][j]; scr[i][j] = " "; } weaponPos++; }


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


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


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


    for (int i = 1; i < 14; i++)//все "космические" элементы смещаются на элемент влево for (int j = 0; j < 49; j++) { if (scr[i][j] == "\\" && scr[i] == "¤" || scr[i][j] == "=" && scr[i] == "¤" || scr[i][j] == "/" && scr[i] == "¤") if (lifes > 1) { cout << "\a"; lifes--; weaponPos = 7; GameStart(scr, lifes, &timer); Sleep(1000); } else GameOver(odometer); if (scr[i][j] != "3" && scr[i][j] != "\\" && scr[i][j] != "=" && scr[i][j] != "/" && scr[i][j] != "-" && scr[i] != "-") scr[i][j] = scr[i]; if (scr[i][j] == "¤") scr[i] = " "; } for (int i = 1; i < 14; i++)//все снаряды смещаются на элемент вправо for (int j = 48; j > < 12; i++)//рандомное появление космического мусора { if (rand() % 10 == 1) scr[i] = "¤"; }

    При движении корабля вверх или вниз в этот момент космический мусор будет уничтожен без урона кораблю, все благодаря отбойникам



    Если в данный момент не увернуться от мусора стрелкой вниз – корабль будет разбит


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


    Впрочем, хоть поля состоят из материалов, схожих на космический мусор, их нельзя разрушить отбойниками. Соприкосновение любой части корабля с полями приводит к неминуемому краху. Также, как и попадание космического мусора в лицевую часть корабля. Если в такие моменты на приборной панели есть обозначение еще хотя бы одной «попытки» - игра как будто начинается сначала, но сохранив набранный счет и потеряв одну «попытку». Скорость же сбрасывается до начального значения в 12км/с.


    Если же игрок «разбился», а попыток не осталось – игровой сеанс заканчивается, а игроку предлагается ввести его имя, чтобы сохранить свой результат в «зале славы».



    Предложение игроку ввести имя, чтобы сохранить свой результат в «зале славы»


    Приложение обрабатывает 2 файла:

    • «TopChart.bin» - двоичный файл для хранения таблицы лидеров. Данные хранятся в структурах (ник игрока, его счет, дата завершения игрового сеанса). Данные дозаписываются в конец файла при окончании игры. При вызове пункта «Зал славы» файл открывается для чтения с возможностью редактирования. Далее объявляется динамический массив структур, в который переписываются данные из файла, после чего массив сортируется и форматированно выводится в консоль (максимально возможное число результатов – 12, если массив содержит 13 результатов – последний отбрасывается после сортировки). Далее файл перезаписывается массивом структур результатов, после чего массив уничтожается.
    • «CurrentSave.bin» - двоичный файл для хранения сохраненной игры. Вызывается для чтения при запуске подпункта «Продолжить» пункта «Игра». Может содержать данные для восстановления одного незавершенного игрового сеанса: номер строки, в которой содержится нос корабля, количество пройденных километров, количество оставшихся попыток, расположение обьектов на экране. С помощью этих данных формируется игровой сеанс, в точности повторяющий незавершенный. Во избежание нечестной игры, при загрузке сеанса из файла – файл удаляется. При нажатии Escape во время игры данный файл создается, и в него записываются все необходимые данные для успешного дальнейшего продолжения игрового сеанса.

    Пункт главного меню «Помощь» - функция, принимающая параметр от 0 до 22, отображающая последующие 12 строк по 50 символов от входного параметра. Управление осуществляется рекурсивно с помощью стрелок вверх и вниз.


    void Help(int switcher) { system("cls"); cout << "ПРОКРУТКА: СТРЕЛКИ ВВЕРХ/ВНИЗ | ВЕРНУТЬСЯ: ESCAPE\n"; char arr = { " УПРАВЛЕНИЕ В МЕНЮ Передвигаться по пунктам – СТРЕЛКИ ВВЕРХ/ВНИЗ Выбрать пункт – ПРОБЕЛ или ENTER Вернуться в предыдущее меню – ESCAPE УПРАВЛЕНИЕ В ИГРЕ Передвигаться вверх/вниз – СТРЕЛКИ ВВЕРХ/ВНИЗ Сделать выстрел – ПРОБЕЛ Вернуться в меню, сохранив игру – ESCAPE БРИФИНГ Вы – пилот космического корабля, попавшего в космическую бурю. Вам необходимо не разбиться и пролететь как можно большее расстояние. Корабль оборудован динамическим управлением. Чем быстрее вы летите – тем острее поворачивает судно. Корабльавтоматически постепенно разгоняется до 40 км/с. Вы можете сбивать космический мусор с помощью магнитной пушки, встроенной в судно, а также боковыми отбойниками. При управлении кораблем на щитке приборов отображается пройденная дистанция, текущая скорость и количество оставшихся «ячеек отката» (отображаются символом «&»), изначально их 3. Если решите прекратить игру – просто нажмите ESCAPE. Игра сохранится, и вы сможете ее продолжить даже после перезапуска приложения с помощью пункта «ПРОДОЛЖИТЬ!». В главном меню можно посмотреть таблицу почетных пилотов. Добейтесь своего права там оказаться! АВТОРСТВО Svjatoslav Laskov – AUTHOR Igor Marchenko – COACH National Technical University «Kharkiv Polytechnic Institute» 2016" }; for (int i = 0, buf = switcher; i < 13; i++) { for (int j = buf * 50; j < buf * 50 + 50; j++) cout << arr[j]; if (i != 12) cout << endl; buf++; } int controller = _getch();//получить значение нажатой клавиши if (controller == 224)//если была нажата стрелка controller = _getch();//то определить какая именно if (controller == 72)//если стрелка вверх if (switcher > < 22) Help(switcher + 1); else Help(22); if (controller == 27)//если Escape StartMenu(2); }

    Пункт главного меню «Выход» - осуществляет выход из приложения.


    Руководство пользователя

    УПРАВЛЕНИЕ В МЕНЮ
    o Передвигаться по пунктам – СТРЕЛКИ ВВЕРХ/ВНИЗ
    o Выбрать пункт – ПРОБЕЛ или ENTER
    o Вернуться в предыдущее меню – ESCAPE
    УПРАВЛЕНИЕ В ИГРЕ
    o Передвигаться вверх/вниз – СТРЕЛКИ ВВЕРХ/ВНИЗ
    o Сделать выстрел – ПРОБЕЛ
    o Вернуться в меню, сохранив игру – ESCAPE
    БРИФИНГ
    Вы – пилот космического корабля, попавшего в космическую бурю. Вам необходимо не разбиться и пролететь как можно большее расстояние.


    Корабль оборудован динамическим управлением. Чем быстрее вы летите – тем острее поворачивает судно. Корабль автоматически постепенно разгоняется до 40 км/с.


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


    Если решите прекратить игру – просто нажмите ESCAPE. Игра сохранится, и вы сможете ее продолжить даже после перезапуска приложения с помощью пункта «ПРОДОЛЖИТЬ!».


    В главном меню можно посмотреть таблицу почетных пилотов. Добейтесь своего права там оказаться!

    Итог

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


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


    Исходный код

    #include "conio.h" #include "windows.h" #include "ctime" #include using namespace std; struct player//определение структуры, хранящей данные о результатах какого-либо завершенного игрового сеанса { char name; int score; int mday; int mon; int year; }; struct save//определение структуры, хранящей данные о незавершенном игровом сеансе { int weaponPos; int timer; int odometer; int lifes; char scr; }; void ScreenOutput(char scr)//функция поэлементного вывода массива в консоль { system("cls"); for (int i = 0; i < 14; i++) { for (int j = 0; j < 50; j++) cout << scr[i][j]; if (i != 13) cout << endl; } } //блок прототипов функций void StartMenu(int switcher);//функция, вызывающаяся из главного меню, содержит пункты "ИГРА" и "ПРОДОЛЖИТЬ" void GameMenu(int switcher);//функция главного меню void GameStart(char scr, int lifes, int *timer);//функция, определяющая начальный символьный массив при запуске нового игрового сеанса void Game(int var);//функция игровго сеанса void GameOver(int score);//функция, спрашивающая имя игрока, и записывающая его результат в бинарный файл void Help(int switcher);//функция помощи игроку void TopChart();//функция "ЗАЛ СЛАВЫ" - отображает список лидеров void Help(int switcher) { system("cls"); cout << "ПРОКРУТКА: СТРЕЛКИ ВВЕРХ/ВНИЗ | ВЕРНУТЬСЯ: ESCAPE\n"; char arr = { " УПРАВЛЕНИЕ В МЕНЮ Передвигаться по пунктам – СТРЕЛКИ ВВЕРХ/ВНИЗ Выбрать пункт – ПРОБЕЛ или ENTER Вернуться в предыдущее меню – ESCAPE УПРАВЛЕНИЕ В ИГРЕ Передвигаться вверх/вниз – СТРЕЛКИ ВВЕРХ/ВНИЗ Сделать выстрел – ПРОБЕЛ Вернуться в меню, сохранив игру – ESCAPE БРИФИНГ Вы – пилот космического корабля, попавшего в космическую бурю. Вам необходимо не разбиться и пролететь как можно большее расстояние. Корабль оборудован динамическим управлением. Чем быстрее вы летите – тем острее поворачивает судно. Корабльавтоматически постепенно разгоняется до 40 км/с. Вы можете сбивать космический мусор с помощью магнитной пушки, встроенной в судно, а также боковыми отбойниками. При управлении кораблем на щитке приборов отображается пройденная дистанция, текущая скорость и количество оставшихся «ячеек отката» (отображаются символом «&»), изначально их 3. Если решите прекратить игру – просто нажмите ESCAPE. Игра сохранится, и вы сможете ее продолжить даже после перезапуска приложения с помощью пункта «ПРОДОЛЖИТЬ!». В главном меню можно посмотреть таблицу почетных пилотов. Добейтесь своего права там оказаться! АВТОРСТВО Svjatoslav Laskov – AUTHOR Igor Marchenko – COACH National Technical University «Kharkiv Polytechnic Institute» 2016" }; for (int i = 0, buf = switcher; i < 13; i++) { for (int j = buf * 50; j < buf * 50 + 50; j++) cout << arr[j]; if (i != 12) cout << endl; buf++; } int controller = _getch();//получить значение надатой клавиши if (controller == 224)//если была нажата стрелка controller = _getch();//то определить какая именно if (controller == 72)//если стрелка вверх if (switcher > 0) Help(switcher - 1); else Help(0); if (controller == 80)//если стрелка вниз if (switcher < 22) Help(switcher + 1); else Help(22); if (controller == 27)//если Escape StartMenu(2); } void StartMenu(int switcher) { system("cls"); switch (switcher) { case 1: cout << "\n\n\n << ИГРАТЬ! >>\n\n ПОМОЩЬ!\n\n ЗАЛ СЛАВЫ\n\n ВЫХОД"; break; case 2: cout << "\n\n\n ИГРАТЬ!\n\n << ПОМОЩЬ! >>\n\n ЗАЛ СЛАВЫ\n\n ВЫХОД"; break; case 3: cout << "\n\n\n ИГРАТЬ!\n\n ПОМОЩЬ!\n\n << ЗАЛ СЛАВЫ >>\n\n ВЫХОД"; break; case 4: cout << "\n\n\n ИГРАТЬ!\n\n ПОМОЩЬ!\n\n ЗАЛ СЛАВЫ\n\n << ВЫХОД >>"; break; } int choice = _getch(); if (choice == 224) choice = _getch(); if (choice == 72) if (switcher != 1) StartMenu(switcher - 1); else StartMenu(4); if (choice == 80) if (switcher != 4) StartMenu(switcher + 1); else StartMenu(1); if (choice == 13 || choice == 32) { if (switcher == 1) GameMenu(1); if (switcher == 2) Help(0); if (switcher == 3) TopChart(); if (switcher == 4) _exit(0); } } void GameMenu(int switcher) { system("cls"); if (switcher == 1) cout << "\n\n\n\n\n << НОВАЯ ИГРА! >>\n\n ПРОДОЛЖИТЬ!"; else cout << "\n\n\n\n\n НОВАЯ ИГРА!\n\n << ПРОДОЛЖИТЬ! >>"; int choice = _getch(); if (choice == 224) choice = _getch(); if (choice == 72 || choice == 80) GameMenu(3 - switcher); if (choice == 27) StartMenu(1); if (choice == 13 || choice == 32) Game(switcher); } void GameStart(char scr, int lifes, int *timer) { for (int i = 0; i < 14; i++)//очищение от мусора for (int j = 0; j < 50; j++) scr[i][j] = " "; for (int i = 50; lifes > 0; i--, lifes--, scr[i] = "&"); *timer = 80; char borderSymbols = { "†", "‡", "¤", " " }; for (int aboveBelow = 0; aboveBelow < 50; aboveBelow++)//прорисовка верхнего и нижнего полей (2 + 2) { scr = borderSymbols; if (scr == "‡") scr = "¤"; scr = borderSymbols; if (scr == "‡") scr = "¤"; } scr = "\\"; scr = "\\";//прорисовка корабля scr = "3"; scr = "="; scr = "="; scr = "/"; scr = "/"; } void GameOver(int score) { system("cls"); player newPlayer;//объявляние структуры newPlayer.score = score;//инициализацие поля набранного счета cout << "Поздравляем Вас!\nВы продержались " << score << " километров.\n\n(Пожалуйста, не используйте кириллические символы)\n(Используйте не более 6 символов)\nОставьте свое имя и станьте примером\nдля подражания будущим игрокам: "; cin.getline(newPlayer.name, 7);//инициализацие поля имени time_t timeCur; time(&timeCur); struct tm * timeCurStruct = localtime(&timeCur); newPlayer.mday = timeCurStruct->tm_mday;//инициализацие даты завершения игры newPlayer.mon = timeCurStruct->tm_mon; newPlayer.year = timeCurStruct->tm_year; FILE *topChart; fopen_s(&topChart, "TopChart.bin", "ab+"); fwrite(&newPlayer, 1, sizeof(player), topChart);//дозапись результата в файл fclose(topChart); TopChart(); } void TopChart() { FILE *topChart; fopen_s(&topChart, "TopChart.bin", "rb+"); system("cls"); if (topChart == NULL)//если произошла ошибка при открытии файла { system("cls"); cout << "Нет ни единого результата."; Sleep(1000); system("cls"); cout << "Нет ни единого результата.."; Sleep(1000); system("cls"); cout << "Нет ни единого результата..."; Sleep(1000); cout << "\nНажмите любую клавишу, чтобы вернуться."; _getch(); StartMenu(3); } fseek(topChart, 0L, SEEK_END); int playerAmount = ftell(topChart) / sizeof(player); player *temp = new player; fseek(topChart, 0L, SEEK_SET); for (int i = 0; i < playerAmount; i++)//копирование содержиомого файла в структкры fread(&temp[i], 1, sizeof(player), topChart); fclose(topChart); for (int i = 1; i < playerAmount; i++)//сортировка структур по спаданию итоговых счетов if (temp[i].score > temp.score) { player tempAlone; strcpy(tempAlone.name, temp[i].name); tempAlone.score = temp[i].score; tempAlone.mday = temp[i].mday; tempAlone.mon = temp[i].mon; tempAlone.year = temp[i].year; strcpy(temp[i].name, temp.name); temp[i].score = temp.score; temp[i].mday = temp.mday; temp[i].mon = temp.mon; temp[i].year = temp.year; strcpy(temp.name, tempAlone.name); temp.score = tempAlone.score; temp.mday = tempAlone.mday; temp.mon = tempAlone.mon; temp.year = tempAlone.year; if (i > 1) i -= 2; else i = 0; } if (playerAmount > 12) playerAmount = 12; cout << "№ " << "Имя" << "\t" << "Счет" << "\t" << "Дата" << endl;//вывод таблицы лидеров в консоль for (int i = 0; i < playerAmount; i++) { cout << i + 1 << ")" << "\t" << temp[i].name << "\t" << temp[i].score << "\t"; if (temp[i].mday / 10 == 0) cout << "0" << temp[i].mday; else cout << temp[i].mday; cout << " "; switch (temp[i].mon) { case 0: cout << "января"; break; case 1: cout << "февраля"; break; case 2: cout << "марта"; break; case 3: cout << "апреля"; break; case 4: cout << "мая"; break; case 5: cout << "июня"; break; case 6: cout << "июля"; break; case 7: cout << "августа"; break; case 8: cout << "сентября"; break; case 9: cout << "октября"; break; case 10: cout << "ноября"; break; case 11: cout << "декабря"; break; } cout << " " << 1900 + temp[i].year << endl; } fopen_s(&topChart, "TopChart.bin", "wb+"); for (int i = 0; i < playerAmount; i++)//запись таблицы лидеров в бинарный файл fwrite(&temp[i], 1, sizeof(player), topChart); fclose(topChart); delete temp; _getch(); StartMenu(3); } int main() { setlocale(LC_ALL, "Rus");//задание кодировки system("mode con cols=51 lines=14");//задание размеров окна консоли system("title Space Invader");//задание описания окна консоли system("color 0A");//задание цвета консоли (0-задний фон; А-передний фон) HANDLE hCons = GetStdHandle(STD_OUTPUT_HANDLE);//получение хендла CONSOLE_CURSOR_INFO cursor = { 100, false };//число от 1 до 100 размер курсора в процентах; false\true - видимость SetConsoleCursorInfo(hCons, &cursor);//применение заданных параметров курсора int timer = 200; cout << " (____/(__) \\_/\\_/ \\___)(____)\n\n\n\n\n\n\n\n\n\n\n __ __ _ _ _ __ ____ ____ ____\n ()((\\/)(\\ / _\\ (\\(__)(_ \\";//вступительная заставка Sleep(timer); system("cls"); cout << " \\___ \\) __// \\((__) _)\n (____/(__) \\_/\\_/ \\___)(____)\n\n\n\n\n\n\n\n\n __ __ _ _ _ __ ____ ____ ____\n ()((\\/)(\\ / _\\ (\\(__)(_ \\\n)(/ /\\ \\/ // \\) D () _)) /";//вступительная заставка Sleep(timer); system("cls"); cout << " / ___)(_ \\ / _\\ / __)(__)\n \\___ \\) __// \\((__) _)\n (____/(__) \\_/\\_/ \\___)(____)\n\n\n\n\n\n\n __ __ _ _ _ __ ____ ____ ____\n ()((\\/)(\\ / _\\ (\\(__)(_ \\\n)(/ /\\ \\/ // \\) D () _)) /\n (__)\\_)__) \\__/ \\_/\\_/(____/(____)(__\\_)";//вступительная заставка Sleep(timer); system("cls"); cout << " ____ ____ __ ___ ____\n / ___)(_ \\ / _\\ / __)(__)\n \\___ \\) __// \\((__) _)\n (____/(__) \\_/\\_/ \\___)(____)\n\n\n\n\n __ __ _ _ _ __ ____ ____ ____\n ()((\\/)(\\ / _\\ (\\(__)(_ \\\n)(/ /\\ \\/ // \\) D () _)) /\n (__)\\_)__) \\__/ \\_/\\_/(____/(____)(__\\_)";//вступительная заставка Sleep(timer); system("cls"); cout << "\n ____ ____ __ ___ ____\n / ___)(_ \\ / _\\ / __)(__)\n \\___ \\) __// \\((__) _)\n (____/(__) \\_/\\_/ \\___)(____)\n\n\n __ __ _ _ _ __ ____ ____ ____\n ()((\\/)(\\ / _\\ (\\(__)(_ \\\n)(/ /\\ \\/ // \\) D () _)) /\n (__)\\_)__) \\__/ \\_/\\_/(____/(____)(__\\_)";//вступительная заставка Sleep(timer); system("cls"); cout << "\n\n ____ ____ __ ___ ____\n / ___)(_ \\ / _\\ / __)(__)\n \\___ \\) __// \\((__) _)\n (____/(__) \\_/\\_/ \\___)(____)\n __ __ _ _ _ __ ____ ____ ____\n ()((\\/)(\\ / _\\ (\\(__)(_ \\\n)(/ /\\ \\/ // \\) D () _)) /\n (__)\\_)__) \\__/ \\_/\\_/(____/(____)(__\\_)";//вступительная заставка cout << "\a"; Sleep(10 * timer);//задержка заставки StartMenu(1); return 0; } void Game(int var) { int weaponPos;//позиция строки дула в массиве int timer;//задержка между перерисовками экрана int odometer;//количество перерисовок экрана, они же итоговые очки int lifes;//количество жизней char control = "&";//переменная управления кораблем int shotPause = 4;//задержка между выстрелами (указывать на одну перерисовку больше) int speed;//скорость корабля char scr; if (var == 1) { weaponPos = 7;//позиция строки дула в массиве odometer = 1;//количество перерисовок экрана, они же итоговые очки lifes = 3;//количество жизней GameStart(scr, lifes, &timer); } else//при восстановлении игрового сеанса из сохранения { FILE *saveBin; fopen_s(&saveBin, "CurrentSave.bin", "rb"); if (!saveBin) { system("cls"); cout << "Нет сохранения."; Sleep(1000); system("cls"); cout << "Нет сохранения.."; Sleep(1000); system("cls"); cout << "Нет сохранения..."; Sleep(1000); Game(1); } fread(&weaponPos, 1, sizeof(int), saveBin); timer = 80; fread(&odometer, 1, sizeof(int), saveBin); fread(&lifes, 1, sizeof(int), saveBin); fread(&scr, 14 * 50, sizeof(char), saveBin); fclose(saveBin); remove("CurrentSave.bin"); } while (true) { int odometerBuf = odometer, odometerDigitLength; for (odometerDigitLength = 0; odometerBuf != 0; odometerBuf /= 10, odometerDigitLength++);//вычисление количества цифр на одометре for (int i = odometerDigitLength, odometerBuf = odometer; i >= 0; i--, scr[i] = odometerBuf % 10 + "0", odometerBuf /= 10);//прорисовка одометра на приборную панель scr = "К"; scr = "М";//дописывание "КМ" odometer++;//наращение одометра speed = 1000 / timer;//обновление спидометра int speedBuf = speed; for (int i = 42; speed != 0; i--, scr[i] = speed % 10 + "0", speed /= 10);//прорисовка спидометра на приборную панель scr = "К"; scr = "М"; scr = "/"; scr = "С";//дописывание "КМ/С" if (_kbhit())//если клавиша была нажата { control = _getch();//переменная примет ее значение if (control == 224) control = _getch(); } if (control == 13 && shotPause == 4 || control == 32 && shotPause == 4)//при нажатии на курок если пушка перезаряжена { scr = "-"; shotPause = 0; } if (shotPause < 4)//перезарядка shotPause++; if (control == 27)//при выходе { FILE *saveBin; fopen_s(&saveBin, "CurrentSave.bin", "wb"); fwrite(&weaponPos, 1, sizeof(int), saveBin); fwrite(&odometer, 1, sizeof(int), saveBin); fwrite(&lifes, 1, sizeof(int), saveBin); fwrite(&scr, 14 * 50, sizeof(char), saveBin); fclose(saveBin); GameMenu(2); } if (control == 72)//при движении корабля вверх if (scr == "\\" || scr == "\\" && scr == "¤" || scr == "\\" && scr == "¤")//если корабль врезался в верхнее поле - игра окончена if (lifes > 1) { cout << "\a"; lifes--; weaponPos = 7; GameStart(scr, lifes, &timer); Sleep(1000); } else GameOver(odometer); else { for (int i = 2; i < 13; i++)//корабль смещается на элемент выше for (int j = 0; j < 49; j++) if (scr[i][j] == "3" || scr[i][j] == "\\" || scr[i][j] == "=" || scr[i][j] == "/") { scr[j] = scr[i][j]; scr[i][j] = " "; } weaponPos--; } if (control == 80)//при движении корабля вниз if (scr == "/" || scr == "/" && scr == "¤" || scr == "/" && scr == "¤")//если корабль врезался в нижнее поле - игра окончена if (lifes > 1) { cout << "\a"; lifes--; weaponPos = 7; GameStart(scr, lifes, &timer); Sleep(1000); } else GameOver(odometer); else { for (int i = 12; i >= 2; i--)//корабль смещается на элемент вниз for (int j = 0; j < 49; j++) if (scr[i][j] == "3" || scr[i][j] == "\\" || scr[i][j] == "=" || scr[i][j] == "/") { scr[j] = scr[i][j]; scr[i][j] = " "; } weaponPos++; } for (int i = 1; i < 14; i++)//все "космические" элементы смещаются на элемент влево for (int j = 0; j < 49; j++) { if (scr[i][j] == "\\" && scr[i] == "¤" || scr[i][j] == "=" && scr[i] == "¤" || scr[i][j] == "/" && scr[i] == "¤") if (lifes > 1) { cout << "\a"; lifes--; weaponPos = 7; GameStart(scr, lifes, &timer); Sleep(1000); } else GameOver(odometer); if (scr[i][j] != "3" && scr[i][j] != "\\" && scr[i][j] != "=" && scr[i][j] != "/" && scr[i][j] != "-" && scr[i] != "-") scr[i][j] = scr[i]; if (scr[i][j] == "¤") scr[i] = " "; } for (int i = 1; i < 14; i++)//все снаряды смещаются на элемент вправо for (int j = 48; j >= 0; j--) if (scr[i][j] == "-") if (j != 48) { scr[i] = "-"; scr[i][j] = " "; } else scr[i][j] = " "; char borderSymbols = { "†", "‡", "¤", " " }; scr = " ";//рандомное заполнение новых элементов краев scr = borderSymbols; if (scr == "‡") scr = "¤"; scr = " "; scr = borderSymbols; if (scr == "‡") scr = "¤"; for (int i = 3; i < 12; i++)//рандомное появление космического мусора { if (rand() % 10 == 1) scr[i] = "¤"; } ScreenOutput(scr);//вывод экрана if (control != "&")//"обнуление" управляющей переменной control = "&"; if (timer > 25)//ускорение корабля timer--; Sleep(timer);//задержка перерисовки } }


    Загрузить исполняемый файл.exe можно тут.

    Здравствуй, Хабрахабр!

    На хабре не очень много уроков по созданию игр, почему бы не поддержать отечественных девелоперов?
    Представляю вам свои уроки, которые учат создавать игры на C++ с использованием SDL!

    Что нужно знать

    • Хотя бы начальные знания C++ (использовать будем Visual Studio)
    • Терпение

    О чем эта часть?

    • Мы создадим каркас для всех игр, в качестве отрисовщика будем использовать SDL. Это библиотека для графики.

    В следующих постах будет больше экшена, это лишь подготовка:)

    Почему SDL?

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

    Теперь можно стартовать.

    1.1. Начало начал

    Скачиваем SDL с официального сайта.
    Создаем проект Win32 в Visual Studio, подключаем lib"ы и includ"ы SDL (если вы не умеете этого делать, то гугл вам в помощь!)

    Также необходимо использовать многобайтную кодировку символов. Для этого идем в Проект->Свойства->Свойства конфигурации->Набор символов->Использовать многобайтную кодировку.

    Создаем файл main.cpp
    #include int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int) { return 0; }
    Пока что он ничего не делает.

    Царь и бог каркаса - класс Game
    Game.h
    #ifndef _GAME_H_ #define _GAME_H_ class Game { private: bool run; public: Game(); int Execute(); void Exit(); }; #endif
    Game.cpp
    #include "Game.h" Game::Game() { run = true; } int Game::Execute() { while(run); return 0; } void Game::Exit() { run = false; }

    Создаем файл Project.h, он нам очень пригодится в будущем
    #ifndef _PROJECT_H_ #define _PROJECT_H_ #include #include "Game.h" #endif

    Изменяем main.cpp
    #include "Project.h" int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int) { Game game; return game.Execute(); }

    Уже чуточку получше, но все равно как-то не густо.

    1.2. Графика

    Создаем аж 2 класса - Graphics для отрисовки графики и Image для отрисовки картинок

    Graphics.h
    #ifndef _GRAPHICS_H_ #define _GRAPHICS_H_ #include "Project.h" #include "Image.h" class Image; class Graphics { private: SDL_Surface* Screen; public: Graphics(int width, int height); Image* NewImage(char* file); Image* NewImage(char* file, int r, int g, int b); bool DrawImage(Image* img, int x, int y); bool DrawImage(Image* img, int x, int y, int startX, int startY, int endX, int endY); void Flip(); }; #endif

    Image.h
    #ifndef _IMAGE_H #define _IMAGE_H #include "Project.h" class Image { private: SDL_Surface* surf; public: friend class Graphics; int GetWidth(); int GetHeight(); }; #endif

    Изменяем Project.h
    #ifndef _PROJECT_H_ #define _PROJECT_H_ #pragma comment(lib,"SDL.lib") #include #include #include "Game.h" #include "Graphics.h" #include "Image.h" #endif

    SDL_Surface - класс из SDL для хранения информации об картинке
    Рассмотрим Graphics
    NewImage - есть 2 варианта загрузки картинки. Первый вариант просто грузит картинку, а второй после этого еще и дает прозрачность картинке. Если у нас красный фон в картинке, то вводим r=255,g=0,b=0
    DrawImage - тоже 2 варианта отрисовки картинки. Первый рисует всю картинку целиком, второй только часть картинки. startX, startY - координаты начала части картинки. endX, endY - конечные координаты части картинки. Этот метод рисования применяется, если используются атласы картинок. Вот пример атласа:

    (изображение взято из веб-ресурса interesnoe.info)

    Рассмотрим Image
    Он просто держит свой сурфейс и дает право доступа к своим закрытым членам классу Graphics, а он изменяет сурфейс.
    По сути, это обертка над SDL_Surface. Также он дает размер картинки

    Graphics.cpp
    #include "Graphics.h" Graphics::Graphics(int width, int height) { SDL_Init(SDL_INIT_EVERYTHING); Screen = SDL_SetVideoMode(width,height,32,SDL_HWSURFACE|SDL_DOUBLEBUF); } Image* Graphics::NewImage(char* file) { Image* image = new Image(); image->surf = SDL_DisplayFormat(SDL_LoadBMP(file)); return image; } Image* Graphics::NewImage(char* file, int r, int g, int b) { Image* image = new Image(); image->surf = SDL_DisplayFormat(SDL_LoadBMP(file)); SDL_SetColorKey(image->surf, SDL_SRCCOLORKEY | SDL_RLEACCEL, SDL_MapRGB(image->surf->format, r, g, b)); return image; } bool Graphics::DrawImage(Image* img, int x, int y) { if(Screen == NULL || img->surf == NULL) return false; SDL_Rect Area; Area.x = x; Area.y = y; SDL_BlitSurface(img->surf, NULL, Screen, &Area); return true; } bool Graphics::DrawImage(Image* img, int x, int y, int startX, int startY, int endX, int endY) { if(Screen == NULL || img->surf == NULL) return false; SDL_Rect Area; Area.x = x; Area.y = y; SDL_Rect SrcArea; SrcArea.x = startX; SrcArea.y = startY; SrcArea.w = endX; SrcArea.h = endY; SDL_BlitSurface(img->surf, &SrcArea, Screen, &Area); return true; } void Graphics::Flip() { SDL_Flip(Screen); SDL_FillRect(Screen,NULL, 0x000000); }
    В конструкторе инициализируется SDL и создается экран.
    Функция Flip должна вызываться каждый раз после отрисовки картинок, она представляет получившееся на экран и чистит экран в черный цвет для дальнешней отрисовки.
    Остальные функции малоинтересны, рекомендую разобраться в них самому

    Image.cpp
    #include "Image.h" int Image::GetWidth() { return surf->w; } int Image::GetHeight() { return surf->h; }
    Нет, вы все правильно делаете, этот файл и должен быть таким:)

    Надо изменить Game.h, Game.cpp и main.cpp
    Game.h
    #ifndef _GAME_H_ #define _GAME_H_ #include "Project.h" class Graphics; class Game { private: bool run; Graphics* graphics; public: Game(); int Execute(int width, int height); void Exit(); }; #endif
    Тут мы добавляем указатель на Graphics и в Execute добавляем размер экрана

    Game.cpp
    #include "Game.h" Game::Game() { run = true; } int Game::Execute(int width, int height) { graphics = new Graphics(width,height); while(run); SDL_Quit(); return 0; } void Game::Exit() { run = false; }

    Ничего особенного, разве что не пропустите функцию SDL_Quit для очистки SDL

    Main.cpp
    #include "Project.h" int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int) { Game game; return game.Execute(500,350); }
    Тут мы создаем экран размером 500 на 350.

    1.3. Ввод

    Надо поработать со вводом с клавиатуры

    Создаем Input.h
    #ifndef _INPUT_H_ #define _INPUT_H_ #include "Project.h" class Input { private: SDL_Event evt; public: void Update(); bool IsMouseButtonDown(byte key); bool IsMouseButtonUp(byte key); POINT GetButtonDownCoords(); bool IsKeyDown(byte key); bool IsKeyUp(byte key); byte GetPressedKey(); bool IsExit(); }; #endif
    SDL_Event - класс какого-нибудь события, его мы держим в Input"е для того, чтобы не создавать объект этого класса каждый цикл
    Ниже расположены методы, не представляющие особого интереса. Примечание: методы с окончанием Down вызываются, когда клавиша была нажата, а с окончанием Up - когда опущена.

    Input.cpp
    #include "Input.h" void Input::Update() { while(SDL_PollEvent(&evt)); } bool Input::IsMouseButtonDown(byte key) { if(evt.type == SDL_MOUSEBUTTONDOWN) if(evt.button.button == key) return true; return false; } bool Input::IsMouseButtonUp(byte key) { if(evt.type == SDL_MOUSEBUTTONUP) if(evt.button.button == key) return true; return false; } POINT Input::GetButtonDownCoords() { POINT point; point.x = evt.button.x; point.y = evt.button.y; return point; } bool Input::IsKeyDown(byte key) { return (evt.type == SDL_KEYDOWN && evt.key.keysym.sym == key); } bool Input::IsKeyUp(byte key) { return (evt.type == SDL_KEYUP && evt.key.keysym.sym == key); } byte Input::GetPressedKey() { return evt.key.keysym.sym; } bool Input::IsExit() { return (evt.type == SDL_QUIT); }
    Здесь мы обрабатываем наш объект событий в функции Update, а остальные функции просто проверяют тип события и его значения.

    Изменяем теперь Game.h и Game.cpp
    #ifndef _GAME_H_ #define _GAME_H_ #include "Project.h" #include "Graphics.h" class Graphics; #include "Input.h" class Input; class Game { private: bool run; Graphics* graphics; Input* input; public: Game(); int Execute(int width, int height); Graphics* GetGraphics(); Input* GetInput(); void Exit(); }; #endif
    Как видно, мы добавили указатель на Input и создали методы-возвращатели Graphics и Input

    Game.cpp
    #include "Game.h" Game::Game() { run = true; } int Game::Execute(int width, int height) { graphics = new Graphics(width,height); input = new Input(); while(run) { input->Update(); } delete graphics; delete input; SDL_Quit(); return 0; } Graphics* Game::GetGraphics() { return graphics; } Input* Game::GetInput() { return input; } void Game::Exit() { run = false; }

    1.4. Итоги

    Это был первый урок. Если вы дошли до этого места, я вас поздравляю! У вас есть воля, присущая программисту:) Смотрите ссылки в начале статьи на последующие уроки для того, чтобы узнать еще много нового!

    По всем вопросам обращайтесь в ЛС, а если вам не повезло быть зарегистрированным на хабре, пишите на мейл [email protected]

    Компьютерные игры - это большой бизнес. Суммарная выручка индустрии видеоигр в США достигла 23,5 миллиардов долларов в прошлом году, что на 5% больше, чем в 2014. За каждой великой игрой стоят программисты, которые вносят существенный вклад в конечный продукт. Конечно, для создания разных игр используются разные языки программирования. В данной статье мы представим вам несколько самых популярных.

    Язык ассемблера

    Многие игры для Sega и Dendy были написаны на различных диалектах языка ассемблера, включая Super Mario Brothers.

    Игры серии Super Mario были проданы тиражом более 70 миллионов копий. IGN назвала третью часть Super Mario Brothers самой великой игрой всех времён.

    Язык Си

    Язык Си до сих пор остаётся одним из самых популярных языков программирования из-за своей относительной простоты и чёткой структуры. Компания id Software использовала Си для создания игры Doom, впервые выпущенной в 1993 году.

    Doom была названа самой влиятельной FPS-игрой, став прообразом многих других игр от первого лица и 3D-игр в общем. По приблизительным оценкам Doom набрал около 10 миллионов установок в 1995 году.

    С++

    Язык С++ использовался для создания многих современных операционных систем, софта, игр и игровых движков. Благодаря его гибкости, игры можно относительно несложно портировать с ПК на консоли и в обратном направлении. Одной из самых популярных игр, написанных на С++, является World of Warcraft.

    С момента запуска было продано 14 миллионов копий. 48% подписчиков проживают в азиатском регионе, 22% из США. На вики по WoW содержится более 100 000 статей.

    C#

    Разработанный компанией Microsoft в 2000 году, С# стал довольно популярен среди разработчиков игр. Движок Unity, широко используемый при создании игр для ПК, консолей и мобильных устройств, написан преимущественно на С#. Одна из самых заметных игр в данном классе - Angry Birds.

    Angry Birds находится на третьем месте по популярности среди всех игры для iOS всех времён, сразу за Candy Crush Saga и Fruit Ninja. Стоимость разработки первой версии игры составила порядка $140 000, что является очень скромным числом в своём роде. Четыре человека работали над игрой суммарно порядка восьми месяцев.

    Java

    Java является в некотором роде родственником C#. Они развиваются под влиянием друг друга, оба имеют сборщики мусора и объектно-ориентированы. Но Java изначально позиционируется как платформонезависимый язык, что означает, что он (по задумке) работает абсолютно одинаково на всех устройствах. Истории успешных игр, написанных на Java, включают в себя RuneScape и Minecraft.

    Альфа-версия игры была создана всего за 6 дней. Minecraft - вторая самая продаваемая игра в мире. Изначально она называлась «Cave Game».

    Хотите найти больше материалов по разработке игр и, может быть, даже разработать одну свою? Загляните в .

    Я - тот ещё фрукт. Все мои личные игровые проекты, которыми я занимался в последнее время, были написаны на «vanilla» C. Больше никто так не делает, поэтому, полагаю, вам может быть интересно узнать, почему я сделал такой выбор.
    Написанное дальше содержит мнение о языках программирования, которое вам может не понравиться. Я предупреждал .

    Что мне нужно от языка

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

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

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

    Чего я хочу от языка

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

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

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

    Ещё больше меня волнует скорость компилятора. Я не какой-нибудь буддийский мастер концентрации, и ждать больше 10 секунд - расточительство. Хуже того, это выбивает из потока. Вроде только глянул Twitter, а 5 минут куда-то пропали.

    Я не адепт ООП. Большую часть времени, проведённого за работой, я имел дело с классами и объектами. Но чем дальше, тем меньше я понимаю, почему надо так жёстко объединять код и данные. Я хочу работать с данными, как с данными, и писать код, который лучше всего подходит в конкретной ситуации.

    Альтернативы

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

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

    C# и Java имеют схожие проблемы. Это многословные и сложные монстры, а мне нужен маленький простой зверёк. Оба языка направляют программиста прямиком в пучину ООП, а я против этого. Как и в большинстве высокоуровневых языков, многие сложные вещи тут скрываются так, что ничего не мешает случайно выстрелить себе в ногу.

    Мне очень нравится Go. Во многих аспектах это изобретённый заново C, с поправкой на то, что до представления его публике он продумывался несколько лет. Я хотел бы использовать Go, но есть один огромный подводный камень - сборка мусора. Разработка игр на Go сомнительна, ведь сборщик мусора будет приостанавливать весь игровой мир, чего разработчик не может позволить. Также тут всё не очень хорошо с игровыми библиотеками. И хотя всегда можно приспособить для этого дела библиотеку на C, причём без особых проблем, это всё равно порождает много лишней работы. Кроме того, у меня есть сомнения насчёт перспектив. Go был бы неплох для веба, но это стремительно меняющаяся среда. Особенно это почувствовалось со смертью Flash.

    JavaScript мне абсолютно не нравится. Он предоставляет столько свободы, что мне непонятно, как люди умудряются писать сколько-нибудь сложные проекты на нём. И не хочу даже пытаться его пробовать.

    Haxe выглядит гораздо перспективнее остальных языков в этом списке. У него нет проблем с библиотеками. Если я снова начну писать под веб, то обязательно познакомлюсь с ним поближе. Несколько беспокоит относительная молодость языка, будет ли он жить? Больше мне добавить нечего, с Haxe я успел лишь немного поиграться, не углубляясь.

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

    Почему C - лучший выбор для меня

    Хоть C и опасен, зато надёжен. Это очень острый нож, способный отрубить пальцы так же легко, как нарезать овощи. Но он прост, и научиться правильно его использовать труда не составит.

    Он быстрый. А когда дело доходит до компиляции, я и представить себе не могу, что какой-то язык способен сделать это быстрее.
    Есть возможность писать код так, чтобы он работал везде. И обычно это относительно несложно. Трудно представить, что однажды это изменится.

    Есть отличная поддержка библиотек и инструментов.

    Хоть меня это и несколько печалит, но C до сих пор остаётся лучшим языком для меня.

    Я совсем не хочу сказать что-то вроде: «Эй, вы тоже должны писать на C». Я осознаю, что мои предпочтения весьма специфичны. Кроме того, по количеству, написанного мной на разных языках, код на «vanilla» C занимает лидирующую позицию, так что это уже часть моей зоны комфорта.

    Так что да, C для меня - лучший выбор.

    От переводчика

    Перевод местами достаточно вольный, но не в ущерб смыслу или содержанию.

    Подготовил перевод специально к пятнице, в этот день он особенно уместен, на мой взгляд. Хоть автор оригинального текста и пишет, кажется, на полном серьезе… вы сами всё понимаете, если прочитали. Как истину прочитанное воспринимать не стоит.

    С предложениями, пожеланиями и замечаниями, как обычно, в ЛС.