用JavaScript跳转动画

时间:2013-01-30 15:40:15

标签: javascript animation canvas game-physics

我最新的Hobby Project是一个使用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. 当Up-Key被按下时,Hero停留在空中。我尝试用一​​些布尔变量解决这个问题,但我无法弄明白如何让英雄再次失望。
  2. 现在,我实施了一个“肮脏的黑客”,导致Hero被重新粉刷50px,但我想要一个平稳的跳跃,以便Hero在上升时变慢并且在下降时加速。我查了很多教程和如此多的示例代码,但我太愚蠢了解它,我是如何得到我想要的动画。
  3. 希望你们能为我的问题给我一些建议(我不是要求最终的代码,我只需要一些提示)。

1 个答案:

答案 0 :(得分:1)

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

首先,在我看来,如果检查第一个条件,jumping就好了。如果第一个条件之一是真的,那么他是否跳跃并不重要。不过,我不能轻易判断每个条件是否属实,所以我会假设玩家在举起时,

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

正常执行。

现在,假设这一点,我认为你的问题是jumping仅取决于玩家是否持有,因为只要jumping为真,就会变为假。这是不正确的。

当玩家按下向上键时跳跃应该设置为true,但是当它们移除时应该设置为false。当动画到达地面时,它应该设置为false。

你遇到的另一个问题是你实际上并没有使用英雄的属性来渲染它的跳跃位置,你只是在抵消它。也许这只是你的解决方法,直到问题解决了,但它很难分辨出角色何时到达地面,因为你不能在跳跃后开始降低角色(增加y值),因为你从来没有提过它们通过降低y值。

那我们该如何解决这个问题?

以下是我的建议。由于重构,你可能会在完成时找到更优雅的方法来实现它,但是你现在设置它的方式我觉得它会正常工作:

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

这有帮助吗?