【问题标题】:Canvas Context.drawImage() is leaving behind duplicates of Sprite on UpdatePosition()Canvas Context.drawImage() 在 UpdatePosition() 上留下 Sprite 的副本
【发布时间】:2019-09-27 05:36:58
【问题描述】:

我一直在用 HTML 的 Canvas 元素试验一个基本的游戏循环。许多在线教程都没有详细介绍渲染和 canvas.ctx(上下文)的概念。

我正在尝试做的事情非常简单:在画布元素上渲染图像,然后在 keydown 时更新其位置并将其渲染到新位置,使其在屏幕上移动。 基本上,每个视频游戏都用它的 sprite 做什么。

通过这些教程告诉我ctx.drawImage(image, x, y, ...) 可以解决这个问题。然而,在我的版本中最终发生的事情本质上是当你在 Windows 上赢得纸牌游戏时发生的事情。 每次游戏循环时它都会重复精灵的图像,就好像它正在创建一个全新的精灵一样。精灵本身并没有移动,似乎在左/右/等处生成了一个新的精灵原来的。我知道我每次迭代游戏循环时都会调用ctx.drawImage(...)。但是,当我使用ctx.clearRect(...) 时,这并没有发生。它完全按照我的预期工作。我不完全确定为什么用 ctx 创建矩形而创建图像却不行。

我的问题是:有没有一种方法可以简单地更新精灵的位置,而无需在每个循环中创建一个全新的版本?

这是我的相关代码:

let lastRender = 0; // For the general loop

let image = new Image();
image.src = "/img/image.png";

let state = {
    pressedKeys: {
        // left, right, up, down: false
    },

    position: {
        x: canvas.width / 2,
        y: canvas.width / 2
    },

    speed: 20
}

let pepsi = new Sprite({
    img: image,
    width: 100,
    height: 100
)};


function Sprite (options) {
    this.img = options.img;
    this.width = options.width;
    this.height = options.height;

    this.render = function(){
        ctx.drawImage(
        this.img,
        state.position.x,
        state.position.y
        )
    }
}

function updatePosition(progress) {
        //pressedKeys is just an object that relates WASD to the key codes 
        //     and their respective directions, it's ignorable

        if (state.pressedKeys.left) {
            state.position.x -= state.speed;
        }

        if (state.pressedKeys.right) {
            state.position.x += state.speed;
        }

        if (state.pressedKeys.up) {
            state.position.y -= state.speed;
        }

        if (state.pressedKeys.down) {
            state.position.y += state.speed;
        }
}


function draw() {
    pepsi.render();
}

function loop(timestamp) {
    let progress = timestamp - lastRender;

    update(progress) // <-- Updates position, doesn't touch draw()

    draw(); // <-- Runs pepsi.render(); each loop

    lastRender = timestamp;             
    window.requestAnimationFrame(loop); 
}

window.requestAnimationFrame(loop); // for the general loop 

如果您对这个项目的设置方式有任何疑虑(例如,使用 each Sprite 的 state.position),那么除了解决我的问题。不是孤立的。我从无上下文、非特定的在线教程中获得了大部分代码,但我理解了大部分代码,除了渲染。

另外,如果您以前见过这类问题,并且对说“可能重复 {Borderline Tangentially-Related Post from Four Years A}”,那么这里有一些建议: 再次回答问题。它实际上对你没有任何负面影响。

【问题讨论】:

    标签: javascript loops rendering sprite


    【解决方案1】:

    您获得的纸牌拖尾效果来自于每一帧都被绘制在最后一帧的顶部这一事实。画布不会在帧之间自动清除。

    你提到你使用过clearRect,clearRect的使用是清除指定矩形内的所有像素。

    因此,如果您将ctx.clearRect(0, 0, canvas.width, canvas.height) 放在pepsi.render() 之前的绘图函数中,则应该在绘制下一帧之前清除画布。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多