Javascript JS游戏中的画布渲染视错觉(简单复制图形)-修复?

Javascript JS游戏中的画布渲染视错觉(简单复制图形)-修复?,javascript,canvas,Javascript,Canvas,我正在用javascript创建一个侧面滚动的太空射手。到目前为止,一切似乎都运转良好。然而,在画布渲染中有一个奇怪的错误,我不能完全弄清楚(并且很难描述,所以请容忍我!) 我有一个玩家可以通过点击鼠标左键来发射射弹。当弹丸第一次离开玩家时,在短暂的一秒钟内,似乎有两个弹丸,直到它们最终合并到一个弹丸中。我并没有创造两个,所以这看起来像是一个视觉错觉(如果你连续快速发射几枚炮弹,这是最明显的) 真正奇怪的是,当我试图捕捉到这一事件的截图时,一切看起来都很好。有人知道发生了什么事吗 玩家代码,包括

我正在用javascript创建一个侧面滚动的太空射手。到目前为止,一切似乎都运转良好。然而,在画布渲染中有一个奇怪的错误,我不能完全弄清楚(并且很难描述,所以请容忍我!)

我有一个玩家可以通过点击鼠标左键来发射射弹。当弹丸第一次离开玩家时,在短暂的一秒钟内,似乎有两个弹丸,直到它们最终合并到一个弹丸中。我并没有创造两个,所以这看起来像是一个视觉错觉(如果你连续快速发射几枚炮弹,这是最明显的)

真正奇怪的是,当我试图捕捉到这一事件的截图时,一切看起来都很好。有人知道发生了什么事吗

玩家代码,包括射弹(小提琴中的完整代码)

var Player=(函数(){
// ------------------------------------------------------------------------------------------------
//玩家变量
// ------------------------------------------------------------------------------------------------
var w=50;
var h=50;
var x=0;
var y=0;
var射弹=[];
// ------------------------------------------------------------------------------------------------
//将事件绑定到全局画布
// ------------------------------------------------------------------------------------------------
Canvas.bindEvent('mousemove',函数(e){
y=(e.pageY-Canvas.element.getBoundingClientRect().top)-(h/2);
});
Canvas.bindEvent('click',函数(){
(50,(y+(h/2))-10);
});
// ------------------------------------------------------------------------------------------------
//功能
// ------------------------------------------------------------------------------------------------
var createSproject=函数(x,y){
射弹({
x:x,
y:y
})
};
变量更新=函数(){
对于(var p=projectles.length-1;p>=0;p--){
射弹[p].x+=10;
if(projectles[p].x>Canvas.element.width)projectles.splice(p,1);
}
};
var render=函数(){
Canvas.context.fillStyle='white';
Canvas.context.fillRect(x,y,w,h);
对于(var p=0;p
Js小提琴演示:

编辑
根据@Pimskie的回答,这确实看起来像是一种视错觉——所以我现在的问题是,我该如何减少这种影响?我计划在未来实现一项功能,允许玩家切换武器(其中一些玩家会**实际*发射多发炮弹),但我不希望这种效果继续存在,以免混淆。

我猜这确实是一种错觉。 检查此更新的小提琴:


我删除了一个
requestAnimationFrame
,并将另一个替换为一个非常慢的
setInterval
,只是为了演示。您只能看到创建了一个项目符号

我猜这确实是一种视错觉。 检查此更新的小提琴:


我删除了一个
requestAnimationFrame
,并将另一个替换为一个非常慢的
setInterval
,只是为了演示。您只能看到创建了一个项目符号

是的,这是一种视错觉。第一次发射时它看起来有多个方块的原因是因为你的眼睛集中在大的静态舰船方块上。一旦你的眼睛开始跟随运动路径,那么它看起来更像是一个流动的正方形,而不是每秒重绘60或30次的正方形。将一张纸或手放在屏幕上,覆盖屏幕的左半部分。把注意力集中在那张纸上,开几枪。你会注意到,这些镜头看起来像是多次的,就像刚刚发射时一样。这是一个你的心看到3个不同的帧作为同一个


requestAnimationFrame取决于浏览器和计算机的帧速率。在大多数情况下,这是60帧/秒。60到70fps是大多数监视器的极限,因此尝试超过这个极限是没有意义的。但是,通过在投射物上使用尾随跟踪器效果,可以创建更流畅的运动错觉。这需要在每个投射物后面创建2到3个额外的正方形,这些正方形的不透明度越来越小。

是的,这是一种视错觉。第一次发射时它看起来有多个方块的原因是因为你的眼睛集中在大的静态舰船方块上。一旦你的眼睛开始跟随运动路径,那么它看起来更像是一个流动的正方形,而不是每秒重绘60或30次的正方形。将一张纸或手放在屏幕上,覆盖屏幕的左半部分。把注意力集中在那张纸上,开几枪。你会注意到,这些镜头看起来像是多次的,就像刚刚发射时一样。这是一个你的心看到3个不同的帧作为同一个

requestAnimationFrame取决于浏览器和计算机的帧速率。在大多数情况下,这是60帧/秒。60到70fps是大多数监视器的极限,因此尝试超过这个极限是没有意义的。但是,通过在投射物上使用尾随跟踪器效果,可以创建更流畅的运动错觉。这将涉及到在每个发射物后面创建2或3个额外的正方形
var Player = (function () {
    // ------------------------------------------------------------------------------------------------
    // PLAYER VARIABLES
    // ------------------------------------------------------------------------------------------------
    var w = 50;
    var h = 50;
    var x = 0;
    var y = 0;
    var projectiles = [];

    // ------------------------------------------------------------------------------------------------
    // BIND EVENTS TO THE GLOBAL CANVAS
    // ------------------------------------------------------------------------------------------------
    Canvas.bindEvent('mousemove', function (e) {
        y = (e.pageY - Canvas.element.getBoundingClientRect().top) - (h / 2);
    });

    Canvas.bindEvent('click', function () {
        createProjectile(50, (y + (h / 2)) - 10);
    });

    // ------------------------------------------------------------------------------------------------
    // FUNCTIONS
    // ------------------------------------------------------------------------------------------------
    var createProjectile = function (x, y) {
        projectiles.push({
            x: x,
            y: y
        })
    };

    var update = function () {
        for (var p = projectiles.length - 1; p >= 0; p--) {
            projectiles[p].x += 10;

            if (projectiles[p].x > Canvas.element.width)projectiles.splice(p, 1);
        }
    };

    var render = function () {
        Canvas.context.fillStyle = 'white';
        Canvas.context.fillRect(x, y, w, h);

        for (var p = 0; p < projectiles.length; p++) {
            Canvas.context.fillStyle = 'red';
            Canvas.context.fillRect(projectiles[p].x, projectiles[p].y, 5, 5);
        }
    };

    // ------------------------------------------------------------------------------------------------
    // Exposed Variables and Functions
    // ------------------------------------------------------------------------------------------------
    return {
        update: update,
        render: render
    }
})();