@lord_Iohan

Как сделать правильно анимацию прыжка персонажа на блок?

У меня есть персонаж, который запрыгивает на блок и спокойно слезает с него, но при этом он не может прыгать на самом блоке. Не могу понять, как исправить, чтобы мог. Функция, в которой я пытаюсь всё это делать, называется moveMan.
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Jump</title>
</head>
<body>
<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>
<script>
    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 ((dx + 45 <= secondLineX)) {
                dy = canvas.height - jackHeight - 15;
            }
            if ((dx - 55 + jackWidth) >= (secondLineX + secondWidth)) {
                dy = canvas.height - jackHeight - 15;
            }
            //отрабатывает прыжок на блок!!!!!!!!!!!!!!!!!!!!!!!!
            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);
                console.log('hi');
            }

            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();
</script>
</body>
</html>
  • Вопрос задан
  • 721 просмотр
Пригласить эксперта
Ответы на вопрос 1
dollar
@dollar
Делай добро и бросай его в воду.
Вы считаете новые координаты от начальных, а нужно считать новые координаты от предыдущих.

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

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

Таким образом, что касается блока, то в момент прыжка будут просто другие начальные координаты. Функции прыжка должно быть пофиг, что это за координаты, она просто задает вектор скорости, если есть поверхность, от которой можно оттолкнуться. Дальнейший расчет движения уже проблема не функции прыжка, а других функций.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы