- == [ЧАСТЬ 2] == -- ¦ Введение Привет! Это - Grant Smith, или Denthor из ASPHYXIA. Это - вторая часть моей Программы обучения для начинающих программистов. В этой части, я буду обрабатывать палитру со скоростью мысли. Что, черт возьми, такое - паллитра? Как я считываю ее? Как я ее устанавливаю? Как я прекращаю "пух" который появляется на экране когда я изменяю палитру? Как я делаю экран черным, используя палитру? Как я зажигаю экран? Как я гашу экран? Почему телефонные звонки так дороги? На большинство этих вопросов будет отвечено в этой, второй части моего Рядя Трейнеров для Паскаля. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= ¦ Что такое - паллитра? Несколько недель назад мой друг запустил игру. В игре была машина с синими полосами поперек. Когда машина была активизирована, в то время как половина полос оставалась той же самой, другая начинала изменять цвет и яркость. Он спросил меня как две полосы того же самого цвета внезапно становятся разными? Ответ прост: программа изменяла палитру. Вы уже знаете из первой части, что имеется 256 цветов в режиме MCGA, пронумерованных от 0 до 255. Но вы еще не знаете что каждый цвет составлен из различной интенсивности красного, зеленого и синего(R, G и B), основных цветов (Вы должны были узнать относительно основных цветов в школе). Эти интенсивности - числа между 0 и 63. Например ярко-красный цвет мог бы быть получен установкой R в 63, G в 0, и B в 0. Это означает два цвета могут выглядеть одинаково, и если вы рисуете изображение, используя оба, никто не будет способен сообщить различие между ними .., И только если их снова изменить, вы увидите отличие. Также, изменяя цвета всей палитры, вы можете получить такие эффекты как Постепенное исчезновение и Постепенное появление экрана, которые можно найти во многих демках и играх. Манипуляция с палитрой может быть весьма запутывающей для некоторых людей, потому что цвета, которые выглядят, одинаково - фактически полностью разные. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= ¦ Как я могу в палитре считать значение цвета? Это очень легко сделать. Чтобы считать значение цвета, вы вводите необходимый номер цвета в порт $3c7, затем, последовательно читаете значения R, G и B из порта $3c9. Просто, huh? Вот процедура, которая делает это для вас: Procedure GetPal(ColorNo : Byte; Var R,G,B : Byte); Begin Port[$3c7] := ColorNo; R := Port[$3c9]; G := Port[$3c9]; B := Port[$3c9]; End; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= ¦ Как я устанавливаю значение цвета в палитре? Это - столь же просто как 3.1415926535897932385. Что Вы делаете, так это вводите номер цвета, который хотите изменить в порт $3c8, затем, последовательно вводите значения R, G и B соответственно в порт $3c9. Поскольку вы все столь ленивы я написал процедуру для вас ;-) Procedure Pal(ColorNo : Byte; R,G,B : Byte); Begin Port[$3c8] := ColorNo; Port[$3c9] := R; Port[$3c9] := G; Port[$3c9] := B; End; Asphyxia не использует вышеупомянутые процедуры, мы используем ассемблерные версии, которые будут даваться ЛЮДЯМ, ОТВЕЧАЮЩИМ НА ЭТОТ РЯД ТРЕНЕРОВ (Hint, Hint) =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= ¦ Как я прекращаю "пух", который появляется на моем экране, когда я изменяю палитру? Если вы использовали палитру раньше, то заметили, что имеется немного "пуха" на экране, когда она изменяется ее. Мы избегаем этого следующим путем: Имеется электронный луч на вашем мониторе, который постоянно обновляет ваш экран сверху донизу. Поскольку он идет до низа экрана, требуется время для этого, чтобы добраться снова до вершины экран, чтобы модифицировать экран снова. Период, перемещения от основания до вершины называется Verticle Retrace. В течение Verticle Retrace вы можете изменять палитру без того, чтобы портить то, что на экране. Что мы делаем, так это ждем, пока Verticle Retrace не будет запущен путем вызова некоторой процедуры; это означает, что все что мы сделаем, теперь будет показываться только после Verticle Retrace, так что мы можем делать все виды странных и необычных вещей с экраном в течение этого обратного хода и только результат будет показан, когда обратный ход закончен. Это - крутой путь, поскольку значит, что, когда мы изменяем палитру, "пух" не появится на экране! Четко, huh? ;-) Используй это мудро, мой сын. ОБРАТИТЕ ВНИМАНИЕ: WaitRetrace может быть большой помощью вашему кодированию... Код, который выполняется за один обратный ход будет подразумевать, что демка выполнится с одинаковой скоростью на разных компах независимо от компьютерной скорости (если только вы не делаете очень многого в течение WaitRetrace и компьютер не - slooooow). procedure WaitRetrace; assembler; label l1, l2; asm mov dx,3DAh l1: in al,dx and al,08h jnz l1 l2: in al,dx and al,08h jz l2 end; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= ¦ Как я делаю экран черным, используя палитру? Это основы: только установите значения R,G и B всех цветов в 0, например вот так: Procedure Blackout; VAR loop1:integer; BEGIN WaitRetrace; For loop1:=0 to 255 do Pal (loop1,0,0,0); END; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= ¦ Как я постепенно зажигаю экран? Ok, это может быть ОЧЕНЬ эффективно. Что вы должны сначала делать - сохранить палитру в массив: VAR Pall := Array [0.255,1..3] of BYTE; От 0 до 255 - для этих 256 цветов в режиме MCGA; от 1 до 3 - R, G и B значений интенсивности; Procedure GrabPallette; VAR loop1:integer; BEGIN For loop1:=0 to 255 do Getpal (loop1,pall[loop1,1],pall[loop1,2],pall[loop1,3]); END; Это загружает всю палитру в массив. Теперь вы делаете экран черным (см. выше), и рисуете то, что хотите без показа ;-) . Затем, то что вы делаете, - это обновляете палитру. Для каждого цвета вы проверяете, такой ли он как в сохраненной палитре. Если нет, - увеличиваем их на 1. Так как интенсивности находятся в диапазоне от 0 до 63 вам надо это сделать всего 64 раза. Procedure Fadeup; VAR loop1,loop2:integer; Tmp : Array [1..3] of byte; BEGIN For loop1:=1 to 64 do BEGIN WaitRetrace; For loop2:=0 to 255 do BEGIN Getpal (loop2,Tmp[1],Tmp[2],Tmp[3]); If Tmp[1]0 then dec (Tmp[1]); If Tmp[2]>0 then dec (Tmp[2]); If Tmp[3]>0 then dec (Tmp[3]); Pal (loop2,Tmp[1],Tmp[2],Tmp[3]); END; END; END; Снова, чтобы замедлить вышеупомянутое, поместите задержку выше WaitRetrace. Постепенное гашение экрана выглядит НАМНОГО более внушительнее простой очистки экрана; Для Востановления палитры используйте : Procedure RestorePallette; VAR loop1:integer; BEGIN WaitRetrace; For loop1:=0 to 255 do pal (loop1,Pall[loop1,1],Pall[loop1,2],Pall[loop1,3]); END; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= ¦ На прощание... Хорошо, на большинство этих оригинальных вопросов, ответил ;-) следующая программа весьма большая, так что может потребоваться время, чтобы разобраться в ней. Упорно продолжайте заниматься и это будет преодолено. ЕСТЬ ЗДЕСЬ КТО НИБУДЬ !?! P.S. Наша новая демка должна быть скоро ..., ожидайте. [ And so she came across him, slumped over his keyboard yet again . 'It's three in the morning' she whispered. 'Let's get you to bed'. He stirred, his face bathed in the dull light of his monitor. He mutters something. As she leans across him to disconnect the power, she asks him; 'Was it worth it?'. His answer surprises her. 'No.' he says. In his caffiene-enduced haze, he smiles. 'But it sure is a great way to relax.' ] - Grant Smith Tue 13 July, 1993 2:23 am. Увидимся на следующей неделе. Denthor