Анимация прыжка персонажа на блок

106
29 марта 2021, 10:10

У меня получилось сделать так, чтобы Джек запрыгивал на блок, но никак не получается осуществить его падение, если он с этого блока сходит. Походу, само запрыгивание сделано не очень правильно. Его реализация находится в последней функции moveMan

    const canvasFon = document.getElementById('fon'); 
    let ctxFon = canvasFon.getContext('2d'); 
    const canvas = document.getElementById('field'); 
    let ctx = canvas.getContext('2d'); 
 
    ctxFon.fillStyle = 'black'; 
    let secondLineX = 250, 
        thirdLineY = 450, 
        secondWidth = 428; 
    ctxFon.fillRect(secondLineX, thirdLineY, secondWidth, 25); 
 
    function jack() { 
        let sprite = new Image(); 
        sprite.src = 'https://www.emu-land.net/forum/index.php?action=dlattach;topic=77145.0;attach=175283;image'; 
        let tick_count = 0, 
            rightPressed = false, //определение нажатых кнопак, изначальное значение false, так как кнопки не нажаты 
            leftPressed = false, 
            jackWidth = 34, //ширина, высота 
            jackHeight = 89, 
            sx = 0, 
            dx = 100, //координаты 
            dy = canvas.height - jackHeight - 15, 
            jumpPressed = false, 
            jumpCount = 0, 
            jumpLength = 75,//длина прыжка по горизонтали 
            jumpHeight = 0;//высота прыжка 
        sprite.onload = function () { //отрисовка стоящего сузуки при загрузке, его стандартное состояние 
            stayMan(dy); 
        }; 
 
        function stayMan(y) { 
            ctx.clearRect(0, 0, canvas.width, canvas.height); 
            ctx.drawImage(sprite, 50, 178, 39, 89, dx, y, jackWidth, jackHeight); 
        } 
 
        function jumpMan() { 
            ctx.clearRect(0, 0, canvas.width, canvas.height); 
            ctx.drawImage(sprite, 0, 355, 57, 89, dx, dy - jumpHeight, 57, jackHeight); 
        } 
 
        function drawMan() { //отрисовка мальчика во время движения 
            ctx.clearRect(0, 0, canvas.width, canvas.height);//очистка канваса 
            sx = (sx === 510 ? 0 : sx + 34); //переброс в начало 
            ctx.drawImage(sprite, sx, 0, 32, 89, dx, dy, jackWidth, jackHeight);//отображение первого спрайта 
        } 
 
        function forKeydown(e) { 
            if (e.keyCode === 32) jumpPressed = true; //пробел 
            if (e.keyCode === 37) leftPressed = true; //стрелочка лево 
            if (e.keyCode === 39) rightPressed = true;//стрелочка право 
        } 
 
        function forKeyup(e) { 
            if (e.keyCode === 37) { 
                leftPressed = false; 
                stayMan(dy); 
            } 
            if (e.keyCode === 39) { 
                rightPressed = false; 
                stayMan(dy); 
            } 
        } 
 
        document.addEventListener('keydown', forKeydown, false); 
        document.addEventListener('keyup', forKeyup, false); 
 
 
        function moveMan() { 
            if (rightPressed && dx < canvas.width - jackWidth) { 
                tick(); 
                dx += 4 
            } 
            if (leftPressed && dx > 0) { 
                tick(); 
                dx -= 4 
            } 
            if (jumpPressed) { 
                jumpCount++; 
                jumpHeight = 2 * jumpLength * Math.sin(Math.PI * jumpCount / jumpLength); //отнимается от dy, значит мальчик становится выше 
                jumpMan(); 
            } 
 
            //отрабатывает прыжок на блок!!!!!!!!!!!!!!!!!!!!!!!! 
            if ((dy - jumpHeight + jackHeight <= thirdLineY) && ((dx + 45 >= secondLineX) && (dx - 45 + jackWidth) <= (secondLineX + secondWidth))) { 
                if((dx + 45 <= secondLineX)){ 
                    dy = canvas.height - jackHeight - 15; 
                } 
                jumpCount = 0; 
                jumpPressed = false; 
                jumpHeight = -75; 
                dy = thirdLineY - jackHeight + 15; 
                stayMan(thirdLineY - jackHeight + 15); 
    
            } 
 
            if (jumpCount > jumpLength) { 
                jumpCount = 0; 
                jumpPressed = false; 
                jumpHeight = 0; //ничего не отнимается, значит возвращается в исходную позицию 
                stayMan(dy); 
            } 
        } 
 
        setInterval(moveMan, 10); 
 
        function tick() { 
            if (tick_count > 10) { //количвество отрисованных кадров, влияние на скорость 
                tick_count = 0; 
                drawMan(dy); 
            } 
            tick_count += 1; 
        } 
    } 
 
    jack();
<div style="position: relative;"> 
<canvas id="fon" style="position: absolute" width="928" height="600"></canvas> 
<canvas id="field" width="928" height="600" style="position: absolute">hi</canvas> 
</div>

Answer 1

У вас пока ничего не написано про падение Джека с блока (если я правильно понял). Надо в вашем игровом цикле moveMan проверять падает ли Джек (для этого надо проверить, что у него под ногами пусто) и отключать другие возможности пока он не перестанет падать, отнимая его высоту.

Определение есть ли что-то под ногами Джека и есть проверка коллизий ("алгоритм пересечения предметов") о котором вам говорят в комментариях. Вы такую проверку уже делаете, когда реализуете остановку прыжка Джека на платформе (сравниваете координаты Джека и платформы).

Если вы структурируете свой код, то сможете справится со сложностью таких взаимодействий. Например все блоки (в том числе и пол, на котором Джек стоит в самом низу) можно поместить в массив и потом на каждой итерации цикла проверять не упёрся ли Джек в один из них. Код для всех блоков будет одинаковый (отличаются только их координаты) и ваш Джек сможет запрыгивать не на один, а на любое количество блоков.

Пробуйте и у вас получится.

Answer 2

Вычисляйте пересечение Джека с препятствиями. Скорее всего вам придётся таки познакомиться с суммой Минковского.

Понятная статья на хабре - "Как Минковский во Flappy Bird играл", и менее понятная в вики - "Сумма Минковского".

READ ALSO
Как запустить код в VS Code?

Как запустить код в VS Code?

Взялся изучать JS, установил VS CodeНаписал код, однако запустить его не могу

128
Module build failed (from ./node_modules/babel-loader/lib/index.js):ошибка в webpack.dev.js?

Module build failed (from ./node_modules/babel-loader/lib/index.js):ошибка в webpack.dev.js?

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

86
Привязки Python к JS и наоборот

Привязки Python к JS и наоборот

Подскажите способы примирить языки Python3 и JSКак можно реализовать вызов функции и передачу/получение параметров из одного языка в другой

116
Звездный рейтинг для сайта

Звездный рейтинг для сайта

Всем, привет) Пробую по примеру сделать звездный рейтинг для сайта, но не могу понять где ошибка в моем кодеВроде все делаю как в примере, но у меня...

101