ria pc game
fle game engine - движок для создания игр
fle game engine - движок для создания игр


Balls and holes PC game / Balls and Holes PC игра
Вакансии
Игродельня
Today
18 февраля 2019 5:00
Вход Регистрация Забыли пароль ?

Balls on Lift / Шарики на лифте - Как создать игру - серия уроков - Рисуем шарик / How make the game - series of lessons - draw ball
Шарики на лифте - Как создать игру - Рисуем шарик     13.09.2016   В данном уроке мы научимся рисовать вот такой шарик  
подробнее...

Теги создание сайтов, создание игр, дизайн, игры, информатика, уроки photshop, php, c++, музыка, delphi, cms, робосайт
Статьи сайта
megainformatic - Game craft - моделируем scv - шаг 1 (часть 2)

megainformatic - Game craft - моделируем scv - шаг 2 (часть 3)

megainformatic - Game craft - Наложение текстуры на модель робота scv (часть 4)

megainformatic - Game craft - Прорисовка текстуры робота SCV шаг 5

megainformatic - Game craft - Экспорт модели из 3ds max в формат X

megainformatic - Game craft - отображение scv модели в формате x в d3d9-приложении

megainformatic - Game craft - управление игрой от Direct Input в d3d9 - приложении

megainformatic - Game craft - игровая камера в d3d9 - приложении

megainformatic - Приключения Кости Коробкина - Как я провел лето - онлайн комикс - страница 1

megainformatic - Приключения Кости Коробкина - Как я провел лето - онлайн комикс - страница 2

megainformatic - Приключения Кости Коробкина - Как я провел лето - онлайн комикс - страница 3

megainformatic - Приключения Кости Коробкина - Как я провел лето - онлайн комикс - страница 4

megainformatic - Приключения Кости Коробкина - Как я провел лето - онлайн комикс - страница 5

megainformatic - Приключения Кости Коробкина - Как я провел лето - онлайн комикс - страница 6

megainformatic - Приключения Кости Коробкина - Как я провел лето - онлайн комикс - страница 7

megainformatic - Приключения Кости Коробкина - С новым годом - интерактивный комикс (kk hny) - онлайн комикс - страница 1

megainformatic - Приключения Кости Коробкина - С новым годом - интерактивный комикс (kk hny) - онлайн комикс - страница 2

megainformatic - Приключения Кости Коробкина - С новым годом - интерактивный комикс (kk hny) - онлайн комикс - страница 3

megainformatic - Приключения Кости Коробкина - С новым годом - интерактивный комикс (kk hny) - онлайн комикс - страница 4

megainformatic - Приключения Кости Коробкина - С новым годом - интерактивный комикс (kk hny) - онлайн комикс - страница 5

megainformatic - Приключения Кости Коробкина - С новым годом - интерактивный комикс (kk hny) - онлайн комикс - страница 6

megainformatic - Приключения Кости Коробкина - С новым годом - интерактивный комикс (kk hny) - онлайн комикс - страница 7

megainformatic - Костя Коробкин - СЕКРЕТНЫЙ ПРОЕКТ - интерактивный комикс (kk scp) - онлайн комикс - страница 1

megainformatic - Костя Коробкин - СЕКРЕТНЫЙ ПРОЕКТ - интерактивный комикс (kk scp) - онлайн комикс - страница 2

megainformatic - Костя Коробкин - СЕКРЕТНЫЙ ПРОЕКТ - интерактивный комикс (kk scp) - онлайн комикс - страница 3

megainformatic - Костя Коробкин - СЕКРЕТНЫЙ ПРОЕКТ - интерактивный комикс (kk scp) - онлайн комикс - страница 4

megainformatic - Костя Коробкин - СЕКРЕТНЫЙ ПРОЕКТ - интерактивный комикс (kk scp) - онлайн комикс - страница 5

megainformatic - Костя Коробкин - СЕКРЕТНЫЙ ПРОЕКТ - интерактивный комикс (kk scp) - онлайн комикс - страница 6

megainformatic - Костя Коробкин - СЕКРЕТНЫЙ ПРОЕКТ - интерактивный комикс (kk scp) - онлайн комикс - страница 7

megainformatic - Веселый Буквоежка - онлайн комикс - страница 1

megainformatic - Веселый Буквоежка - онлайн комикс - страница 2

megainformatic - Веселый Буквоежка - онлайн комикс - страница 3

megainformatic - Веселый Буквоежка - онлайн комикс - страница 4

megainformatic - Веселый Буквоежка - онлайн комикс - страница 5

megainformatic - Веселый Буквоежка - онлайн комикс - страница 6

megainformatic - Веселый Буквоежка - онлайн комикс - страница 7

megainformatic - Веселый Буквоежка - онлайн комикс - страница 8

megainformatic - Веселый Буквоежка - онлайн комикс - страница 9

megainformatic - Веселый Буквоежка - онлайн комикс - страница 10

megainformatic - Веселый Буквоежка - онлайн комикс - страница 11

megainformatic - Веселый Буквоежка - онлайн комикс - страница 12

megainformatic - Веселый Буквоежка - онлайн комикс - страница 13

megainformatic - Веселый Буквоежка - онлайн комикс - страница 14

megainformatic - Веселый Буквоежка - онлайн комикс - страница 15

megainformatic - Веселый Буквоежка - онлайн комикс - страница 16

megainformatic - Веселый Буквоежка - онлайн комикс - страница 17

megainformatic - Веселый Буквоежка - онлайн комикс - страница 18

megainformatic - Веселый Буквоежка - онлайн комикс - страница 19

megainformatic - Веселый Буквоежка - онлайн комикс - страница 20

megainformatic - Веселый Буквоежка - онлайн комикс - страница 21

megainformatic - Веселый Буквоежка - онлайн комикс - страница 22

megainformatic - Веселый Буквоежка - онлайн комикс - страница 23

megainformatic - Эмулятор ZX-Spectrum, БК-0010.01 и их работа в эмуляторе DosBox 0.74

megainformatic - Костя Коробкин - В гостях у тёти Светы (kk as) - онлайн комикс - страница 1

megainformatic - Костя Коробкин - В гостях у тёти Светы (kk as) - онлайн комикс - страница 2

megainformatic - Костя Коробкин - В гостях у тёти Светы (kk as) - онлайн комикс - страница 3

подробнее

Обзор антивирусных средств защиты



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

Существуют самые различные антивирусы - бесплатные, платные, требующие установки или не требующие её, осуществляющие проверку файлов по требованию или самостоятельно.

Какие антивирусы самые известные и проверенные на сегодняшний день ?

Скажу сразу - универсального антивируса от всех вирусов не существует. Точнее он есть, но - это Ваша голова :)))

То есть каким бы "крутым" и "дорогим" не был Ваш антивирус только Вы сами в состоянии защитить себя на 100% от вирусов и потенциально опасных программ.

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

Антивирусы требуют постоянного обновления своих антивирусных баз и способны ловить и обезвреживать только известные им вирусы.

То есть никакой антивирус не в состоянии защитить Вас от вновь появившегося вируса, против которого еще не разработана вакцина ( набор правил по его обезвреживанию ).

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

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

Какой вред может причинить Вам КОМПЬЮТЕРНЫЙ ВИРУС ?

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

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

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

