【问题标题】:How to move object with keyboard in javascript如何在javascript中使用键盘移动对象
【发布时间】:2014-06-28 09:59:00
【问题描述】:

当我移动对象时,它很慢并且不会沿对角线移动,只会向上、向下、向右和向左移动。

我该如何解决这个问题,这是一个好的开始方式还是我应该这样做?

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext('2d');
canvas.width = 600;
canvas.height = 600;
var object = {
    height: 40,
    width: 40,
    x: 10,
    y: 10, 
    color: "#FF0000"        
}

document.addEventListener('keydown', function(event) {
    //left
    if(event.keyCode == 37) {
        object.x -= 1;
    }
    //top
    else if(event.keyCode == 38) {
        object.y -= 1;
    }
    //right
    else if(event.keyCode == 39) {
        object.x += 1;
    }
    //bottom
    else if(event.keyCode == 40) {
        object.y += 1;
    }
});

function renderCanvas(){
    ctx.fillStyle = "#000000";
    ctx.fillRect(0, 0, 600, 600);
} 
function renderObject(){
    ctx.fillStyle = "#FF0000";
    ctx.fillRect(object.x, object.y, object.width, object.height);
}
function run(){
    renderCanvas();
    renderObject();
}

setInterval(run, 10);

这是jsfiddle

我是 javascript 的新手,我真的需要这方面的帮助 ;)

【问题讨论】:

  • 您也许可以使用 js 或 css 关键帧为移动设置动画,使其沿对角线移动。但是您必须检查是否有 2 个箭头以某种方式被按下。就像 if (event.keyCode == 37 AND event.keyCode == 40)... 不确定它是否有效。否则,当箭头被按下时,您必须设置一个标志,并检查该标志是否与另一个箭头处于活动状态......
  • 尝试取出 else if 并用 ifs 替换它(否则键总是互斥的)。我不确定这是否有效……

标签: javascript html canvas keylistener frame-rate


【解决方案1】:

使用标志或带有在按键被按下和释放时更新的标志的对象:

var Keys = {
        up: false,
        down: false,
        left: false,
        right: false
    };

然后在关键事件中更新:

window.onkeydown = function(e) {
    var kc = e.keyCode;
    e.preventDefault();

    if      (kc === 37) Keys.left = true;  // only one key per event
    else if (kc === 38) Keys.up = true;    // so check exclusively
    else if (kc === 39) Keys.right = true;
    else if (kc === 40) Keys.down = true;
};

window.onkeyup = function(e) {
    var kc = e.keyCode;
    e.preventDefault();

    if      (kc === 37) Keys.left = false;
    else if (kc === 38) Keys.up = false;
    else if (kc === 39) Keys.right = false;
    else if (kc === 40) Keys.down = false;
};

这将允许您检查同时按下的键(如果您想连续移动,您需要在循环中检查键对象的状态,否则您将获得重复延迟):

if (Keys.up) {
    dy+=3;
}
else if (Keys.down) {  // both up and down does not work so check excl.
    dy-=3;
}

if (Keys.left) {
    dx+=3;
}
else if (Keys.right) {
    dx-=3;
}

FIDDLE

