Опубликован: 07.11.2006 | Уровень: специалист | Доступ: свободно
Лекция 8:

Обнаружение коллизий

Кубок мира по пинг-понгу

  1. Оставьте последний фильм открытым на протяжении всего данного упражнения, так как мы будем использовать его код в качестве основы. Удалите левую и правую стенки и замените их "ракетками". В качестве ракетки вы можете просто нарисовать вертикальную линию любой длины и преобразовать ее в фильм с именем pc (я добавил надписи на ракетках, чтобы следующий рисунок был понятнее).
  2. Создайте дубликат фильма pc и назовите его player. Перетащите инстансы обоих фильмов на рабочее место и разместите их на новом слое с именем paddles.
  3. Назовите инстансы именами pc_mc и player_mc соответственно. Вручную разместите pc на позиции (50,200) и player на (500, 200). Позиции _y не так важны, так как они будут динамически обновляться в нашем ActionScript, а их стартовым значением будет центр поля.

  4. Начнем с добавления нескольких управляющих элементов onEnterFrame для двух ракеток.
    init();
      function init() {
        RIGHT = 500;
        LEFT = 50;
        TOP = 50;
        BOTTOM = 350;
        ball_mc.velX = 0;
        ball_mc.velY = 0;
        ball_mc.onEnterFrame = move;
        pc_mc.onEnterFrame = pcMove;
        player_mc.onEnterFrame = playerMove;
      }
  5. Дальше определяем функции pcMove и playerMove. pcMove начинается как простое уравнение приближения, поэтому ракетка компьютера будет всегда пытаться попасть на позицию шарика. Чтобы было интереснее, мы позволим этой ракетке двигаться только в том случае, если шарик передвигается в ее направлении (ball_mc.velX<0). Ракетка player, т.е. ракетка игрока? будет просто проверять нажатие клавиш [ВВЕРХ] и [ВНИЗ] и, в случае нажатия, перемещаться, соответственно, вверх или вниз. В обоих случаях с ракетками будет использоваться проверка коллизий по расстоянию, чтобы не допустить их исчезновения с игрового поля.
    function pcMove() {
        if (ball_mc.velX<0) {
          this._y += (ball_mc._y-this._y)/5;
        }
        if (this._y>bottom-this._height/2) {
          this._y = bottom-this._height/2;
          this.vy = 0;
        }
        if (this._y<top+this._height/2) {
          this._y = top+this._height/2;
          this.vy = 0;
        }
      }
      function playerMove() {
        if (Key.isDown(Key.UP)) {
          this._y -= 10;
        } else if (Key.isDown(Key.DOWN)) {
          this._y += 10;
        }
        if (this._y>bottom-this._height/2) {
          this._y = bottom-this._height/2;
          this.vy = 0;
        }
        if (this._y<top+this._height/2) {
          this._y = top+this._height/2;
          this.vy = 0;
        }
      }
    Пример 7.2.
  6. Начальные скорости шарика установлены на значение 0, чтобы можно было принимать решение, где и когда начинать игру. Это реализуется присвоением _root функции приемника событий Key, а также установкой события onKeyDown на начало движения шарика. Добавьте следующие четыре строки в функцию init и затем создайте функцию serve в конце всего кода.
    Key.addListener(_root);
      _root.onKeyDown = serve;
      pcServe = true;
      baseSpeed = 10;
    
      function serve() {
        if (Key.getCode(j == Key.SPACE) {
          if (playerServe) {
            ball_mc.velX = -baseSpeed;
            ball_mc.velY = Math.random()*20-10;
            playerServe = false;
          } else if (pcServe) {
            ball_mc.velX = baseSpeed;
            ball_mc.velY = Math.random()*20-10;
            pcServe = false;
          }
        }
      }

    Теперь при запуске игры, шарик не движется до тех пор, пока вы не нажмете пробел. Когда значением pcServe станет "истина", будет выполнен второй блок, и шарик направится к ракетке игрока.

  7. Если запустить код сейчас, перед вами будет неплохая игра в пинг-понг, однако будет заметен один недостаток. Попробуйте упустить шарик - он все равно отскочит. Вспомните, что мы не реализуем здесь настоящего столкновения с ракеткой, а лишь пользуемся математическим вычислением позиции шарика. Вместо того, чтобы переделывать пол-игры, мы лишь внесем некоторые изменения. Мы будем проверять, ударяется ли шарик перед отскоком именно о ракетку.

    Это значит, что шарик должен находиться ниже верхнего края ракетки, но выше нижнего ее края. Если он находится между этими двумя точками при ударе о right, значит, есть попадание. Если шарик пролетел мимо, он исчезает. Здесь мы могли бы применить старый добрый hitTest, однако я воспользуюсь этим случаем для представления новой концепции и действия под названием getBounds. Это одна из редко используемых команд. Она как бы разбивает hitTest на составные части и позволяет использовать именно те из них, которые необходимы.

    getBounds - это метод объекта movieClip. При вызове он возвращает объект. Этот объект имеет четыре параметра, которые сообщают нам о местоположении фильма. Вот способ использования данного метода.

    boundsObject=movieClip.getBounds (scope);

    boundsObject имеет следующие четыре параметра: xMin, xMax, yMin и yMax. Они логически соответствуют четырем краям граничного прямоугольника фильма. Однако, вместо того, чтобы заставлять Flash вычислять, что находится внутри, а что вне рамки, мы теперь можем работать с численными значениями. Теперь можно математическим путем определять наши собственные коллизии, пользуясь значением ширины и т.п., как мы делали в случае со стенками.

    Единственное, что осталось здесь определить, это параметр scope (область). Параметры min и max возвращаемого объекта boundsObject представлены в пикселях, но относительно чего? Это и есть наша область. В основном вам нужно будет вводить _root в качестве области, или любую другую позицию на временной диаграмме, на которой вы осуществляете проверку коллизий. Это даст вам значения X и Y фильма из _root.

    Если вы сделали сам фильм областью, он будет возвращать значения своих углов такими, каковы они есть с его точки зрения. Например, квадрат со стороной 100 пикселей с центральной точкой регистрации всегда будет возвращать значения -50 и 50 в качестве минимального и максимального значений, независимо от того, в каком месте экрана находится фильм. С точки зрения фильма, он распространяется на 50 пикселей вверх от центра, на 50 пикселей вниз, на 50 влево и на 50 вправо.


Игорь Хан
Игорь Хан
След не остается
Александр Коргапольцев
Александр Коргапольцев
Вопрос по содержанию лекции №2, курс Flash MX Studio
Татьяна Ефимова
Татьяна Ефимова
Россия, г. Чебоксары