Зачем же такие ВИРУСЫ ? Такие вирусы используются для проведения хакерских DDoS атак на сайты.

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

Такие программы называются брандмауэрами (brandmauer) и файр воллами (firewall).

Они защищают от атак извне и изнутри.

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

Итак, какие есть антивирусы ?

Сначала остановимся на бесплатных, т. к. они доступны каждому.

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

avz - бесплатная лечащая утилита.

Платные и условно-бесплатные антивирусные системы.

nod smart security - достаточно хорошо зарекомендовавшее себя решение для защиты от любых видов угроз. Основной недостаток - это конечно ежегодная оплата за продление лицензии. Стоимость лицензии колеблется от 1700 до 2700 руб и выше.

drweb - серьезный и проверенный временем антивирус, а также ряд модулей к нему. Имеет 30 дневный бесплатный период. Лицензия на год от 1300 руб и выше.

kaspersky - также очень серьезный и проверенный годами антивирусный набор. Имеет 30 дневный бесплатный период. Лицензия на год от 1600 руб и выше.

outpost - по данному антивирусу сказать ничего не могу, т. к. им не пользовался. Неожиданностью стало отсутствие бесплатного периода пользования. Лицензия на год стоит от 900 руб и выше.

avira - достаточно быстрый и легкий антивирус, имеет 30 дневный бесплатный период, лицензия на год от 1000 руб.

panda - очень быстрый и легкий антивирус, работающий на облачных технологиях. мне очень понравился. Имеет бесплатный период на 30 дней. Лицензия на год от 1080 руб.

mc afee - Достаточно серьезный антивирус. Бесплатный период на 30 дней. Лицензия на год от 1000 руб.

avast - Продукт чешских производителей. Разрабатывается с 1988 года. Лицензия на год от 900 руб. Приятный ГОВОРЯЩИЙ !!! интерфейс, защита от известных вирусов. При использовании нареканий не было. Включает в себя также брандмауэр (для версии Internet Security)

trend micro - Хорошая защита от интернет-угроз. Бесплатный период на 31 день. Лицензия на год от 2000 руб. Лично мне не понравилось то, что данный антивирус удаляет всё без спросу, не оставляя возможности восстановить удаленный файл (папки для карантина или изоляции файла не существует). Будучи добавленным в исключения подозрительный (по мнению антивируса) файл всё равно удаляется. Поэтому попробовав данный антивирус я решил от него отказаться.

norton antivirus - Продукт Symantec. Разрабатывается с 1993 года. Лицензия на год от 990 руб. Бесплатный период на 30 дней. Личный опыт использования пока отсутствует.

Данный список еще будет дополняться и уточняться. Если у Вас есть информация по какому-то не описанному здесь антивирусу - пожалуйста воспользуйтесь формой комментария внизу данной страницы и напишите о нём. Спасибо за внимание !

Как работают антивирусы ?

подробнее

Проект социальной сети

megainformatic cms social



РУКОВОДСТВО ПОЛЬЗОВАТЕЛЯ

Заходим на сайт

http://megainformatic.ru/webprojects/mcs_pb/

Чтобы войти в личный кабинет в форме ВХОД НА САЙТ вводим известные вам логин и пароль.

После входа в ЛИЧНЫЙ КАБИНЕТ (далее ЛК для краткости) вы увидите текст приветствия и верхнее выпадающее меню.

Все действия в вашем ЛК выполняются посредством ВЕРХНЕГО ВЫПАДАЮЩЕГО МЕНЮ, а также кнопок или пунктов представленных на странице, которая откроется при выборе того или иного пункта.

Рассмотрим работу каждого из пунктов меню.

РАЗДЕЛ - Управление.

УПРАВЛЕНИЕ > Профиль

Выбрав данный пункт Вы попадаете на страничку личного профиля, где можно изменить или загрузить ваше фото, задать или изменить существующие ЛОГИН, ПАРОЛЬ и другие необходимые поля.

Внеся изменения просто нажмите кнопку СОХРАНИТЬ. Все сделанные изменения при этом будут сохранены.

УПРАВЛЕНИЕ > Страницы

Данный раздел позволяет вам менять Заголовки Ваших Личных страниц на сайте. Вы также видите названия их файлов и ссылки. Чтобы отредактировать контент страницы воспользуйтесь кнопкой РЕДАКТИРОВАТЬ расположенной справа от нужной страницы в таблице списка страниц.

Обратите внимание !!! Данный раздел доступен только пользователям с ролью не ниже АГЕНТ.

УПРАВЛЕНИЕ > Настройки

Данный пункт доступен только пользователю с ролью СУПЕРАДМИН.

Он позволяет управлять отображением ЛИЧНЫХ СТРАНИЦ указанного пользователя, а также задавать ГЛОБАЛЬНЫЕ НАСТРОЙКИ по обработке ВХОДЯЩИХ сообщений.

Принцип работы - аналогичный - выбрав данный пункт меню Вы попадете на страницу. Введя в поле ID номер нужного пользователя (user_id) и нажав кнопку РЕДАКТИРОВАТЬ Вы увидите страницы данного пользователя, которые ему доступны в его ЛК.

Установите/Снимите нужные галочки и нажмите кнопку СОХРАНИТЬ ИЗМЕНЕНИЯ.

Чтобы изменить НАСТРОЙКИ ОБЩИЕ ДЛЯ ВСЕХ КАБИНЕТОВ аналогично - задайте нужные значения и нажмите кнопку СОХРАНИТЬ ИЗМЕНЕНИЯ.

УПРАВЛЕНИЕ > Выход

Позволяет ВАМ завершить сеанс работы в вашем ЛК и перейти на главную страницу сайта.





РАЗДЕЛ - Пользователи

ПОЛЬЗОВАТЕЛИ > Список

Отображает список всех зарегистрированных пользователей сайта.

ПОЛЬЗОВАТЕЛИ > Претенденты

Отображает список претендентов - пользователей которые задали вопрос на сайте, но еще не посетили страницу ХОЧУ ЗАРЕГИСТРИРОВАТЬСЯ.

ПОЛЬЗОВАТЕЛИ > Ждут регистрацию

Выводит список пользователей, которые задали вопрос на сайте и посетили ссылку ХОЧУ ЗАРЕГИСТРИРОВАТЬСЯ.

ПОЛЬЗОВАТЕЛИ > Новый кабинет

Данный раздел позволяет вам зарегистрировать нового пользователя. Просто введите wtr_id который можно посмотреть в разделе ПОЛЬЗОВАТЕЛИ > Ждут регистрацию

а затем нажмите кнопку ПОДТВЕРДИТЬ





РАЗДЕЛ - Контент

КОНТЕНТ > Личные страницы

Позволяет вам редактировать контент ваших личных страниц. Этот же раздел открывается автоматически при работе в разделе - УПРАВЛЕНИЕ > Страницы

когда Вы нажмёте кнопку РЕДАКТИРОВАТЬ у одной из страниц списка представленного в виде таблицы.





РАЗДЕЛ - История

История > Посещения

Позволяет вам отслеживать историю посещаемости всех страниц вашего сайта.

История > Сообщения

Позволяет вам работать с системой внутренних сообщений сайта. Вопросы поступающие с личных страниц КОНТАКТЫ попадают во ВХОДЯЩИЕ сообщения пользователя, которому принадлежит личная страница КОНТАКТЫ.

