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

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

  1. Это не слишком годится для достижения преследуемых нами целей, поэтому мы применим _root. Добавьте следующую новую строку в функцию move.
    function move() {
        this._x += this.velX;
        this._y += this.velY;
        if (this._x>right-(this._width/2)) {
        playerBounds = player_mc.getBounds(_root);

    Теперь playerBounds будет содержать четыре параметра, упомянутые ранее. Параметры, которые нас больше всего интересуют - это yMin и yMax. Если ball_mc._y находится между этими двумя значениями после передачи им точки, определенной выражением right-(this._width/2), то он ударяется о ракетку игрока.


  2. Добавим другое условное выражение с использованием логического оператора AND (&&). Имейте в виду, что при этом также учитывается ширина шарика, поэтому мы реализуем проверку не только относительно центра шарика. Таким образом, мы получим гораздо более реалистичный удар.
    function move() {
        this._x += this.velX;
        this._y += this.velY;
        if (this._x>right-(this._width/2)) {
          playerBounds = player_mc.getBounds(_root);
          upper = playerBounds.yMin - this._height/2;
          lower = playerBounds.yMax + this._height/2;
          if (this._y>upper && this._y<lower) {
            this.velX *= -1;
            this.velY += Math.random()*20 - 10;
            this._x = right-(this._width/2);
          }
        }
      }
  3. Внутри блока кода мы также добавим некоторую степень случайности фактора velY. В противном случае шарик будет просто отскакивать вперед-назад под одними и теми же углами. Мы также немного увеличим скорость - всего лишь на один процент - чтобы немного усложнить игру. Имейте в виду, что мы должны увеличить как текущую скорость velX, так и baseSpeed, чтобы на следующей "подаче" скорость шарика возрастала.
    if (this._y>upper && this._y<lower) {
        this.velX *= -1;
        this.velY += Math.random()*20-10;
        this._x = right-(this._width/2);
        baseSpeed *= 1.01;
        this.velX *= 1.01;
      }
  4. Теперь мы знаем, что будет, если шарик попадет в ракетку, но нам нужно также решить, что будет, если шарик пройдет мимо нее. Мы будем возвращать шарик на середину экрана, изменять его скорость и направление случайным образом и увеличивать количество очков оппонента. Это реализовано в блоке else.
    function move() {
        this._x += this.velX;
        this._y += this.velY;
        if (this._x>right-(this._width/2)) {
          playerBounds = player_mc.getBounds(_root);
          if (this._y>playerBounds.yMin && this._y<playerBounds.yMax) {
            this.velX *= -1;
            this._x = right-(this._width/2);
        } else {
          this._x = 275;
          this._y = 200;
          this.velX = 0;
          this.velY = 0;
          pcScore++;
          playerServe = true;
        }
      }

    Здесь вы можете реализовать все, что вам придет в голову. Мне хватило и того, что я добавил динамическое текстовое поле слева вверху рабочего места с именем переменной pcScore.


  5. Окончательный код игры.
    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;
        Key.addListener(_root);
        _root.onKeyDown = serve;
        pcServe = true;
        baseSpeed = 10;
      }
      function move() {
        this._x += this.velX;
        this._y += this.velY;
        if (this._x>right-(this._width/2)) {
          playerBounds = player_mc.getBounds(_root);
          upper = playerBounds.yMin-this._height/2;
          lower = playerBounds.yMax+this._height/2;
          if (this._y>upper && this._y<lower) {
            this.velX *= -1;
            this.velY += Math.random()*20-10;
            this._x = right-(this._width/2);
            baseSpeed *= 1.01;
            this.velX *= 1.01;
          } else {
            this._x = 275;
            this._y = 200;
            this.velX = 0;
            this.velY = 0;
            pcScore++;
            playerServe = true;
          }
        }
        if (this._x<left+(this._width/2)) {
          pcBounds = pc_mc.getBounds (_root);
          if (this._y>pcBounds.yMin-this._height/2 &&
            Кthis._y<pcBounds.yMax+this._height/2) {
            this.velX *= -1;
            this.velY += Math.random()*20-10;
            this._x = left+(this._width/2);
            baseSpeed *= 1.01;
            this.velX *= 1.01;
          } else {
            this._x = 275;
            this._y = 200;
            this.velX = 0;
            this.velY = 0;
            playerScore++;
            pcServe = true;
          }
        }
        if (this._y>bottom-(this._height/2)) {
          this.velY *= -1;
          this._y = bottom-(this._height/2);
        }
        if (this._y<top+(this._height/2)) {
          this.velY *= -1;
          this._y = top+(this._height/2);
        }
      }
      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;
        }
      }
      function serve() {
        if (Key.getCode() == 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. vel Y = Math.random()*20-10;
            pcServe = false;
          }
        }
      }
    Пример 7.3.

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

    Можете смело экспериментировать с этой игрой. В коде на диске есть несколько дополнений, однако вы сами можете создать очень много интересного.

Игорь Хан
Игорь Хан

у меня аналогичная ситуация. Однако, если взять пример из приложения (ball_motion_04_click for trial.fla) то след остается. при этом заметил, что в моем проекте в поле "One item in library" виден кружок, в то время как в приложенном примере такого кружка нет.

Вопрос знатокам, что не так?

Александр Коргапольцев
Александр Коргапольцев

объект созданый мной упорно не желает оставлять след(единственное что добился, так это то что шарик резво гоняется за курсором) функция duplicateMovieClip остаётся не активной, т.е. следа от объекта не остаётся, но если я тоже самый код вбиваю в учебный файл всё работает, не могу понять где я ошибаюсь и почему в документе созданном заново, не работает код начиная от функции duplicateMovieClip? 

Тамара Ионова
Тамара Ионова
Россия, Нижний Новгород, НГПУ, 2009
Магомед Алисултанов
Магомед Алисултанов
Россия, Волгоград, лицей 2