Скроллинг игрового мира. Или как реализовать прокрутку карты?

В своем примитивном примере редактора уровней я как раз остановился на реализации прокрутки игровой карты. Сама реализация прокрутки карты достаточно проста и одинакова практически для всех типов игр с картами: вид сбоку, вид сверху, изометрия и т.п. Но не смотря на простоту реализации прокрутки у многих возникают с этим проблемы.

Автор блога Хи3 достаточно доходчиво разъяснил принцип перемещения карты. Но, признаюсь честно, подобный подход лично мне не нравится. Я считаю, что он не универсален, так как из-за такого подхода могут возникнуть различные сложности в будущем. Поэтому я расскажу о несколько другом подходе.

Для начала разберемся что есть прокрутка карты. Фактически в любой игре, где игровой уровень выходит за пределы игрового экрана — необходима реализация прокрутки карты. А чаще нужно, чтобы карта двигалась в противоположную сторону от персонажа, когда тот перемещается. То есть как будто камера следит за героем.

Игровой мир и область видимости.

Поскольку во Flash не существует никаких камер, то двигать нам прийдется весь игровой мир. То есть в действительности получается так, как будто мы смотрим в окошко на некий мир, и когда персонаж убегает из вида нам нужно пододвинуть весь мир так, чтобы персонаж опять попал в область видимости нашего окошка — «камеры».

Скролл игровой карты.

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

Начнем пример с простого перемещения игровой карты. Реализуем у класса игровой карты два простых метода, через которые будет осуществляться запуск прокрутки карты.

        
public function hScroll(val:Number):void
{
  _speedX += val;
}
    
public function vScroll(val:Number):void
{
  _speedY += val;
}

Тут все достаточно просто _speedX и _speedY — это локальные переменные игровой карты с текущей скоростью движения. Теперь надо реализовать метод движения карты, который будет ее двигать.

private function enterFrameHandler(e:Event):void
{
  /* Прибавляем скорость к положению карты */
  x += int(_speedX);
  y += int(_speedY);
      
  /* Применяем торможение к скорости */
  _speedX *= .9;
  _speedY *= .9;
}

Скорость движения прибавляем к положению карты, а потом выполняем замедление скорости, чтобы после того как вызов методов hScroll() или vScroll() прекратился, карта еще некоторое время продолжала двигаться по энерции.

Использование прокрутки выглядит следующим образом:

private function keyDownHandler(e:KeyboardEvent):void
{
  switch (e.keyCode)
  {      
    case 39 : _gameMap.hScroll(-2); break; // Влево
    case 37 : _gameMap.hScroll(2); break; // Вправо
    case 40 : _gameMap.vScroll(-2); break; // Вверх
    case 38 : _gameMap.vScroll(2); break; // Вниз
  }
}

Результат выглядит так:

Кликните в сетку и используйте клавиши со стрелками для перемещения карты.

Как остановить прокрутку при выходе видимой области за пределы карты?

Обычно в играх не допускается выезд «камеры» за пределы карты — это не только помогает игроку понять, что он уперся в границу уровня и дальше ничего нет, но и позволяет разработчику не заморачиваться над детализацией ненужных частей уровня. Ограничения перемещения карты сделать достаточно просто. Необходимо лишь проверять положение игровой карты и не допускать ее смещение дальше установленных границ. Для этого нам надо знать размеры игровой карты и размеры окна. Метод движения карты переделываем следующим образом:

private function enterFrameHandler(e:Event):void
{      
  /* Прибавляем скорость к положению карты */
  x += int(_speedX);
  y += int(_speedY);
      
  /* Горизонтальная прокрутка */
  if (x > 0) // Выезд за левый край
  {
    x = 0;
    _speedX = 0;
  }
  else if (x < -_mapWidth + SCR_WIDTH) // Выезд за правый край
  {
    x = -_mapWidth + SCR_WIDTH;
    _speedX = 0;
  }
      
  /* Вертикальная прокрутка */
  if (y > 0) // Выезд за верхний край
  {
    y = 0;
    _speedY = 0;
  }
  else if (y < -_mapHeight + SCR_HEIGHT) // Выезд за нижний край
  {
    y = -_mapHeight + SCR_HEIGHT;
    _speedY = 0;
  }      
      
  /* Применяем торможение к скорости */
  _speedX *= .9;
  _speedY *= .9;
}