Тут представлено 3 папки - ВХОДЯЩИЕ, ОТПРАВЛЕННЫЕ И КОРЗИНА.

Сообщения (вопросы), на которые уже был дан ответ помечаются иконкой в виде карандаша.





ТЕСТИРОВАНИЕ ОБЩИХ СООБЩЕНИЙ История > Сообщения нажать кнопку ОБЩИЕ

задаем вопрос любому пользователю

для тестирования отправки напоминаний о заданных вопросах
=====

задаем в настройках время напоминания [Сообщение "ждёт" чтобы на него ответили] равное 0, а время

после напоминания [Сообщение "ждёт" после напоминания хозяину:] в значение отличное от нуля

открываем любую страницу пользователя или типовую страницу

чтобы сработал cron (обработчик заданных по времени программных исполнителей задач).



заходим по FTP в папку входящих сообщений пользователя, которому бы задан вопрос

и если открыть файл свежего сообщения текстовым редактором, то там будет видно,

что файл помечен как remainded



Для сравнения если открыть другие сообщения, то там будет в первой строчке стоять не слово remainded а какое-либо число,

означающее id агента, которому был адресован вопрос.

для тестирования переноса сообщений на которые по истечении заданного времени не был получен ответ даже после напоминания,
======

нужно выставить настройки

задаем в настройках время напоминания [Сообщение "ждёт" чтобы на него ответили] отличное от 0, а время

после напоминания [Сообщение "ждёт" после напоминания хозяину:] равное нулю

открываем любую страницу пользователя или типовую страницу

чтобы сработал cron (обработчик заданных по времени программных исполнителей задач).

теперь если зайти в любой личный кабинет то, там в папке ОБЩИХ сообщений должны появиться сообщения, на которые не был дан

ответ

ОСОБЕННОСТЬ работы временных задач cron такова, что поймать момент времени, когда будет выполняться cron не представляется возможным.

ПОЭТОМУ ЗАРАНЕЕ ИЗВЕЩАЙТЕ РАЗРАБОТЧИКА о НАЧАЛЕ ТЕСТИРОВАНИЯ ВОЗМОЖНОСТЕЙ ОБЩИХ СООБЩЕНИЙ

чтобы я мог внести соответствующие ТЕСТОВЫЕ корректировки в скрипт и сообщить ВАМ о том, что момент времени наступит ТОГДА-ТО.



УСТАНОВКА СИСТЕМЫ на сайт joomla

1) в панели управления joomla отключаем стандартный модуль авторизации joomla

2) в панели управления joomla создаем модуль mod_custom

и вставляем туда код для формы авторизации (выделен коричневым цветом)

[admin_panel_dir] = адрес админ-панели

например

http://megainformatic.ru/webprojects/mcs_pb/pb/holder

Вход на сайт

<form name="enter_form" method="post" action="[admin_panel_dir]/index.php">

Логин:  <input name="login" type="text" id="loginid" size="20" maxlength="80">


Пароль:<input name="passwid" type="password" id="passwid" size="20" maxlength="80">


<input type="submit" name="enterid" id="enterid" value="Войти">

</form>

включаем вывод созданного модуля взамен модуля вывода стандартной авторизации

3) саму систему устанавливаем в подпапку pb в папке сайта joomla

путём копирования всех файлов системы megainformatic cms social в папку pb

4) правим файл pb/config.php

прописав в нём корректный путь и другие настройки

$system_name = 'megainformatic cms social'; //название системы

$site_url = 'http://megainformatic.ru/webprojects/mcs_pb/pb'; //пропишите адрес к вашему сайту

$admin_panel_dir = 'holder'; //здесь укажите имя папки для модуля административной панели

$superadmin_email = 'my@megainformatic.ru'; //емайл адрес СУПЕРАДМИНИСТРАТОРА САЙТА

//настройки доступа к бд

$dbhost = "127.0.0.1"; //сервер базы данных обычно 127.0.0.1 либо localhost

$dbsite = "mcs"; //сюда нужно вписать имя созданной вами для сайта базы данных

$dbuser = "root"; //это имя пользователя базы данных - для локального сайта можно вписать root

$dbpassw = ""; //пароль доступа к базе данных, для локального сайта можно не использовать

5) (таблицы для mcs нужно внедрить в базу данных сайта joomla, таблицам дать имена с префиксом mbp_ )

проверяем нет ли в таблицах базы данных интегрируемого сайта таблиц с префиксом mbp_ и если нет - прописываем этот префикс

в файле pb/includes/constants.php

$table_prefix = 'mbp_';

из архива baza_dannyh берем дамп базы данных db_dump.sql

и вставляем его в базу данных интегрируемого сайта (через phpMyAdmin)

6) в шаблоне внедряемого сайта блок контента надо выделить тегами

<div id="mcspb_content">

</div> <!-- end of mc -->



подробнее

     
 
Урок 4 Построение класса приложения
 
О том, что потребуется для данного урока читайте в основном разделе - уроки delphi directx 8.1
 
Далее у читателя подразумевается наличие базовых знаний языка Delphi.
 
[назад] [страница 2] [далее] [к содержанию]
 
Познакомившись с кодом класса CD3DApplication описанным в модуле D3DApp.pas библиотеки delphi directx 8.1 мы переходим к рассмотрению класса TD3DGameApp являющегося базовым классом D3D-приложения, используемым в игре "Ну, Погоди!". По большому счету ничего нового о функционировании D3D-приложения Вы здесь не узнаете, однако в качестве примера того, как строится конкретный базовый класс на примере конкретной законченной игры дальнейшее повествование будет Вам все же небезынтиресно.
 

Начнём с того, что модуль D3DApp.pas и CD3DApplication в игре "Ну, Погоди!" не применяется вообще. Вместо этого был создан самостоятельный базовый класс ориентированный именно на потребности конкретной игры, а не на те особенности, которые необходимо было рассмотреть в качестве примера во всех приложениях из DirectX SDK. Иными словами назначение класса CD3DApplication именно демонстративное.

Класс TD3DGameApp, который мы рассмотрим ниже, ориентирован на определенную конкретику, связанную с особенностями проекта игры "Ну, Погоди!"

 
Функционирование приложения строится на тех же принципах, которые мы рассматривали начиная с 1 урока.
 

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

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

 

Что потребуется при написании собственной игры?

Сначала я перечислю то, что потребуется обязательно при реализации абсолютно любой игры -

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

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

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

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

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

 
Теперь рассмотрим конкретные примеры того, что имеет место в коде игры "Ну, Погоди!". Замечу, что всё описанное ни в коем случае не является и не должно являться для Вас догмой. Поработав с примером и над созданием собственной игры Вы обязательно уясните для себя что-то свое и будете делать то, что Вам потребуется по-своему, а не так как описано здесь один в один. Другими словами по мере приобретения Вами опыта Вы сами решите что и как должно происходить в Вашем коде.
 

Опустим описание реализации кода методов TD3DGameApp.Create, Create_ и Destroy, так как оно за небольшими исключениями полностью похоже на то, что мы рассматривали на протяжении предыдущих 3х уроков.

Рассмотрим метод TD3DGameApp.OneTimeSceneInit

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

 

Далее действие происходит уже внутри FrameMove и Render. В зависимости от состояния приложения происходит загрузка необходимого минимума ресурсов, начинается опрос действий со стороны пользователя посредством DirectInput. Реакция на события выбора меню TMainMenu реализована вызовом обработчиков пунктов данных меню.

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

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

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

Внутри данного метода исполняется g_d3dApp.Render3DEnvironment; в котором и реализовано выполнение упомянутых выше методов FrameMove и Render.

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

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

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

В состоянии asInit происходит лишь смена состояния на новое asEndInit, которое сразу же переключит приложение в состояние готовности - asReady

Такие сложности связаны именно с периодической природой Render3DEnvironment, поэтому ОБЯЗАТЕЛЬНО! учитывайте этот момент, иначе будете получать всевозможные ошибки времени выполнения.

В состоянии asReady начинается ожидание действий со стороны пользователя (UpdateInput).

Назначение клавиш каждому из действий происходит в процедуре DefineDefaultKeys.

Обработка этих действий происходит в режимах готовности (asReady) и игры (asGame).

Режим паузы в ответ на действие GamePause переключает индикатор паузы m_bPaused на противоположное значение. В коде формирования игровой ситуации FrameMoveGameSituation учитывается состояние данного индикатора.

Также проверяется нажатие клавишы выхода из игры - действие GameExit.

Нажатие нарисованных на игровой панели клавиш при помощи мыши обрабатывается здесь следующим образом. Если выполняется действие PressButton, то определяются в каком месте находится при этом указатель мыши. Попадание его в определенную область вызывает срабатывание нужной кнопки на игровой панели. GameButtonDownUp применяется для корректной отработки нажатий/отпусканий клавиш игровой панели. В момент отпускания клавиши игровой панели срабатывает привязанное к ней действие. Кроме того, красным клавишам управления волком сопоставлены действия от клавиатуры LeftUpCatch, LeftDownCatch, RightUpCatch, RightDownCatch, т. к. по мере нарастания скорости игры требуется более высокая реакция игрока.

 

 

В состоянии asGame выполняется метод FrameMoveGameScene. Заглянув в его код Вы увидите несколько различных режимов, в которых может находиться игра:

gmRestart, gmGameA, gmGameB, gmTimer, gmSetAlarm, gmEndSetAlarm, gmStartGameOver, gmGameOver, gmStartLoadWinMultic, gmShowWinText, gmWinMultic, gmShowGameAMaxScore,
gmShowGameBMaxScore

 

Перечислим их назначение.

gmRestart - этот режим выполняет перезапуск игры независимо от текущего режима и переход в состояние готовности. Этот режим эмулирует поведение электронной игры "Ну, Погоди!" сразу же после ее включения.

gmGameA - запускает игру А, при этом яйца скатываются одновременно только с 3х лотков, прервать игру можно путем рестарта, паузы или закрытия приложения

gmGameB - аналогично, но яйца катятся с 4х лотков

gmTimer - эмуляция поведения электронной игры "Ну, Погоди!" в режиме отсчета времени. Отображается реальное время системных часов аналогичное тому, что имеется в правом нижнем углу экрана Windwows (в трее).

gmSetAlarm, gmEndSetAlarm - эмуляция режима установки времени подачи сигнала будильника, при этом если игра запущена, то в режимах "игра А", "игра Б" или отсчет времени в заданное время будет подан сигнал будильника

gmStartGameOver, gmGameOver - проигрыш, игра находится в состоянии ожидания дальнейших действий пользователя

gmStartLoadWinMultic, gmShowWinText, gmWinMultic - победа! игрок набрал трижды 999 очков. при этом будет показан поздравительный текст, а затем небольшой анимированный мультфильм с участием волка, зайца и других персонажей

gmShowGameAMaxScore, gmShowGameBMaxScore - режим показа максимального набранного в данном режиме количества очков - срабатывает в момент нажатия и удержания клавиш "игра А" или "игра Б" на игровой панели

 

Вам наверное интересно как осуществляется отображение графики в игре?

Начнём с того, что заглянем внутрь методов LoadGameTextures, RestoreGameTextures, InvalidateGameTextures, FreeGameTextures. В этих методах показано, как имена текстур из текстового файла загружаются сначала в список имен, а затем по этому списку производится загрузка и построение списка текстур (объектов класса TD3DImage2D). Из списка имен также считываются параметры размещения и масштабирования изображений.

В режиме игры А или Б сначала происходит вызов FrameMoveGameSituation;

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

1) Если индикатор паузы переключен в True, то DXTimer сбрасывается, а метод завершает работу;

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

3) Определяется текущее положение волка

4) Генерируются новые яйца на лотках, анимируется их качение по лоткам, анимируется выглядывание зайца из окошка, постепенно наращивается темп игры

5) Проверяется и анимируется разбивание яиц

6) Осуществляется мерцание и сброс (если требуется) штрафных очков

Вывод графики происходит внутри метода Render также в зависимости от состояния приложения.

DrawGameView > DrawGameScene осуществляет собственно рисование в зависимости от режима игры.

Внутри DrawGameScene вы увидите, что проблема вывода каждого игрового изображения сводится к вызову метода DrawGameElement с указанием в качестве параметра индекса отображаемого элемента (игровой панели, волка, зайца, яйца и т.д.). Лишь для игрового счета, счета штрафных очков и показаний времени используются отдельные методы, но и они построены на использовании метода DrawGameElement

В реализации метода DrawGameElement нет ничего сложного. В зависимости от индекса вызывается нужный объект TD3DImage2D с вызовом его метода Draw2. Параметры вывода (координаты и масштабные коэффициенты извлекаются из параметров объекта PGamePanelElement).

 

Вот собственно и весь вывод графики.

Вывод звука осуществляется еще проще. Достаточно Вам посмотреть методы

function CreateSoundObjects(h_Wnd: HWND): HRESULT;
procedure DestroySoundObjects;
function LoadSoundList: HResult;
procedure FreeSoundList;
procedure PlaySound(Index: Integer);
procedure PlayEggRun;

и то, где и как происходит их вызов. Можете например воспользоваться поиском по заданной фразе или просто просматривая код.

 
Конечно простота реализации данной игры обусловлена в большой степени ее особенностями. Большинство объектов статичны, анимация сводится лишь к скрытию одних и показу других картинок. Логика игры также достаточно проста.
 
Возможно чуть более сложным Вам покажется использование 2D-анимации, которая применяется в призовом мультфильме. Этот процесс также основан на использовании класса TD3DImage2D. Более подробно о нём мы поговорим в 7 уроке.
 
Вот кажется и всё вкратце, о создании базового класса игрового приложения, который применялся в игре "Ну, Погоди!". Если есть вопросы - милости просим на форум или пишите на мой e-mail.
 
Но думаю, что особых трудностей не будет. Нужно лишь поэкспериментировать над созданием собственного, пусть пока небольшого, но уже полноценного игрового проекта. Удачи Вам!!!
 
[назад] [страница 2] [далее] [к содержанию]
 
     
     
     
     
подробнее

     
  [Назад] [Все уроки] [Далее]  
     
 

12/06/2008 Воспроизведение файлов в форматах *.it, *.xm, *.s3m, *.mod

продолжение...

 
[назад]
 

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

