【问题标题】:Canvas drawing for my web application我的 Web 应用程序的画布绘图
【发布时间】:2016-06-14 00:38:21
【问题描述】:

我刚开始在我的网页游戏项目中使用 Canvas,遇到了一个问题。

我正在使用这段代码来渲染游戏:

function render(f){
if(charoffset.x == null) charoffset.x = charpos.x*tilescale;
if(charoffset.y == null) charoffset.y = charpos.y*tilescale;

if(!tiles) tiles = [];
if(f){
    log("Welcome.","gold");
    
}
var canPassthrough = function (){
    if ((def.passable(this.type))&&(typeof this.type !== 'undefined')){
        return true;
    }
    else {
        return false;
    }
};
if(!f) lighting.update();
canvas.getContext("2d").clearRect(0,0,sq,sq);
for (var i = 0; i < map[charlvl].length; i++){
    if(!tiles[i]) tiles[i] = [];
    for (var j = 0; j < map[charlvl][i].length; j++){
        if(!tiles[i][j]) tiles[i][j] = placetile(i,j);
        drawtile(tiles[i][j]);
        placeitem(i,j);
    }
}
ui.overlay.text("casting shadows...");
//shadowcaster(20);
    var tex = document.createElement("img");
    tex.src = "../img/charplaceholder.png";
    var hero = canvas.getContext("2d");
    hero.globalAlpha = 1.0;
    if(charoffset.x>=map_scroll.x&&charoffset.y*tilescale>=map_scroll.y){
        var pos = {
            x: charoffset.x - map_scroll.x - tilescale,
            y: charoffset.y - map_scroll.y - tilescale
        };
        hero.drawImage(tex,pos.x,pos.y,tilescale,tilescale);
    }
function placetile(x,y){
    var obj = {};
    obj.type = map[charlvl][x][y].id;
    obj.canPassthrough = canPassthrough;
    obj.state = {explored: false, lit: false};
    obj.coords = {x:x,y:y};
    obj.offset = {x:x*tilescale,y:y*tilescale};
    return obj;
}
function drawtile(t){
    if(t.offset.x>=map_scroll.x&&t.offset.y>=map_scroll.y){
        var pos = {
            x: t.offset.x - map_scroll.x - tilescale,
            y: t.offset.y - map_scroll.y - tilescale
        };
        if(!t.state.explored&&!t.state.lit){
            return false;
        }
        else if(t.state.lit&&t.state.explored){
            
            var tex = document.createElement("img");
            var tile = canvas.getContext("2d");
            tex.src = def.css.tile(t.type);
            tile.globalAlpha = 1.0;
            tile.drawImage(tex,pos.x,pos.y,tilescale,tilescale);
            return true;
        }
        else if(t.state.explored&&!t.state.lit){
            var tex = document.createElement("img");
            var tile = canvas.getContext("2d");
            tex.src = def.css.tile(t.type);
            tile.globalAlpha = 0.25;
            tile.drawImage(tex,pos.x,pos.y,tilescale,tilescale);
            return true;
        }
    }
}
function placeitem(x,y){
    return;
    if (loot[charlvl][x][y]){
        for(var i=0;i<loot[charlvl][x][y].length;i++){
            var tile = document.createElement("div");
            var tileid = loot[charlvl][x][y][i].type;
            tile.className = def.css.item(tileid);
            tile.coords = {x:x,y:y};
            document.getElementById("x" + x + "y" + y).appendChild(tile);
        }
    }
}

if(f){
    camera.center(charpos.x,charpos.y);
    ui.overlay.text("loading the dungeon...");
    ui.overlay.hide();
}
}

函数render()由各种事件触发,例如角色移动、地图拖动、光照更新等。

这是结果:

我想在墙壁上添加嵌入阴影,以便更清晰地看到这些墙壁。我尝试使用画布上下文阴影进行试验,并使用了这个: 它应该在 100、100 处绘制一个透明矩形和一个阴影,大小为 20、20,但是这会将阴影应用于每个绘制的图块。

我觉得我画错了。任何人都可以解释如何有效地 使用canvas达到想要的效果?

【问题讨论】:

  • canvas 的行为就像一个状态机,每当你改变一个状态时,例如shadowBlur 它将应用于所有后续调用 fill / stroke / ....
  • @le_m 但我可以更改某些图块的 alpha 以指示已探索和点亮

标签: javascript html canvas


【解决方案1】:

不要使用 2D API 阴影选项,它们非常非常慢(这是对它们有多糟糕的轻描淡写)。您最好将阴影创建为 tile 集的一部分并使用 ctx.globalAlpha 设置为小于 1 和/或使用多种复合模式之一来渲染它们。例如ctx.globalCompositeOperation = "multiply";overlaycolor-burnhard-lightsoft-light。您甚至可以使用组合来获得非常好的阴影效果。

将阴影创建为图块集的一部分会产生更逼真的效果,因为阴影 API 仅适用于从漂浮在平面上方的平面对象投射的阴影,而不适用于从屏幕突出且可能具有倾斜侧面的 3D 对象在 z 方向上。

如果您不希望将阴影创建为瓦片集的一部分,请考虑通过阴影 API 选项使用屏幕外画布在加载时创建阴影瓦片集。然后使用 alpha 和复合选项从它渲染到画布

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-20
    • 1970-01-01
    • 2014-04-23
    • 1970-01-01
    • 2015-04-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多