Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   BitmapData.hitTest() для объекта с объектами из массива (http://www.flasher.ru/forum/showthread.php?t=210009)

sam_dmitry 15.01.2015 01:19

BitmapData.hitTest() для объекта с объектами из массива
 
Здравствуйте. Я еще новичок, так что извиняюсь за нубский вопрос)

Вопрос который меня интересует - проверка столкновений между объектом игрока и объектами из массива - это 2 разных типа объектов.
HitTestObject и HitTestPoint мне не подошли, в силу кривости их проверки для объектов неопределенных форм или я как-то неправильно их готовил...

Есть небольшой код. Описание того что в нем происходит:
1)Игрок управляет первым объектом, который привязан к курсору мышки
2) Сверху вниз по (Y), на игрока падают одинаковые клоны второго объекта, созданные через массив.
3) Падающие объекты произвольной формы. форма объекта игрока пока просто - круг, но тоже предполагается произвольная.

Гугл подсказал о чудесной проверке по пикселям Bitmapdata.hittest().
Я нашел хороший урок с исходниками, в котором реализована эта тема. Разобрался с ним - смог применить к двум объектам, которые изначально расположены на поле и которые можно таскать курсором.

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

Если понадобиться, закину сюда исходники кода, но надеюсь и так все понятно.
Заранее благодарен

PainKiller 15.01.2015 16:49

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

sam_dmitry 16.01.2015 02:50

Вложений: 1
Как раз и пробовал интегрировать код, из урока выше.
Вкратце про мой проект - он состоял из 3-х классов: описание игрока, описание врага, основной код игры - добавляющий на игровое поле игрока и врагов из массива по таймеру, а так же делал проверку столкновений через HitTestPoint. С ним все работал как надо, но результат не устроил меня, как я писал выше. Прикрепляю его сюда на всякий случай.
Код AS1/AS2:

// Главный код игры
package
{
        import flash.display.MovieClip;
        import flash.utils.Timer;
        import flash.events.TimerEvent;
        public class AvoiderGame extends MovieClip
        {
                // ПЕРЕМЕННЫЕ
                public var army:Array; //переменная для массива врагов,
                public var avatar:Avatar; // Переменная для создания игрока
                public var gameTimer:Timer; // переменная для таймера
                private var _collisionTest:CollisionTest; //Переменная для теста столкновений- зависит от класса Теста столкновений
 
                // Создаем ГЛАВНУЮ ФУНКЦИЮ ЦИКЛА ИГРЫ
                public function AvoiderGame()
                {
                        avatar = new Avatar(); // конкретный тип игрока, привязанный к классу описания игрока
            addChild(avatar ); // добавляем на экран игрока
                        avatar.x = mouseX; // привязываем игрока к координатам мыши по Х и Y ниже
            avatar.y = mouseY;
 
                        army = new Array(); //Создаем новый экземляр для класса массива врагов
                        var newEnemy = new Enemy(100,-15);
                        army.push(newEnemy); //Добавляем нового созданного врага в массив (army)
                        addChild(newEnemy); // добавляем на игровое поле врага из массива
 
                    gameTimer = new Timer( 25 ); // Создаем новый экземпляр - Таймер.
                        gameTimer.addEventListener(TimerEvent.TIMER, onTick); // Создаем слушатель события для таймера. Если оно произошло - событие первое в скобках, то запускается функция - второе в скобках.
                        gameTimer.start(); // запускаем таймер после запуска игры
                }
                //Создаем ФУНКЦИЮ ДЛЯ СОБЫТИЯ, ПРОИСХОДЯЩЕЕ ПОСЛЕ ИСТЕЧЕНИЯ ТАЙМЕРА - т.е. каждые 25 м/с
                public function onTick(timerEvent:TimerEvent ):void
                {
                        if(Math.random() < 0.2) // Уменьшаем частоту тиков (появления врагов) и делаем ее немного рандомной
                        {
                                var randomX:Number = Math.random() * 550; // Создаем переменную рандома, для появления врагов по оси Х, по всей длинне от 0 - 400
                                var newEnemy:Enemy = new Enemy(randomX,-15);
                                army.push(newEnemy);
                                addChild(newEnemy);
                        }
                        avatar.x = mouseX; // игрок двигается за мышкой по Х и Y ниже
            avatar.y = mouseY;
 
                        for each (var enemy:Enemy in army) //  Цикл проходит через все строчки в массиве и каждому объекту массива говорит что делать
                        {
                        // ГОВОРИМ ВСЕМ НОВЫМ ВРАГАМ ДВИГАТЬСЯ ВНИЗ
                        enemy.moveDownABit(); // используем описанную функцию в классе описания Врага. Применяется для каждого нового созданного врага.
                        if ( avatar.hitTestPoint(enemy.x+20,enemy.y+20,true))  // Проверка. Если произошло событие в скобках - аватар столкнулся с врагом, то происходит событие описанное ниеже в {}
                {
                        trace("столкновение");
                          gameTimer.stop(); // Останавливаем таймер
                }
                        }
 
                }
 
        }
 
}

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