procedure TfrmMain.FormClose

 
FMUSIC_StopAllSongs(); //останавливаем все играющие звуковые файлы
for Index := 0 to MAX_SONGS - 1 do
begin
if FSongs[Index].Module <> nil then
begin
FMUSIC_FreeSong(FSongs[Index].Module);
//освобождаем ресурсы памяти от трекерских файлов и
end
else if FSongs[Index].Stream <> nil then
begin
FSOUND_Stream_Stop(FSongs[Index].Stream);
//файлов-потоков (таких как wav, mp2, mp3, ogg и подобных)
FSOUND_Stream_Close(FSongs[Index].Stream);
end;
end;
FSpectrum.Free;
//удаляем объект спектрального анализатора

FMOD_Unload; //и выгружаем библиотеку fmod.dll из памяти

 

Мы выяснили что должно происходить во время старта и уничтожения приложения.

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

 

загрузка - procedure TfrmMain.btnLoadClick

Проверяем сколько файлов уже есть в списке и выводим предупреждение об ошибке если их больше допустимого

SongCount := lbxFiles.Items.Count;

if SongCount = MAX_SONGS then
begin
Application.MessageBox(PChar(Format('Limit of %d songs reached', [MAX_SONGS])), 'Load error', MB_OK or MB_ICONHAND);
Exit;
end;

 

Для очередного элемента открытых файлов -

Пробуем открыть файл как трек, а затем как поток

Stream := nil;
Module := FMUSIC_LoadSong(PChar(dlgOpen.Files[Index]));
if Module = nil then
begin
Stream := FSOUND_Stream_Open(PChar(dlgOpen.Files[Index]), FSOUND_NORMAL or FSOUND_LOOP_NORMAL, 0, 0);
end;

Если никак не удалось - снова предупреждение

if (Module = nil) and (Stream = nil) then
begin
Application.MessageBox(FMOD_ErrorString(FSOUND_GetError), 'Load error', MB_OK or MB_ICONHAND);
Continue;
end;

 

Если трек загрузился, то установить громкость для данного трека на максимум, а шаг панорамы на 15%

if Module <> nil then
begin
FMUSIC_SetMasterVolume(Module, 255);
if (FMUSIC_GetType(Module) = FMUSIC_TYPE_MOD) or (FMUSIC_GetType(Module) = FMUSIC_TYPE_S3M) then
FMUSIC_SetPanSeperation(Module, 0.15); // 15% crossover
end;

 

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

FSongs[SongCount].Module := Module;
FSongs[SongCount].Stream := Stream;
FSongs[SongCount].Playing := False;

lbxFiles.Items.Add(ExtractFileName(dlgOpen.Files[Index])); //эта особенность актуальна лишь для примера testbed.dpr
lbxFiles.ItemIndex := SongCount;
//имя файла добавляется в список и текущим в списке становится данный файл

 

После этого вызывается псевдо-щелчок по файлу. Это приводит к считыванию текущих параметров из модуля (потока) данного файла, но это уже более актуально для примера testbed.dpr, хотя что-то может пригодиться и в игровом приложении

{...}

lbxFilesClick(nil);

 

выгрузка мелодии из памяти -

procedure TfrmMain.btnDeleteClick

определяем текущий элемент списка и останавливаем,

Index := lbxFiles.ItemIndex;
if Index < 0 then
Exit;

btnStopClick(nil);

 

а затем удаляем его -

lbxFiles.Items.Delete(Index);
// сдвигаем нижележащие элементы на освободившуюся позицию
if lbxFiles.Items.Count > 0 then
begin
if Index < lbxFiles.Items.Count - 1 then
begin
for Index2 := Index to lbxFiles.Items.Count - 2 do
FSongs[Index2] := FSongs[Index2 + 1];
end;
if Index < lbxFiles.Items.Count then
lbxFiles.ItemIndex := Index
else
lbxFiles.ItemIndex := lbxFiles.Items.Count - 1;
end;
lbxFilesClick(nil); //оcвежаем параметры для нового текущего файла

 

Воспроизведение мелодии -

procedure TfrmMain.btnPlayClick

Выбранная мелодия останавливается, если она уже играла

Index := lbxFiles.ItemIndex;

if Index < 0 then
Exit;

if FSongs[Index].Playing then
btnStopClick(Sender);

Включаем воспроизведение текущей мелодии списка

if FSongs[Index].Module <> nil then
begin
FSongs[Index].Playing := FMUSIC_PlaySong(FSongs[Index].Module);
if not FSongs[Index].Playing then
Application.MessageBox(FMOD_ErrorString(FSOUND_GetError), 'Play song', MB_OK or MB_ICONHAND);
end

 

или потока, если это поток

else if FSongs[Index].Stream <> nil then
begin
FSongs[Index].Channel := FSOUND_Stream_Play(FSOUND_FREE, FSongs[Index].Stream);
FSongs[Index].Playing := FSongs[Index].Channel >= 0;
if not FSongs[Index].Playing then
begin
Application.MessageBox(FMOD_ErrorString(FSOUND_GetError), 'Play stream', MB_OK or MB_ICONHAND);
end

 

если звуковой поток уже играет, то включить воспроизведение стерео, громкость на максимум

else
begin
FSOUND_SetPan(FSongs[Index].Channel, FSOUND_STEREOPAN);
FSOUND_SetVolume(FSongs[Index].Channel, 255);
end;

 

Остановка воспроизведения -

procedure TfrmMain.btnStopClick

Определяем текущую мелодию

Index := lbxFiles.ItemIndex;

if Index < 0 then
Exit;

Если это трекерский модуль - применяем команду остановки для него

if FSongs[Index].Module <> nil then
FMUSIC_StopSong(FSongs[Index].Module)

если это потоковое аудио - применяем другую команду остановки
else if FSongs[Index].Stream <> nil then
FSOUND_Stream_Stop(FSongs[Index].Stream);

Текущий канал потока - неопределен, индикатор проигрывания сброшен
FSongs[Index].Channel := -1;
FSongs[Index].Playing := False;

 

Регулировка громкости текущей мелодии -

Если не установка регулятора глобальной громкости

if not FSettingMasterVolume then
begin

Определяем текущую композицию
Index := lbxFiles.ItemIndex;
if Index > -1 then
begin

для модуля применяем свою команду
if FSongs[Index].Module <> nil then
begin
FMUSIC_SetMasterVolume(FSongs[Index].Module, trkMasterVolume.Position);
lblSongMasterVolume.Caption := Format('%3.3d', [trkMasterVolume.Position]);
//это актуально для элемента управления

//регулятором
end
else if FSongs[Index].Stream <> nil then

для потока - свою
begin
FSOUND_SetVolume(FSongs[Index].Channel, trkMasterVolume.Position);
lblSongMasterVolume.Caption := Format('%3.3d', [trkMasterVolume.Position]);
//это актуально для элемента управления

//регулятором
end;
end;
end;

 

Регулировка текущего воспроизводимого паттерна в трекерском модуле -

переход к предыдущему паттерну порядка воспроизведения -

procedure TfrmMain.btnPrevOrderClick(Sender: TObject);
var
Index: Integer;
Order: DWORD;
begin

считываем текущий модуль
Index := lbxFiles.ItemIndex;
if Index < 0 then
Exit;

если это трекерский модуль - считываем текущий индекс элемента порядка воспроизведения и уменьшаем его на 1
if FSongs[Index].Module = nil then
Exit;
Order := FMUSIC_GetOrder(FSongs[Index].Module);
if Order > 0 then
FMUSIC_SetOrder(FSongs[Index].Module, Order - 1);
end;

 

