如何旋转画布矩形数组

时间:2015-05-26 17:16:15

标签: javascript arrays canvas

我正在为我正在上课的最后一个项目创建一个Pentomino益智游戏。我创建了所有必需的拼图,并可以拖动here周围的拼图。我已经尝试过这段代码来旋转数组(不使用位于小提琴底部的canvas.rotate()&),它基本上交换了X&绘制新作品时的Y坐标:

var newPiece = targetPiece;
pieces.splice(pieces.indexOf(targetPiece), 1);
targetPiece = null;
console.log(newPiece);
var geometry = [];
for (var i = 0; i < newPiece.geometry.length; i++) {
    geometry.push([newPiece.geometry[i][3], newPiece.geometry[i][0]]);
}
var offset = [newPiece.offset[1], newPiece.offset[0]];
console.log(geometry);
console.log(offset);
newPiece.geometry = geometry;
newPiece.position = geometry;
newPiece.offset = offset;
pieces.push(newPiece);
console.log(pieces);
for (var j = 0; j < pieces.length; j++) {
    draw(pieces[j]);
}

这样做不正常,但有希望。

this fiddle中,我已将问题分解为单个部分并尝试使用canvas.rotate()通过双击旋转数组,但实际发生的是它正在旋转数组的每个部分(我认为),这不会导致任何事情发生,因为数组的每个块只是一个50x50的矩形,当你旋转一个正方形时,它看起来就像一个正方形。

function doubleClickListener(e) {
var br = canvas.getBoundingClientRect();
mouse_x = (e.clientX - br.left) * (canvas.width / br.width);
mouse_y = (e.clientY - br.top) * (canvas.height / br.height);
var pieceToggle = false;
for (var i = 0; i < pieces.length; i++) {
    if (onTarget(pieces[i], mouse_x, mouse_y)) {
        targetPiece = pieces[i];
        rotate(targetPiece);
    }
}
}

function rotate() {
targetPiece.rotationIndex = targetPiece.rotationIndex === 0 ?
1 : targetPiece.rotationIndex === 1 ?
2 : targetPiece.rotationIndex === 2 ?
3 : 0;
for (var j = 0; j < pieces.length; j++) {
    draw(pieces[j]);
}
}

仅供参考,我已经尝试将拼图作为单独的多边形创建,但无法弄清楚如何使用mousedown事件捕获它并使用mousemove移动它,所以我放弃了它用于相对简单的画布矩形数组抓住&amp;移动。

对此有一个强力解决方案,以及一个完全重写的解决方案,我宁愿避免这两种解决方案(我要反对截止日期)。蛮力解决方案是为所有可能的部件(旋转和镜像)创建几何图形,这需要63个单独的几何变体用于12个部件并管理这些状态。重写将是使用fabric.js(我可能会在课程结束后做,因为我想要一个功能齐全的拼图)。

我希望能够做的是通过双击旋转五个数组的数组(不管它连续90°旋转哪个方向)。

接近可用的谜题:

@absolom 的帮助下,这就是我所拥有的,你只需点击鼠标即可拖动。拖动,通过双击旋转一块,并通过右键单击镜像一块(好吧,大多数情况下,它实际上不会旋转,直到你下一步移动它,我正在努力)。这些碎片的Z顺序是被操纵的,这样你正在使用的碎片总是在顶部(它必须是阵列中最后一个出现在所有其他碎片之上):

Pentominoes II

最终解决方案

我刚刚将游戏递归评分,感谢所有的帮助!还有更多的调整需要完成,如果我重写它还有一些我会改变的东西,但我对结果非常满意。

Pentominoes Final

2 个答案:

答案 0 :(得分:2)

快速&amp;脏:

快速&amp;脏解决方案是当组装2件以上时,您可以创建它们的单个图像(使用内存中的画布)。这样,您就可以将2片作为1个图像作为单个实体移动/旋转。

更合适:

如果以后必须拆卸2件装配件,那么你需要更合适的方法来保持每件的转换状态。更恰当的方法是为每个部分分配一个变换矩阵。

Stackoverflow撰稿人Ken Fyrstenberg(K3N)编写了一个很好的脚本,允许您使用转换矩阵跟踪单个多边形(例如您的rects):https://github.com/epistemex/transformation-matrix-js

答案 1 :(得分:1)

code能做你需要的吗? rotate方法现在看起来像这样:

   function rotate(piece) {
       for (i = 0; i < piece.geometry.length; i++) {
           var x = piece.geometry[i][0];
           var y = piece.geometry[i][2];
           piece.geometry[i][0] = -y;
           piece.geometry[i][3] = x;
       }
       drawAll();
   }

我简化了几何和定位的处理方式。它并不完美,但它可以为您提供一些如何处理问题的提示。

请注意,此解决方案有效,因为每个部件都由具有相同颜色的块组成,并且您的旋转为90度。我只是移动块来模拟旋转,但没有任何东西旋转本身。如果你以不同的方式构建你的作品,或者你需要以不同的角度旋转,那么你需要采用另一种方法,如转换矩阵。

<强>更新

以下是更好的解决方案:fiddle