我在将缓冲区画布上的画布复制到页面上的画布时遇到了一些困难。到目前为止,我已经构建了一个Render对象,一个Level对象,我有我的主游戏循环(目前只是一个启动函数)。
我能够很好地写入Render对象中的缓冲画布(如果我添加了一个document.body.append()语句,画布成功附加到具有必要内容的文档)但我无法从缓冲区复制帆布到我的主画布。请参阅下面的代码片段:
function Renderer(bufferWidth, bufferHeight) {
var c=document.createElement('canvas');
var ctx=c.getContext('2d');
c.width=bufferWidth;
c.height=bufferHeight;
this.getBufferContext = function() { return ctx; };
this.getBufferElement = function() { return c; };
this.drawToCanvas = function(canvasCtx) {
canvasCtx.drawImage(c,0,0);
};
}
var c = document.getElementById('mycanvas');
var ctx = c.getContext('2d');
var render = new Renderer(c.width, c.height);
var level1 = new Level('images/imagequality.png');
level1.Draw(render.getBufferContext());
render.drawToCanvas(ctx);
请注意,渲染器位于单独的文件中,并使用HTML页面中的脚本标记加载。
如前所述,drawToCanvas()函数似乎无法将数据从一个画布成功复制到另一个画布。附加我的源画布确认它包含预期的数据。
编辑:我在下面列出了我的关卡代码。
function Level(mapname) {
var map=new Image();
map.src=mapname;
this.Draw = function(renderer) {
map.onload = function() { renderer.drawImage(map,0,0); };
};
}
答案 0 :(得分:3)
我有个好消息,我有坏消息。
好消息是你在这里展示的代码100%有效 这是演示:http://jsbin.com/upatij/edit#javascript,html,live
坏消息:这意味着您的级别代码中的某些内容被破坏,因为我的存根级别代码在您的框架中完美运行... :-(
存根级别:
function Level() {
this.Draw = function(xxctx) {
for (var i = 0; i < 30; i++) {
xxctx.moveTo(10 + (i * 40 % 300), 10 + (parseInt(i / 6, 10) * 40));
xxctx.lineTo(40 + (i * 40 % 300), 40 + (parseInt(i / 6, 10) * 40));
xxctx.moveTo(40 + (i * 40 % 300), 10 + (parseInt(i / 6, 10) * 40));
xxctx.lineTo(10 + (i * 40 % 300), 40 + (parseInt(i / 6, 10) * 40));
}
xxctx.stroke();
};
}
祝你好运! -ck 强>
在您查看您的级别代码之后:
问题是同步性问题,你在这里使用类是通过欺骗性命名隐藏你的问题,因为你的Level.Draw根本不是一个绘图函数...让我为你解开它: / p>
var c = document.getElementById('mycanvas');
var ctx = c.getContext('2d');
// var render = new Renderer(c.width, c.height);
var Renderer_c = document.createElement('canvas');
var Renderer_ctx = Renderer_c.getContext('2d');
document.body.appendChild(Renderer_c); //added to show
Renderer_c.width = c.width;
Renderer_c.height = c.height;
// var level1 = new Level('images/imagequality.png');
var map = new Image();
document.body.appendChild(map); //add to show
map.src = 'http://th06.deviantart.net/fs71/150/i/2011/255/9/5/omnom_upside_down_by_earnurm-d49pjnl.png';
console.log('at ' + 1);
// level1.Draw(render.getBufferContext());
map.onload = function() {
console.log('at ' + 3);
//this happens async:
alert('drawing now!');
Renderer_ctx.drawImage(map,0,0);
};
console.log('at ' + 2);
// render.drawToCanvas(ctx);
ctx.drawImage(Renderer_c, 0, 0);
如果您运行该代码,您将看到在调用onload
其他所有内容已执行的那一刻,您将注意到控制台将如何读取:
at 1
at 2
at 3
因此,在alert('drawing now!');
被执行的那一刻......
// render.drawToCanvas(ctx);
ctx.drawImage(Renderer_c, 0, 0);
已经运行了......基本上你的Draw()
函数实际上是一个异步的“加载”。不幸的是,你目前的概念化是行不通的。你的Draw()
函数需要像这样异步:
function Level(mapname) {
var map=new Image();
document.body.appendChild(map); //add to show
map.src=mapname;
this.asyncDraw = function(renderer, onComplete) {
map.onload = function() {
renderer.drawImage(map,0,0);
onComplete();
};
};
}
然后在您的示例中应该像这样调用该函数:
level1.asyncDraw(render.getBufferContext(), function() {
render.drawToCanvas(ctx);
});
我应该继续说这种类型的异步性使得HTML5游戏编程有点棘手,因为你真的不得不抛弃“Loading ...”微调器并且不要进入渲染循环直到所有“资源”装了。在所有实用性中,您需要“准备好”的概念,例如。 Load(fOnReady)
和Draw(ctx)
而非asyncDraw(ctx, fOnReady)
...
更新的jsbin在这里:http://jsbin.com/upatij/2/edit
希望这有助于确认