для переключения на следующий паттерн всё аналогично кроме строк -

т.е. приращаем индекс на +1

if Order < FMUSIC_GetNumOrders(FSongs[Index].Module) then
FMUSIC_SetOrder(FSongs[Index].Module, Order + 1);

 

внутри метода периодической работы таймера представлены ряд интересных команд -

procedure TfrmMain.tmrMainTimer(Sender: TObject);
var
Index: Integer;
begin

для игрового проекта это по большому счету не особо нужная информация, но все-таки полезна
lblCPU.Caption := Format('%.1f%%', [FSOUND_GetCPUUsage]);
//например можно определять загруженность процессора
lblChannels.Caption := Format('%3.3d', [FSOUND_GetChannelsPlaying]);
//музыкой и количество занятых звуковых каналов

//это полезно, т.к. для музыки не существует такого понятия как FPS, зато вышеуказанные параметры могут служить в какой-то мере для целей оценки быстродействия работающего проекта
Index := lbxFiles.ItemIndex;
if Index > -1 then
begin
ShowSpectrum;
ShowDynamicSongInfo(Index);
//данный метод будет полезен с точки зрения наблюдения за текущей позицией воспроизведения
if FMUSIC_IsFinished(FSongs[Index].Module) and chkPlaylist.Checked then
//если мелодия кончилась и установлен индикатор работы в режиме плей-листа - т.е. списка воспроизведения, то переход к следующей мелодии
begin
btnStopClick(nil);
Inc(Index);
if Index >= lbxFiles.Items.Count then
Index := 0;
lbxFiles.ItemIndex := Index;
lbxFilesClick(nil);
btnPlayClick(nil);
end;
end;
{ ... }

end;

 

Конфигурирование - выбор драйвера и параметров фильтрации -

Настройки конфигурирования происходят в модуле формы TfrmConfig -

С точки зрения наших задач заслуживает внимания метод модуля config.pas -

Считываются параметры установленные в окне формы конфигуратора и применяются к объекту FSOUND.

procedure TfrmConfig.btnOkClick(Sender: TObject);
var
Flags: Cardinal;
begin
FSOUND_SetOutput(OutputTypes[cbxOutputType.ItemIndex]);
FSOUND_SetDriver(cbxOutputDevice.ItemIndex);
FSOUND_SetMixer(TFSoundMixerTypes(cbxMixerType.ItemIndex));
Flags := 0;
if chkSoftwareMIDI.Checked then
Flags := Flags or FSOUND_INIT_USEDEFAULTMIDISYNTH;
if chkGlobalFocus.Checked then
Flags := Flags or FSOUND_INIT_GLOBALFOCUS;
FSOUND_Init(OutputRates[cbxOutputRate.ItemIndex], 128, Flags);
end;

 
Оставшиеся нерассмотренными здесь методы, я думаю, Вы разберете самостоятельно.
 
Теперь переходим к практическим упражнениям - реализации использования FMOD 3.75 для воспроизведения музыки и звуков в трекерских и потоковых форматах.
 

Файл fmod.dll размещаем в папке проекта, в настройках проекта указываем ссылку на интерфейсы в delphi-исходниках - fmod375;

В секции interface

uses

добавляем ссылку на fmodtypes

В секции implementation

uses

добавляем ссылки на fmod, fmoderrors

 

Внутри класса приложения объявляем 2 метода -

//music functions
procedure InitMusicLib;
procedure FreeMusicLib;

 

Пишем реализацию данных методов -

procedure TD3DGameApp.InitMusicLib;
var
Index: Integer;
begin
FMOD_Load(nil);

{ Check version numbers }
if FMOD_VERSION > FSOUND_GetVersion then
begin
MessageBox(g_d3dApp.m_hWnd, PChar(Format('API version %3.2f is newer than DLL version %3.2f', [FMOD_VERSION, FSOUND_GetVersion])), 'Version mismatch', MB_OK or MB_ICONERROR);
Halt;
end;

{ Initialize FSOUND }
try
if not FSOUND_SetOutput(FSOUND_OUTPUT_DSOUND) then
raise Exception.Create('FSOUND_SetOutput failed');
if not FSOUND_SetDriver(0) then
raise Exception.Create('FSOUND_SetDriver failed');
if not FSOUND_SetMixer(FSOUND_MIXER_QUALITY_AUTODETECT) then
raise Exception.Create('FSOUND_SetMixer failed');
if not FSOUND_SetHWND(g_d3dApp.m_hWnd) then
raise Exception.Create('FSOUND_SetHWND failed');
except
MessageBox(g_d3dApp.m_hWnd, FMOD_ErrorString(FSOUND_GetError), 'Initialization', MB_OK or MB_ICONHAND);
raise;
end;

if not FSOUND_Init(22050, 128, 0) then
begin
MessageBox(g_d3dApp.m_hWnd, FMOD_ErrorString(FSOUND_GetError), 'FSOUND_Init', MB_OK or MB_ICONHAND);
Halt;
end;

{ Initialize song list to empty }
for Index := 0 to MAX_SONGS - 1 do
begin
FSongs[Index].Module := nil;
FSongs[Index].Stream := nil;
FSongs[Index].Channel := -1;
end;

FTrackNumber := 0;
FNumTracks := 0;

LoadPlaylist(DefaultThemes); //данный метод будет реализован далее (см. ниже)

end;

 

procedure TD3DGameApp.FreeMusicLib;
var
Index: Integer;
begin
FMUSIC_StopAllSongs;
for Index := 0 to MAX_SONGS - 1 do
begin
if FSongs[Index].Module <> nil then
begin
FMUSIC_FreeSong(FSongs[Index].Module);
end
else if FSongs[Index].Stream <> nil then
begin
FSOUND_Stream_Stop(FSongs[Index].Stream);
FSOUND_Stream_Close(FSongs[Index].Stream);
end;
end;

FreePlayList; //данный метод будет реализован далее (см. ниже)

FMOD_Unload;
end;

 
Как видим нам почти ничего даже переделывать не пришлось, только опустили кое-какой код и изменили вызовы MessageBox.
 

Я организую вызов данных методов внутри TD3DGameApp.CreateSoundObjects и TD3DGameApp.DestroySoundObjects.

Где будете делать это Вы - решать Вам. Можете поступить аналогично. Следует иметь в виду, что метод InitMusicLib должен вызываться только после того, как окно приложения будет создано и обработчик окна - m_hWnd в нашем случае обретет своё действительное значение - в противном случае будут только ошибки... ошибки... и ошибки...

 

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

Загрузка списка мелодий из текстового файла const DefaultThemes = 'Media\Music\muzon_themes.txt'; -

Код уже должен быть Вам знаком по предыдущему повествованию, особо нового ничего нет

procedure TD3DGameApp.LoadPlaylist(PlayList: string);
var
Index: Integer;
Module: PFMusicModule;
Stream: PFSoundStream;
SongCount: Integer;
begin

создаем список строк будущего плей-листа и загружаем
FTMSPlayList := TStringList.Create;
try
FTMSPlayList.LoadFromFile(PlayList);
except
MessageBox(g_d3dApp.m_hWnd, PChar('Playlist '+PlayList+' not found!'),
'Playlist load Error', MB_OK or MB_ICONHAND);
end;