_mapWidth — ширина игровой карты;
_mapHeight — высота игровой карты;
SCR_WIDTH — ширина игрового экрана;
SCR_HEIGHT — высота игрового экрана.

Теперь результат выглядит так:

Кликните в сетку и используйте клавиши со стрелками для перемещения карты.

Как заставить камеру следить за персонажем?

Перемещение карты с ограничениями движения мы реализовали, а теперь самое интересное — это реализация следящей «камеры» за персонажем.

Не знаю как вам, а меня лично раздражает, когда в играх реализуют мертвую привязку камеры к персонажу. Обычно это выглядит так: персонаж бежит и весь мир в это время тоже двигается. Я предпочитаю реализовывать более щадящую прокрутку. Выражается это в том, что когда персонаж не пытается покинуть пределы экрана и остается в пределах видимости, камера не двигается за ним и тем самым не утомляет игрока лишними движениями. Возможно некоторые не догадываются, но такую камеру очень просто реализовать. Нужно лишь добавить условные границы на игровом экране и при их пересечении героем включать прокрутку в необходимую сторону.

Пересечение границы.

Наблюдаемый объект пытается покинуть область видимости, не упустить его! :)

Проверку пересечений с границами необходимо выполнять непосредственно в коде движения объекта за которым должная следить камера и если он выходит за установленные границы вызывать методы карты hScroll() или vScroll(). Я добавил в пример объект который постоянно движется и отскакивает от границ карты. Метод его движения выглядит так:

public function enterFrameHandler(e:Event):void
{
  /* Движение */
  x += _speedX;
  y += _speedY;
      
  /* Проверка столкновения со стенками карты */
  if (x > _map.mapWidth || x < 0) _speedX *= -1;
  if (y > _map.mapHeight || y < 0) _speedY *= -1;

  updMapPos(); // Скролл карты
}

Проверка выхода объекта за допустимые границы вынесена в отдельный метод updMapPos(). Он выглядит следующим образом:

private function updMapPos():void
{
   if (x < Math.abs(_map.x ) + _border)
    _map.hScroll(1); // Вправо
  else if (x > Math.abs(_map.x ) + GameMap.SCR_WIDTH - _border)
    _map.hScroll(-1); // Влево
      
   if (y < Math.abs(_map.y ) + _border)
    _map.vScroll(1); // Вниз
  else if (y > Math.abs(_map.y ) + GameMap.SCR_HEIGHT - _border)
    _map.vScroll(-1); // Вверх
}

Принцип действия прост. Единственный показатель прокрутки карты — это ее координаты, причем они всегда отрицательные. Зная координаты карты мы можем найти текущее положение экрана на ней и посчитать границы пересекая которые объект включает прокрутку. В переменной _border находится размер границы.

Теперь пример выглядит так:

Шарик всегда в области видимости. Карту так же можно попытаться перемещать клавишами со стрелками.

Это собственна вся основа прокрутки карты, изменяя размер границ, скорость прокрутки и замедление движения карты можно настроить прокрутку практически под любые задачи.

Кстати, если летающий объект из примера заменить курсором мыши то получится скроллинг мышкой как в большинстве современных стратегий.

Скачать исходник примера .zip — 30 кб.

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


Индикаторы: Action Script 3, Уроки
Постоянная ссылка

 

 

Отличный урок!
Особенно понравился кусок - "Как заставить камеру следить за персонажем?"

GreeeN
18 Октября 2009
— 09:23
#

спасибо! очень полезно

Dyrk
18 Октября 2009
— 11:05
#

Спасибо, хороший урок. Но мне немножко не нравится ступенчатая дерганность прокрутки. Надо будет помозговать, чтобы такого придумать.