【讨论】:

  • 我会将 2 个方向保存为像素增量:hor = -5, ver = -5 用于向上和向左。我也喜欢这个。
  • @Rudie 谢谢。使用标志可以更轻松地处理速度和可变速度,但这当然与上下文有关。
  • 链接坏了:(
【解决方案2】:

标志,是的,但 2 就足够了:dxdy

http://jsfiddle.net/rudiedirkx/paw4X/1/

var dx = 0, dy = 0;
var speed = 100; // px per second

var activeKey = 0;
document.addEventListener('keydown', function(e) {
    if (activeKey == e.keyCode) return;
    activeKey = e.keyCode;

    //left
    if (e.keyCode == 37) {
        console.log('start moving LEFT');
        dx = -1;
    }
    //top
    else if (e.keyCode == 38) {
        console.log('start moving UP');
        dy = -1;
    }
    //right
    else if (e.keyCode == 39) {
        console.log('start moving RIGHT');
        dx = 1;
    }
    //bottom
    else if (e.keyCode == 40) {
        console.log('start moving DOWN');
        dy = 1;
    }
});
document.addEventListener('keyup', function(e) {
    switch (e.keyCode) {
        case 37: // left
        case 39: // right
            console.log('stop moving HOR');
            dx = 0;
            break;

        case 38: // up
        case 40: // down
            console.log('stop moving VER');
            dy = 0;
            break;
    }

    activeKey = 0;
});

function fun(){
    renderCanvas();

    object.x += dx / 60 * speed;
    object.y += dy / 60 * speed;
    renderObject();

    requestAnimationFrame(fun);
}
requestAnimationFrame(fun);

丑陋的activeKey 部分是必要的,因为有些键盘每 X 毫秒重复一次keydown 事件,直到按键被释放。

【讨论】:

  • 只是对键重复发表评论:他们的键盘本身会重复。如果您更改设置,操作系统可能会更改此设置,但浏览器(犯有许多其他罪过)不是这里的坏人 :-)
  • @GameAlchemist 我不知道。我相信你。谢谢。
【解决方案3】:
    var object = {
height: 40,
width: 40,
x: 10,
y: 10, 
color: "#FF0000"        
    }

您似乎忘记了分号。让我告诉你:

    var object = {
height: 40,
width: 40,
x: 10,
y: 10, 
color: "#FF0000"        
};

【讨论】:

【解决方案4】:

使用数字键盘怎么样?

这些数字键已经标有上/下/左/右箭头键,因此使用 1、3、7、9 进行对角线移动对用户来说是可以理解和方便的。

为了加快您的移动速度,您可以在每次击键时添加 1 个以上的像素。

要沿对角线移动,您需要同时更改 object.x 和 object.y 的值。

// move 4 pixels with each key

var distance=4;

// for example, move diagonally up & left
object.x-=distance;
object.y-=distance;

这是示例代码和演示:http://jsfiddle.net/m1erickson/RnJLZ/

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
    body{ background-color: ivory; }
    canvas{border:1px solid red;}
</style>
<script>
$(function(){

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");

    var distance=4;
    var object = {
        height: 40,
        width: 40,
        x: 10,
        y: 10, 
        color: "#FF0000"        
    }

    renderObject();

    document.body.onkeydown=function(event){

        switch(event.keyCode){
            case 97: // 1
                object.x-=distance;
                object.y+=distance;        
                break;
            case 98: // 2
                object.x+=0;
                object.y+=distance;
                break;
            case 99: // 3
                object.x+=distance;
                object.y+=distance;        
                break;
            case 100: // 4
                object.x-=distance;
                object.y+=0;        
                break;
            case 101: // 5
                object.x+=0;
                object.y+=0;        
                break;
            case 102: // 6
                object.x+=distance;
                object.y+=0;        
                break;
            case 103: // 7
                object.x-=distance;
                object.y-=distance;        
                break;
            case 104: // 8
                object.x+=0;
                object.y-=distance;        
                break;
            case 105: // 9
                object.x+=distance;
                object.y-=distance;        
                break;
        }

        renderObject();

    }

    function renderObject(){
        if(ctx.fillStyle!=object.color.toLowerCase()){
            console.log(ctx.fillStyle,object.color);
            ctx.fillStyle=object.color;
        }
        ctx.clearRect(0,0,canvas.width,canvas.height);
        ctx.fillRect(object.x,object.y,object.width,object.height);
    }


}); // end $(function(){});
</script>
</head>
<body>
    <canvas id="canvas" width=300 height=300></canvas>
</body>
</html>