SongCount := FTMSPlayList.Count;

предупредить, если мелодий в списке больше допустимого!

if SongCount = MAX_SONGS then
begin
MessageBox(g_d3dApp.m_hWnd, PChar(Format('Limit of %d songs reached',
[MAX_SONGS])), 'Load error', MB_OK or MB_ICONHAND);
Exit;
end;

загружаем файлы списка в массив FSongs

for Index := 0 to SongCount - 1 do begin
Stream := nil;
Module := FMUSIC_LoadSong(PChar(FTMSPlayList[Index]));
if Module = nil then
begin
Stream := FSOUND_Stream_Open(PChar(FTMSPlayList[Index]),
FSOUND_NORMAL or FSOUND_LOOP_NORMAL, 0, 0);
end;

if (Module = nil) and (Stream = nil) then
begin
MessageBox(g_d3dApp.m_hWnd, FMOD_ErrorString(FSOUND_GetError),
'Load error', MB_OK or MB_ICONHAND);
Continue;
end;

if Module <> nil then
begin
FMUSIC_SetMasterVolume(Module, 255);
if (FMUSIC_GetType(Module) = FMUSIC_TYPE_MOD)
or (FMUSIC_GetType(Module) = FMUSIC_TYPE_S3M) then
FMUSIC_SetPanSeperation(Module, 0.15); // 15% crossover
end;

FSongs[Index].Module := Module;
FSongs[Index].Stream := Stream;
FSongs[Index].Playing := False;
end;
end;

 

Метод FreePlaylist выглядит совсем просто -

procedure TD3DGameApp.FreePlaylist;
begin
FreeAndNil(FTMSPlayList);
end;

 

Воспроизводим и останавливаем нужный трэк или поток по его номеру в массиве FSongs -

procedure TD3DGameApp.PlayItem(Index: Integer);
begin
if (Index < 0) or (Index > FTMSPlayList.Count-1) then
Exit;


if FSongs[Index].Playing then
StopItem(Index);

if FSongs[Index].Module <> nil then
begin
FSongs[Index].Playing := FMUSIC_PlaySong(FSongs[Index].Module);
if not FSongs[Index].Playing then
MessageBox(g_d3dApp.m_hWnd, FMOD_ErrorString(FSOUND_GetError),
'Play song', MB_OK or MB_ICONHAND);
end
else if FSongs[Index].Stream <> nil then
begin
FSongs[Index].Channel := FSOUND_Stream_Play(FSOUND_FREE,
FSongs[Index].Stream);
FSongs[Index].Playing := FSongs[Index].Channel >= 0;
if not FSongs[Index].Playing then
begin
MessageBox(g_d3dApp.m_hWnd, FMOD_ErrorString(FSOUND_GetError),
'Play stream', MB_OK or MB_ICONHAND);
end
else
begin
FSOUND_SetPan(FSongs[Index].Channel, FSOUND_STEREOPAN);
FSOUND_SetVolume(FSongs[Index].Channel, 255);
end;
end;
end;

procedure TD3DGameApp.StopItem(Index: Integer);
begin
if (Index < 0) or (Index > FTMSPlayList.Count-1) then
Exit;

if FSongs[Index].Module <> nil then
FMUSIC_StopSong(FSongs[Index].Module)
else if FSongs[Index].Stream <> nil then
FSOUND_Stream_Stop(FSongs[Index].Stream);
FSongs[Index].Channel := -1;
FSongs[Index].Playing := False;
end;

 

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

Сначала реализуем удаление -

 
procedure TD3DGameApp.DeleteSong(Index: Integer);
var
Index2: Integer;
begin
if (Index < 0) or (Index > FTMSPlayList.Count-1) then
Exit;

StopItem(Index);
FTMSPlayList.Delete(Index);
// Move all following items up one position
if FTMSPlayList.Count > 0 then
begin
if Index < FTMSPlayList.Count - 1 then
begin
for Index2 := Index to FTMSPlayList.Count - 2 do
FSongs[Index2] := FSongs[Index2 + 1];
end;
end;
end;

 

Теперь добавление -

function TD3DGameApp.AddSong(Filename: string): Integer;
var
Module: PFMusicModule;
Stream: PFSoundStream;
SongCount: Integer;
begin
SongCount := FTMSPlayList.Count;

if SongCount = MAX_SONGS then
begin
MessageBox(g_d3dApp.m_hWnd, PChar(Format('Limit of %d songs reached',
[MAX_SONGS])), 'Load error', MB_OK or MB_ICONHAND);
result := -1;
Exit;
end;


Stream := nil;
Module := FMUSIC_LoadSong(PChar(Filename));
if Module = nil then
begin
Stream := FSOUND_Stream_Open(PChar(Filename),
FSOUND_NORMAL or FSOUND_LOOP_NORMAL, 0, 0);
end;

if (Module = nil) and (Stream = nil) then
begin
MessageBox(g_d3dApp.m_hWnd, FMOD_ErrorString(FSOUND_GetError),
'Load error', MB_OK or MB_ICONHAND);
result := -1;
Exit;
end;

if Module <> nil then
begin
FMUSIC_SetMasterVolume(Module, 255);
if (FMUSIC_GetType(Module) = FMUSIC_TYPE_MOD)
or (FMUSIC_GetType(Module) = FMUSIC_TYPE_S3M) then
FMUSIC_SetPanSeperation(Module, 0.15); // 15% crossover
end;

result := FTMSPlayList.Add(Filename);

FSongs[result].Module := Module;
FSongs[result].Stream := Stream;
FSongs[result].Playing := False;

end;

 

Регулируем громкость - значения громкости 0 - тишина, 255 - максимум

procedure TD3DGameApp.Volume(SongIndex: Integer; Value: Byte);
begin
if (SongIndex < 0) or (SongIndex > FTMSPlayList.Count-1) then
Exit;

if FSongs[SongIndex].Module <> nil then
FMUSIC_SetMasterVolume(FSongs[SongIndex].Module, Value)
else if FSongs[SongIndex].Stream <> nil then
FSOUND_SetVolume(FSongs[SongIndex].Channel, Value);

end;

 

Регулировка позиции воспроизведения модуля по паттернам - переход к следующему/предыдущему паттерну -

function TD3DGameApp.Go2NextPattern(SongIndex: Integer): Integer;
begin
result := -1;

if (SongIndex < 0) or (SongIndex > FTMSPlayList.Count-1) then
Exit;

if FSongs[SongIndex].Module = nil then
Exit;
result := FMUSIC_GetOrder(FSongs[SongIndex].Module);
if result < FMUSIC_GetNumOrders(FSongs[SongIndex].Module) then begin
result := result + 1;
FMUSIC_SetOrder(FSongs[SongIndex].Module, result);
end;
end;

function TD3DGameApp.Go2PrevPattern(SongIndex: Integer): Integer;
begin
result := -1;

if (SongIndex < 0) or (SongIndex > FTMSPlayList.Count-1) then
Exit;

if FSongs[SongIndex].Module = nil then
Exit;
result := FMUSIC_GetOrder(FSongs[SongIndex].Module);
if result < FMUSIC_GetNumOrders(FSongs[SongIndex].Module) then begin
result := result - 1;
FMUSIC_SetOrder(FSongs[SongIndex].Module, result);
end;
end;

 

