使用$()。keydown平滑平铺游戏角色动作

时间:2015-08-02 03:14:51

标签: jquery canvas keypress keydown keyup

我想在我的平铺游戏中实现角色移动,这样它就不会通过关键事件向服务器发送垃圾邮件。目前,我已使用setInterval限制了发送的事件数量。

我的想法出现问题:

  1. 如果玩家没有在合适的时间点按某个键,则该动作可能无效

  2. 连续点击一个键(例如右箭头),只会在setInterval拾取事件时发送键事件。这使它看起来很麻烦。

  3. 我的代码很好:

    1. 如果你所做的只是拿着钥匙,那就完美了。

    2. 您可以通过一次按住两个键来对角移动。代码存储了正在按下的键。

    3. 可能会有所帮助的事情:

      1. 取消对关键事件的限制,去抖可以很好地工作。我只是不希望玩家通过按住键将垃圾邮件发送到比其他方式更快的速度。 (我没有在去抖代码方面取得多大成功)
      2. 以下是我的代码的简要基本示例:http://jsfiddle.net/empXx/66/

        var canvas = document.getElementById('c'),
            ctx = canvas.getContext("2d"),
            tileSize = 10;
        var holdingUp = false;
        var holdingDown = false;
        var holdingLeft = false;
        var holdingRight = false;
        var cx = 150;
        var cy = 150;
        
        $(document).keydown(function(e) {
            if(e.which==37) { holdingLeft = true; }
            if(e.which==38) { holdingUp = true; }
            if(e.which==39) { holdingRight = true; }
            if(e.which==40) { holdingDown = true;  }
        });
        $(document).keyup(function(e) {
            if(e.which==37) { holdingLeft = false; }
            if(e.which==38) { holdingUp = false; }
            if(e.which==39) { holdingRight = false; }
            if(e.which==40) { holdingDown = false; }
        });
        
        ctx.fillRect(150, 150, tileSize, tileSize);
        setInterval(function() {
            if(holdingUp) {
                cls();
                ctx.fillRect(cx, cy - tileSize, tileSize, tileSize);
                cy -= tileSize;
            } else if(holdingDown) { 
                cls();
                ctx.fillRect(cx, cy + tileSize, tileSize, tileSize);
                cy += tileSize;
            }
            if(holdingLeft) {
                cls();
                ctx.fillRect(cx - tileSize, cy, tileSize, tileSize); 
                cx -= tileSize;
            } else if(holdingRight) {
                cls();
                ctx.fillRect(cx + tileSize, cy, tileSize, tileSize);
                cx += tileSize;
            }
        }, 120);
        
        function cls() { ctx.clearRect(0, 0, canvas.width, canvas.height); }
        

        如何让这个游戏互动更顺畅,让用户更加愉快,同时降低垃圾邮件的数量?

1 个答案:

答案 0 :(得分:0)

感谢John S的原始修复。我稍微修改了代码以使其更好。目前,如果用户左右握住,则玩家将不会移动。这是一个比处理键优先级更简单的解决方案,具体取决于按下的顺序。我也这样做,以便upCount / downCount等,当holdUp& holdingDown是活跃的。左右动作相同。

简化jsfiddle with bare basics here

实施此代码的生产游戏+反垃圾邮件/作弊检测是here

JSFiddle代码,根据SO的要求:

var canvas = document.getElementById('c'),
    ctx = canvas.getContext("2d"),
    tileSize = 10;
var holdingUp = false;
var holdingDown = false;
var holdingLeft = false;
var holdingRight = false;
var cx = 150;
var cy = 150;

var upCount = 0;
var downCount = 0;
var leftCount = 0;
var rightCount = 0;

$(document).keydown(function(e) {
    if(e.which==37 && !holdingLeft) { holdingLeft = true; leftCount++; }
    if(e.which==38 && !holdingUp) { holdingUp = true; upCount++; }
    if(e.which==39 && !holdingRight) { holdingRight = true; rightCount++; }
    if(e.which==40 && !holdingDown) { holdingDown = true; downCount++;  }
});
$(document).keyup(function(e) {
    if(e.which==37) { holdingLeft = false; }
    if(e.which==38) { holdingUp = false; }
    if(e.which==39) { holdingRight = false; }
    if(e.which==40) { holdingDown = false; }
});

ctx.fillRect(150, 150, tileSize, tileSize);
setInterval(function() {
    if(!(holdingUp && holdingDown)) {
        if((upCount > 0) || holdingUp) {
            if (upCount > 0) { upCount--; }
            cls();
            ctx.fillRect(cx, cy - tileSize, tileSize, tileSize);
            cy -= tileSize;
        } else if((downCount > 0) || holdingDown) { 
            if (downCount > 0) { downCount--; }
            cls();
            ctx.fillRect(cx, cy + tileSize, tileSize, tileSize);
            cy += tileSize;
        }
    } else {
        downCount = upCount = 0;
    }
    if(!(holdingLeft && holdingRight)) {
        if((leftCount > 0) || holdingLeft) {
            if (leftCount > 0) { leftCount--; }
            cls();
            ctx.fillRect(cx - tileSize, cy, tileSize, tileSize); 
            cx -= tileSize;
        } else if((rightCount > 0) || holdingRight) {
            if (rightCount > 0) { rightCount--; }
            cls();
            ctx.fillRect(cx + tileSize, cy, tileSize, tileSize);
            cx += tileSize;
        }
    } else {
        leftCount = rightCount = 0;
    }
}, 120);

function cls() { ctx.clearRect(0, 0, canvas.width, canvas.height); }