1

我最新的爱好项目是一个使用 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

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

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

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

4

1 回答 1

1

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

首先,在我看来,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。
  • 由于您是根据跳跃更新它们的坐标,因此在您的渲染函数中,您可以消除任何跳跃逻辑并仅根据坐标绘制图像。

这些帮助有用?

于 2013-01-30T16:04:07.980 回答