Студопедия

Главная страница Случайная страница

КАТЕГОРИИ:

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Листинг 12.2. Шпионим за часами (SPY.C)._____






// ВКЛЮЧАЕМЫЕ ФАЙЛЫ ///////////////////////////////////////////////

#include < dos.h>

#include < bios.h>

#nclude < stdio.h>

#include < math.h>

#include < conio.h>

#include < graph.h>

// ОПРЕДЕЛЕНИЯ//////////////////////////////////

#define TIME_KEEPER_INT 0x1C

// ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ ///////////////////////////////

void (_interrupt _far *old_Isr)();

// хранит старый обработчик прерывания

long time=0;

// функции ////////////////////////////////////

void _interrupt _far Timer()

{

// Увеличивает глобальную переменную.

// Еще раз отметим, что мы можем это делать, так как при входе

// в процедуру обработки прерывания регистр DS указывает на сегмент

// глобальных данных нашей программы,

time++;

} // конец Timer

// ОСНОВНАЯ ПРОГРАММА ////////////////////////////////

void main(void)

{

// установка процедуры обработки прерывания

Old_Isr = _dos_getvect(TIME_KEEPER_INT);

_dos_setvect(TIME_KEEPER_INT, Timer);

// ожидание нажатия клавиши пользователем

while(! kbhit())

{

// вывод переменной. Примечание: сама по себе функция main

// значение этой переменной не изменяет...

_settextposition(0, 0);

printf(" \nThe timer reads: %ld ", time);

} // конец while

// восстановление старого обработчика прерывания

_dos_setvect(TIME_KEEPER_INT, Old_Isr);

} // конец функции main

Запустив программу, приведенную в Листинге 12.2, вы увидите, что приращение счетчика происходит очень быстро. Фактически, значение этой переменной увеличивается каждую 1/18.2 секунды — так настроены по умолчанию внутренние системные часы. (Не переживайте, очень скоро мы научимся управлять и ими). Главное, что сама программа не увеличивает значенй переменной time. Этим занимается исключительно подпрограмма обслужива ния прерывания.

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

Игровой цикл

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

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

§ Проинициализировать все системы;

§ Начать игровой цикл;

§ Получить команды игрока;

§ Отработать логику игры и проделать все необходимые преобразования участвующих в игре объектов;

§ Визуализировать графическое изображение;

§ Вернуться к началу цикла.

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

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

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

§ Время, затраченное на реализацию игры;

§ Скорость выполнения программы;

§ Простота модификации;

§ Легкость отладки.

Этот список можно продолжить, однако это, пожалуй» наиболее важные факторы.

В четырнадцатой главе, «Связь», мы займемся игрой, которую я назвал Net-Tank. Это работающий через последовательный порт симулятор танкового боя, со звуковыми эффектами, потрясающей графикой, различным оружием и полностью интерактивным режимом игры. Цикл этой игры приведен на рисунке 12.4.

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

§ Инициализацию объектов игры;

§ Удаление объектов;

§ Ввод данных локальным игроком;

§ Ввод данных удаленным игроком;

§ Выполнение преобразований;

§ Расчет столкновений;

§ Вызов подпрограммы, перемещающей снаряды;

§ Воспроизведение графического изображения в автономном буфере экрана. В нужный момент это изображение мгновенно возникнет на экране.

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

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

Автономные функции

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


Допустим, например, что мы хотим сделать функцию, которая медленно изменяет содержимое регистра определенного цвета. Этот регистр может использоваться для изображения различных мелких деталей на экране. При выполнении функции изменяется цвет регистра, и таким образом изменяется один из цветов экрана. Результат работы этой функции отражается только на изображении. Функция, решающая подобную задачу идеально приспособлена для автономной работы. В Листинге 12.3 приведен текст программы, реализующей такую функцию.


Поделиться с друзьями:

mylektsii.su - Мои Лекции - 2015-2024 год. (0.007 сек.)Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав Пожаловаться на материал