Главная страница Случайная страница КАТЕГОРИИ: АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
Листинг 7.3. Новая функция Draw_Sprite() с отсечением.
void Draw_Sprite_Clip(sprite_ptr sprite) { // Эта функция рисует спрайт на экране и отсекает области, // выходящий за границы экрана. Функция написана в // демонстрационных целях. char far *work_sprite; int work_offset=0, offset, x_off, x, y, xs, ys, xe, ye, clip_width, clip_heigth; unsigned char data; // Получить указатель на спрайт xs=sprite-> x; ys=sprite-> y; // Расчет координат прямоугольника, описывающего спрайт xe=xs+sprite_width-1; ye=ys+sprite_height-1; // Проверка полной невидимости спрайта // (то есть лежит ли он полностью за пределами экрана) if((xs> =SCREEN_WIDTH) || (ys> ==SCREEN HEIGHT) | | (xs< =(-sprite_width))||(ys< =(-sprite_height))) { return; } // конец оператора if
// Спрайт частично видим, следовательно, необходимо // рассчитать рисуемую область // Отсечение по координате Х if(xs< 0) xs=0; else if(xe> =SCREEN_WIDTH) xe=SCREEN_WIDTH-l; //Отсечение по координате Y if(ys< 0) уs=0; else if(ye> =SCREEN_HEIGHT) ye=SCREEN_HEIGHT-1; // Расчет новой высоты и ширины clip_width=xe-xs+l; clip height=ye-ys+l; // Расчет рабочего смещения на основе нового начального // значения координаты Y work_offset=(sprite-> y-ys)*sprite_width; x_off=(xs-sprite-> x); // Построение усеченного спрайта // Для упрощения дадим указателю на спрайт новое имя work_sprite = sprite-> frames[sprite-> curr_frame]; // Расчет смещения, спрайта в видеобуфере offset = (ys< < 8) + (ys< < 6) + sprite-> xs; for (y=0; y< clip_height; y++) { // Копируем следующую строку в видеобуфер for (х=0; x< clip_width; x++) ( // Проверка пикселя на " прозрачность" (то есть на 0); // если пиксель " непрозрачный" - рисуем if ((data=work_sprite[work_offset+x+x_off])) double_buffer[offset+x+x_off] = data; } // конец цикла по X // Переход к следующей строке в видеобуфере // и в растровом буфере спрайта offset += SCREEN_WIDTH; work_offset += sprite_width; } // конец цикла по У } // конец функции Как и к двум первым листингам этой главы, к Листингу 7.3 надо относиться достаточно скептически. Эта программа, конечно, делает то, что ей и положено, однако не учитывает при этом контекста. А контекст — это все! Например, в вашей игре все картинки могут располагаться посередине. Тогда в отсечении у вас просто отпадет необходимость. Возможно, ваш объект всегда будет двигаться по горизонтали, в этом случае не потребуется выполнять вертикальное отсечение и вы сможете провести оптимизацию части предварительной обработки. Иными словами, всегда пытайтесь создавать ваши функции для конкретной ситуации и для определенной игры. В данном случае передо мной стояла несколько иная задача — объяснить вам суть проблемы. Если вы поняли идею, то, потратив определенное время и силы, найдете свое правильное решение. Контроль столкновения спрайтов Часто бывает нужно проверить, не произошло ли в нашей игре столкновение двух или более спрайтов. Контроль столкновения между спрайтами не сложнее контроля столкновений между астероидом и кораблем. Эту тему мы обсуждали в четвертой главе. Чтобы выяснить это, достаточно посмотреть, имеются ли общие точки хотя бы у одной из четырех границ спрайта с другой областью. Алгоритм 7.2 исполняет подобный тест.
|