【问题标题】:Sampling images from other images and storing them javascript从其他图像中采样图像并将它们存储在javascript中
【发布时间】:2021-09-11 08:09:06
【问题描述】:

我制作了一个 javascript tilemap 渲染器,为了渲染单个图块,它从特定偏移量获取 tileatlas 的内容:

ctx.drawImage(this.tileAtlas, tileXIndex, tileYIndex, 16, 16, x, y, this.singleTileSize, this.singleTileSize);

其中 tileIndexX 和 Y 是预先计算的偏移量,但我认为这会减慢我的程序速度,所以我的问题是:是否可以在启动时执行此操作,所以当我将 tileAtlas 初始化为图像时,存储单个瓷砖作为单独的图像?喜欢这个伪代码:

    function onStartup(){
        tileSprites = [];
        for(let i = 0; i < amountOfTiles){
            // calculate offsets based off of i

            tileSprites.push(tileAtlas.getImageAtOffset(offsetX, offsetY))
        }
        return tileSprites;
    }

或者有什么我缺少的更有效的东西吗?它会减慢我的代码速度吗?

编辑,如果有帮助,这里是完整的渲染代码:

function Layer(w, h){
    let t = {};
    t.can = document.createElement("canvas");
    t.ctx = t.can.getContext("2d");
    t.can.width = w;
    t.can.height = h;
    return t;
}

class Renderer extends MapHandler{
    _tileAtlas;
    _layers;

    singleTileSize;

    width;
    height;

    constructor(){
        super();

        this.width = innerWidth;
        this.height = innerHeight;

        this.tileAtlas = new Image();
        this.tileAtlas.src = "src/assets/tileatlas.png";

        this.singleTileSize = 16;

        this._layers = [];

        let t = {};
        t.can = document.getElementById("GameScreen");
        t.ctx = t.can.getContext("2d");
        this._layers.push(t);

        // Map layer
        this._layers.push(new Layer(this.width, this.height));

        // Still unused entity sprite layer
        this._layers.push(new Layer(this.width, this.height));

        this.resetSize();
    }

    drawTile(ctx, val, x, y){
        let tileXIndex = (val % 112) * 16;
        let tileYIndex = Math.floor(val / 112);
    
        ctx.drawImage(this.tileAtlas, tileXIndex, tileYIndex, 16, 16, x, y, this.singleTileSize, this.singleTileSize);
    }

    resetSize(){
        let w = innerWidth;
        let h = innerHeight;
        for(let i in this._layers){
            this._layers[i].can.height = h;
            this._layers[i].can.width = w;
        }
    }

    renderMap(ctx, map, offsetX, offsetY){
        ctx.imageSmoothingEnabled = false;
    
        if(typeof(map)!="object"){console.log("Error rendering map: typeof map isn't 'object'");return;}
    
        for(let y = 0, a = map.length; y < a; y++){
    
            let mapY = Math.round(y * this.singleTileSize + offsetY * this.singleTileSize);
    
            if(mapY<-this.singleTileSize){continue};
            if(mapY>this.height){break};
    
            for(let x = 0, aa = map[y].length; x < aa; x++){
                let c = map[y][x];
    
                let mapX = Math.round(x * this.singleTileSize + offsetX * this.singleTileSize);
    
                if(mapX<-this.singleTileSize){continue};
                if(mapX>this.width){break};
    
                this.drawTile(ctx, c.val, mapX, mapY);
            }
        }
    }

    clear(){
        for(let i = 0; i < this._layers.length; i++){
            this._layers[i].ctx.clearRect(0, 0, this.width, this.height);
        }
    }
    
    renderToCanvas(){
        for(let i = this._layers.length-2; i >= 0; i--){
            this._layers[i].ctx.drawImage(this._layers[i+1].can, 0, 0);
        }
    }

    getRenderingContext(layer){
        return this._layers[layer].ctx;
    }
}

extends MapHandler 部分仅提供当前地图和可用地图列表。此外,赋予 renderMap() 函数的地图是一个二维数组,其中填充了“平铺”对象,代码如下:

function Tile(val){
    this.val=val;
}

我认为没那么重要,但实际上里面有对象而不只是图块的单个值这一事实可能很重要,我真的不知道。

再次编辑

我找到了另一种主要加快速度的方法,我突然觉得每帧重绘所有内容是一个非常糟糕的主意,所以我在启动时(在屏幕外画布上)绘制了一张巨大的地图,然后将其渲染到每次都在屏幕上,而不是在所有不同的块中循环。所以,是的,找到答案了哈哈。

【问题讨论】:

    标签: javascript rendering


    【解决方案1】:

    我找到了解决办法,你可以在上下文中使用 getImageData() 函数从特定的 x 和 y 获取图像数据,如下所示:

    let data = ctx.getImageData(100, 100, 20, 20)
    

    这将为您提供 100、100、20x20 分辨率的画布内容。然后,您可以使用 putImageData() 将其绘制到其他地方,如下所示:

    ctx.putImageData(data, 500, 500)
    

    这会将所述数据放在画布上的 500、500 处。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-02
      相关资源
      最近更新 更多