【问题标题】:Jump Animation in JavaScriptJavaScript 中的跳转动画
【发布时间】:2015-06-24 06:45:52
【问题描述】:

我最新的爱好项目是一个使用 JavaScript 的非常简单的 Jump'n'Run 游戏。我已经编写了一些代码(借助 lostdecadegames 的教程)并阅读了有关 GameLoop 的所有内容。

var start = true;

// Create the canvas
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = 1200;
canvas.height = 480;
document.body.appendChild(canvas);

var jumping = false;
var gravity = 1.5;
var pressed = true;


// Background image
var bgReady = false;
var bgImage = new Image();
bgImage.onload = function () {
    bgReady = true;
};
bgImage.src = "background.png";

// Hero image
var heroReady = false;
var heroImage = new Image();
heroImage.onload = function () {
    heroReady = true;
};
heroImage.src = "hero.png";

// Monster image
var monsterReady = false;
var monsterImage = new Image();
monsterImage.onload = function () {
    monsterReady = true;
};
monsterImage.src = "monster.png";

// Game objects
var hero = {
    speed_x: 50,
    speed_y_up: 50,
    speed_y_down: 50, // movement in pixels per second
    velocity_x: 50,
    velocity_y: 50
};

// Handle keyboard controls
var keysDown = {};

addEventListener("keydown", function (e) {
    keysDown[e.keyCode] = true;
}, false);

addEventListener("keyup", function (e) {
    delete keysDown[e.keyCode];
}, false);


// Update game objects
var update = function (modifier) {
    if(38 in keysDown) { // Player holding up
        jumping = true;
        //hero.y -= hero.speed_y_up * modifier;
    }   
    if (40 in keysDown) { // Player holding down
        hero.y += hero.speed_y_down * modifier;
    }
    if (37 in keysDown) { // Player holding left
        hero.x -= hero.speed_x * modifier;
    }
    if (39 in keysDown) { // Player holding right
        hero.x += hero.speed_x * modifier;
    }

};


// Draw everything
var render = function () {
    if (bgReady) {
        ctx.drawImage(bgImage, 0, 0);
    }

    if (heroReady) {
        if(hero.y > 0 && hero.y < 480 && hero.x <= -32)
            {
            hero.x = hero.x + 1232;
            ctx.drawImage(heroImage, hero.x, hero.y);
            }
        else if(hero.y > 0 && hero.y < 480 && hero.x >= 1200)
            {
            hero.x = hero.x - 1232;
            ctx.drawImage(heroImage, hero.x, hero.y);
            }
        else if(jumping)
            {
            ctx.drawImage(heroImage, hero.x, hero.y-100);
            jumping = false;
            }
        else ctx.drawImage(heroImage, hero.x, hero.y);
    }

    if (monsterReady) {
        ctx.drawImage(monsterImage, monster.x, monster.y);
    }


};


// The main game loop
var main = function () {
    var now = Date.now();
    var delta = now - then;

    update(delta / 500);
    render();

    then = now;
};

// Starting the game!
reset();
var then = Date.now();
setInterval(main, 1); // Execute as fast as possible

如您所见,我已经添加了一个固定重力变量和一些速度变量。英雄的动作非常流畅,所以这没问题。 跳转动画有 2 个问题:

  1. 当持续按下向上键时,英雄停留在空中。我试图用一些布尔变量来解决这个问题,但我不知道如何让英雄再次崩溃。
  2. 现在,我实施了一个“肮脏的 hack”,它会导致英雄被重新绘制高 50 像素,但我想要一个平滑的跳跃,这样英雄在上升时会变慢,而在下降时会加速。我查找了很多教程和示例代码,但我太愚蠢了,无法弄清楚如何获得所需的动画。

希望你们能给我一些关于我的问题的建议(我不是要最终的代码,我只是需要一些提示)。

【问题讨论】:

    标签: javascript animation canvas game-physics


    【解决方案1】:

    很难准确理解 if (heroReady) 中的 if 语句在做什么,因为这些数字对我来说没有任何意义,但在我看来,你的问题就在那里。

    首先,在我看来,jumping 应该检查第一个条件。如果第一个条件之一为真,那么他是否在跳跃都无关紧要。不过,我无法轻易判断每个条件何时为真,因此我将假设当玩家举起时,

    else if(jumping)
    {
        ctx.drawImage(heroImage, hero.x, hero.y-100);
        jumping = false;
    }
    

    正常执行。

    现在,假设,我认为你的问题是jumping 完全取决于玩家是否坚持,因为一旦jumping 为真,它就会变为假。这是不正确的。

    当玩家按下向上键时,跳跃应该设置为真,但当他们移除它时应该设置为假。动画落地时应设置为false。

    你遇到的另一个问题是你实际上并没有使用英雄的属性来渲染它的跳跃位置,你只是在抵消它。也许这只是您在问题解决之前的解决方法,但是很难判断角色何时落地,因为您无法在角色跳跃后开始降低角色(增加 y 值),因为您从未抬起它们通过减小 y 值。

    那么我们该如何解决呢?

    这是我的建议。由于重构,您可能会在完成时找到更优雅的方式来执行此操作,但您现在设置它的方式我认为它会正常工作:

    • 当他们按下时立即设置jumping,就像你正在做的那样,但前提是jumping == false,因为大概你的英雄无法进行空中跳跃。
    • 在您设置 jumping(以及在同一 if 语句中)后,立即更新它们的速度。
    • 在您的更新部分,添加另一个 if 来判断玩家是否在跳跃,无论他们是否按下任何键。如果是,请根据重力减小它们的动量。然后,检查他们的动量是否与他们开始跳跃时增加的动量相反。换句话说,检查他们向下移动的速度是否与开始跳跃时向上移动的速度完全相同。这恰好发生在他们开始跳跃的 y 坐标上。 (这比只检查他们的位置更可靠,因为它可以在多个 y 位置工作。)另一种方法是存储一个变量,其中包含他们跳跃时所在的 y 坐标。无论哪种方式,如果他们的跳转已经结束,请将 jumping 设置为 false。
    • 由于您是根据跳跃来更新它们的坐标,因此在您的渲染函数中,您可以消除任何跳跃逻辑,只根据坐标绘制图像。

    这有帮助吗?

    【讨论】:

    • 我现在就试试这个。谢谢,希望这会成功。
    • 我遇到了类似的问题,并提出了类似的解决方案(即将起始位置存储在变量中),但担心再次跳跃只会覆盖起始 pos 变量。我忘记了它不会,因为只要当前位置高于起始位置,你就不能跳跃...... - 问题是它不能扩展到能够降落在任何东西上,即如果你可以跳到东西上,然后你不能在它们上面跳,因为你的 pos 仍然太高。所以我想这在这个意义上是一种黑客行为。所以我要问的是:
    • 将跳跃变量更新为 false 的最佳方法是什么?
    • 没关系,明白了。 - 简短的回答:这取决于你首先使用什么样的功能来跳转。我使用了 setInterval、setTimeout 和 clearInterval 的组合(即重复做一些事情直到时间到了,然后清除) - 所以在最后添加一个转向跳转到 false 很容易。只需要在调用它的部分添加真正的跳转,就像 OP 一样。谢谢两位! :)
    猜你喜欢
    • 2011-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-31
    • 1970-01-01
    • 2013-11-27
    • 2021-04-18
    • 1970-01-01
    相关资源
    最近更新 更多