Быстро? Точно? Двайной!


А давайте еще поговорим об управлении с помощью клавиатуры! В этот раз я не буду рассказывать прописные истины, а покажу что-то на мой взгляд интересное, что поможет по-новому взглянуть на клавишное управление в играх. Пройдемте под кат!




Двайной? 0о

Мой старый знакомый по специфике работы своей неоднократно посещал Поднебесную. Во время одного из таких визитов его сопровождала девушка, неплохо владеющая русским и сведущая в прочих аспектах, необходимых для проведения переговоров. Во время перерыва у них произошел короткий диалог:

– Вы очень хорошо говорите по-русски! Изучали где-то? Или жили в наших краях?
– Двайной!

Нужно ли говорить, что это лаконичное «двайной!», которое навсегда вытеснило устаревшее «обадва!», мы вознесли в ранг русских иероглифов и первое время использовали просто где надо и не надо! Лаконичней может быть только английское «both!», но где мы, а где Лондон!

Зачем?

Многие разработчики скажут, что управление с помощью клавиш — это уныло и не круто ваще, есть мышка — она удобней! И многие правы! Но вот ведь как бывает. Мастеришь ты игру, скажем, некое подобие арканоида. Подумываешь о порте на мобилу, и тут оп-па! Судите сами. Таскать объект, елозя пальцем по стеклу, — не комильфо, да и порой пол-игры можно рукой перекрыть. Расставить по краям кнопки — отлично! Но это же арканоид! Тут нужно с одной стороны из края в край быстро перенестись, а с другой стороны суметь более-менее точно выставить биту для ловкого отскока!

Как быть?

Делал я как-то одну игрушку, скажем, что-то наподобие Subway Surfers. Только в игре моей главный герой перемещался не дискретно (по трем заготовленным дорожкам), а вполне себе плавно, по всей ширине. Управлялось это все дело мышкой. И было это весело, удобно и все такое. Но вот когда дошло дело до порта игры, встал вопрос о замене управления без потери фана, скорости и точности.

Представляю вашему вниманию мое решение:


(кликнув по фону, можно выключить/включить рамку)

В результате получился некий компромисс между быстрым переносом из края в край и относительно точным позиционированием. При этом не нужно нажимать какие-то кнопочки, переключающие режим (быстро-точно), и придумывать еще что-то.

Ну и, собственно, код:


import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
import flash.geom.Point;

stage.frameRate = 30;

// Это наш ГэГэ. В рамках этой демки он у нас будет
// двигаться только по оси X.
var _gg:Sprite;

// Модуль скорости движения.
var _velValue:Number = 30.0;

// Тут все необходимое для "волшебного" управления.
var _cursor:Point;
var _cursorResponse:Number = 0.2;

// Направление, задаваемое игроком.
var _direction:Point = new Point();

// А тут у нас вспомогательные переменные, для работы с клавой.
var _keyL:Boolean = false;
var _keyR:Boolean = false;
var _keyU:Boolean = false;
var _keyD:Boolean = false;

// Рисуем демо сцену
createDemoScene()

// Слушем необходимые события.
stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);

/** Рисует простенькую демо сцену. */
function createDemoScene():void
{
        _gg = new Sprite();
        _gg.graphics.beginFill(0xff3300);
        _gg.graphics.drawCircle(0, 0, 10);
        _gg.graphics.endFill();
        
        _gg.x = stage.stageWidth / 2;
        _gg.y = stage.stageHeight / 2;
        addChild(_gg);
        
        _cursor = new Point(_gg.x, _gg.y);
}

/** Весь движняк, как обычно. */
function onEnterFrame(event:Event):void
{
        // Вычисляем скорость на основании вектора направления.
        var velocity:Point = _direction.clone();
            velocity.normalize(_velValue);

        // Если нужно остановиться
        if (_direction.x == 0)
        {
                // Эта процедура позволяет нам решить сразу две задачи:
                // 1. остановить ГэГэ, как только была отпущена кнопка;
                // 2. остановить его, все же, не как вкопанного;
                _cursor.x += (_gg.x - _cursor.x) * 0.5;
        }
        // Если нужно двигаться
        else
        {
                // Тупо на полной скорости мотаем "курсором" по экрану.
                _cursor.x += velocity.x;
        }
        
        // А теперь наш ГэГэ стремится к невидимому курсору,
        // но как бы не спеша, не во весь опор.
        _gg.x += (_cursor.x - _gg.x) * _cursorResponse;
}

/** Когда наступили на кнопочку на клавиатуре. */
function onKeyDown(event:KeyboardEvent):void
{
        switch (event.keyCode)
        {
                case Keyboard.LEFT:
                case Keyboard.A:
                        _keyL = true;
                        _direction.x = -1;
                        break;
                case Keyboard.RIGHT:
                case Keyboard.D:
                        _keyR = true;
                        _direction.x = 1;
                        break;
                case Keyboard.UP:
                case Keyboard.W:
                        _keyU = true;
                        _direction.y = -1;
                        break;
                case Keyboard.DOWN:
                case Keyboard.S:
                        _keyD = true;
                        _direction.y = 1;
                        break;
        }
}

/** Когда кнопочку отпустили, соответственно. */
function onKeyUp(event:KeyboardEvent):void
{
        switch (event.keyCode)
        {
                case Keyboard.LEFT:
                case Keyboard.A:
                        _keyL = false;
                        _direction.x = _keyR ? 1 : 0;
                        break;
                case Keyboard.RIGHT:
                case Keyboard.D:
                        _keyR = false;
                        _direction.x = _keyL ? -1 : 0;
                        break;
                case Keyboard.UP:
                case Keyboard.W:
                        _keyU = false;
                        _direction.y = _keyD ? 1 : 0;
                        break;
                case Keyboard.DOWN:
                case Keyboard.S:
                        _keyD = false;
                        _direction.y = _keyU ? -1 : 0;
                        break;
        }
}


И чо?

Управление получилось интересное. Можно пробовать менять параметры, смещать баланс в сторону точности или же наоборот. В игровых условиях наблюдается быстрое привыкание игрока и хороший темп роста ловкости. Моя 5-летняя дочка весьма быстро начала совершенно безошибочно проходить уровень за уровнем в игре, на которой я впервые опробовал представленное управление.

Возможно, некоторые ваши игры с новым управлением обретут шанс на успешный порт на платформы, где кроме кнопочек нам ничего больше и не остается!
  • +11

Комментарии (7)

0
Теперь на игрушку линк давай, оценим тоже )
(про девушку и «Двайной» не понял)
0
А, кажись понял, но тут напрашивается «Оба!» )
0
Ну так и есть, конечно :) но девочка же — китаянка! Ей показалось, что это вполне себе по-русски :)
+1
Дык нелинейность же, известна 100500 лет :) В старых приставочных шутерах, идейных потомках вольфейнштэйна, в силу отсутствия мыши, нелинейность широко применялась: чем дольше жмешь кнопку «вбок» — тем быстрее вертает мордой.
И это все равно костыль, не заменяющий мышь и тач :)
  • ADF
  • ADF
0
У тебя самая обычная фобия клавишного управления :)
0
Ага, меня в детстве клавиатурой избили :]
0
Оу, это объясняет :) но не оправдывает!
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.