2012-02-17 91 views
2

我在将画布从缓冲区画布复制到页面上的画布时遇到了一些困难。到目前为止,我已经构建了一个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页面中使用script标签加载。

如前所述,drawToCanvas()函数似乎没有成功将数据从一个画布复制到另一个画布。追加我的源画布确认它包含预期的数据。

编辑:我在下面列出了我的关卡代码。

function Level(mapname) { 
    var map=new Image(); 
    map.src=mapname; 

    this.Draw = function(renderer) { 
     map.onload = function() { renderer.drawImage(map,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,是不是平局功能在所有...让我解开它你:

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游戏编程有点棘手,因为您必须抛出“加载...”微调器,并在加载所有“资源”之前不要进入渲染循环。在所有的实践中,你都需要“准备就绪”的概念。 Load(fOnReady)Draw(ctx),而不是仅仅asyncDraw(ctx, fOnReady) ...

更新jsbin是在这里:http://jsbin.com/upatij/2/edit

希望这有助于-ck

+0

感谢您的反馈。如果您有兴趣,我已将我的关卡代码附加到原始文件。在那里没有什么特别的事情发生......到目前为止,它只是向提供的画布上下文(渲染器)绘制单个图像。 FWIW我在我的HTML页面中的body.onload函数中调用了函数launch()中的绘图代码(创建上下文,渲染器,级别等)。 – RavB 2012-02-17 21:17:15