Сашка
18 Октября 2009
— 12:07
#

Ступенчатость прокрутки возникает из-за того что в какой то момент скрость прокрутки становится больше скорости движения самого объекта. В итоге объект не попадает в экранные границы и движение карты замедляется. Исправить это можно несколькими способами. Например изменить замедление прокрутки с .9 до .8 или меньше. Но самое действенное решение не давать «камере» (игровому миру) двигаться быстрее чем двигается объект за которым следим. Для этого методы hScroll() и vScroll() переделываем примерно так:

function hScroll(val:int, max:int = 20):void
{
_speedX += val;
if (max < 0) _speedX = (_speedX < max) ? max : _speedX;
if (max > 0) _speedX = (_speedX > max) ? max : _speedX;
}

А использовать прокрутку так:

_map.hScroll(1, скорость_объекта);

Таким образом «камера» не будет двигаться быстрее объекта и дерганности не будет.

Ant.Karlov
18 Октября 2009
— 23:02
#

А что с лагами при прокрутке делаешь? (Когда в мире много вложенных клипов лежит, или когда сам мир отнюдь не маленький)

Krylov.EP
19 Октября 2009
— 12:30
#

А это отдельная интересная история :)

Ant.Karlov
19 Октября 2009
— 23:15
#

А еще есть мое любимое свойство scrollRect.
Простите за AS2, но суть такова:
import flash.geom.Rectangle;
var camera:Rectangle = new Rectangle(0,0,320,240); // 320x240 - видимая часть клипа
myWorld_mc.onEnterFrame = function():Void
{
camera.x ++;
camera.y++;
this.scrollRect = camera;
};

Плюс этого метода в том, что он быстрый и родной, а минус в том, что минимальное перемещение = 1 пиксель, то есть никакого сглаживания, в прочем, мне кажется для игр это не так смертельно.

Murejib
23 Ноября 2009
— 00:30
#

@Murejib, cпасибо! Интересный прием, не знал о таком.
На счет минуса: если в играх игровые карты состоят из множества объектов, то в любом случае приходится карту двигать на целые числа, чтобы спрайты не «скакали» и двигались равномерно. То есть минимальная скорость как раз получается не менее 1 пикселя.

Ant.Karlov
25 Ноября 2009
— 13:27
#

У меня вопрос, как реализовать скролинг для изометрии? В обичних проекция все получается, а вот с изометрией нет... Помогите пж

Xcite
25 Апреля 2010
— 00:26
#

@Xcite, вывод игровой карты в изометрии отличается от обычного вида с боку/сверху только тем, что при отображении плитки их координаты смещаются по диагонали, а принцип прокрутки карты практически такой же. То есть чтобы сделать простой скролл карты, нам достаточно изменять начальные координаты карты с которых начинается вся её отрисовка точно так же как мы это делаем для простой карты.

Чтобы я мог дать какой-то конкретный ответ и помочь, мне следует задать конкретный вопрос, в чем именно возникла проблема в реализации прокрутки в изометрии? (можно почтой)

Ant.Karlov
25 Апреля 2010
— 20:05
#

Дело в том, что я строю карту из плитки, тоесть подгружаю кучу плиточек в отдельний клип, потом укорачиваю его на 50%, далее заганяю еще в один клип и уже его разворачиваю на 45 градусов. получается изометрия вроде. А теперь собственно проблема - когда я передвигаю героя внутри первого клипа и вместе с ним двигаю весь мир, тоесть второй клип вместе в первим внутри и темже героем дабы получился скролинг, оно не работает так как надо, тоесть "камера" не держит героя в центре экрана, а сползает куда-то, и чем дальше двигатся, то она вобще выпускает его из виду. Дело в том что если его не изометрировать, тоесть не разворачивать на 45 градусов, то все работает, а в изометрии уже нет. Я подозреваю, вернее даже уверен, что проблема в различии координат, локальних от глобальних в изометрии. пробовал как то преобразовивать, но не могу добится нужного результата. Помогите, пожалуйста. Заранее благодарен. Если надо, то вышлю исходник на почту.