【讨论】:

    【解决方案5】:

    我试过了,看起来你必须设置标志。我想出了这个:http://jsfiddle.net/medda86/y6WU9/

    html

    <div class="pic"></div>
    

    css

    html,body{
    width:100%;
    height:100%;
    margin:0px;}
    
    .pic{
    position:absolute;
    margin-left:100px;
    margin-top:100px;
    width:100px;
    height:100px;
    background-color:#ccc;}
    

    jquery

    // MOVE OBJECT DIAGONALLY
    $(document).ready(function(){
    
        var movementSpeed = 10;
        var intervalSpeed = 60;
        var runAnimation = false;
        var animationSpeed = 10;
    
        var leftMarginLimit = parseInt($('.pic').parent().css('width')) - parseInt($('.pic').css('width'));
        var topMarginLimit = parseInt($('.pic').parent().css('height')) - parseInt($('.pic').css('height'));
        var leftMargin = parseInt($('.pic').css('margin-left'));
        var topMargin = parseInt($('.pic').css('margin-top'));
        var animationComplete = true;
    
        // flags
        var left = false;
        var right = false;
        var up = false;
        var down = false;
    
        $(document).keyup(function(key) {
    
            if (key.which == 37){left = false;}
            if (key.which == 39){right = false;}
            if (key.which == 38){up = false;}
            if (key.which == 40){down = false;}
        });
    
        $(document).keydown(function(key) {
    
            if (key.which == 37){left = true;}
            if (key.which == 39){right = true;}
            if (key.which == 38){up = true;}
            if (key.which == 40){down = true;}
        });
    
    
    
    
        setInterval(runMovement,intervalSpeed);
    
        function runMovement() {
    
            if (animationComplete){
    
                // LEFT
                if (left){
                    leftMargin -=movementSpeed;
                    if (leftMargin < 0){leftMargin = 0;}
                    if (leftMargin > leftMarginLimit){leftMargin = leftMarginLimit;}
                }
    
                // RIGHT
                if (right){
                    leftMargin +=movementSpeed;
                    if (leftMargin < 0){leftMargin = 0;}
                    if (leftMargin > leftMarginLimit){leftMargin = leftMarginLimit;}
                }
    
                // UP
                if (up){
                    topMargin -=movementSpeed;
                    if (topMargin < 0){topMargin = 0;}
                    if (topMargin > topMarginLimit){topMargin = topMarginLimit;}
                }
    
                // DOWN
                if (down){
                    topMargin +=movementSpeed;
                    if (topMargin < 0){topMargin = 0;}
                    if (topMargin > topMarginLimit){topMargin = topMarginLimit;}
                }
    
                    // ANIMATION?
                    if (runAnimation){
                        animationComplete = false;
                        $('.pic').animate({'margin-left': leftMargin+'px','margin-top': topMargin+'px'},animationSpeed,function(){
                            animationComplete = true;
                        });
                    }
                        else{
                            $('.pic').css({'margin-left': leftMargin+'px','margin-top': topMargin+'px'});
                        }
    
            }
        }
    });
    

    您可以更改这些设置,例如移动对象的速度以及是否要运行动画,并设置动画速度。你也可以在这里设置间隔..游戏速度:P

    var movementSpeed = 10;
    var intervalSpeed = 60;
    var runAnimation = false;
    var animationSpeed = 10;
    

    编辑:我必须添加 setinterval,但在 keydown 和 keyup 中出现了一些问题。现在你可以更顺畅地四处走动了:)

    【讨论】:

    • 使用requestAnimationFrame() 而不是setInterval()。它每 1/60 秒触发一次,或者在浏览器可以处理的范围内触发一次。您必须手动请求每个动画帧,而不仅仅是第一个(如setInterval)。
    猜你喜欢
    • 1970-01-01
    • 2019-03-18
    • 1970-01-01
    • 2021-11-10
    • 1970-01-01
    • 2015-08-14
    • 2015-08-12
    • 1970-01-01
    • 2014-08-17
    相关资源
    最近更新 更多