Предотвращение перекрытия элементов во время анимации

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

Числам присваивается случайная "х" позиция в начале и затем анимируется сверху с той же скоростью.

Проблема, с которой я сталкиваюсь, заключается в том, что при запуске программы элементы иногда могут перекрываться, потому что им дается аналогичная позиция "x" в начале.

Мне нужно сказать программе, чтобы она не давала одинаковую позицию "x", пока элемент, использующий ее, не достаточно, чтобы экран не перекрывался.

Проблема заключается в худшем, когда игра начинается.

Вот соответствующий код...

var currentMoving = [];

function moveRandom(id) {

    // Mark this one as animating
    currentMoving.push(id);

    var cPos = $('#container').offset();
    var cHeight = $('#container').height();
    var cWidth = $('#container').width();
    var bWidth = $('#' + id).width();

    var bHeight = $('#' + id).css('top', '395px').fadeIn(100).animate({
        'top': '-55px'
    }, AnimationSpeed,'linear').fadeOut();

    maxWidth = cPos.left + cWidth - bWidth;
    minWidth = cPos.left;
    newWidth = randomFromTo(minWidth, maxWidth);

    $('#' + id).css({
        left: newWidth
    }).fadeIn(100, function () {
        setTimeout(function () {
            $('#' + id).fadeOut(10);

            // Mark this as no longer animating                
            var ix = $.inArray(id, currentMoving);
            if (ix !== -1) {
                currentMoving.splice(ix, 1);
            }
            window.cont++;
        }, 100);
    });
}

Вот скрипка - http://jsfiddle.net/pUwKb/68/

Ответ 1

Вот простое решение, но не самое оптимальное.

1/Вместо случайного x пометьте свой холст сетками и выберем только смещение x, равное 50 пикселям (ширина вашего окна), поэтому ящик можно запустить из любой из 12 сеток в вашем холсте размером 600 пикселей.

| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12

2/Когда ящик запускается в любой сетке, заблокируйте эту сетку в течение 1 секунды или 2 секунд, чтобы ваш генератор случайных позиций для новых ящиков не генерировал эту сетку, пока она не заблокирована.

3/Через некоторое время очистите блокировку для сетки.

http://jsfiddle.net/pUwKb/72/

Фрагмент кода для создания x-позиции на основе сетки вместо случайного x: [строки 230-238]

function randomFromToPosition(from, to) {
    /* align boxes in grids instead of random positions */
    do {
    var pos = Math.floor(Math.random() * (to - from + 1) + from);
    var roundedPos = Math.floor(pos/50)*50;
    } while(lockedGrid[roundedPos] == true);

    return roundedPos;
}

Блокировка и разблокировка сетки: [строки 289-300]

        maxWidth = cPos.left + cWidth - bWidth;
        minWidth = cPos.left;
        newWidth = randomFromToPosition(minWidth, maxWidth);

        lockedGrid[newWidth] = true; // Lock the grid position
        setTimeout(function(){
            delete lockedGrid[newWidth];
        },2000);      // free the lock after 2 seconds.

Ответ 2

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

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

При проверке конфликтов, если обнаружено столкновение, самым простым решением было бы рассчитать разницу в высоте между новым объектом и той, с которой он столкнулся, чтобы немного поместить новый объект.

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