Xcite
26 Апреля 2010
— 01:45
#

@Xcite, у вас «не честная» изометрия ;) Я тут много всего написал, но потом все стер чтобы вас не путать... Присылайте исходник на почту, на пальцах не разобраться в проблеме.

Ant.Karlov
26 Апреля 2010
— 03:23
#

Ясно, хорошо. Я уже отослал исходник на вашу почту.

Xcite
27 Апреля 2010
— 19:30
#

уважаемый Ant.Karlov! если не затруднит , расскажите вашу систему гравитации в игре(тоесть как игрок прыгает, падает, коллизится с полом на разных уровнях) по средствам AC3...

Стас
28 Мая 2010
— 17:40
#

@Стас, в кратце на такой вопрос не ответить, к сожалению. В целом все работает примерно как в этом примере у Хитри, но только на AS3. А подробнее будет позже в цикле записей раскрывающих создание игры от начала и до конца.

Ant.Karlov
3 Июня 2010
— 18:00
#

@Ant.Karlov, а когда же выйдет этот цикл статей?

Я не робот!
25 Августа 2010
— 16:14
#

@Я не робот!, какой цикл статей вы имеете в виду? Если речь идет о разработки игры от и до — то подготовкой этого материала я смогу заняться только после того как будет закончена работа над Mining Truck 2.

Ant.Karlov
26 Августа 2010
— 23:02
#

@Ant.Karlov, именно о этом цикле статей я и говорил :) Спасибо!

Я не робот!
29 Августа 2010
— 19:01
#

@Ant.Karlov, Сделал как вы говорили
http://www.ant-karlov.ru/skrolling-igrovogo-mira.html#item160

Но карта все равно очень сильно дергается. пытался уменьшить "замедление прокрутки" но в таком случае объект медленно смещается от центра и если двигаться от левого верхнего угла к правому нижнему углу карты то к самому низу объект практически скрывается за камерой... Может еще что то посоветуете?

Я не робот!
30 Августа 2010
— 14:58
#

Здравствуйте, пожалуйста, какой код нужно использовать для реализации такого эффекта прокрутки. при чем три слоя - передний, средний и задний, помогите ПЛИЗ!! вот пример - http://ladio.ru/flash/en/index.html#

Len
25 Октября 2010
— 01:59
#

@Я не робот!, под словом «дергается» вы подразумеваете что обгоняет объект, останавливается, а потом когда объект вновь достигает границы экрана опять начинает двигаться?

Извиняюсь, что так поздно обнаружил ваш комментарий.

Ant.Karlov
25 Октября 2010
— 03:56
#

@Len, чтобы получить такой эффект для разных слоев, достаточно задние слои двигать с меньшей скоростью чем основной слой, в остальном код не должен особо отличатся.

Ant.Karlov
25 Октября 2010
— 03:58
#

