PDA

Просмотр полной версии : Алгоритмы Клавиатура, мышь, слушатели событий.


WaldeMar1321
07.11.2015, 19:22
Приятно времени суток всем. есть такой вопрос, внутри приложения должны быть непрекращающиеся события привязанные к клавиатуре и мыши. Но, при вызове "KeyboardEvent.KEY_DOWN", при удержании клавиши, сначала дергается объект в нужном направлении, потом замирает, а только потом едет как надо. Движение с комбинированными клавишами работает только в первом рывке. В чем проблема, кто-то знает как это решается?? С мышью еще хуже, событие "MouseEvent.MOUSE_DOWN" должно выполнятся пока кнопка нажата, и удерживается. но оно выполняется только в момент единичного нажатия. типа "CLICK".

udaaff
07.11.2015, 19:28
К сожалению в AS3 нету такого свойства, которое бы позволяло получить состояние клавиши нажата/ненажата. Запоминайте состояние: нажали - едем (больше не слушаем событие), отпустили - не едем.

undefined
07.11.2015, 19:30
В таких случаях при первом нажатии вешается слушатель ENTER_FRAME. и в нем события KEY_PRESSED/CLICK повторяются циклически и по KEY_RELEASED/MOUSE_UP удаляем ENTER_FRAME

ZackMercury
07.11.2015, 19:35
Вот готовый класс by caseyryan для клавиатуры.
package {

import flash.display.Stage;
import flash.events.Event;
import flash.events.KeyboardEvent;

public class Key {

private static var initialized:Boolean = false;
private static var keysDown:Object = {};

public static function initialize(stage:Stage):void {
if (!initialized) {
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed);
stage.addEventListener(KeyboardEvent.KEY_UP, keyReleased);
stage.addEventListener(Event.DEACTIVATE, clearKeys);
initialized = true;
}
}

public static function isDown(keyCode:uint):Boolean {
if (!initialized) {
throw new Error("Key class has not yet been initialized.");
}
return Boolean(keyCode in keysDown);
}

private static function keyPressed(event:KeyboardEvent):void {
keysDown[event.keyCode] = true;
}

private static function keyReleased(event:KeyboardEvent):void {
if (event.keyCode in keysDown) {
delete keysDown[event.keyCode];
}
}

private static function clearKeys(event:Event):void {
keysDown = {};
}
}
}

Пользоваться

Key.initialize(stage);
//В обработчике ENTER_FRAME:
if(Key.isDown(Keyboard.W) || Key.isDown(Keyboard.UP))
obj.y -= 1;


Насчёт мыши вы неправы. Логически верно, что нажатие один раз, и отпускание один раз. Или вы не согласны?

EndoCrinologist
07.11.2015, 19:52
Видел решение у одного разработчика:

stage.addEventListener(Event.ENTER_FRAME, onStage);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onDown);
stage.addEventListener(KeyboardEvent.KEY_UP, onUp);

function onDown(e:KeyboardEvent)
{
keypressed[e.keyCode] = true;
}
function onUp(e:KeyboardEvent)
{
keypressed[e.keyCode] = false;
}
function onStage(e:Event)
{
var hero_dx = stage.mouseX - hero.x;
var hero_dy = stage.mouseY - hero.y;
var hero_grad = Math.atan2(hero_dy,hero_dx) * 180 / Math.PI;
hero.rotation = hero_grad;

if (keypressed[37] || keypressed[65]) hero.x -= speed;
if (keypressed[38] || keypressed[87]) hero.y -= speed;
if (keypressed[39] || keypressed[68]) hero.x += speed;
if (keypressed[40] || keypressed[83]) hero.y += speed;

if (hero.x > 800 + hero.width) hero.x = 0 - hero.width;
if (hero.y > 600 + hero.width) hero.y = 0 - hero.width;
if (hero.x < 0 - hero.width) hero.x = 800 + hero.width;
if (hero.y < 0 - hero.width) hero.y = 600 + hero.width;
}

WaldeMar1321
08.11.2015, 15:33
Не то чтобы согласен. Нажатие может быть продолжительным действием, ведь есть же просто действие CLICK, вот оно одноразовое по идее. Но видимо, мне придется использовать подобную технологию (одну из любезно предоставленных мне здесь), и для мыши.

illuzor
08.11.2015, 16:43
WaldeMar1321, найдите любое поле ввода, и зажмите любую буквенную клавишу на клавиатуре. Что происходит? Сначала появляется один символ, а через секунду символы появляются один за другим быстро. Вот и флешплеер обрабатывает нажатия так же.

ZackMercury
08.11.2015, 17:08
WaldeMar1321, все события с устройств ввода делятся на 2 части - это начало и конец.
Например, событие клавиатуры KeyboardEvent.KEY_DOWN - это событие начала нажатия, а
KeyboardEvent.KEY_UP - это отпускание клавиши. То, что при длительном нажатии клавиши он
посылает событие многократно - неправильно с точки зрения логики, но с этим ничего не сделаешь.
MouseEvent.MOUSE_DOWN же работает исключительно правильно с точки зрения логики, он отсылается один раз при нажатии левой кнопки мыши, и соответствующее событие ловится при отпускании -
MouseEvent.MOUSE_UP.

Представьте, какие трудности ждали бы программиста, если бы всё работало не так.
Нужно, допустим, при нажатии на кнопку у клипа запустить анимацию, а при отпускании мыши - останавливать.

Пишем

var clip:MovieClip = new MovieClip();//допустим, это наш клип.
var button:Button = new Button(); //допустим, это наша кнопка.

button.addEventListener(MouseEvent.MOUSE_DOWN, function(e:Event):void
{
clip.gotoAndPlay(1);
});
button.addEventListener(MouseEvent.MOUSE_UP, function(e:Event):void
{
clip.gotoAndStop(1);
});


Тут всё будет работать как надо, но что если бы вместо этого MOUSE_DOWN посылал бы событие каждый кадр? Ничего бы не работало.
Логика этих событий такова, что есть MOUSE_DOWN - начало нажатия, и есть MOUSE_UP - конец нажатия, и всё, что между ними можно делать в обработчике ENTER_FRAME.
Есть TouchEvent.TOUCH_BEGIN, а есть TouchEvent.TOUCH_END, что вызывается при нажатии на экран на сенсорном экране, и при отжатии.
Есть KeyboardEvent.KEY_DOWN, а есть KeyboardEvent.KEY_UP.

EndoCrinologist
08.11.2015, 19:50
WaldeMar1321, а чем вам не угодило решение с добавлением полученного keyCode в массив?

WaldeMar1321
08.11.2015, 23:09
наличие массива, там где он в принципе не нужен.

Zebestov
08.11.2015, 23:33
Hello, Keyboard! (http://gamedevblogs.ru/blog/developing/1379.html)