【问题标题】:KonvaJS / HTML5 canvas infinite looping tilemap. Setting camera positionkonvajs / html5 canvas无限循环tilemap。设置相机位置
【发布时间】:2019-05-07 00:03:34
【问题描述】:

我正在尝试创建一个基于主“网格”的无限循环画布。在这里用视口中心的网格按比例缩小小提琴。

JS Fiddle here

在小提琴中,我的中心有彩色方块的主网格,我希望它们在各个方向上无限平铺。显然这在现实中是不可能的,所以我想通过根据滚动方向重新绘制网格来给出无限的错觉。

我发现了一些不错的文章: https://developer.mozilla.org/en-US/docs/Games/Techniques/Tilemaps/Square_tilemaps_implementation:_Scrolling_maps

https://gamedev.stackexchange.com/questions/71583/html5-dynamic-canvas-grid-for-scrolling-a-big-map

最好的方法似乎是获取拖动方向,然后将相机重置到该点,因此图层在主画布视口下滚动,这意味着相机永远无法到达主视口画布的边缘。

我一直致力于为鼠标拖动添加一些事件侦听器:

Fiddle with mouse events

 var bMouseDown = false;
    var oPreviousCoords = {
        'x': 0,
        'y': 0
    }
    var oDelta;
    var oEndCoords;
    var newLayerTop;


    $(document).on('mousedown', function (oEvent) {
        bMouseDown = true;
        oPreviousCoords = {
            'x': oEvent.pageX,
            'y': oEvent.pageY
        }
    });

    $(document).on('mouseup', function (oEvent) {
        bMouseDown = false;

        oPreviousCoords = {
            'x': oEvent.pageX,
            'y': oEvent.pageY
        }


        oEndCoords = oDelta


        if(oEndCoords.y < -300){


            if(newLayerTop){
                newLayerTop.destroy();
            }

            layerCurentPosition = layer.position();

            newLayerTop = layer.clone();
            newLayerTop.position({
                x:  layerCurentPosition.x,
                y:  layerCurentPosition.y -1960
            });


            stage.add(newLayerTop)

            stage.batchDraw();



        }

    });

    $(document).on('mousemove', function (oEvent) {


        if (!bMouseDown) {
            return;
        }

        oDelta = {
            'x': oPreviousCoords.x - oEvent.pageX,
            'y': oPreviousCoords.y - oEvent.pageY
        }


    });

但我无法可靠地计算出每个方向的坐标以及如何重置相机位置。

【问题讨论】:

  • 关于初始 JS Findle 的一些警告:第 1 行中的 last_position 从未使用过;第 24、37、43、187 行缺少分号;第 47 行中不必要的分号。
  • 这两个小提琴都不适合我。两者都只显示空白页。控制台显示类似Konva warning: Can not change width of layer 的警告。
  • 这两个小提琴都不适合我。我只看到一个空白页。
  • 小提琴也不适合我。我只看到一个空白页。
  • 这个小提琴:jsfiddle.net/kiksy/dvn2wyh5/25 正在工作,但是您可能需要滚动才能看到方块。

标签: javascript html canvas konvajs


【解决方案1】:

由于您需要“无限”画布,因此我建议不要使用滚动,并使画布与用户视口一样大。然后您可以模拟相机,并且每次移动时,您都需要在画布上绘制一个新网格。您只需要仔细计算网格的位置即可。

const stage = new Konva.Stage({
  container: 'container',
  width: window.innerWidth,
  height: window.innerHeight,
  draggable: true
});

const layer = new Konva.Layer();
stage.add(layer);


const WIDTH = 100;
const HEIGHT = 100;

const grid = [
  ['red', 'yellow'],
  ['green', 'blue']
];

function checkShapes() {
  const startX = Math.floor((-stage.x() - stage.width()) / WIDTH) * WIDTH;
  const endX = Math.floor((-stage.x() + stage.width() * 2) / WIDTH) * WIDTH;
  
  const startY = Math.floor((-stage.y() - stage.height()) / HEIGHT) * HEIGHT;
  const endY = Math.floor((-stage.y() + stage.height() * 2) / HEIGHT) * HEIGHT;
 
  
  for(var x = startX; x < endX; x += WIDTH) {
    for(var y = startY; y < endY; y += HEIGHT) {
      const indexX = Math.abs(x / WIDTH) % grid.length;
      const indexY = Math.abs(y / HEIGHT) % grid[0].length;
      layer.add(new Konva.Rect({
        x,
        y,
        width: WIDTH,
        height: HEIGHT,
        fill: grid[indexX][indexY]
      }))
    }
  }
}


checkShapes();
layer.draw();

stage.on('dragend', () => {
  layer.destroyChildren();
  checkShapes();
  layer.draw();
})
  <script src="https://unpkg.com/konva@^2/konva.min.js"></script>
  <div id="container"></div>

如果您需要滚动,您可以在舞台上收听wheel 事件并朝所需方向移动。

【讨论】:

  • 谢谢,但这不是无限的。期望的结果是方块会不断循环,使其无法到达边缘、顶部底部、左侧或右侧。
  • 这里解释了一点逻辑,gamedev.stackexchange.com/questions/71583/… 但我正在寻找一个无限循环的瓦片地图。
  • 抱歉,刚刚发现可行!我在滚动而不是拖动。
  • 很好,它有帮助。您可以手动添加滚动。收听wheel 事件并在其中更改舞台的位置。
  • 这个我还在扯头发。试图让文本留在正确的位置。这是我的意思的一个简化的小提琴:jsfiddle.net/kiksy/jqo2h3dx/2 文本不会留在框中,我真的不明白为什么 X Y 与重绘时的矩形相同?
猜你喜欢
  • 2019-05-04
  • 2013-08-09
  • 2012-02-28
  • 2014-03-20
  • 2020-11-24
  • 1970-01-01
  • 1970-01-01
  • 2018-05-16
  • 1970-01-01
相关资源
最近更新 更多