@Ant.Karlov, не могли бы вы написатть как именно должен выглядеть этот код на AS3, проблем в том что я этот код не знаю(((

Len
25 Октября 2010
— 12:48
#

почему Ваш код у меня не работает, перед ним подразумевается наличие еще кода?

Кукла
28 Октября 2010
— 18:13
#

@Len, прочитайте пожалуйста внимательно запись к которой вы оставляете комментарии, как раз в ней довольно подробно все описал.

Ant.Karlov
28 Октября 2010
— 18:31
#

@Кукла, смотрите исходники приглашающиеся к уроку.

Ant.Karlov
28 Октября 2010
— 18:32
#

Спасибо огромное, урок восхитительный!

Berlion
3 Января 2011
— 02:38
#

Не мог не написать, сам долго думал и пробовал, ваш урок очень помог. Спасибо.

Djuice
14 Марта 2011
— 05:15
#

Столкнулся с проблемой, когда двигаю изометрический мир путем изменения координат спрайта - довольно ощутимо тормозит. Скорее всего из-за частой прорисовки всех объектов спрайта в новых координатах, как избежать такой нагрузки? Во многих играх все плавно происходит вне зависимости от кол-ва объектов и сложности графики. Хотя ИМХО координаты объектов внутри спрайта меняться не должны и соответственно весь спрайт не должен заново перерисовываться...

Виталий
14 Апреля 2011
— 23:35
#

@Виталий:
Попробуйте то же самое с неизометрическим миром, и тоже будет тормозить. Дело не в том, что мир изометрический, дело в плохой реализации механизмов отрисовки.

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

Сделайте глобальный DisplayObjectContainer и прикрепляйте к нему все свои спрайты и клипы, скроллинг осуществляйте воздействием на объект transformation глобального DisplayObjectContainer.Все его дочерние объекты унаследуют эту трансформацию.

BuxomBerry
15 Апреля 2011
— 17:05
#

@Виталий, чтобы игра не тормозила при скролле карты, в первую очередь надо позаботится об отсечении всего того, что не попадает в область видимости. То есть те тайлы и те объекты которые игрок не видет в текущий момент времени (не попадают в игровой экран) — их нужно удалять из системы прорисовки чтобы ресурсы на их рендер не затрачивались. В дебаг плеере в контекстном меню есть пункт меню «Show redraw regions» (Показать области перерисовки), если вы растяните флешку, например, на весь экран и включите области перерисовки то вы увидите что и как рендерит флешплеер.

Так же, если уж BuxomBerry упомянул сортировку объектов для изометрмической карты, от себя добавлю что объекты нужно сортировать только те которые так же находятся в видимой области, а объекты выходящие за приделы экрана исключать из алгоритма сортировки.

Ant.Karlov
16 Апреля 2011
— 11:01
#

Чувствую это будет довольно сложно сделать. Спасибо за ответы, буду думать как это все реализовать..

Виталий
16 Апреля 2011
— 19:11
#

@Виталий, ничего сложного на самом деле нет: отсечение далется точно так же как и для любой 2d карты из тайлов. А сортировку следует выполнять по x+y каждого спрайта. То есть складваем координаты x и y каждого тайла - это будет индекс глубины видимости, далее сортируем массив со всеми тайлами через array.sortOn() и на выходе получаем список тайлов в правильном порядке, далее меняем индекс видимости согласно номеру клипа в отсортированном массиве (если используются клипы конечно). Это если в кратце :)

Ant.Karlov
16 Апреля 2011
— 22:10
#

Я использую только Спрайты, т.к. пишу в FlashDevelop, а клипы только для CS. Сортировку пока не использую, т.к. что с ней что без нее лаги при скроллинге не приемлемы, хочится чтобы все было красиво и плавно, может многого хочу =) Не помогают и cashAsBitmap, может еще что-то есть не знаю, я новичек в АS.
2BuxomBerry[b] Я использую глобальный спрайт ака World от которого наследую все остальные, кроме спрайтов Меню ака кнопочки, вы это имели ввиду? а насчет transformation не совсем понял. У спрайтов есть наследуемый метод трансформ, но я пока не могу понять как им пользоваться. Мир перемещаю перемещением World, методом startDrag() или изменением координат x,y соответственно все вложенные спрайты и объекты двигаются вместе с ним.
[b]2Ant.Karlov
карта не особо большая у меня, больше экрана на на 100-200 пикселей разве что, при экране плеера 700*700. Правда использую тайлы по 5пикселей в поле 100х100 =) Я плохо представляю производительность Флэш, поэтому играю так с ресурсами, возможно я переборщил =) но карта тормозит даже без объектов (кроме тайлов пола)

Виталий
17 Апреля 2011
— 00:51
#

