Поворот одного изображения (но не других) на холсте html5? - PullRequest
4 голосов
/ 10 июля 2010

У меня есть спрайт, который я анимирую на холсте html с использованием обычного бликования листа спрайта.В некоторых ключевых событиях я хотел бы изменить направление спрайта (то есть перевернуть его или повернуть на 180 градусов), не меняя ничего (другие спрайты) на холсте.

Кто-нибудь знает, как это сделать?сделать это?

Ответы [ 4 ]

2 голосов
/ 13 ноября 2012

Так что у меня возникла эта проблема с моей игрой; У меня были ячейки для анимации вверх, вниз и влево, но нет правых ячеек. Поэтому мне нужно было перевернуть левые клетки, чтобы нарисовать правые клетки.

Для каждого спрайта я отслеживаю его текущую верхнюю и левую части холста, а также верхнюю и левую части каждой ячейки в листе спрайта.

Я видел предыдущие ответы, показывающие простое горизонтальное переворачивание как просто перевод источника и переворачивание (обратный масштаб) осей, НО это не учитывает, что при спрайтах, переворачивание источника будет испортить точку регистрации спрайта (вверху и слева на холсте).

Эта проблема проявлялась в правильном отражении спрайта, но его позиция была отклонена по ширине спрайта. Я решил это с учетом ширины спрайта. Обратите внимание, как я использую CanvasRenderingContext2D.prototype.drawImage с 9 аргументами, поскольку я нарезаю спрайт из листа спрайта:

// check if we need to flip image (special case for right movement)
if(sprite.translated){
  context.save();
  context.translate(context.canvas.width, 0);
  context.scale(-1, 1);
  context.drawImage(sprite.sheet,
    cell.left,
    cell.top,
    sprite.width,
    sprite.height,
    // secret sauce: change the destination's X registration point
    context.canvas.width - sprite.left - sprite.width,
    sprite.top,
    sprite.width, sprite.height);
  context.restore();
} else {
  // Assumes cells are all the same width and height, set in sprite
  context.drawImage(sprite.sheet, cell.left, cell.top, sprite.width,
  sprite.height, sprite.left, sprite.top, sprite.width, sprite.height);
}

Примечание: я также мог бы выполнить математику в переводе, так как она предназначена для упрощения вычислений в другом месте.

1 голос
/ 13 июля 2010

Хотя я ценю ответ Штефа, после небольшого исследования я обнаружил, что вращение холста, которое вы фактически используете для отображения, не кажется идеальным.Сохранение, вращение и восстановление при попытке создания сложных анимаций (иначе говоря, Street Fighter 2, а не астроиды) заставляет холст мерцать даже в Chrome.

Однако я нашел полезную стратегию.Идея заключается в том, что вы на самом деле создаете два холста, один из которых предназначен для вашей игры, а другой будет своего рода буфером, и он будет использоваться для поворота или масштабирования ваших спрайтов.Вы по существу трансформируете холст буферного буфера, рисуете изображение, которое хотите, а затем переносите его на свой основной холст и восстанавливаете (или нет) буфер.Таким образом, вы только вращаете скрытый холст и воздействуете только на спрайт, а не на всю игровую доску.

Код выглядит примерно так (работа в процессе):

mainContext.clearRect(lastXpos, lastYpos, lastWidth, lastHeight);
backContext.clearRect(0, 0, lastWidth, lastHeight);
lastXpos = xpos;
lastYpos = ypos;
lastWidth = width;
lastHeight = height;


backContext.save();

//check the direction of the sprite
//turn the backContext to this direction   
//SPRITE_INVERTED==-1
if (spriteXDirection == SPRITE_INVERTED || spriteYDirection == SPRITE_INVERTED) 
{
    var horScale = 0;
    var verScale = 0;

    if (spriteXDirection == SPRITE_INVERTED)
    {
    horScale = width;
    }

    if (spriteYDirection == SPRITE_INVERTED)
    {
    verScale = height;
    }


    backContext.translate(horScale, verScale);
    backContext.scale(spriteXDirection, spriteYDirection);


}


//draw the sprite not we always use 0,0 for top/left
backContext.drawImage(animations[currentPlay].sheet,
                animationX,
                animationY,
                width,
                height, 0, 0, width, height);

//Get the image data from the back context
var image = backContext.getImageData(0, 0, width, height);


//flip the back context back to center - or not, I haven't decided how to optimize this yet.
backContext.restore();


//transfer the image to your main context
mainContext.putImageData(image, xpos, ypos);

Это избавило меня от многих головных болей в понимании того, как переводить мои спрайты без перемещения всего на моей игровой доске повсюду.Похоже, что он работает лучше, чем изменение основного контекста.

1 голос
/ 11 июля 2010

Просто перерисовать спрайт с преобразованием rotate. Преобразования в контексте HTML Canvas 2D

Canvas - это просто буфер за пределами экрана. Он не будет очищен, если вы не скажете это, и ничего не изменится, если вы не скажете это.

Существует множество различных ситуаций, в которых вам, возможно, придется перерисовать область или вокруг спрайта. В противном случае вы получите побочный эффект, когда часть старого спрайта все еще видна под новым рисунком, или другие рисунки затеняются. Вот некоторые причины:

  • Ваш спрайт частично прозрачен,
  • Ваш спрайт частично полупрозрачный,
  • Другие рисунки сделаны поверх вашего спрайта,
  • Ваш спрайт не прямоугольный,
  • Вы делаете сальто, не кратное 90 градусам.

Так что это может быть немного больше работы, и есть несколько разных подходов к этому. Вы можете просто перерисовать всю сцену или только определенные объекты в этом месте, возможно, используя метод clip.

Совершенно другим направлением может быть использование других элементов HTML, img или div, с абсолютным позиционированием и преобразованиями CSS3. По сути, это небольшая хитрость, чтобы делегировать рендеринг вашей сцены браузеру.

0 голосов
/ 13 октября 2017

Почему бы вам не использовать save () и восстановить

ctx.save(); // save current state
ctx.rotate(Math.PI); // rotate
ctx.drawImage(link,x,y,20,20); // draws a chain link or dagger
ctx.restore(); // restore original states (no rotation etc)

Как повернуть одно изображение на холсте?

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