Прикрепляю код, в котором я пытался запустить проверку BitmapData.hitTest()
Код AS1/AS2:

// Главный код игры
package
{
        import flash.display.MovieClip;
        import flash.utils.Timer;
        import flash.events.TimerEvent;
        public class AvoiderGame extends MovieClip
        {
                // ПЕРЕМЕННЫЕ
                public var army:Array; //переменная для массива врагов,
                public var avatar:Avatar; // Переменная для создания игрока
                public var gameTimer:Timer; // переменная для таймера
                private var _collisionTest:CollisionTest; //Переменная для теста столкновений- зависит от класса Теста столкновений
 
                // Создаем ГЛАВНУЮ ФУНКЦИЮ ЦИКЛА ИГРЫ
                public function AvoiderGame()
                {
                        avatar = new Avatar(); // конкретный тип игрока, привязанный к классу описания игрока
            addChild(avatar ); // добавляем на экран игрока
                        avatar.x = mouseX; // привязываем игрока к координатам мыши по Х и Y ниже
            avatar.y = mouseY;
 
                        army = new Array(); //Создаем новый экземляр для класса массива врагов
                        var newEnemy = new Enemy(100,-15);
                        army.push(newEnemy); //Добавляем нового созданного врага в массив (army)
                        addChild(newEnemy); // добавляем на игровое поле врага из массива
 
                    gameTimer = new Timer( 25 ); // Создаем новый экземпляр - Таймер.
                        gameTimer.addEventListener(TimerEvent.TIMER, onTick); // Создаем слушатель события для таймера. Если оно произошло - событие первое в скобках, то запускается функция - второе в скобках.
                        gameTimer.start(); // запускаем таймер после запуска игры
 
                        // create an new instance of the CollisionTest class
                        _collisionTest = new CollisionTest();
                }
 
                //Function that checks for all possible collisions
 
                private function checkForCollisions():void
                {
                        // test avatar vs enemy
                        if (_collisionTest.complex(avatar, enemy))
                        {
                        trace("столкновение");
                          gameTimer.stop(); // Останавливаем таймер
                        }
 
                        // test enemy vs avatar
                        if (_collisionTest.complex(enemy, avatar))
                        {
                        trace("столкновение");
                          gameTimer.stop(); // Останавливаем таймер
                        }
 
                }
 
 
                //Создаем ФУНКЦИЮ ДЛЯ СОБЫТИЯ, ПРОИСХОДЯЩЕЕ ПОСЛЕ ИСТЕЧЕНИЯ ТАЙМЕРА - т.е. каждые 25 м/с
                public function onTick(timerEvent:TimerEvent ):void
                {
                        if(Math.random() < 0.2) // Уменьшаем частоту тиков (появления врагов) и делаем ее немного рандомной
                        {
                                var randomX:Number = Math.random() * 550; // Создаем переменную рандома, для появления врагов по оси Х, по всей длинне от 0 - 400
                                var newEnemy:Enemy = new Enemy(randomX,-15);
                                army.push(newEnemy);
                                addChild(newEnemy);
                        }
                        avatar.x = mouseX; // игрок двигается за мышкой по Х и Y ниже
            avatar.y = mouseY;
 
                        for each (var enemy:Enemy in army) //  Цикл проходит через все строчки в массиве и каждому объекту массива говорит что делать
                        {
                        // ГОВОРИМ ВСЕМ НОВЫМ ВРАГАМ ДВИГАТЬСЯ ВНИЗ + Делаем проверку столкновений
                        enemy.moveDownABit(); // используем описанную функцию в классе описания Врага. Применяется для каждого нового созданного врага.
                        checkForCollisions();
                        }
 
                }
 
        }
 
}

На всякий случай прикрепляю проект со вторым вариантом кода Вложение 31347

PainKiller 16.01.2015 12:18

Вложений: 1
Ошибка возникает, потому что в checkForCollisions() переменная enemy не объявлена, а в саму функцию вы её не передаете. Читайте про область видимости переменных в as3.

Прилагаю исправленную версию.

sam_dmitry 17.01.2015 03:41

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

Теперь возник еще один вопрос попутно... Проверка столкновений в моем проекте работает совсем не как ожидалось - не как в уроке по ссылке. Падающие объекты могут задевать объект игрока и при этом не определяются столкновения. Работает все примерно как при HitTestPoin. В уроке по ссылке столкновения определялись при первом соприкосновении пикселей у проверяемых объектов.

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

PainKiller 17.01.2015 21:09

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


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

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