поствил по 10*10 пикселей на тайл, лагает меньше, странно, но хочу еще вопрос задать, правда не по теме, но всеже:
хочу сделать плавное появление/исчезание спрайта. Пробовал сделать изменяя в цикле с Timer`ом для задержек альфа канал спрайта, но как-то нето, не плавно и ИМХО ресурсоемко, возможно есть другой метод?

Виталий
17 Апреля 2011
— 00:58
#

@Виталий, карта 100x100 клеточек это 10000 спрайтов. Тут ничего не поможет если рендерить всегда всю карту как есть. Нужно делать так чтобы на сцене были только те спрайты (тайлы) которые игрок видет в текущий момент времени, а остальные удалять из видимой области (не рендерить).

Как раз вчера я написал запись про «Тотальную растеризацию» с тестовыми флешками где можно видеть, что даже при наличии 2000 спрайтов с оптимизированным выводом графики не все гладко работает. Так что тут в первую очередь нужно делать упор на отброс всего того что за приделами игрового экрана.

Все правильно, плавное затухание делается через sprite.alpha. Но делать его нужно не в Timer, а в обработчике события Event.ENTER_FRAME.

Ant.Karlov
17 Апреля 2011
— 11:34
#

Я совсем новичок во флеше. Пытаюсь сделать "слежение" объекта за курсором вот так: (TestObj.as)
public function enterFrameHandler(e:Event):void
{
var dx:Number = mouseX - x;
var dy:Number = mouseY - y;
var pRad:Number = Math.atan2(dy,dx);
var pDeg:Number = (180*pRad)/Math.PI;
this.rotation = pDeg;
var xsp:Number = x + 5 * Math.cos(pRad);
var ysp:Number = y + 5 * Math.sin(pRad);
x = xsp;
y = ysp;

if (x > _map.mapWidth || x < 0) _speedX *= -1;
if (y > _map.mapHeight || y < 0) _speedY *= -1;
updMapPos();
}

Получается полная билиберда. Вобщем ничего не получается. Не подскажете в чем промах?

Sir D
20 Августа 2011
— 15:57
#

@Sir D, собрал небольшую демку на основе приведенного куска кода и все работает отлично. Подозреваю что проблема либо в условиях на выход за приделы карты либо в методе updMapPos().

Ant.Karlov
20 Августа 2011
— 21:51
#

В том и дело, "локально" то этот код работает. А вот при использовании умной прокрутки - нет. Т.е. объект мало того что не следует за курсором, но даже ориентироваться на него не хочет.

Правда если этот же код вынести в enterFrameHandler в App, то слежение отлично работает. Работает даже прокрутка. Но зона перемещения объекта ограничивается одним игровым экраном. Т.е. экран - то перемещается при попадании объекта за border, но объект дальше 550 по горизонтали (например) двигаться отказывается, упираясь в невидимую "рамку".
Что ж, буду копать дальше =)
Спасибо за прекрасные статьи.

Sir D
21 Августа 2011
— 02:30
#

@Sir D, значит проблем в некорректном перехвате координат мыши. Сделайте перехватчик координат мыши в основном приложении и храните их в глобальных переменных класса чтобы можно было к ним получать доступ из любого другого класса игры.

Так же при расчете угла и поиске векторной скорости при необходимости не забывайте учитывать текущее смещение карты.

Ant.Karlov
21 Августа 2011
— 11:21
#

Спасибо за статью. Нашел для себя много полезной информации

Андрей
22 Февраля 2012
— 12:02
#

Меня вот что интересует, не подскажите? Как сделать подобную анимацию http://www.mirshapok.ru/ во Flash примеры находил, но там советуют Paralax.

Калин
11 Июля 2012
— 03:52
#

Спасибо Антон!
Очень помогли этим уроком, уверен что найду на вашем сайте ещё много интересного.

Вячеслав
28 Сентября 2012
— 16:17
#

Спасибо за урок! Отлично реализовал скролинг в редакторе, но проблема в том что редактор подсвечивает клетки только в начальном положении, помогите пожалуйста!

b2
11 Ноября 2012
— 20:25
#

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

var worldMouseX:int = Math.abs(world.x) + mousePosX;
var worldMouseY:int = Math.abs(world.y) + mousePosY;

Где word.x-y — это положение мира, mousePosX-Y — это экранные координаты мира, а worldMouseX-Y — это координаты мыши в игровом мире.

Ant.Karlov
12 Ноября 2012
— 00:33
#

Спасибо огромное! Все получилось! Так еще долго бы мучался :)

b2
12 Ноября 2012
— 12:28
#

Спасибо за статью )

Misha333
25 Июня 2013
— 17:43
#

С чем может быть связано, что исходники работают, только если есть не больше 2-х fla-файлов, если привязываю 3-ий и более, например, Game, Universe, как здесь http://www.ant-karlov.ru/towerdefence-1-struktura-igri.html расписана структура, то выдает ошибку #1009 ("null")?

Alex-Sline
1 Декабря 2014
— 12:49
#

Здравствуйте.
Подскажите, а как реализовать вращение игрового мира вокруг персонажа?
Попробую объяснить. Например, есть некая игра с видом сверху, в которой персонаж может передвигаться по 8-и направлениям, но при этом в какой бы точке игровой карты он не находился, игровой мир можно вращать (по нажатию каких-то клавиш, например) относительно персонажа.
Ну и отсюда же второй вопрос: допустим, в той же игре есть некий враг, который находится в некой точке карты в определённом положении и выполняет какие-то действия (например, идёт влево, останавливается, идёт вправо). Как реализовать привязку такого врага к игровому миру, чтобы он тоже крутился вместе с ним?

Я подозреваю, что obj.rotation надо как-то задействовать, но дальше -затык...

Юрий
9 Сентября 2015
— 01:15
#

@Юрий, в вашей ситуации варианта всего два:

1. Вращать весь игровой мир таким образом чтобы его локальные координаты оставались прежними. В случае с Flash вам просто нужно весь игровой мир помещать в один клип и вращать непосредственно этот клип. При этом вложенные объекты в этот клип вообще не заметят никакого вращения и будут передвигаться по локальным координатам внутри клипа.

2. Вращать непосредственно камеру, но этот трюк работает только в фреймворках которые имеют такой объект как камера и поддерживают её вращение (например Unity).

Небольшое примечание: прежде чем делать вращение камеры в 2D игре, нужно быть уверенным в том, что от таких фокусов у игрока не закружится голова. Обратите особое внимание на то, что в целом, очень мало 2D игр в которых есть особая необходимость во вращении камеры. Как правило это необходимо только в тех случаях где геймплей завязан на эту возможность. В остальном в 2D играх не принято вращать камеру, вспомните хотя бы первые части GTA где вид строго сверху — камера там всегда статична. А если бы она вращалась, то у многих бы игроков вероятно кружилась голова и возникала бы лишняя дизориентация в игровом мире.

Ant.Karlov
9 Сентября 2015
— 11:52
#

Ant.Karlov, огромное спасибо за подсказку.

Юрий
9 Сентября 2015
— 21:02
#

Как раз то, что необходимо!!!
Правда нужен Ваш совет.
Все никак не могу перейти на AS 3.0, поэтому мучаюсь с 2,0. Отсюда вопрос - Исходника для AS 2.0 случайное нету?

Warpatch
2 Мая 2016
— 16:58
#

@Warpatch,

> Отсюда вопрос - Исходника для AS 2.0 случайное нету?

Нет, исходников для AS2, к сожалению, нет. Но, я думаю, что это не должно быть проблемой, так как сам код отличаться ничем не будет, кроме того куда будут добавлены слушатели событий для ENTER_FRAME.

Если будут какие-то вопросы по коду, пишите.

Ant.Karlov
6 Мая 2016
— 10:40
#

Спасибо за дельный совет. Правда сделал немного по-другому!
Но возникла другая проблема. Описать четко не смогу, поэтому прикладываю исходник:

http://my-files.ru/lmv3rm

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

Warpatch
8 Мая 2016
— 22:51
#

@Warpatch, не могу скачать ваш исходник, при попытке загрузить файл по ссылке, возникает сообщение, что сервис временно не доступен. Выложите файл в DropBox или пришлите его мне по почте (почту можно найти в разделе "об авторе").

Ant.Karlov
9 Мая 2016
— 09:16
#

исходник

Как-то так)

Warpatch
9 Мая 2016
— 12:17
#