Для целей отладки будет полезно получать параметры производительности системы FMOD -

var
Index: Integer;
begin
SS_CPUUsage := Format('%.1f%%', [FSOUND_GetCPUUsage]);
SS_Channels := Format('%3.3d', [FSOUND_GetChannelsPlaying]);

if CurrentSongIndex > -1 then
begin
if FMUSIC_IsFinished(FSongs[CurrentSongIndex].Module) and PlaylistMode then
begin
StopItem(CurrentSongIndex);
Index := CurrentSongIndex;
Inc(Index);
if Index >= FTMSPlayList.Count then
Index := 0;
CurrentSongIndex := Index;
PlayItem(Index);
end
else if FMUSIC_IsFinished(FSongs[CurrentSongIndex].Module) and
not PlaylistMode then begin
PlayItem(CurrentSongIndex);
end;
end;

данный метод должен вызываться периодически (аналогично FrameMove). Здесь также проверяется режим плей-листа. Если он установлен, то будет проигрываться следующий файл списка, в противном случае будет бесконечно воспроизводиться композиция с индексом CurrentSongIndex.

 
Если Ваш игровой проект будет поддерживать в опции настроек установку каких-либо аудио-параметров - выбор драйвера, параметры фильтрации и т.п., то можете реализовать их установку по аналогии с тем, как это выполнено в рассмотренном нами выше примере.
 

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

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

 
     
  [Назад] [Все уроки] [Далее]  
     
Creating game on fle game engine - Simple game / Создание игры на fle game engine - Simple game

7 - Moving game scene



We slowly crept on to the next question.

читать данную статью на русском





Content

page 1 - Sprites

page 2 - Objects

page 3 - Overlay objects

page 4 - Coding - Setting parameters for the Scene Editor fge and write code to display the sprite ball in your first gaming application

page 5 - Show jumped ball

page 6 - Loading game scene

page 7 - Moving game scene

page 8 - Closing of the scene from the cavities by means of a black texture with a slot, restricts the movement of the scene

page 9 - We realize getting into the correct hole and around the holes - holes define the boundaries of sprites and sprite jumped ball

page 10 - Testing collisions

page 11 - Game score, sounds, music







3) Learning to control the movement of the scene - so she moved with mouse movements.

To implement the control component DirectInput is used in the game. It is part of DirectX and serves to control the game. The standard is supported by the device keyboard and mouse.

We need something to move around the screen in order to see our actions. Let us first learn how to move around the screen, our jumping ball. And only then will move the action on scene - forcing it to move, but not the ball.

Thus, you will learn several things: how to move around the screen sprites, how to perform control the game through DirectInput and finally, how to move the gaming scene.

In fact, tracking the mouse movements do not even want to use DirectInput. It is, in principle, it can carry out, but you can do without it. DirectInput will be needed mainly for tracking clicks the left mouse button, when we do something linked with it. As long as we do not need it, we leave this question in the near future.

Thus, to track mouse movement in module start.h add the following code

void LoadGameDataBlock();//this code, which must be added after

//move the mouse pointer
void ChangeGameCursorPos(); //is the code that you need to add



And in module start.cpp add

in method

CD3DGameApp::FrameMove

case APPSTATE_READY:

UpdateInput( &m_UserInput ); //this code, which must be added after

//move the mouse pointer
ChangeGameCursorPos(); //is the code that you need to add



and at the very end of the module start.cpp

add the implementation of this method -

void CD3DGameApp::ChangeGameCursorPos()
{
POINT CursorPos;
GetCursorPos(&CursorPos);

RECT rcClip;
GetWindowRect(m_hWndMain, &rcClip);

LONG cursor_at_window_x = CursorPos.x - rcClip.left;
LONG cursor_at_window_y = CursorPos.y - rcClip.top;

LONG cursor_spr_left_limit = 0;
LONG cursor_spr_top_limit = 0;
LONG cursor_spr_right_limit = (LONG)m_dwScreenWidth;
LONG cursor_spr_bottom_limit = (LONG)m_dwScreenHeight;

if ( cursor_at_window_x < cursor_spr_left_limit )
cursor_at_window_x = cursor_spr_left_limit;

if ( cursor_at_window_x > cursor_spr_right_limit )
cursor_at_window_x = cursor_spr_right_limit;

if ( cursor_at_window_y < cursor_spr_top_limit )
cursor_at_window_y = cursor_spr_top_limit;

if ( cursor_at_window_y > cursor_spr_bottom_limit )
cursor_at_window_y = cursor_spr_bottom_limit;

m_scrCursorPos.x = (float)cursor_at_window_x;
m_scrCursorPos.y = (float)(cursor_at_window_y);
g_AI_Ball_Sprite.m_v2Pos = m_scrCursorPos;
}



All - now with the mouse movements of our ball moving with it. What we need, and not for the ball, but for most scenes.

Jumping ball moved by mouse



Now you know how to move sprites, it may be useful to you to create other games.

Now disable the movement of the ball with the mouse - to comment out this line of code -

//g_AI_Ball_Sprite.m_v2Pos = m_scrCursorPos;


Save changes to the project, recompile the application. And we see that the ball does not move when you move the mouse.

To implement the move game scene, I think you have guessed, it is necessary to substitute instead of coordinates used for the sprite ball ... right! - To substitute the coordinates of the scene. The only question is how to do it.

If there was a certain object in a scene, and he would have been the property of storing the global position of the scene on the screen, changing which we could achieve the desired effect.

But we already have such a facility! - If you remember from page 6 - Loading game scene, it is called

m_pGameSceneDataFile

Already good. Do you remember what method was added to it? It was associated with scrolling scenes.

ScrollGameScene ?

Yes ! It is. Look at some code in there, and you may have already guessed what code you need to write. More precisely only a few lines of code.

Let's write it.

//g_AI_Ball_Sprite.m_v2Pos = m_scrCursorPos; //after this commented line add the following code

POINT Pos;
Pos.x = cursor_at_window_x;
Pos.y = cursor_at_window_y;

D3DXVECTOR2 vPos;
Screen2Vector(&Pos, &vPos);

g_fHorizontalScrollOffset = vPos.x;
g_fVerticalScrollOffset = vPos.y;
ScrollGameScene();



Save changes to the project, recompile the application. And we see that now when you move the mouse moves game scene.



We have achieved the desired !!!

However, as you can see, there are some drawbacks.

1) This is when the scene leaves the screen in its place is empty - blue background.

and

2) The fact that the ball is not always beautiful falls in a hole. If he is a little below the hole or slightly to the left or to the right - it turns out is not beautiful. Part of the ball overlaps background simulating upper visible part of the hole.

To solve the first problem, you can either increase the size of the stage, or on top of the scene to impose a rectangle with a slot through which is visible only a small part of it.

But to solve the second problem, you can come up with more clever ways. On them will be discussed on the next page. Stay with us ! :)



[previous] [next]



megainformatic live chat
Начать беседу
X
 

Registered comments



fle game engine - движок для создания игр
fle game engine - движок для создания игр


Something: Unexplained 2 captive of desires / Нечто: Необъяснимое 2 в плену желаний
Костя Коробкин Комикс Коллекционное издание - 6 комиксов, 81 страница, 220 mp3 треков
megainformatic Размещение баннерной рекламы у нас
Время загрузки: 1,0002