![]() |
Модераторы: javastic, AntonSaburov |
![]() ![]() ![]() |
|
TigraZver |
|
||||
Новичок Профиль Группа: Участник Сообщений: 12 Регистрация: 26.3.2008 Репутация: нет Всего: нет |
Помогите кто может.
Пробежалась по темам о getKeyStates() и keyPressed(int keyCode) и не нашла ответ на мой вопрос. Как я понимаю getKeyStates() позволяет опросить состояние клавы на момент вызова, может быть нажато несколько кнопок. Например ка это делается у меня:
Проблема у меня возникает в вызове StartScene(GameMenu.Process(IS_UP,IS_DOWN,IS_FIRE)):
В эмуляторе все работает так как надо - верх, вниз, fire - переход происходит и выполняется. Но вот при тестировании на Motorole происходит двойное нажатие - перескакивает через один. , В одной из тем разбиралась подобная проблема и один из челов предложил, что keyRelease считаеться за еще одно нажатие, поэтому следует переопределить этот метод. Подскажите как это сделать в данной конструкции или как по другому решить данную проблемку. Добавлено через 3 минуты и 9 секунд Да еще один баг, если так можно назвать. На Моторе Fire или кнопка 5 не активны. Вместо этого клавиша # - выполняет ее действия. Как исправить чтоб работало как надо? |
||||
|
|||||
TigraZver |
|
|||
Новичок Профиль Группа: Участник Сообщений: 12 Регистрация: 26.3.2008 Репутация: нет Всего: нет |
Ну пока ответов нет, накрутила сама кое что:
flag глобальный. Криво конечно... Но другого варианта пока нет. Но помогло не сильно. Задержка небольшая получилась, но дело вроде в том, что нажатие кнопки Мотор воспринимает как длинное нажатие, то есть как многоразовое нажатие. Чем дольше держишь кнопку тем больше нажатий. Вообщем кто знает как избавиться от этого чуда - напишите. Жду. |
|||
|
||||
Dummy |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 263 Регистрация: 21.5.2007 Репутация: 7 Всего: 19 |
Небольшая поправочка, GameCanvas.getKeyStates() возвращает не совсем состояние клавиатуры на момент вызова. Она возвращает переменную-защелку, в которой биты, соответствующие нажатым с момента последнего вызова getKeyStates() клавишам, выставлены в 1, а остальные - в 0. Т. е. любая клавиша, нажатая между двумя вызовами GameCanvas.getKeyStates() (или от момента старта мидлета до первого вызова getKeyStates()), будет включена в возвращаемое значение, даже если на момент вызова она уже отжата. Твой код учитывает эту особенность?
Это сообщение отредактировал(а) Dummy - 1.6.2008, 21:33 |
|||
|
||||
TigraZver |
|
|||
Новичок Профиль Группа: Участник Сообщений: 12 Регистрация: 26.3.2008 Репутация: нет Всего: нет |
Я так понимаю что не учитывает. Какие есть варианты ? Где посмотреть , что почитать?: Добавлено через 9 минут Обнулять значение нажатой клавиши после каждого считывания? |
|||
|
||||
Dummy |
|
||||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 263 Регистрация: 21.5.2007 Репутация: 7 Всего: 19 |
getKeyStates() обнуляет внутреннее состояние защелки после каждого вызова. Можно, например, при переходе в новое состояние, вызывать getKeyStates() вхолостую, просто чтобы сбросить накопленные ранее клавиши. Т. е. при каждом
ты делаешь getKeyStates(). Мое личное мнение - стиль кодирования в твоем примере зубодробительный (без обид ![]()
Это сообщение отредактировал(а) Dummy - 2.6.2008, 13:29 |
||||||
|
|||||||
i_SweP |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 126 Регистрация: 23.6.2007 Репутация: нет Всего: нет |
А решение-то простое! Надо сделать задержку в цикле.
Например
И никакой keyReleased() не считается за ещё одно нажатие. Это сообщение отредактировал(а) i_SweP - 2.6.2008, 20:49 |
|||
|
||||
TigraZver |
|
||||||||||||||
Новичок Профиль Группа: Участник Сообщений: 12 Регистрация: 26.3.2008 Репутация: нет Всего: нет |
Ну прежде всего спасибо за инфу, приняла к сведению. ![]() Только твой вариант с отдельной функцией и в ней уже описывать getKeyStates() в данном случае мне не много не подходит так как у меня главный класс class Engine extends GameCanvas implements Runnable и в него включены остальные в том числе и Меню и сама Игра - Game :
там же и определена функция, которая снимает показание с клавиш и уже в зависимости от того какая сцена запущена, выполняет функцию Process() в своих собственных классах( например : GameEng.Process(IS_UP,IS_DOWN,IS_LEFT,IS_RIGHT,IS_FIRE) - снятие показания клавиш для самой игры, GameMenu.Process(IS_UP,IS_DOWN,IS_FIRE) - для меню, и т.д) :
а уже в самом классе, например того же Game в функции Process() я прописываю действия на эти клавиши:
А в классе Menu я использую кнопки верх вниз и ввод для перехода с одной подменюшки на другую:
переменная ret возвращает новое значение сцены и уже в классе Engine происходит обработка в его собственном Process() (описание в самом начале). Так вот предложенный тобой вариант как я понимаю предполагает, что эти функции, и класса Игра, и Меню будут прописаны в главном классе Ядре, чтоб иметь возможность применить метод getKeyStates(). Или же прописывать GameCanvas в каждом классе. если я не так тебя поняла, поясни пожалуйста. на данный момент кнопки рабочие, и в Игре и в Меню так как надо, только в Меню все же перескакивают довольно резво и от быстрого одноразового нажатия. Может есть вариант прописки по KEY_REPEAT? И еще одна вещь которая работает не так как надо - FIRE_PRESSED - реагирует на #, а не на 5 или центральную клавишу джойстика. Пробовала через FIRE и KEY_NUM5 - javax.microedition.lcdui.Canvas, не то не другое не работает. Может есть идеи на этот счет? |
||||||||||||||
|
|||||||||||||||
Dummy |
|
||||||||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 263 Регистрация: 21.5.2007 Репутация: 7 Всего: 19 |
i_SweP, объясни, пожалуйста, что за проблема решается таким способом. Вообще, решения вида "задержки на магическое число миллисекунд" вряд ли могут являться исчерпывающими, т. к. их магические свойства имеют свойства пропадать при переходе на другую платформу, версию JVM и т. п.
Ну, базовый смысл уловлен правильно. В рамках того кода, что у тебя уже есть, можно передавать каким-либо образом каждой сцене твой Engine, у которого при каждой смене состояния Дизайн, сделанный тобой, честно говоря, не слишком хороший и не слишком в Java-стиле даже для меня, не большого специалиста в области архитектурных решений и никакого специалиста в области игр. Я бы как минимум сотворил для всех сцен: Menu, About и других - общий родительский абстрактный класс Scene с абстрактным методом Process, который бы каждый из них переопределил, как нужно. А Engine хранил бы одну ссылку на текущую сцену и просто вызывал бы Process(). Да и раз уж Engine по смыслу контроллер, то можно было бы отделить его от GameCanvas. Потом на основании того, что Process() текущей сцены возвращает, можно принимать решение в Engine о том, в какое состояние переходить дальше. Я, например, так переписал - и получилось, что, вроде бы, и не надо лишний раз вызывать getKeyStates():
Правда, обнуление защелки при переходе на новую сцену может быть не слишком хорошим решением - часть нажатий в момент перехода между сценами, может потеряться. Критично ли это - решать в каждом конкретном случае. По-моему, в моем варианте можно обойтись и без этого (убрать первый canvas.getKeyStates() в update()).
Можно попробовать простенький тестик - переопределить в Canvas / GameCanvas keyPressed() и вывести для # код game action:
Если клавише # действительно соответствует game action FIRE, то, видимо, остается только смириться - так вот на этой мотороле сделано. Если нет - дальше будем думать))) Это сообщение отредактировал(а) Dummy - 2.6.2008, 22:29 |
||||||||||
|
|||||||||||
i_SweP |
|
||||
Шустрый ![]() Профиль Группа: Участник Сообщений: 126 Регистрация: 23.6.2007 Репутация: нет Всего: нет |
А вот и сам удивляюсь магии. Хотя, конечно, это не универсальное решение. Как я понял основная проблема тут:
Если добавить паузу, результат весьма заметен Не верите, запустите пример в атаче И вот его код:
Это сообщение отредактировал(а) i_SweP - 3.6.2008, 12:23 Присоединённый файл ( Кол-во скачиваний: 1 ) ![]() |
||||
|
|||||
Dummy |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 263 Регистрация: 21.5.2007 Репутация: 7 Всего: 19 |
Все, догнал, в чем дело. Спасибо, i_SweP, твой пример помог уяснить суть проблемы
![]() Я просто не очень внимательно прочитал спецификацию. А там написано, что getKeyStates() выставляет соответствующий бит с случае, если кнопка была нажата хоть раз с момента последнего вызова getKeyStates() или нажата в настоящий момент. Если внутри цикла, который ты описал, нет задержки в виде Thread.sleep() или явной отдачи управления планировщику потоков через Thread.yield(), то существует вероятность (которая в твоем случае реализуется постоянно), что при заходе на новую итерацию цикла событие о том, что соответствующая клавиша (например, FIRE) уже отжата, еще не успеет отработать, и соответствующий бит в защелке (FIRE_PRESSED) еще не будет сброшен, а успеет сброситься только, например, через итерацию или еще позже, в результате получится. Иными словами, в этом примере проявляется инерционность системы событий JVM (вполне ожидаемое и нормальное явление). TigraZver, Если ты еще не начала читать мой длинный пост от 2.6.2008, 22:26, то и не читай пока ![]() В твоем случае самым простым (хотя и далеко не универсальным) решением будет вставка Thread.sleep() на небольшой интервал или, вероятно, лучше - Thread.yield() после каждого getKeyStates(). Но вообще говоря, я бы рекомендовал следующее решение. Для тех случаев, когда нужна дискретность нажатий и инерция может приводить к багам (например, для случая перемещения по элементам меню вверх-вниз), использовать обработку keyPressed() / keyReleased(). Когда нужны "непрерывные", длительные нажатия и небольшая инерционность не является критичной (перемещение курсора или другого объекта по игровому полю) - можно использовать GameCanvas.getKeyStates(). |
|||
|
||||
TigraZver |
|
||||
Новичок Профиль Группа: Участник Сообщений: 12 Регистрация: 26.3.2008 Репутация: нет Всего: нет |
Ну во первых, Dummy, я успела прочитать твой предыдущий пост и считаю, что было весьма полезно. Тест на кнопки дал неоднозначный результат. На моторе при нажатии на # показывает - "key 35 --> gAct 0" , 5 -- "key 53 --> gAct 8" , 2 -- "key 50 --> gAct 1" , 4 -- "key 52 --> gAct 2" , 6 -- "key 54 --> gAct 5" , 8 -- "key 56 --> gAct 6" , Fire на джойстике - "key 20 --> gAct 8" , Up на джойстике - "key -1 --> gAct 1" , Left на джойстике - "key -2 --> gAct 2" , Right на джойстике - "key -5 --> gAct 5" , Down на джойстике - "key -6 --> gAct 6" , при нажатии на # - стреляет, а при 5 или Fire - ничего не происходит. может заменить по коду ? теперь по поводу инерции: Thread.sleep() - есть :
но использовать его в качестве решения мне не подходит , так как во время игры в классе Game будет тормозить мой Звездолет. А он то как раз летает так как надо. А вот в меню слишком быстро. Поэтому второй вариант про использование keyPressed() / keyReleased() мне кажется подойдет больше. переделываю, позже напишу что получилось. есть замечания, предложения пишите. п.с. И конечно Dummy, i_SweP признательное мое мерси за терпение и помощь ![]() |
||||
|
|||||
![]() ![]() ![]() |
FAQ раздела лежит здесь! |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Java ME (J2ME) | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |