Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Некоторые мысли о контроллерах клавиатуры (http://www.flasher.ru/forum/showthread.php?t=139421)

incvizitor 30.04.2010 15:48

incvizitor, вы промахнулись с проблематикой треда)))

чё?

orcpochta 30.04.2010 16:24

на самом деле все гонево - второй вариант самый нормальный и ничему не противоречит, вроде, если пользоваться им аккуратно

Psycho Tiger 30.04.2010 17:56

Цитата:

в чем подход-то?
Цитата:

Чтобы слушать события нажатий клавиш всей сцены контроллеру придется вешать слушатели на stage, и тут возникает следующая делема:
Цитата:

2) Можно передать в конструктор контроллера ссылку на stage, но тогда внешний код должен будет гарантировать, что во время передачи stage доступен, но тут уже возникают всякие проблемы, связанные с тем, почему собственно убрали глобальный _stage из AS3.
Это ответ на ваш вопрос, какой подход использовать и вы сами на него ответили, посмотрев на класс. Передавать stage как ссылку.
Цитата:

То, что вы предложили, это своего рода блокнот, который можно открыть и посмотреть запись нажата ли сейчас кнопка и какая нажата последней.
Можно любой класс обозвать так. Переменные записаны, можно залезть и прочитать их значение как в блокноте.
Цитата:

и как вы предлагаете им пользоваться в рамках озвученного мной примера? вешать ENTER_FRAME слушатель, который каждый кадр будет лезть в этот блокнот смотреть кнопки? - бред же
Вы о чем то другом думаете. Я расписал случаи использования 50/50. Если нужен класс для работы с клавиатурой - класс silin`а. Если нужно узнать, когда нажата кнопка какая то кнопка - класс для работы с клавиатурой нафиг не нужен.

orcpochta 30.04.2010 18:09

Цитата:

Вы о чем то другом думаете. Я расписал случаи использования 50/50. Если нужен класс для работы с клавиатурой - класс silin`а. Если нужно узнать, когда нажата кнопка какая то кнопка - класс для работы с клавиатурой нафиг не нужен.
что значит класс для работы с клавиатурой? я в первом своем посте описал ситуацию для какой работы с клавиатурой мне нужен класс и я вижу, что класс силина из совершенно какой-то другой оперы

расскажите просто, как вы используете силинский класс - т.е. практическое применение))

i.o. 30.04.2010 18:48

orcpochta, конечно второй вариант - передать стэйдж по ссылке в конструктор или в init какой-нить. А то это вообще бред, создавать на базе DisplayObject'a контроллер клавы, а потом его еще добавлять в дисплей-лист, чтобы stage появился, и только потом начинать слушать события от клавиатуры. Возникает вопрос - зачем контроллеру клавы нужно быть визуальным объектом, при чем добавленным на сцену??
Ответ - незачем, поэтому вариант 2

Psycho Tiger 30.04.2010 19:53

Цитата:

что значит класс для работы с клавиатурой?
Кхм. Когда вы говорили "контроллер для работы с клавиатурой" я думал о MVC, но поняв, что это слабо вяжется с реальностью предположил что вы имели ввиду обычный класс, который удобно помогает работать с клавиатурой. Я не прав? Что хотите Вы?

А, класс, рассылающий события... Для игры... кхм. Здорово. Что имеем?
Подписываемся на 4 события, (влево-вправо-вверх-вниз), а то и на больше - не во всех играх 4 кнопки. 4 обработчика, ну ладно, так удобней, ок. Но мы заводим ради этого ещё один класс, который диспатчит событие... чтобы было удобней.
Считаем строчки кода:
4 подписка на событие.
4 описание заголовка методов
4 отписка от методов
12 строк кода.

Или если инлайново:
1 подписка
1 отписка
1 заголовок метода
4 ифа (или 8 кейсов+свич)

7-12 строк против 12. То есть, проще говоря, проще и дешевле по производительности писать код ЗАНОВО, чем использовать методы своего же класса. Это стоит того?


Теперь по вопросу зачем мне этот класс: всегда, когда нужно узнать, нажата ли клавиша в данный момент. Не очень важна, когда кнопка нажата одна, но если должна быть нажата комбинация 2 клавиш - класс отлично выручает.

orcpochta 30.04.2010 21:33

Цитата:

Что хотите Вы?
В первом посте все четко было сказано:
"Сразу пример, чтобы легче представить: в игре слушает нажатия различных кнопок, отфильтровывает из них кнопки LEFT, RIGHT, UP, DOWN (и дубляж A, D, W, S), режет повторения, если кнопка уже нажата, и рассылает соответствующие события "leftPressed"/"leftReleased", "rightPressed"/"rightReleased" и т.д..." - куда уж яснее?

Цитата:

А, класс, рассылающий события... Для игры... кхм. Здорово. Что имеем?
Подписываемся на 4 события, (влево-вправо-вверх-вниз), а то и на больше - не во всех играх 4 кнопки. 4 обработчика, ну ладно, так удобней, ок.
Ну во первых каждая кнопка - это не одно событие, а два: "нажата", "отжата". Это можно использовать к примеру так: "нажата" - запускает действо, "отжата" - запускает плавное затухание вызванного действа.

Цитата:

Но мы заводим ради этого ещё один класс, который диспатчит событие... чтобы было удобней.
Считаем строчки кода:
4 подписка на событие.
4 описание заголовка методов
4 отписка от методов
12 строк кода.
Мы заводим удобный контроллер клавиатуры, который если надо поддерживает несколько групп клавиш для однотипных действий (W-A-S-D и стрелки UP-LEFT-DOWN-RIGHT), проверяет, чтобы не вызывалось событие уже нажатой клавиши, проверяет, чтобы не запускалось событие от дублирующей клавиши, если нажата клавиша идентичного действия, и не запускает событие от отжатой клавиши, если до этого была нажата другая клавиша идентичного действия, а эта не нажалась по той же причине. - И все это делает легко и просто, а мы об этом даже не думаем. И уж конечно не считаем строчки кода.

Цитата:

Или если инлайново:
1 подписка
1 отписка
1 заголовок метода
4 ифа (или 8 кейсов+свич)

7-12 строк против 12. То есть, проще говоря, проще и дешевле по производительности писать код ЗАНОВО, чем использовать методы своего же класса. Это стоит того?
Вы плохо понимаете принципы ООП - именно это того и стоит, что я имею простой, легко настраиваемый на любые кнопки класс, который могу использовать везде, где надо слушать события клавиатуры, а не мешу все в одно кучу. То, что вы предлагаете, называется процедурное программирование в классах - вы должны были об этом недавно читать во флейме, тем более, что вроде сами тему эту и поднимали...)))

Цитата:

Теперь по вопросу зачем мне этот класс: всегда, когда нужно узнать, нажата ли клавиша в данный момент. Не очень важна, когда кнопка нажата одна, но если должна быть нажата комбинация 2 клавиш - класс отлично выручает.
знаете, для таких простых действий мне как-то совершенно не взбрело бы в голову пользоваться чужим классом, тем более, что это:
1) не входило в рамки моего вопроса;
2) все это легко настраивается в том же классе клавиатурного контроллера или его расширениях.

----------------------------------

Вот, собственно, мой контроллер:
Код AS3:

package
{
        import flash.display.Stage;
        import flash.events.Event;
        import flash.events.EventDispatcher;
        import flash.events.KeyboardEvent;
 
        /**
        * ...
        * @author Andrey Polkanov - andrey@polkanov.com - www.polkanov.com
        */

        public class KeyboardController extends EventDispatcher
        {
 
                //----- Public static constants -----
                public static const UP_PRESSED:String                = "upPressed";
                public static const DOWN_PRESSED:String        = "downPressed";
                public static const LEFT_PRESSED:String        = "leftPressed";
                public static const RIGHT_PRESSED:String        = "rightPressed";
 
                public static const UP_RELEASED:String                = "upReleased";
                public static const DOWN_RELEASED:String        = "downReleased";
                public static const LEFT_RELEASED:String        = "leftReleased";
                public static const RIGHT_RELEASED:String        = "rightReleased";
 
 
 
                //----- Private static constants -----
                //Arrows: UP - 38, DOWN - 40, LEFT - 37, RIGHT - 39
                //Chars: W - 87, S - 83, A - 65, D - 68
                private static const DEFAULT_LEGAL_KEYS:Object =
                {       
                        38: [KeyboardController.UP_PRESSED,        KeyboardController.UP_RELEASED],
                        40: [KeyboardController.DOWN_PRESSED,        KeyboardController.DOWN_RELEASED],
                        37: [KeyboardController.LEFT_PRESSED,        KeyboardController.LEFT_RELEASED],
                        39: [KeyboardController.RIGHT_PRESSED,        KeyboardController.RIGHT_RELEASED],
 
                        87: [KeyboardController.UP_PRESSED,        KeyboardController.UP_RELEASED],
                        83: [KeyboardController.DOWN_PRESSED,        KeyboardController.DOWN_RELEASED],
                        65: [KeyboardController.LEFT_PRESSED,        KeyboardController.LEFT_RELEASED],
                        68: [KeyboardController.RIGHT_PRESSED,        KeyboardController.RIGHT_RELEASED]
                };
 
 
 
                //----- Private variables -----
                private var stage:Stage;
 
                private var legalKeys:Object;
                private var keyCache:Object;
 
 
 
                //----- Constructor -----
                public function KeyboardController (stage:Stage, legalKeys:Object = null)
                {
                        super( );
 
                        this.stage = stage;
                        this.legalKeys = legalKeys;
 
                        init( );
                }
 
 
 
                //----- Public functions -----
                public function destroy ( ):void
                {
                        stage.removeEventListener(KeyboardEvent.KEY_DOWN, keyDownListener);
                        stage.removeEventListener(KeyboardEvent.KEY_UP, keyUpListener);
                }
 
 
 
                //----- Private functions -----
                private function init ( ):void
                {
                        if (!legalKeys) legalKeys = KeyboardController.DEFAULT_LEGAL_KEYS;
 
                        keyCache = new Object( );
 
                        stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownListener);
                        stage.addEventListener(KeyboardEvent.KEY_UP, keyUpListener);
                }
 
                private function keyDownListener (e:KeyboardEvent):void
                {
                        var key:String = String(e.keyCode);
 
                        if (legalKeys.hasOwnProperty(key) && !keyCache.hasOwnProperty(legalKeys[key][0]))
                        {
                                keyCache[legalKeys[key][0]] = key;
 
                                dispatchEvent(new Event(legalKeys[key][0]));
                        }
                }
 
                private function keyUpListener (e:KeyboardEvent):void
                {
                        var key:String = String(e.keyCode);
 
                        for (var i:String in keyCache)
                        {
                                if (keyCache[i] == key)
                                {
                                        delete keyCache[i];
 
                                        dispatchEvent(new Event(legalKeys[key][1]));
                                }
                        }
                }
 
        }
 
}

вот мэйн, чтобы можно было потрейсить:
Код AS3:

package 
{
 
        import flash.display.Sprite;
        import flash.events.Event;
 
        /**
        * ...
        * @author Andrey Polkanov - andrey@polkanov.com - www.polkanov.com
        */

        public class Main extends Sprite
        {
 
                public function Main ( ):void
                {
                        if (stage) init();
                        else addEventListener(Event.ADDED_TO_STAGE, init);
                }
 
                private function init(e:Event = null):void
                {
                        removeEventListener(Event.ADDED_TO_STAGE, init);
                        // entry point
 
                        /**
                        *@usage Если надо определить свои кнопки, отличные от умолчания (курсоры и W-A-S-D),
                        * то можно расширить класс или прям в том месте, где будет создаваться контроллер,
                        * задать ему описательный объект доступных клавиш и событийных констант.
                        *
                        * Определяет только стрелки UP и DOWN:
                        *var legalKeys:Object = {        38: [KeyboardController.UP_PRESSED, KeyboardController.UP_RELEASED],
                        *                                                        40: [KeyboardController.DOWN_PRESSED, KeyboardController.DOWN_RELEASED]}
                        * Каждый элемент - это:
                        * (поле) код клавиши: (значение массив)["константа, определяющая событие нажатия", "константа, определяющая событие отпускания для этой кнопки"]
                        *
                        * Передаем этот описательный объект в конструктор:
                        *var keyboard:KeyboardController = new KeyboardController(stage, legalKeys);
                        */

 
                        var keyboard:KeyboardController = new KeyboardController(stage);
 
                        keyboard.addEventListener(KeyboardController.UP_PRESSED, upPressedListener);
                        keyboard.addEventListener(KeyboardController.UP_RELEASED, upReleasedListener);
 
                        keyboard.addEventListener(KeyboardController.DOWN_PRESSED, downPressedListener);
                        keyboard.addEventListener(KeyboardController.DOWN_RELEASED, downReleasedListener);
 
                        keyboard.addEventListener(KeyboardController.LEFT_PRESSED, leftPressedListener);
                        keyboard.addEventListener(KeyboardController.LEFT_RELEASED, leftReleasedListener);
 
                        keyboard.addEventListener(KeyboardController.RIGHT_PRESSED, rightPressedListener);
                        keyboard.addEventListener(KeyboardController.RIGHT_RELEASED, rightReleasedListener);                       
                }
 
                private function upPressedListener (e:Event):void
                {
                        trace(e.type);
                }               
                private function upReleasedListener (e:Event):void
                {
                        trace(e.type);
                }
 
                private function downPressedListener (e:Event):void
                {
                        trace(e.type);
                }               
                private function downReleasedListener (e:Event):void
                {
                        trace(e.type);
                }
 
                private function leftPressedListener (e:Event):void
                {
                        trace(e.type);
                }               
                private function leftReleasedListener (e:Event):void
                {
                        trace(e.type);
                }
 
                private function rightPressedListener (e:Event):void
                {
                        trace(e.type);
                }               
                private function rightReleasedListener (e:Event):void
                {
                        trace(e.type);
                }               
 
        }
 
}

Что касается игры, то события должен слушать класс (или его буфер), описывающий определенные догмы поведения - такая гибкость позволяет на различные отображаемые объекты вариативно накладывать различные схемы поведения и различные контроллеры, а не лепить все в одном классе.

Если есть вопросы по коду, спрашивайте - охотно отвечу, почему там так, а не иначе)))

Psycho Tiger 30.04.2010 21:50

Ну, вот что я понял:
1) Я не понимаю принципов ООП
2) Контроллер это не то, что я всегда думал.
3) Модно писать this.property и property вперемешку.
4) Всем объектам, слушающим клавиатуру нужно обязательно иметь ссылку на этот класс - это после огорчения, что _stage убрали. Разумное решение!
5) Не нужно использовать чужие классы для простейших вещей, нужно писать свои.

Свой вопрос Вы решили, спасибо за диалог, на этом закончим.

orcpochta 30.04.2010 21:58

Цитата:

Ну, вот что я понял:
1) Я не понимаю принципов ООП
да вы - Бог, ктоб спорил?)))

Цитата:

2) Контроллер это не то, что я всегда думал.
а зачем вы лезете с MVC туда, где о нем и не заикались?
http://ru.wikipedia.org/wiki/Контроллер

Цитата:

3) Модно писать this.property и property вперемешку.
это один из стилей и он имеет право на жизнь как и любой другой - зачем мне придумывать другое название для итак говорящей за себя переменной?

Цитата:

4) Всем объектам, слушающим клавиатуру нужно обязательно иметь ссылку на этот класс - это после огорчения, что _stage убрали. Разумное решение!
тут какие-то смешные выводы

Цитата:

5) Не нужно использовать чужие классы для простейших вещей, нужно писать свои.
это уж как хотите - я там за себя сказал

Цитата:

вой вопрос Вы решили, спасибо за диалог, на этом закончим.
как вам будет угодно)))

Psycho Tiger 30.04.2010 22:25

Цитата:

да вы - Бог, ктоб спорил?)))
Вы сами мне это сказали, а сейчас высмеиваете себя же?
Цитата:

а зачем вы лезете с MVC туда, где о нем и не заикались?
http://ru.wikipedia.org/wiki/Контроллер
устройство управления в электронике и вычислительной технике.
Вы управляете клавиатурой? Вы её слушаете.

Про переменные - смотрел через строку через две, погорячился, да.

И правда, закончим, незачем.


Часовой пояс GMT +4, время: 19:08.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.