:: СОДЕРЖАНИЕ НОМЕРА
:: Газетные рубрики
:: АВТОРЫ
:: Поиск
:: Поддержка проекта
Webmoney:
|
:: №20 (27.06.2004) Просмотров: 4738
Автор: Александр Шушков / axor / Perspective. Рубрика: В помощь разработчику. Номер: №20 (27.06.2004). Направление движенияВ данный момент я занимаюсь созданием игры, и в один прекрасный момент передо мной возникла задачка: по направлению движения героя необходимо найти нужный спрайт (или группу спрайтов).Для начала введу в курс дела. Итак, сначала у меня производится поиск кратчайшего пути (за что отдельное спасибо одному человеку) некоего персонажа, следствием которого является линейная запись (таблица) из координат героя по которым тот должен достигнуть указанной точки. Затем происходит преобразование этих координат в направление героя, которое получается путем вычитания последующих координат из предыдущих. Таким образом, получается одно из восьми чисел: #FFFF, #0101, #00FF, #0001, #0100, #FF00, #01FF, #FF01. Это при условии, что герой может перемещаться по карте в восьми направлениях. Так же нетрудно заметить, что в списке направлений отсутствует комбинация #0000. Почему? А все потому, что если бы она получилась в результате вычитания, это означало бы, что герой просто стоит на месте, т.е. никуда не двигается, следовательно учитывать эту комбинацию не нужно. Например, в регистре BC, есть одно из восьми указанных выше чисел. Необходимо сделать процедуру, которая преобразует эти числа в число от 0 до 7, которое в свою очередь будет означать то или иное направление героя. Порядок чисел (что естественно) может быть любым. Например, BC=#FFFF. Делаем CALL Calc. На выходе из этой процедуры в регистре A пусть будет число 0. И так для каждого из этих восьми чисел. Сначала я сделал процедурку, которая просто (и тупо) перебирает все варианты. Но что-то мне подсказывало, что эту задачку можно решить более красиво и аккуратно. К сожалению, сам я так ничего и не придумал, поэтому обратился к друзьям по переписке и вот что из этого вышло. Станислав Юдин Вот такая мысль посетила. Набираю сразу в письме... Преобразуем двухбайтное число в четырехбитное. CALC1 LD A,B AND %00000011 LD B,A LD A,C AND %00000011 SLA B SLA B OR B ;находим по таблице нужное значение LD C,A LD B,0 LD HL,TABLE-1 ADD HL,BC LD A,(HL) RET TABLE DB 3 ;1 DB 0 ;2 DB 2 ;3 DB 4 ;4 DB 1 ;5 DB 0 ;6 DB 6 ;7 DB 0 ;8 DB 0 ;9 DB 0 ;10 DB 0 ;11 DB 5 ;12 DB 7 ;13 DB 0 ;14 ;ОБРЕЗАТЬ НЕЛЬЗЯ! DB 0 ;15 ;ОБРЕЗАТЬ НЕЛЬЗЯ! Может быть где-то и есть ошибки, но суть надеюсь ясна. Что скажешь? Или плохое решение? Влад Сотников Поскольку в последовательности чисел я не заметил четкой закономерности, то иначе, как перебором, не сделать. Но перебор можно постараться сделать красивым и компактным. В предлагаемом варианте искомое число должно быть в data, иначе из цикла мы не выйдем. В противном случае вариант можно модифицировать. CALC2 ;IN: [BC] - NUMBER XOR A LD HL,DATA LOOP LD E,(HL) INC HL LD D,(HL) INC HL EX DE,HL AND A SBC HL,BC RET Z EX DE,HL INC A JR LOOP DATA DW #FFFF DW #00FF DW #01FF DW #FF00 DW #0100 DW #0101 DW #FF01 DW #0001 Еще вариант... Я, как всегда, экономлю на памяти, а не на тактах. CALC3 ;IN: [BC] ;OUT: [D] XOR A LD D,A LD HL,DATA LOOP2 LD A,C CP (HL) INC HL JR NZ,LOOP_12 LD A,B CP (HL) LD A,D RET Z LOOP_12 INC HL INC D JR LOOP2 Павел Стахов Мой вариант считает свои числа в следующей последовательности: ;#ffff=0 (#0000) ;#ff00=1 (#0001) ;#ff01=2 (#0002) ;#00ff=3 (#0100) ;#0000=4 (#0101) - Нужна ли эта комбинация? ;#0001=5 (#0102) ;#01ff=6 (#0200) ;#0100=7 (#0201) ;#0101=8 (#0202) CALC4 INC C INC B LD A,B ADD A,A ADD A,B ADD A,C ;Все, в A номер. Если тебе не нужна комбинация 4, то еще: CP 5 ;5,6,7,8 NC CCF ;C SBC A,00 ;A=A-1 RET Дмитрий Быстров Ты точно не забыл вариант #0000? Если нет, то: CALC5 LD A,C ADD A,A ADD A,C ;-3..3 ADD A,B ;-4..4, 0 НЕЛЬЗЯ ADD A,4 ;0..8, 4 НЕЛЬЗЯ CP 4 ADC A,-1 ;0..7 RET Иван Рощин Можно использовать такое преобразование: ; BC B+1,C (B+1)*3+C ; #FFFF #00FF #FF ; #0101 #0201 7 ; #00FF #01FF 2 ; #0001 #0101 4 ; #0100 #0200 6 ; #FF00 #0000 0 ; #01FF #02FF 5 ; #FF01 #0001 1 ;Соответствующий фрагмент программы: CALC6 INC B LD A,B ADD A,A ADD A,B ADD A,C ;После чего заменяем #FF на 3: CP #FF JR NZ,$+4 LD A,3 RET Если изменять B нельзя, добавляем команду DEC B. * * * Далее с регистром A можно делать все что угодно. Я, например, его использовал следующим образом: ADD A,A ;A=A*8 ADD A,A ADD A,A LD HL,TABL LD E,A LD D,0 ADD HL,DE ;Теперь HL указывает на табличку адресов спрайтов нужного направления. ; Далее ваши действия... TABL UP DW SPRu1 ;Шаг левой ногой DW SPRu2 ;Промежуточный шаг DW SPRu3 ;Шаг правой ногой DW SPRu2 ;Промежуточный шаг DOWN DW SPRd1 ;Шаг левой ногой DW SPRd2 ;Промежуточный шаг DW SPRd3 ;Шаг правой ногой DW SPRd2 ;Промежуточный шаг Благодарю всех откликнувшихся, я рад, что у меня есть такие друзья! Если у кого-то возникнут какие-либо вопросы или предложения, я с удовольствием их выслушаю. |