Javascript画布绘图 - 像素化时很多运动

时间:2015-12-14 14:38:20

标签: javascript html canvas drawing

所以我还在使用HTML Canvas和Javascript编写一个弹跳框演示。到目前为止,逻辑正在按预期工作(好消息!) - 然而,当画布上有大量移动时,事情开始变得......像素化。这是演示我的意思https://jsfiddle.net/hL8epzk3/2/

的小提琴

盒子数量目前为50(问题很明显)。将数字降低到20并且看起来都很好!

(小提琴中的第67行,var box = 20)

如果这是相关的,请在 Google Chrome

中进行测试

我的代码

<!-- GAME WINDOW -->
<canvas id="canvas" width="800" height="600"></canvas>

<div id="menu">
    <button onclick="addBox();">Add Box</button>
</div>

的Javascript

var Box = function(dimensions, color, x, y){
    this.width = dimensions;
    this.height = dimensions;
    this.x = x;
    this.y = y;
    this.velocityX = 10;
    this.velocityY = 10;
    this.color = color;
    this.context = document.getElementById('canvas').getContext('2d');
    this.possibleColors = ['#1abc9c', '#2ecc71', '#3498db', '#9b59b6', '#34495e', '#e67e22', '#c0392b', '#7f8c8d'];

    var that = this;

    this.update = function(){
        this.x += this.velocityX;
        this.y += this.velocityY;
        this.collisionCheck();
    };
    this.render = function(){
        this.context.fillStyle = this.color;
        this.context.fillRect(this.x, this.y, this.width, this.height);
    };
    this.collisionCheck = function(){
        if(this.y > 600 - this.height || this.y < 0){
            this.velocityY *= -1;
            this.generateColor();
        }
        if(this.x > 800 - this.width || this.x < 0){
            this.velocityX *= -1;
            this.generateColor();
        }
    };
    this.generateColor = function(){
        this.color = this.possibleColors[Math.floor((Math.random() * 10) - 1)];
    };

    function addBox(){
        console.log('box added');
    }

    window.renderLayer.addObject(this);
};

var RenderLayer = function(){
    this.objects = [];

    this.addObject = function(obj){
        this.objects[this.objects.length] = obj;
        console.log(this.objects[this.objects.length - 1]);
    };

    this.updateObjects = function(){
        for(var x = 0; x < this.objects.length; x++)
            this.objects[x].update();
    };

    this.renderObjects = function(){
        for(var x = 0; x < this.objects.length; x++)
            this.objects[x].render();
    };
};

function init(){
    window.renderLayer = new RenderLayer();

    window.box = [];
    var boxes = 20;

    for(var x = 0; x < boxes; x++){
        window.box[x] = new Box(50, 'red', Math.floor((Math.random() * 750) + 1),  Math.floor((Math.random() * 550) + 1));
    }

    requestAnimationFrame(update);
}

function update() {
    document.getElementById('canvas').width = document.getElementById('canvas').width;

    window.renderLayer.updateObjects();

    requestAnimationFrame(update);
    requestAnimationFrame(render);
}

function render() {
    window.renderLayer.renderObjects();
}

function addBox(){
    window.box[window.box.length] = new Box(50, 'red', Math.floor((Math.random() * 750) + 1),  Math.floor((Math.random() * 550) + 1));
}

这是出于性能原因吗?有什么办法可以预防吗?当盒子重叠时似乎会发生这种情况,但很难分辨出那么多盒子。

1 个答案:

答案 0 :(得分:1)

没有发生像素化,如果添加暂停按钮,可以看到这一点,或者通过将画布复制到另一个并查看它来捕捉画布的副本。或绘制圆圈而不是框。它看起来像素化的原因是由于你在撞到墙壁时改变盒子的颜色会产生奇怪的效果。不改变颜色会减少视错觉。你的弹跳也是关闭的,每当它们撞到墙壁时盒子都被部分夹住,这也增加了幻觉。

最后,您有可能导致页面锁定,并最终通过在一帧上调用requestAnimationFrame两次的方式抛出调用堆栈溢出。负载较低时一切都很好,但随着负载的增加和帧时间超过帧时间的1/60,首先你将开始在不同的帧上进行更新和渲染,然后请求将开始累积在调用堆栈上,导致更奇怪的行为并最终导致调用堆栈溢出。

每帧只调用一次requestAnimationFrame以避免此问题。