清除矩形方法clearRect无效

11

我正在用JavaScript制作一个乒乓球游戏,以此来学习制作游戏,并且我想将其面向对象化。

我无法让clearRect正常工作。它所做的只是画一条越来越长的线。以下是相关代码:

function Ball(){
    this.radius = 5;
    this.Y = 20;
    this.X = 25;
    this.draw = function() {
        ctx.arc(this.X, this.Y, this.radius, 0, Math.PI*2, true);
        ctx.fillStyle = '#00ff00';
        ctx.fill();
    };
}

var ball = new Ball();

function draw(){
    player.draw();
    ball.draw();
}

function update(){
    ctx.clearRect(0, 0, 800, 400);
    draw();
    ball.X++;
}
我已经尝试将ctx.clearRect部分放入draw()ball.draw()函数中,但它不起作用。 我还尝试使用白色的fillRect,但结果相同。 我该怎么解决?

3
你能否在 jsFiddle 上设置它,以帮助解释“画一条越来越长的线”? - alex
我之前尝试过,但没能在那里使其工作,我会再试一次。 - justanotherhobbyist
我不知道如何使用JSFiddle,JavaScript的部分似乎没有被包括进去。我还是把代码保存在那里了,也许你可以使它正常工作:http://jsfiddle.net/hustlerinc/25qWe/ - justanotherhobbyist
2个回答

30
你真正的问题是没有关闭圆形路径。
在绘制圆形之前添加ctx.beginPath()。 jsFiddle
另外,一些提示...
  • 您的资产不应该负责自己的绘制(它们的draw()方法)。相反,也许定义它们的视觉属性(它是一个圆形?半径?),并让您的主要渲染函数处理canvas特定的绘制(这也有一个优点,即您可以轻松地将渲染器切换到常规DOM元素或WebGL)。
  • 请使用requestAnimationFrame()而不是setInterval()。目前支持不太好,因此您可能需要使用setInterval()或递归的setTimeout()模式来模拟其功能。
  • 您的clearRect()应传递canvas元素的尺寸(或在其他地方定义它们)。在您的渲染函数中包含它们类似于“魔数”,可能会导致后续维护问题。

@alex,关于第一个提示,你怎么做到的?使用类似开关结构的渲染器来检测对象类型,然后使用它们的属性进行渲染吗? - jonathancardoso
@JCM 这是一种做法。有时我喜欢在我的游戏对象上放置一个 getDrawDescriptor(),告诉渲染器如何绘制元素,但从不使用直接的 Canvas API 调用。 - alex
@alex 嗯,有趣。谢谢。 - jonathancardoso
@alex,非常感谢!viewport.width = viewport.width;太强大了! - Hank
糟糕的答案。原因在于:“将画布宽度设置为自身不仅会清除画布,还会清除所有画布状态。这意味着它会清除转换矩阵、当前剪切区域以及以下所有属性:strokeStyle、fillStyle、globalAlpha、lineWidth、lineCap、lineJoin、miterLimit、shadowOffsetX、shadowOffsetY、shadowBlur、shadowColor、globalCompositeOperation、font、textAlign和textBaseline。”来自http://simonsarris.com/blog/346-how-you-clear-your-canvas-matters在修复问题之前,请使用fillRect;否则,您可能会引入其他意外的错误。 - sws
显示剩余6条评论

0

window.onload = function() {

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


var cvsW = cvs.Width;
var cvsH = cvs.Height;

var snakeW = 10;
var snakeH = 10;



function drawSnake(x, y) {

    ctx.fillStyle = '#FFF';
    ctx.fillRect(x*snakeW, y * snakeH, snakeW, snakeH);


    ctx.fillStyle = '#000';
    ctx.strokeRect(x*snakeW, y * snakeH, snakeW, snakeH);
}


// drawSnake(4, 5)

//create our snake object, it will contain 4 cells in default

var len = 4;
var snake = [];

for(var i = len -1; i >=0; i--) {

    snake.push(
        {
            x: i,
            y: 0
        }
    )
};


function draw() {
    ctx.clearRect(0, 0, cvsW, cvsH)
    for(var i = 0; i < snake.length; i++) {
        var x = snake[i].x;
        var y = snake[i].y;

    
        drawSnake(x, y)
    }

    


//snake head

var snakeX = snake[0].x;
var snakeY = snake[0].y;

//remove to last entry (the snake Tail);

snake.pop();

// 创建一个新的头部,基于之前的头部和方向;

snakeX++;


let newHead = {

    x: snakeX,
    y: snakeY
}



snake.unshift(newHead)

}

setInterval(draw, 60);

}

我的clearRect不起作用,问题在哪里以及解决方案是什么?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接