Как скопировать содержимое со скрытого холста на видимый холст? - PullRequest
2 голосов
/ 17 февраля 2012

У меня возникли некоторые трудности при копировании холста из моего буферного холста на холст на моей странице.До сих пор я построил объект 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);

Обратите внимание, что Renderer находится в отдельном файле и загружается с использованием тегов script на моей HTML-странице.

Как упоминалось ранее, функция drawToCanvas () не может успешно копировать данные с одного холста на другой.Добавление моего исходного холста подтверждает, что оно содержит ожидаемые данные.

edit: я перечислил мой код уровня ниже.

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

    this.Draw = function(renderer) {
        map.onload = function() { renderer.drawImage(map,0,0); };
    };
}

1 Ответ

4 голосов
/ 18 февраля 2012

У меня есть хорошие новости, и у меня есть плохие новости.

Хорошие новости: код, который вы здесь показывает, работает на 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() функция фактически является асинхронной"Load".К сожалению, ваша текущая концепция не работает.Ваша 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...