我刚刚开始在我的网页游戏项目中使用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来达到预期的效果?
答案 0 :(得分:3)
不要使用2D API阴影选项,它们非常慢(并且这是对它们有多糟糕的轻描淡写)。最好将阴影创建为图块集的一部分,并将ctx.globalAlpha
设置为小于1并使用多种复合模式中的一种进行渲染。例如ctx.globalCompositeOperation = "multiply";
或overlay
,color-burn
,hard-light
和soft-light
。您甚至可以使用组合来获得非常好的阴影效果。
将阴影作为图块集的一部分创建将提供更逼真的效果,因为阴影API仅适用于从平面上方浮动的平面对象投射的阴影,而不适用于从屏幕突出的可能具有倾斜边的3D对象在z方向。
如果您不希望将阴影作为图块集的一部分创建,请考虑使用屏幕外观画布通过阴影API选项在onload上创建阴影图块集。然后使用alpha和复合选项从那里渲染到画布