Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在任意方向连续滚动一个大型无缝图像_Java_Android_Image_Math - Fatal编程技术网

Java 在任意方向连续滚动一个大型无缝图像

Java 在任意方向连续滚动一个大型无缝图像,java,android,image,math,Java,Android,Image,Math,这个问题与游戏有关,但我认为它可以应用于其他用例 我有一个比屏幕大的无缝图像。大约两倍大。目标是使此图像可以在曲面上的任何方向滚动。这是Android的 我看到了一些关于一般图像的问题/答案,但不是无缝图像 这里的区别,我的问题是如何处理滚动,在某些情况下,显示的图像可能有4个独立的部分(当用户沿对角线滚动图像的一半时) 很明显,当您想将图像边到边滚动时,该如何操作。使用世界值,并使用矩形显示您所在位置的某种“视口” 比如: Rect oRect1 = new Rect(dWorldX, dWo

这个问题与游戏有关,但我认为它可以应用于其他用例

我有一个比屏幕大的无缝图像。大约两倍大。目标是使此图像可以在曲面上的任何方向滚动。这是Android的

我看到了一些关于一般图像的问题/答案,但不是无缝图像

这里的区别,我的问题是如何处理滚动,在某些情况下,显示的图像可能有4个独立的部分(当用户沿对角线滚动图像的一半时)

很明显,当您想将图像边到边滚动时,该如何操作。使用世界值,并使用矩形显示您所在位置的某种“视口”

比如:

Rect oRect1 = new Rect(dWorldX, dWorldY, dWorldX + canvas.getWidth(), dWorldY + canvas.getHeight());
Rect oRect2 = new Rect(0, 0, canvas.getWidth(), canvas.getHeight());

canvas.drawBitmap(largeBitmapTexture, oRect1, oRect2, new Paint());
     (-100,-100)  (0,-100)      (100,-100)    (200,-100)
    ******************************************
    *            *             *             *
    *            *             *             *
    *            *             *             *
    *            *             *             *
    *(-100,0)    *(0,0)        *(100,0)      *(200,0)
    ******************************************
    *            *             *             *
    *            *             *             *
    *            *             *             *
    *            *             *             *
    *(-100,100)  *(0,100)      *(100,100)    *(200,100)
    ******************************************
    *            *             *             *
    *            *             *             *
    *            *             *             *
    *            *             *             *
    *(-100,200)  *(0,200)      *(100,200)    *(200,200)
    ******************************************
     (-100,-100)  (0,-100)      (100,-100)    (200,-100)
    ******************************************
    *            *             *             *
    *            *             *             *
    *            *             *             *
    *            *             *             *
    *(-100,0)    *(0,0)        *(100,0)      *(200,0)
    ******************************************
    *            *             *             *
    *            *             *             *
    *            *     (75,75) * (125,75)    *
    *            *          #######          *
    *(-100,100)  *(0,100)   #  *  #          *(200,100)
    ************************#*****#***********
    *            *          #  *  #          *
    *            *          #######          *
    *            *    (75,125) * (125,125)   *
    *            *             *             *
    *(-100,200)  *(0,200)      *(100,200)    *(200,200)
    ******************************************              
但是,当位图无缝且连续滚动时,这对我来说是一个编程挑战。我是否使用了一堆if语句?有没有更有效的方法来做这样的事情

编辑:还有一些想法。这里的一个复杂问题是世界(x,y)是无限大的。因此,我必须使用屏幕宽度和高度的划分来显示需要显示的内容。我最初考虑只进行4次Rect迭代,因为屏幕上的图像不会超过4个。如果这有意义的话。我想我只是对如何计算有点模糊

编辑:这是我现在拥有的代码,以及@glowcoder的建议

public void draw(Canvas canvas){
    int iImagesOverX=0;
    int iImagesOverY=0;

    iImagesOverX = (int)dX / mCloud.getIntrinsicWidth();
    iImagesOverY = (int)dY / mCloud.getIntrinsicHeight();
    mCloud.setBounds(iImagesOverX * (int)mCloud.getIntrinsicWidth() , iImagesOverY * (int)mCloud.getIntrinsicHeight() , (iImagesOverX * (int)mCloud.getIntrinsicWidth()) + mCloud.getIntrinsicWidth() ,  (iImagesOverY * (int)mCloud.getIntrinsicHeight()) + mCloud.getIntrinsicHeight() );
    Log.d(TAG, "bounds:"+ mCloud.getBounds());
    mCloud.draw(canvas);
    mCloud.setBounds((iImagesOverX + 1) * (int)mCloud.getIntrinsicWidth() , iImagesOverY * (int)mCloud.getIntrinsicHeight() , ((iImagesOverX + 1) * (int)mCloud.getIntrinsicWidth()) + mCloud.getIntrinsicWidth() ,  (iImagesOverY * (int)mCloud.getIntrinsicHeight()) + mCloud.getIntrinsicHeight() );
    mCloud.draw(canvas);
    mCloud.setBounds((iImagesOverX + 1) * (int)mCloud.getIntrinsicWidth() , (iImagesOverY + 1)* (int)mCloud.getIntrinsicHeight() , ((iImagesOverX + 1) * (int)mCloud.getIntrinsicWidth()) + mCloud.getIntrinsicWidth() ,  ((iImagesOverY + 1) * (int)mCloud.getIntrinsicHeight()) + mCloud.getIntrinsicHeight() );
    mCloud.draw(canvas);
    mCloud.setBounds((iImagesOverX) * (int)mCloud.getIntrinsicWidth() , (iImagesOverY + 1)* (int)mCloud.getIntrinsicHeight() , ((iImagesOverX) * (int)mCloud.getIntrinsicWidth()) + mCloud.getIntrinsicWidth() ,  ((iImagesOverY + 1) * (int)mCloud.getIntrinsicHeight()) + mCloud.getIntrinsicHeight() );
    mCloud.draw(canvas);
    Log.d(TAG, "imagesoverx:"+ iImagesOverX);
}
我必须将dX和dY添加到边界以使图像移动。但是,一旦向右移动一个“磁贴”,第三个磁贴就不会出现


所以这在一定程度上是可行的,但不完全是我需要的。共有4个面板,但仅因为bounds和draw的4个实例。我需要这4个面板来画出它们需要的位置,无论我们使用x和y在哪里。

我认为谷歌地图在你四处平移时也会做类似的事情。 他们将地图分成许多更小的瓷砖(128x128或196x196)。 如果您想要更平滑的滚动,您需要预先加载一些位图。
这些都是位图虚拟化技术。

基本思想是,您有一个无限平面,其中包含在各个方向反复重复的图像。然后你就有了一个“视口”——你可以把它看作是一个窗口,它限制了你对无限平面的观察。换句话说,视口“下方”的无限平面的面积就是屏幕上实际显示的面积

因此,当视口的左上角位于(0,0)时,可以看到从(0,0)到(50,50)的无限平面部分(假设视口的宽度和高度为50像素)。类似地,如果视口位于(238753),则可以看到从(238753)到(288803)的无限平面部分

如果图像为100x100,则无限平面的形状如下:

Rect oRect1 = new Rect(dWorldX, dWorldY, dWorldX + canvas.getWidth(), dWorldY + canvas.getHeight());
Rect oRect2 = new Rect(0, 0, canvas.getWidth(), canvas.getHeight());

canvas.drawBitmap(largeBitmapTexture, oRect1, oRect2, new Paint());
     (-100,-100)  (0,-100)      (100,-100)    (200,-100)
    ******************************************
    *            *             *             *
    *            *             *             *
    *            *             *             *
    *            *             *             *
    *(-100,0)    *(0,0)        *(100,0)      *(200,0)
    ******************************************
    *            *             *             *
    *            *             *             *
    *            *             *             *
    *            *             *             *
    *(-100,100)  *(0,100)      *(100,100)    *(200,100)
    ******************************************
    *            *             *             *
    *            *             *             *
    *            *             *             *
    *            *             *             *
    *(-100,200)  *(0,200)      *(100,200)    *(200,200)
    ******************************************
     (-100,-100)  (0,-100)      (100,-100)    (200,-100)
    ******************************************
    *            *             *             *
    *            *             *             *
    *            *             *             *
    *            *             *             *
    *(-100,0)    *(0,0)        *(100,0)      *(200,0)
    ******************************************
    *            *             *             *
    *            *             *             *
    *            *     (75,75) * (125,75)    *
    *            *          #######          *
    *(-100,100)  *(0,100)   #  *  #          *(200,100)
    ************************#*****#***********
    *            *          #  *  #          *
    *            *          #######          *
    *            *    (75,125) * (125,125)   *
    *            *             *             *
    *(-100,200)  *(0,200)      *(100,200)    *(200,200)
    ******************************************              
现在,假设视口的左上角为75,75。从图形上看,它看起来像:

Rect oRect1 = new Rect(dWorldX, dWorldY, dWorldX + canvas.getWidth(), dWorldY + canvas.getHeight());
Rect oRect2 = new Rect(0, 0, canvas.getWidth(), canvas.getHeight());

canvas.drawBitmap(largeBitmapTexture, oRect1, oRect2, new Paint());
     (-100,-100)  (0,-100)      (100,-100)    (200,-100)
    ******************************************
    *            *             *             *
    *            *             *             *
    *            *             *             *
    *            *             *             *
    *(-100,0)    *(0,0)        *(100,0)      *(200,0)
    ******************************************
    *            *             *             *
    *            *             *             *
    *            *             *             *
    *            *             *             *
    *(-100,100)  *(0,100)      *(100,100)    *(200,100)
    ******************************************
    *            *             *             *
    *            *             *             *
    *            *             *             *
    *            *             *             *
    *(-100,200)  *(0,200)      *(100,200)    *(200,200)
    ******************************************
     (-100,-100)  (0,-100)      (100,-100)    (200,-100)
    ******************************************
    *            *             *             *
    *            *             *             *
    *            *             *             *
    *            *             *             *
    *(-100,0)    *(0,0)        *(100,0)      *(200,0)
    ******************************************
    *            *             *             *
    *            *             *             *
    *            *     (75,75) * (125,75)    *
    *            *          #######          *
    *(-100,100)  *(0,100)   #  *  #          *(200,100)
    ************************#*****#***********
    *            *          #  *  #          *
    *            *          #######          *
    *            *    (75,125) * (125,125)   *
    *            *             *             *
    *(-100,200)  *(0,200)      *(100,200)    *(200,200)
    ******************************************              
在本例中,视口的角位于(75,75)、(75125)、(125,75)和(125125)。因此,您可以看到图像的右下角位于(0,0),图像的左下角位于(100,0),以此类推

现在,假设您实现了一个函数,该函数计算特定点所在的网格。具体来说,它返回包含该点的栅格的左上角。举几个例子:

gridContainingPoint(0,0)      -> (0,0)
gridContainingPoint(50,50)    -> (0,0)
gridContainingPoint(100,100)  -> (100,100)
gridContainingPoint(123, -27) -> (100,-100)
此功能的实现相当简单:

Point gridContainingPoint(Point pt) {
    int newX = ((int)Math.floor(pt.x/100f)) * 100;
    int newY = ((int)Math.floor(pt.y/100f)) * 100;
    return new Point(newX, newY);
}
现在,要确定需要绘制哪些图像,需要为视口的每个角调用
gridContainingPoint()
方法。在本例中,您将得到:

    gridContainingPoint(75,75)   -> (0,0)
    gridContainingPoint(75,125)  -> (0,100)
    gridContainingPoint(125,75)  -> (100, 0)
    gridContainingPoint(125,125) -> (100, 100)
现在,您可以明确地知道需要绘制哪些图像才能完全覆盖视口

在绘制图像之前,必须正确设置视口。默认情况下,在画布上开始绘制时,视口的位置为(0,0)。因此,您只能看到绘制在画布上的(0,0)x(50,50)区域内的对象。但是,我们希望视口的位置为(75,75),以便在区域(75,75)x(125125)中看到东西。为此,需要调用
Canvas.translate()
方法。例如,
canvas.translate(-75,-75)
。它必须是负数,因为从概念上讲,它是在视口下方移动画布,而不是移动视口

现在,使用对
gridContainingPoint()
的4个调用中的信息,在(0,0)、在(0100)、在(100,0)和在(100,100)处绘制图像。你完成了:)

需要记住的几件事-本例中使用的数字不是您想要使用的实际数字

首先,视口的大小不是50x50,而是绘制视图时的实际大小。您可以通过
View.getWidth()
View.getHeight()
来实现这一点

其次,您需要根据图像大小调整网格大小和相关计算-我怀疑您使用的图像是100x100


最后,请记住,当您为视口的每个角点调用
gridContainingPoint()
方法时,它可能会为多个角点返回相同的网格。例如,如果视口改为位于(25,25),则它将返回每个角的(0,0)图像,因为(25,25)、(25,75)、(75,25)和(75,75)都在从(0,0)到(100100)的图像中。因此,这将是您必须绘制的唯一图像,以便完全覆盖视口。

因为您知道您的图像明显大于画布,所以您知道您一次只能在屏幕上看到图像的一个角。这是有用的

将当前位置设为x,y,原点为0,0。让你的形象是w,h的尺寸

计算从原点到您上方的完整图像数。这只是x/w和